mcp-scraper 0.3.27 → 0.3.40

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 (45) hide show
  1. package/dist/bin/api-server.cjs +2475 -1154
  2. package/dist/bin/api-server.cjs.map +1 -1
  3. package/dist/bin/api-server.js +3 -3
  4. package/dist/bin/mcp-scraper-cli.cjs +1 -1
  5. package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
  6. package/dist/bin/mcp-scraper-cli.js +1 -1
  7. package/dist/bin/mcp-scraper-install.cjs +1 -1
  8. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  9. package/dist/bin/mcp-scraper-install.js +1 -1
  10. package/dist/bin/mcp-stdio-server.cjs +346 -7
  11. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  12. package/dist/bin/mcp-stdio-server.js +7 -4
  13. package/dist/bin/mcp-stdio-server.js.map +1 -1
  14. package/dist/bin/paa-harvest.cjs +109 -5
  15. package/dist/bin/paa-harvest.cjs.map +1 -1
  16. package/dist/bin/paa-harvest.js +2 -2
  17. package/dist/{chunk-TRNSXR46.js → chunk-DVRPXPYH.js} +22 -3
  18. package/dist/chunk-DVRPXPYH.js.map +1 -0
  19. package/dist/{chunk-QSSH4RCX.js → chunk-GMTS35L6.js} +111 -7
  20. package/dist/chunk-GMTS35L6.js.map +1 -0
  21. package/dist/chunk-I5EFBTYE.js +7 -0
  22. package/dist/chunk-I5EFBTYE.js.map +1 -0
  23. package/dist/{chunk-H74L743B.js → chunk-KJWNVQFL.js} +39 -2
  24. package/dist/chunk-KJWNVQFL.js.map +1 -0
  25. package/dist/{chunk-6KHGYJIT.js → chunk-QLQYNE7E.js} +255 -14
  26. package/dist/chunk-QLQYNE7E.js.map +1 -0
  27. package/dist/{db-FP2ABUU4.js → db-LYQENFPW.js} +2 -2
  28. package/dist/index.cjs +109 -5
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +8 -0
  31. package/dist/index.d.ts +8 -0
  32. package/dist/index.js +2 -2
  33. package/dist/{server-KUNOK47B.js → server-HB7WJO3N.js} +1155 -274
  34. package/dist/server-HB7WJO3N.js.map +1 -0
  35. package/dist/{worker-NV4GTIRG.js → worker-TL4J65DE.js} +4 -4
  36. package/package.json +1 -1
  37. package/dist/chunk-6KHGYJIT.js.map +0 -1
  38. package/dist/chunk-DYV72F6A.js +0 -7
  39. package/dist/chunk-DYV72F6A.js.map +0 -1
  40. package/dist/chunk-H74L743B.js.map +0 -1
  41. package/dist/chunk-QSSH4RCX.js.map +0 -1
  42. package/dist/chunk-TRNSXR46.js.map +0 -1
  43. package/dist/server-KUNOK47B.js.map +0 -1
  44. /package/dist/{db-FP2ABUU4.js.map → db-LYQENFPW.js.map} +0 -0
  45. /package/dist/{worker-NV4GTIRG.js.map → worker-TL4J65DE.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../bin/mcp-stdio-server.ts","../../src/harvest-timeout.ts","../../src/lib/browser-service-env.ts","../../src/mcp/http-mcp-tool-executor.ts","../../src/mcp/browser-agent-mcp-server.ts","../../src/services/fanout/export.ts","../../src/version.ts","../../src/mcp/browser-agent-tool-schemas.ts","../../src/mcp/replay-annotator.ts","../../src/errors.ts","../../src/api/outbound-sanitize.ts","../../src/mcp/paa-mcp-server.ts","../../src/mcp/mcp-response-formatter.ts","../../src/mcp/workflow-catalog.ts","../../src/api/seo-link-graph.ts","../../src/api/seo-link-report.ts","../../src/api/seo-issues.ts","../../src/api/image-audit.ts","../../src/mcp/server-instructions.ts","../../src/mcp/mcp-tool-schemas.ts","../../src/schemas.ts","../../src/mcp/rank-tracker-blueprint.ts","../../src/install-terminal.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { HttpMcpToolExecutor } from '../src/mcp/http-mcp-tool-executor.js'\nimport { registerBrowserAgentMcpTools } from '../src/mcp/browser-agent-mcp-server.js'\nimport { registerPaaExtractorMcpTools } from '../src/mcp/paa-mcp-server.js'\nimport { SERVER_INSTRUCTIONS } from '../src/mcp/server-instructions.js'\nimport { renderInstallTerminal } from '../src/install-terminal.js'\nimport { PACKAGE_VERSION } from '../src/version.js'\n\nconst forceStdio =\n process.argv.includes('--stdio') ||\n process.env.MCP_SCRAPER_FORCE_STDIO === '1'\nconst interactiveTerminal = Boolean(process.stdin.isTTY && process.stdout.isTTY)\nconst wantsHelp = process.argv.includes('--help') || process.argv.includes('-h')\n\nif (!forceStdio && (interactiveTerminal || wantsHelp)) {\n const noColor =\n process.argv.includes('--no-color') ||\n process.env.NO_COLOR !== undefined ||\n process.env.FORCE_COLOR === '0' ||\n !process.stdout.isTTY\n\n process.stdout.write(renderInstallTerminal({\n version: PACKAGE_VERSION,\n color: !noColor,\n apiKeyConfigured: Boolean(process.env.MCP_SCRAPER_API_KEY?.trim()),\n }))\n process.exit(0)\n}\n\nfunction readApiKeyFile(): string | undefined {\n const explicitPath = process.env.MCP_SCRAPER_KEY_PATH?.trim()\n const paths = [explicitPath, join(homedir(), '.mcp-scraper-key')].filter(Boolean) as string[]\n for (const path of paths) {\n try {\n const value = readFileSync(path, 'utf8').trim()\n if (value) return value\n } catch {\n void 0\n }\n }\n return undefined\n}\n\nconst apiKey = (\n process.env.MCP_SCRAPER_API_KEY ??\n process.env.MCP_SCRAPER_KEY ??\n process.env.MCP_API_KEY ??\n readApiKeyFile()\n)?.trim()\nif (!apiKey) {\n process.stderr.write('MCP_SCRAPER_API_KEY env var or ~/.mcp-scraper-key is required\\n')\n process.exit(1)\n}\n\nconst baseUrl = process.env.MCP_SCRAPER_BASE_URL?.trim() || process.env.MCP_BASE_URL?.trim() || 'https://mcpscraper.dev'\nconst consoleBaseUrl = process.env.BROWSER_AGENT_CONSOLE_URL?.trim() || baseUrl\nconst server = new McpServer({ name: 'mcp-scraper', version: PACKAGE_VERSION }, { instructions: SERVER_INSTRUCTIONS })\n\nregisterPaaExtractorMcpTools(server, new HttpMcpToolExecutor(baseUrl, apiKey))\nregisterBrowserAgentMcpTools(server, { baseUrl, apiKey, consoleBaseUrl })\n\nconst transport = new StdioServerTransport()\n\nasync function main() {\n await server.connect(transport)\n}\n\nmain().catch(err => {\n process.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`)\n process.exit(1)\n})\n","export const VERCEL_FUNCTION_MAX_MS = 300_000\n\nexport const CLIENT_OVER_SERVER_MARGIN_MS = 15_000\n\nexport interface HarvestTimeoutBudget {\n serverMs: number\n clientMs: number\n}\n\nexport function harvestTimeoutBudget(maxQuestions: number, serpOnly = false): HarvestTimeoutBudget {\n const requested = Number.isFinite(maxQuestions) && maxQuestions > 0 ? Math.trunc(maxQuestions) : 30\n let serverMs: number\n if (serpOnly) serverMs = 110_000\n else if (requested <= 50) serverMs = 170_000\n else if (requested <= 100) serverMs = 230_000\n else serverMs = 285_000\n const clientMs = Math.min(serverMs + CLIENT_OVER_SERVER_MARGIN_MS, VERCEL_FUNCTION_MAX_MS - 5_000)\n return { serverMs, clientMs }\n}\n","export function browserServiceApiKey(): string | undefined {\n const value = (process.env.BROWSER_SERVICE_API_KEY ?? process.env.KERNEL_API_KEY)?.trim()\n return value || undefined\n}\n\nexport function browserServiceProxyId(): string | undefined {\n return undefined\n}\n\nexport function browserServiceProfileName(): string | undefined {\n const value = (\n process.env.BROWSER_AGENT_PROFILE_NAME ??\n process.env.BROWSER_SERVICE_PROFILE_NAME ??\n process.env.KERNEL_BROWSER_PROFILE_NAME ??\n process.env.KERNEL_PROFILE_NAME\n )?.trim()\n return value || undefined\n}\n\nexport function browserServiceProfileSaveChanges(): boolean | undefined {\n const value = (\n process.env.BROWSER_AGENT_PROFILE_SAVE_CHANGES ??\n process.env.BROWSER_SERVICE_PROFILE_SAVE_CHANGES ??\n process.env.KERNEL_BROWSER_PROFILE_SAVE_CHANGES ??\n process.env.KERNEL_PROFILE_SAVE_CHANGES\n )?.trim().toLowerCase()\n if (!value) return undefined\n if (['1', 'true', 'yes', 'on'].includes(value)) return true\n if (['0', 'false', 'no', 'off'].includes(value)) return false\n return undefined\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { IMcpToolExecutor, ISerpIntelligenceToolExecutor } from './IMcpToolExecutor.js'\nimport { harvestTimeoutBudget } from '../harvest-timeout.js'\nimport {\n browserServiceProfileName,\n browserServiceProfileSaveChanges,\n} from '../lib/browser-service-env.js'\nimport type {\n HarvestPaaInput,\n SearchSerpInput,\n ExtractUrlInput,\n MapSiteUrlsInput,\n ExtractSiteInput,\n AuditSiteInput,\n YoutubeHarvestInput,\n YoutubeTranscribeInput,\n FacebookPageIntelInput,\n FacebookAdSearchInput,\n RedditThreadInput,\n FacebookAdTranscribeInput,\n FacebookVideoTranscribeInput,\n InstagramProfileContentInput,\n InstagramMediaDownloadInput,\n MapsPlaceIntelInput,\n MapsSearchInput,\n DirectoryWorkflowInput,\n CreditsInfoInput,\n WorkflowListInput,\n WorkflowRunInput,\n WorkflowStepInput,\n WorkflowStatusInput,\n WorkflowArtifactReadInput,\n CaptureSerpSnapshotInput,\n CaptureSerpPageSnapshotsInput,\n} from './mcp-tool-schemas.js'\n\nfunction youtubeVideoIdFromUrl(url: string | undefined): string | null {\n if (!url) return null\n try {\n const parsed = new URL(url)\n const host = parsed.hostname.replace(/^www\\./, '').replace(/^m\\./, '')\n if (host === 'youtu.be') {\n const id = parsed.pathname.split('/').filter(Boolean)[0]\n return id || null\n }\n if (host === 'youtube.com' || host === 'music.youtube.com') {\n const watchId = parsed.searchParams.get('v')\n if (watchId) return watchId\n const parts = parsed.pathname.split('/').filter(Boolean)\n const markerIndex = parts.findIndex(part => ['shorts', 'embed', 'live'].includes(part))\n if (markerIndex >= 0 && parts[markerIndex + 1]) return parts[markerIndex + 1]\n }\n } catch {\n return null\n }\n return null\n}\n\nasync function readResponseData(res: Response): Promise<unknown> {\n const text = await res.text()\n if (!text.trim()) return null\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n}\n\nfunction httpErrorPayload(path: string, res: Response, data: unknown): Record<string, unknown> {\n const objectData = data && typeof data === 'object' && !Array.isArray(data)\n ? data as Record<string, unknown>\n : null\n const bodyMessage = objectData\n ? objectData.message ?? objectData.error ?? objectData.error_code\n : data\n return {\n ...(objectData ?? { body: data }),\n error: objectData?.error ?? objectData?.error_code ?? 'mcp_http_error',\n error_type: 'http',\n retryable: res.status === 429 || res.status >= 500,\n status: res.status,\n statusText: res.statusText,\n path,\n message: typeof bodyMessage === 'string' && bodyMessage.trim()\n ? bodyMessage\n : `MCP Scraper HTTP ${res.status}${res.statusText ? ` ${res.statusText}` : ''} for ${path}`,\n }\n}\n\nfunction withDefaultHostedProfile<T extends { profile?: string; saveProfileChanges?: boolean }>(input: T): T {\n const profile = input.profile?.trim() || browserServiceProfileName()\n const saveProfileChanges = input.saveProfileChanges ?? browserServiceProfileSaveChanges()\n return {\n ...input,\n ...(profile ? { profile } : {}),\n ...(typeof saveProfileChanges === 'boolean' ? { saveProfileChanges } : {}),\n }\n}\n\nexport class HttpMcpToolExecutor implements IMcpToolExecutor, ISerpIntelligenceToolExecutor {\n private readonly baseUrl: string\n private readonly apiKey: string\n private readonly timeoutMs: number\n private readonly httpTimeoutOverrideMs: number | null\n private readonly serpIntelligenceTimeoutMs: number\n\n constructor(baseUrl: string, apiKey: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n this.apiKey = apiKey\n const rawOverride = process.env.MCP_SCRAPER_HTTP_TIMEOUT_MS\n const parsedOverride = rawOverride === undefined ? NaN : Number(rawOverride)\n this.httpTimeoutOverrideMs = Number.isFinite(parsedOverride) && parsedOverride > 0 ? parsedOverride : null\n this.timeoutMs = this.httpTimeoutOverrideMs ?? 110_000\n const configuredSerpIntelligenceTimeoutMs = Number(process.env.MCP_SCRAPER_SERP_INTELLIGENCE_HTTP_TIMEOUT_MS ?? this.timeoutMs)\n this.serpIntelligenceTimeoutMs = Number.isFinite(configuredSerpIntelligenceTimeoutMs) && configuredSerpIntelligenceTimeoutMs > 0\n ? configuredSerpIntelligenceTimeoutMs\n : this.timeoutMs\n }\n\n private async call(path: string, body: Record<string, unknown>, timeoutMs = this.timeoutMs): 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(timeoutMs),\n })\n const data = await readResponseData(res)\n if (!res.ok) {\n return { content: [{ type: 'text', text: JSON.stringify(httpErrorPayload(path, res, 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 if (err instanceof DOMException && err.name === 'TimeoutError') {\n return {\n content: [{\n type: 'text',\n text: JSON.stringify({\n error: 'mcp_request_timeout',\n error_type: 'timeout',\n retryable: true,\n path,\n timeoutMs,\n message: `MCP Scraper request exceeded ${Math.round(timeoutMs / 1000)}s and was cancelled. Retry with fewer results or use the async API for deep harvests.`,\n }),\n }],\n isError: true,\n }\n }\n return { content: [{ type: 'text', text: msg }], isError: true }\n }\n }\n\n private async getJson(path: string, timeoutMs = this.timeoutMs): Promise<CallToolResult> {\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: 'GET',\n headers: {\n 'x-api-key': this.apiKey,\n },\n signal: AbortSignal.timeout(timeoutMs),\n })\n const data = await readResponseData(res)\n if (!res.ok) {\n return { content: [{ type: 'text', text: JSON.stringify(httpErrorPayload(path, res, 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 private async getTextArtifact(path: string, maxBytes: number, timeoutMs = this.timeoutMs): Promise<CallToolResult> {\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: 'GET',\n headers: {\n 'x-api-key': this.apiKey,\n },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (!res.ok) {\n const data = await res.json().catch(async () => ({ error: await res.text().catch(() => `HTTP ${res.status}`) }))\n return { content: [{ type: 'text', text: JSON.stringify(data) }], isError: true }\n }\n const bytes = Buffer.from(await res.arrayBuffer())\n const sliced = bytes.subarray(0, Math.min(maxBytes, bytes.length))\n return {\n content: [{\n type: 'text',\n text: JSON.stringify({\n contentType: res.headers.get('content-type') ?? 'application/octet-stream',\n bytes: bytes.length,\n truncated: sliced.length < bytes.length,\n maxBytes,\n text: sliced.toString('utf8'),\n }),\n }],\n }\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 const timeoutMs = this.httpTimeoutOverrideMs ?? harvestTimeoutBudget(input.maxQuestions ?? 30).clientMs\n return this.call('/harvest/sync', input as Record<string, unknown>, timeoutMs)\n }\n\n searchSerp(input: SearchSerpInput): Promise<CallToolResult> {\n const timeoutMs = this.httpTimeoutOverrideMs ?? harvestTimeoutBudget(0, true).clientMs\n return this.call('/harvest/sync', { ...input, serpOnly: true } as Record<string, unknown>, timeoutMs)\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 auditSite(input: AuditSiteInput): 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 const videoId = input.videoId?.trim() || youtubeVideoIdFromUrl(input.url)\n if (!videoId) {\n return Promise.resolve({\n content: [{\n type: 'text',\n text: JSON.stringify({\n error_code: 'youtube_video_id_required',\n error: 'Pass videoId from youtube_harvest or a YouTube url that contains a video id.',\n retryable: false,\n }),\n }],\n isError: true,\n })\n }\n return this.call('/youtube/transcribe', { videoId })\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 redditThread(input: RedditThreadInput): Promise<CallToolResult> {\n return this.call('/reddit/thread', input as Record<string, unknown>, this.httpTimeoutOverrideMs ?? 240_000)\n }\n\n facebookAdTranscribe(input: FacebookAdTranscribeInput): Promise<CallToolResult> {\n return this.call('/facebook/transcribe', input as Record<string, unknown>)\n }\n\n facebookVideoTranscribe(input: FacebookVideoTranscribeInput): Promise<CallToolResult> {\n return this.call('/facebook/video-transcribe', input as Record<string, unknown>, this.httpTimeoutOverrideMs ?? 240_000)\n }\n\n instagramProfileContent(input: InstagramProfileContentInput): Promise<CallToolResult> {\n return this.call('/instagram/profile-content', withDefaultHostedProfile(input) as Record<string, unknown>, this.httpTimeoutOverrideMs ?? 240_000)\n }\n\n instagramMediaDownload(input: InstagramMediaDownloadInput): Promise<CallToolResult> {\n return this.call('/instagram/media-download', withDefaultHostedProfile(input) as Record<string, unknown>, this.httpTimeoutOverrideMs ?? 300_000)\n }\n\n mapsPlaceIntel(input: MapsPlaceIntelInput): Promise<CallToolResult> {\n return this.call('/maps/place', input as Record<string, unknown>)\n }\n\n mapsSearch(input: MapsSearchInput): Promise<CallToolResult> {\n return this.call('/maps/search', input as Record<string, unknown>)\n }\n\n directoryWorkflow(input: DirectoryWorkflowInput): Promise<CallToolResult> {\n const cityCount = typeof input.maxCities === 'number' ? input.maxCities : 25\n const concurrency = typeof input.concurrency === 'number' && input.concurrency > 0 ? input.concurrency : 5\n const timeoutMs = this.httpTimeoutOverrideMs ?? Math.min(900_000, Math.max(180_000, Math.ceil(cityCount / concurrency) * 120_000))\n return this.call('/directory/run', input as Record<string, unknown>, timeoutMs)\n }\n\n workflowList(_input: WorkflowListInput): Promise<CallToolResult> {\n return this.getJson('/workflows/definitions')\n }\n\n workflowRun(input: WorkflowRunInput): Promise<CallToolResult> {\n const timeoutMs = this.httpTimeoutOverrideMs ?? Number(process.env.MCP_SCRAPER_WORKFLOW_TIMEOUT_MS ?? 900_000)\n return this.call('/workflows/run', {\n workflowId: input.workflowId,\n input: input.input ?? {},\n webhookUrl: input.webhookUrl,\n }, Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : 900_000)\n }\n\n workflowStep(input: WorkflowStepInput): Promise<CallToolResult> {\n const timeoutMs = this.httpTimeoutOverrideMs ?? Number(process.env.MCP_SCRAPER_WORKFLOW_TIMEOUT_MS ?? 900_000)\n return this.call(`/workflows/runs/${encodeURIComponent(input.runId)}/step`, {}, Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : 900_000)\n }\n\n workflowStatus(input: WorkflowStatusInput): Promise<CallToolResult> {\n return this.getJson(`/workflows/runs/${encodeURIComponent(input.runId)}`)\n }\n\n workflowArtifactRead(input: WorkflowArtifactReadInput): Promise<CallToolResult> {\n return this.getTextArtifact(\n `/workflows/runs/${encodeURIComponent(input.runId)}/artifacts/${encodeURIComponent(input.artifactId)}`,\n input.maxBytes ?? 200_000,\n )\n }\n\n creditsInfo(input: CreditsInfoInput): Promise<CallToolResult> {\n return this.call('/billing/credits', input as Record<string, unknown>)\n }\n\n captureSerpSnapshot(input: CaptureSerpSnapshotInput): Promise<CallToolResult> {\n return this.call('/serp-intelligence/capture', input as Record<string, unknown>, this.serpIntelligenceTimeoutMs)\n }\n\n captureSerpPageSnapshots(input: CaptureSerpPageSnapshotsInput): Promise<CallToolResult> {\n return this.call('/serp-intelligence/page-snapshots', input as Record<string, unknown>, this.serpIntelligenceTimeoutMs)\n }\n\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { browserServiceProfileName, browserServiceProfileSaveChanges } from '../lib/browser-service-env.js'\nimport { exportFanout } from '../services/fanout/export.js'\nimport type { EnrichedFanout } from '../services/fanout/classify.js'\nimport { PACKAGE_VERSION } from '../version.js'\nimport {\n BrowserOpenInputSchema,\n BrowserProfileConnectInputSchema,\n BrowserProfileListInputSchema,\n BrowserCaptureFanoutInputSchema,\n BrowserCaptureFanoutOutputSchema,\n BrowserSessionInputSchema,\n BrowserLocateInputSchema,\n BrowserGotoInputSchema,\n BrowserClickInputSchema,\n BrowserTypeInputSchema,\n BrowserScrollInputSchema,\n BrowserPressInputSchema,\n BrowserReplayStopInputSchema,\n BrowserReplayDownloadInputSchema,\n BrowserReplayMarkInputSchema,\n BrowserReplayAnnotateInputSchema,\n BrowserListInputSchema,\n BrowserOpenOutputSchema,\n BrowserScreenshotOutputSchema,\n BrowserReadOutputSchema,\n BrowserLocateOutputSchema,\n BrowserActionOutputSchema,\n BrowserReplayStartOutputSchema,\n BrowserReplayStopOutputSchema,\n BrowserListReplaysOutputSchema,\n BrowserReplayDownloadOutputSchema,\n BrowserReplayMarkOutputSchema,\n BrowserReplayAnnotateOutputSchema,\n BrowserCloseOutputSchema,\n BrowserListSessionsOutputSchema,\n BrowserProfileConnectOutputSchema,\n BrowserProfileListOutputSchema,\n} from './browser-agent-tool-schemas.js'\nimport { annotateReplayVideo } from './replay-annotator.js'\nimport { sanitizeOutboundDiagnostics } from '../api/outbound-sanitize.js'\n\nexport interface BrowserAgentHttpOptions {\n baseUrl: string\n apiKey: string\n consoleBaseUrl?: string\n timeoutMs?: number\n}\n\nfunction structuredResult(value: Record<string, unknown>, isError = false): CallToolResult {\n const safe = sanitizeOutboundDiagnostics(value)\n return {\n content: [{ type: 'text', text: JSON.stringify(safe) }],\n structuredContent: safe,\n isError,\n }\n}\n\nfunction errorMessage(value: unknown): string {\n if (value && typeof value === 'object') {\n const data = value as Record<string, unknown>\n if (typeof data.error === 'string') return data.error\n if (typeof data.message === 'string') return data.message\n }\n return typeof value === 'string' ? value : 'Browser Agent request failed'\n}\n\nfunction errorResult(tool: string, value: unknown, sessionId: string | null = null, replayId: string | null = null): CallToolResult {\n return structuredResult({\n ok: false,\n tool,\n session_id: sessionId,\n ...(replayId !== null ? { replay_id: replayId } : {}),\n error: errorMessage(value),\n raw: value && typeof value === 'object' ? value as Record<string, unknown> : { value },\n }, true)\n}\n\nfunction actionResult(\n tool: string,\n sessionId: string,\n ok: boolean,\n data: unknown,\n nextRecommendedTool: string | null = 'browser_screenshot',\n): CallToolResult {\n if (!ok) return errorResult(tool, data, sessionId)\n return structuredResult({\n ok: true,\n tool,\n session_id: sessionId,\n result: data && typeof data === 'object' ? data as Record<string, unknown> : { value: data },\n nextRecommendedTool,\n })\n}\n\nfunction outputBaseDir(): string {\n return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || join(homedir(), 'Downloads', 'mcp-scraper')\n}\n\nfunction safeFilePart(value: string): string {\n return value.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 120) || 'replay'\n}\n\nfunction replayFilePath(sessionId: string, replayId: string, filename?: string): string {\n const requested = filename?.trim()\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const name = requested\n ? safeFilePart(requested).replace(/\\.mp4$/i, '')\n : `${stamp}-${safeFilePart(sessionId)}-${safeFilePart(replayId)}`\n return join(outputBaseDir(), 'browser-replays', `${name}.mp4`)\n}\n\nfunction slugPart(value?: string): string | null {\n const trimmed = value?.trim().toLowerCase()\n if (!trimmed) return null\n return trimmed\n .replace(/^https?:\\/\\//, '')\n .replace(/^www\\./, '')\n .replace(/\\/.*$/, '')\n .replace(/[^a-z0-9._-]+/g, '-')\n .replace(/[._-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\nfunction savedProfileNameFromEmail(email?: string): string | null {\n const value = slugPart(email)\n if (!value) return null\n return value.slice(0, 80) || null\n}\n\nfunction isEnrichedFanout(value: unknown): value is EnrichedFanout {\n if (!value || typeof value !== 'object') return false\n const candidate = value as Partial<EnrichedFanout>\n return (\n typeof candidate.platform === 'string' &&\n typeof candidate.capturedAt === 'string' &&\n typeof candidate.prompt === 'string' &&\n Array.isArray(candidate.queries) &&\n Array.isArray(candidate.browsedUrls) &&\n Array.isArray(candidate.citedUrls) &&\n Array.isArray(candidate.browsedOnly) &&\n Array.isArray(candidate.snippets) &&\n !!candidate.counts &&\n !!candidate.aggregates\n )\n}\n\nfunction annotatedReplayFilePath(sessionId: string, replayId: string, filename?: string): string {\n const requested = filename?.trim()\n if (requested) return replayFilePath(sessionId, replayId, requested)\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n return replayFilePath(sessionId, replayId, `${stamp}-${safeFilePart(sessionId)}-${safeFilePart(replayId)}-annotated`)\n}\n\nfunction finiteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value)\n}\n\nfunction expandElementBounds(\n element: { left: number; top: number; width: number; height: number },\n viewport: { width?: number; height?: number } | undefined,\n padding: number,\n) {\n const sourceWidth = finiteNumber(viewport?.width) && viewport!.width > 0 ? viewport!.width : 1920\n const sourceHeight = finiteNumber(viewport?.height) && viewport!.height > 0 ? viewport!.height : 1080\n const left = Math.max(0, element.left - padding)\n const top = Math.max(0, element.top - padding)\n const right = Math.min(sourceWidth, element.left + element.width + padding)\n const bottom = Math.min(sourceHeight, element.top + element.height + padding)\n return {\n left,\n top,\n width: Math.max(1, right - left),\n height: Math.max(1, bottom - top),\n sourceWidth,\n sourceHeight,\n }\n}\n\nexport function buildBrowserAgentMcpServer(opts: BrowserAgentHttpOptions): McpServer {\n const server = new McpServer({ name: 'browser-agent', version: PACKAGE_VERSION })\n registerBrowserAgentMcpTools(server, opts)\n return server\n}\n\nexport function registerBrowserAgentMcpTools(server: McpServer, opts: BrowserAgentHttpOptions): void {\n const baseUrl = opts.baseUrl.replace(/\\/$/, '')\n const consoleBase = (opts.consoleBaseUrl ?? opts.baseUrl).replace(/\\/$/, '')\n const timeoutMs = opts.timeoutMs ?? 90_000\n\n async function req(\n method: string,\n path: string,\n body?: Record<string, unknown>,\n requestTimeoutMs = timeoutMs,\n ): Promise<{ ok: boolean; data: any }> {\n try {\n const res = await fetch(`${baseUrl}${path}`, {\n method,\n headers: { 'Content-Type': 'application/json', 'x-api-key': opts.apiKey },\n body: body ? JSON.stringify(body) : undefined,\n signal: AbortSignal.timeout(requestTimeoutMs),\n })\n const data = await res.json().catch(() => ({}))\n return { ok: res.ok, data }\n } catch (err) {\n return { ok: false, data: { error: err instanceof Error ? err.message : String(err) } }\n }\n }\n\n async function downloadReplay(\n sessionId: string,\n replayId: string,\n filename?: string,\n ): Promise<{ ok: boolean; data: any }> {\n const path = `/agent/sessions/${encodeURIComponent(sessionId)}/replays/${encodeURIComponent(replayId)}/download`\n try {\n const res = await fetch(`${baseUrl}${path}`, {\n method: 'GET',\n headers: { 'x-api-key': opts.apiKey },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (!res.ok) {\n const data = await res.json().catch(async () => ({ error: await res.text().catch(() => `HTTP ${res.status}`) }))\n return { ok: false, data }\n }\n const bytes = Buffer.from(await res.arrayBuffer())\n const filePath = replayFilePath(sessionId, replayId, filename)\n mkdirSync(join(outputBaseDir(), 'browser-replays'), { recursive: true })\n writeFileSync(filePath, bytes)\n return {\n ok: true,\n data: {\n replay_id: replayId,\n file_path: filePath,\n bytes: bytes.length,\n mime_type: res.headers.get('content-type') ?? 'video/mp4',\n download_url: `${baseUrl}${path}`,\n },\n }\n } catch (err) {\n return { ok: false, data: { error: err instanceof Error ? err.message : String(err) } }\n }\n }\n\n const annotations = (title: string, readOnly = false) => ({\n title,\n readOnlyHint: readOnly,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n })\n\n function normalizeLogin(conn: any) {\n return {\n connection_id: conn.connection_id ?? null,\n domain: conn.domain,\n status: conn.status,\n account_email: conn.account_email ?? null,\n note: conn.note ?? null,\n watch_url: conn.connection_id && conn.status !== 'AUTHENTICATED' ? `${consoleBase}/console/auth/${conn.connection_id}` : null,\n last_connected_at: conn.last_connected_at ?? null,\n }\n }\n\n async function fetchConnectedLogins(profile: string): Promise<unknown[]> {\n const list = await req('POST', '/agent/profiles/list', { profile })\n return list.ok && Array.isArray(list.data?.connections) ? list.data.connections.map(normalizeLogin) : []\n }\n\n server.registerTool(\n 'browser_profile_connect',\n {\n title: 'Save a Site Login to a Profile',\n description:\n 'Save a logged-in browser session so this server can reuse a site the user is signed into (ChatGPT, Claude, Reddit, or any account-gated site). Returns an mcpscraper.dev watch_url — give it to the user, they sign in once, and the cookies are saved to a named profile for later browser_open calls. ONE profile holds MANY logins: call this again with the SAME profile and a DIFFERENT domain to stack another account (e.g. add claude.ai to a profile that already has chatgpt.com). Pass note to record what each login is. Side effects: opens a short-lived sign-in session and persists cookies to the profile; it does NOT import the user\\'s existing browser cookies (they log in fresh). NOT for one-off scraping of public pages (use extract_url) and NOT a way to drive the browser (use browser_open). Sample asks: \"save my ChatGPT login\", \"connect my Reddit account\", \"add my Claude login to the same profile\". After the user signs in, poll browser_profile_list until the login reads AUTHENTICATED, then browser_open with the profile.',\n inputSchema: BrowserProfileConnectInputSchema,\n outputSchema: BrowserProfileConnectOutputSchema,\n annotations: annotations('Save a Site Login to a Profile'),\n },\n async input => {\n const domain = slugPart(input.domain) || 'chatgpt.com'\n const setupUrl = input.login_url ?? input.url ?? (domain === 'chatgpt.com' ? 'https://chatgpt.com/' : `https://${domain}/`)\n const profile = input.profile?.trim() || savedProfileNameFromEmail(input.email) || browserServiceProfileName()\n if (!profile) {\n return errorResult('browser_profile_connect', {\n error: 'profile or email is required when BROWSER_AGENT_PROFILE_NAME is not available',\n })\n }\n const accountEmail = input.email?.trim() || null\n const note = input.note?.trim() || null\n const open = await req('POST', '/agent/profiles/onboard', {\n label: input.label ?? `Login setup: ${domain} → ${profile}`,\n profile,\n domain,\n login_url: setupUrl,\n ...(accountEmail ? { account_email: accountEmail } : {}),\n ...(note ? { note } : {}),\n })\n if (!open.ok) return errorResult('browser_profile_connect', open.data)\n const connectedLogins = await fetchConnectedLogins(profile).catch(() => [])\n return structuredResult({\n ok: true,\n tool: 'browser_profile_connect',\n session_id: null,\n auth_connection_id: open.data.connection_id,\n watch_url: `${consoleBase}/console/auth/${open.data.connection_id}`,\n live_view_url: null,\n profile,\n domain,\n setup_url: setupUrl,\n account_email: accountEmail,\n note,\n status: open.data.status ?? null,\n flow_status: open.data.flow_status ?? null,\n flow_step: open.data.flow_step ?? null,\n flow_expires_at: open.data.flow_expires_at ?? null,\n post_login_url: open.data.post_login_url ?? null,\n connected_logins: connectedLogins,\n next_steps: [\n `Give the user watch_url so they can sign in to ${domain}.`,\n 'Poll browser_profile_list (with this profile) until the login reads AUTHENTICATED.',\n 'To add another account to this same profile, call browser_profile_connect again with the same profile and a different domain.',\n 'When authenticated, call browser_open with this profile to drive the logged-in session.',\n ],\n raw: open.data,\n })\n },\n )\n\n server.registerTool(\n 'browser_profile_list',\n {\n title: 'List Saved Logins in a Profile',\n description:\n 'List every site login saved in a profile, each with its current auth status (NEEDS_AUTH / AUTHENTICATED), account email, and note. Use it to (1) see what a profile is connected to before opening a session, and (2) poll a just-saved login until it flips to AUTHENTICATED. Read-only, no cost. Pass profile (or email to derive it); narrow with domain or connection_id to poll a single login. Sample asks: \"what\\'s connected in my profile\", \"is my ChatGPT login ready yet\", \"which accounts are saved\". Pairs with browser_profile_connect (which adds logins) and browser_open (which uses them).',\n inputSchema: BrowserProfileListInputSchema,\n outputSchema: BrowserProfileListOutputSchema,\n annotations: annotations('List Saved Logins in a Profile', true),\n },\n async input => {\n const profile = input.profile?.trim() || savedProfileNameFromEmail(input.email) || browserServiceProfileName()\n if (!profile) {\n return errorResult('browser_profile_list', {\n error: 'profile or email is required when BROWSER_AGENT_PROFILE_NAME is not available',\n })\n }\n const domain = slugPart(input.domain) || undefined\n const res = await req('POST', '/agent/profiles/list', {\n profile,\n ...(domain ? { domain } : {}),\n ...(input.connection_id ? { connection_id: input.connection_id } : {}),\n })\n if (!res.ok) return errorResult('browser_profile_list', res.data)\n const connections = (Array.isArray(res.data?.connections) ? res.data.connections : []).map(normalizeLogin)\n return structuredResult({\n ok: true,\n tool: 'browser_profile_list',\n session_id: null,\n profile,\n connections,\n count: connections.length,\n })\n },\n )\n\n server.registerTool(\n 'browser_open',\n {\n title: 'Open Browser Session',\n description:\n 'Open a direct no-proxy hosted browser session you can drive. Pass a saved profile name to load a session that is already logged into the sites saved in that profile (one profile can hold several logins). To set up or refresh a login first, use browser_profile_connect, then poll browser_profile_list until it reads AUTHENTICATED. Returns a session_id used by all other browser_* tools.',\n inputSchema: BrowserOpenInputSchema,\n outputSchema: BrowserOpenOutputSchema,\n annotations: annotations('Open Browser Session'),\n },\n async input => {\n const profile = input.profile ?? browserServiceProfileName()\n const saveProfileChanges = input.save_profile_changes ?? browserServiceProfileSaveChanges()\n const open = await req('POST', '/agent/sessions', {\n label: input.label,\n ...(profile ? { profile } : {}),\n ...(profile && typeof saveProfileChanges === 'boolean' ? { save_profile_changes: saveProfileChanges } : {}),\n disable_default_proxy: true,\n timeout_seconds: input.timeout_seconds,\n ...(input.url ? { url: input.url } : {}),\n })\n if (!open.ok) return errorResult('browser_open', open.data)\n const session = open.data\n return structuredResult({\n ok: true,\n tool: 'browser_open',\n session_id: session.session_id,\n watch_url: `${consoleBase}/console/${session.session_id}`,\n live_view_url: null,\n url: input.url ?? null,\n hint: 'Call browser_screenshot to see the page. Click by the x,y of an element from the snapshot.',\n raw: session,\n })\n },\n )\n\n server.registerTool(\n 'browser_screenshot',\n {\n title: 'See Page (Screenshot + Elements)',\n description:\n 'Capture what the browser currently shows. Returns a screenshot image PLUS a text snapshot listing interactive elements with their center x,y coordinates, the page url and title, and visible text. This is your primary way to perceive the page. Click elements by their listed x,y. If a Cloudflare/CAPTCHA challenge is visible, wait and screenshot again rather than clicking it.',\n inputSchema: BrowserSessionInputSchema,\n outputSchema: BrowserScreenshotOutputSchema,\n annotations: annotations('See Page', true),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/screenshot`)\n if (!res.ok) return errorResult('browser_screenshot', res.data, input.session_id)\n const { image_base64, mime_type, url, title, elements, text } = res.data\n const content: CallToolResult['content'] = []\n if (image_base64) content.push({ type: 'image', data: image_base64, mimeType: mime_type ?? 'image/png' })\n const structured = {\n ok: true,\n tool: 'browser_screenshot',\n session_id: input.session_id,\n url: url ?? null,\n title: title ?? null,\n text: typeof text === 'string' ? text : '',\n elements: Array.isArray(elements) ? elements : [],\n screenshot: image_base64 ? { mime_type: mime_type ?? 'image/png', inline: true } : null,\n }\n content.push({\n type: 'text',\n text: JSON.stringify(structured),\n })\n return { content, structuredContent: structured }\n },\n )\n\n server.registerTool(\n 'browser_read',\n {\n title: 'Read Page Text + Elements',\n description:\n 'Return the page url, title, visible text, and the list of interactive elements (with x,y) without an image. Cheaper than browser_screenshot when you only need to read content or find a target element to click.',\n inputSchema: BrowserSessionInputSchema,\n outputSchema: BrowserReadOutputSchema,\n annotations: annotations('Read Page', true),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/read`)\n if (!res.ok) return errorResult('browser_read', res.data, input.session_id)\n return structuredResult({\n ok: true,\n tool: 'browser_read',\n session_id: input.session_id,\n url: res.data?.url ?? null,\n title: res.data?.title ?? null,\n text: typeof res.data?.text === 'string' ? res.data.text : '',\n elements: Array.isArray(res.data?.elements) ? res.data.elements : [],\n raw: res.data,\n })\n },\n )\n\n server.registerTool(\n 'browser_locate',\n {\n title: 'Locate DOM Targets',\n description:\n 'Locate exact visible DOM elements or text ranges in the current browser viewport and return left/top/width/height bounds in screenshot pixels. Use this before drawing annotations or when a callout must literally circle, box, underline, or point to a real element. Prefer CSS selectors for exact UI elements; use text when selector is unknown. When a replay is actively recording, the result includes replay_elapsed_seconds for timing.',\n inputSchema: BrowserLocateInputSchema,\n outputSchema: BrowserLocateOutputSchema,\n annotations: annotations('Locate DOM Targets', true),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/locate`, { targets: input.targets })\n if (!res.ok) return errorResult('browser_locate', res.data, input.session_id)\n return structuredResult({\n ok: true,\n tool: 'browser_locate',\n session_id: input.session_id,\n url: res.data?.url ?? null,\n title: res.data?.title ?? null,\n viewport: res.data?.viewport ?? null,\n replay: res.data?.replay ?? null,\n targets: Array.isArray(res.data?.targets) ? res.data.targets : [],\n raw: res.data,\n })\n },\n )\n\n server.registerTool(\n 'browser_goto',\n {\n title: 'Navigate To URL',\n description: 'Navigate an existing browser session to a URL when the user asks you to go to another page or continue browsing in the same session. Use browser_open first if no session exists. Follow with browser_screenshot to see redirects, login walls, CAPTCHA/Cloudflare state, or the loaded page.',\n inputSchema: BrowserGotoInputSchema,\n outputSchema: BrowserActionOutputSchema,\n annotations: annotations('Navigate To URL'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/goto`, { url: input.url })\n return actionResult('browser_goto', input.session_id, res.ok, res.data, 'browser_screenshot')\n },\n )\n\n server.registerTool(\n 'browser_click',\n {\n title: 'Click',\n description: 'Click a visible page target using screenshot pixel coordinates. Use this when the user asks you to press a button, open a menu, choose a result, or activate a visible UI element. Use x/y only from the latest browser_screenshot, browser_read, or browser_locate result; do not guess coordinates. Follow with browser_screenshot when the click may change the page.',\n inputSchema: BrowserClickInputSchema,\n outputSchema: BrowserActionOutputSchema,\n annotations: annotations('Click'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/click`, {\n x: input.x,\n y: input.y,\n button: input.button,\n num_clicks: input.num_clicks,\n })\n return actionResult('browser_click', input.session_id, res.ok, res.data, 'browser_screenshot')\n },\n )\n\n server.registerTool(\n 'browser_type',\n {\n title: 'Type Text',\n description: 'Type text into the currently focused browser field. Use this when the user asks you to fill a search box, form field, login field, or editable text area. Click or Tab to the field first if focus is uncertain. Use browser_press with [\"Return\"] to submit, and browser_screenshot afterward when page state matters.',\n inputSchema: BrowserTypeInputSchema,\n outputSchema: BrowserActionOutputSchema,\n annotations: annotations('Type Text'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/type`, { text: input.text, delay: input.delay })\n return actionResult('browser_type', input.session_id, res.ok, res.data, 'browser_screenshot')\n },\n )\n\n server.registerTool(\n 'browser_scroll',\n {\n title: 'Scroll',\n description: 'Scroll the page to reveal more content before reading, clicking, or locating elements. Positive delta_y scrolls down; negative delta_y scrolls up. Follow with browser_screenshot or browser_read to inspect newly revealed content.',\n inputSchema: BrowserScrollInputSchema,\n outputSchema: BrowserActionOutputSchema,\n annotations: annotations('Scroll'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/scroll`, {\n delta_y: input.delta_y,\n delta_x: input.delta_x,\n x: input.x,\n y: input.y,\n })\n return actionResult('browser_scroll', input.session_id, res.ok, res.data, 'browser_screenshot')\n },\n )\n\n server.registerTool(\n 'browser_press',\n {\n title: 'Press Keys',\n description: 'Press keyboard keys or combinations in the active browser session. Use this for submit, Escape, Tab navigation, select-all, or keyboard shortcuts. Examples: [\"Return\"], [\"Escape\"], [\"Tab\"], [\"Ctrl+a\"], [\"Ctrl+Shift+Tab\"]. Use browser_type for text entry and browser_screenshot after keypresses that may change the page.',\n inputSchema: BrowserPressInputSchema,\n outputSchema: BrowserActionOutputSchema,\n annotations: annotations('Press Keys'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/press`, { keys: input.keys })\n return actionResult('browser_press', input.session_id, res.ok, res.data, 'browser_screenshot')\n },\n )\n\n server.registerTool(\n 'browser_replay_start',\n {\n title: 'Start Recording',\n description: 'Start recording an MP4 replay of the session. Returns replay_id, view_url when available, and a download_url. Use to capture a task for later review; stop with browser_replay_stop.',\n inputSchema: BrowserSessionInputSchema,\n outputSchema: BrowserReplayStartOutputSchema,\n annotations: annotations('Start Recording'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/replay/start`)\n if (!res.ok) return errorResult('browser_replay_start', res.data, input.session_id)\n return structuredResult({\n ok: true,\n tool: 'browser_replay_start',\n session_id: input.session_id,\n replay_id: res.data?.replay_id ?? res.data?.replayId ?? null,\n view_url: res.data?.view_url ?? res.data?.viewUrl ?? null,\n download_url: res.data?.download_url ?? res.data?.downloadUrl ?? null,\n raw: res.data,\n })\n },\n )\n\n server.registerTool(\n 'browser_replay_stop',\n {\n title: 'Stop Recording',\n description: 'Stop a replay recording and expose the final view_url and download_url. Use browser_replay_download to save the MP4 to the configured output directory.',\n inputSchema: BrowserReplayStopInputSchema,\n outputSchema: BrowserReplayStopOutputSchema,\n annotations: annotations('Stop Recording'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/replay/stop`, { replay_id: input.replay_id })\n if (!res.ok) return errorResult('browser_replay_stop', res.data, input.session_id, input.replay_id)\n return structuredResult({\n ok: true,\n tool: 'browser_replay_stop',\n session_id: input.session_id,\n replay_id: res.data?.replay_id ?? res.data?.replayId ?? input.replay_id,\n view_url: res.data?.view_url ?? res.data?.viewUrl ?? null,\n download_url: res.data?.download_url ?? res.data?.downloadUrl ?? null,\n raw: res.data,\n })\n },\n )\n\n server.registerTool(\n 'browser_list_replays',\n {\n title: 'List Replay Videos',\n description: 'List replay recordings for a browser session, including final view_url and authenticated download_url values when available.',\n inputSchema: BrowserSessionInputSchema,\n outputSchema: BrowserListReplaysOutputSchema,\n annotations: annotations('List Replay Videos', true),\n },\n async input => {\n const res = await req('GET', `/agent/sessions/${input.session_id}/replays`)\n if (!res.ok) return errorResult('browser_list_replays', res.data, input.session_id)\n const replays = Array.isArray(res.data?.replays) ? res.data.replays : []\n return structuredResult({\n ok: true,\n tool: 'browser_list_replays',\n session_id: input.session_id,\n replays,\n count: replays.length,\n })\n },\n )\n\n server.registerTool(\n 'browser_replay_download',\n {\n title: 'Download Replay MP4',\n description: 'Download a replay recording through MCP Scraper and save the MP4 under MCP_SCRAPER_OUTPUT_DIR/browser-replays. Use after browser_replay_stop or browser_list_replays.',\n inputSchema: BrowserReplayDownloadInputSchema,\n outputSchema: BrowserReplayDownloadOutputSchema,\n annotations: annotations('Download Replay MP4'),\n },\n async input => {\n const res = await downloadReplay(input.session_id, input.replay_id, input.filename)\n if (!res.ok) return errorResult('browser_replay_download', res.data, input.session_id, input.replay_id)\n return structuredResult({\n ok: true,\n tool: 'browser_replay_download',\n session_id: input.session_id,\n replay_id: input.replay_id,\n file_path: res.data?.file_path ?? null,\n bytes: typeof res.data?.bytes === 'number' ? res.data.bytes : null,\n mime_type: res.data?.mime_type ?? null,\n download_url: res.data?.download_url ?? null,\n })\n },\n )\n\n server.registerTool(\n 'browser_replay_mark',\n {\n title: 'Mark Replay Annotation',\n description:\n 'While a replay is actively recording, locate one exact DOM target and return a ready-to-use annotation object with DOM bounds and replay-relative timing. Use this instead of guessing start_seconds or drawing rough rectangles. Workflow: start browser_replay_start, navigate until the target is visible and stable, call browser_replay_mark for each callout, then stop the replay and pass the returned annotations to browser_replay_annotate.',\n inputSchema: BrowserReplayMarkInputSchema,\n outputSchema: BrowserReplayMarkOutputSchema,\n annotations: annotations('Mark Replay Annotation', true),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/locate`, { targets: [input.target] })\n if (!res.ok) return errorResult('browser_replay_mark', res.data, input.session_id)\n const target = res.data?.targets?.[0]\n const element = target?.element\n const elapsed = res.data?.replay?.replay_elapsed_seconds\n if (!target?.found || !element) {\n return errorResult('browser_replay_mark', { error: target?.error ?? 'target not found in current viewport', target }, input.session_id)\n }\n if (!finiteNumber(elapsed)) {\n return errorResult('browser_replay_mark', { error: 'no active replay clock found; call browser_replay_start before browser_replay_mark' }, input.session_id)\n }\n const padded = expandElementBounds(element, res.data?.viewport, input.padding ?? 8)\n const start = Math.max(0, elapsed + (input.start_offset_seconds ?? -0.25))\n const duration = input.duration_seconds ?? 4\n const annotation = {\n type: input.type ?? 'box',\n start_seconds: Number(start.toFixed(3)),\n end_seconds: Number((start + duration).toFixed(3)),\n left: Math.round(padded.left),\n top: Math.round(padded.top),\n width: Math.round(padded.width),\n height: Math.round(padded.height),\n ...(input.label ? { label: input.label } : {}),\n ...(input.color ? { color: input.color } : {}),\n ...(input.thickness ? { thickness: input.thickness } : {}),\n }\n return structuredResult({\n ok: true,\n tool: 'browser_replay_mark',\n session_id: input.session_id,\n replay_id: res.data?.replay?.replay_id ?? res.data?.replay?.replayId ?? null,\n annotation,\n source_width: padded.sourceWidth,\n source_height: padded.sourceHeight,\n replay: res.data.replay,\n target,\n hint: 'Append annotation to your annotations array. Use source_width/source_height with browser_replay_annotate.',\n })\n },\n )\n\n server.registerTool(\n 'browser_replay_annotate',\n {\n title: 'Annotate Replay MP4',\n description:\n 'Download a browser replay MP4, render visual annotations over it, and save a new annotated MP4 under MCP_SCRAPER_OUTPUT_DIR/browser-replays. Use this after browser_replay_stop when the user wants proof videos with circles, boxes, arrows, underlines, or labels. For accurate timing and placement, prefer annotations returned by browser_replay_mark while the replay is recording; otherwise use exact left/top/width/height bounds from browser_locate. If the replay video size differs from the screenshot coordinate space, pass source_width and source_height.',\n inputSchema: BrowserReplayAnnotateInputSchema,\n outputSchema: BrowserReplayAnnotateOutputSchema,\n annotations: annotations('Annotate Replay MP4'),\n },\n async input => {\n const sourceName = input.filename ? `${input.filename}-source` : undefined\n const downloaded = await downloadReplay(input.session_id, input.replay_id, sourceName)\n if (!downloaded.ok) return errorResult('browser_replay_annotate', downloaded.data, input.session_id, input.replay_id)\n try {\n const sourcePath = String(downloaded.data.file_path)\n const outputPath = annotatedReplayFilePath(input.session_id, input.replay_id, input.filename)\n mkdirSync(join(outputBaseDir(), 'browser-replays'), { recursive: true })\n const result = await annotateReplayVideo(sourcePath, outputPath, {\n annotations: input.annotations,\n sourceWidth: input.source_width,\n sourceHeight: input.source_height,\n sourceLeftOffset: input.source_left_offset,\n sourceTopOffset: input.source_top_offset,\n })\n return structuredResult({\n ok: true,\n tool: 'browser_replay_annotate',\n session_id: input.session_id,\n replay_id: input.replay_id,\n source_file_path: sourcePath,\n annotated_file_path: result.filePath,\n bytes: result.bytes,\n width: result.width,\n height: result.height,\n annotation_count: result.annotationCount,\n mime_type: 'video/mp4',\n })\n } catch (err) {\n return errorResult('browser_replay_annotate', { error: err instanceof Error ? err.message : String(err) }, input.session_id, input.replay_id)\n }\n },\n )\n\n server.registerTool(\n 'browser_close',\n {\n title: 'Close Browser Session',\n description: 'Close and release a browser session when the task is done, when the user asks to stop the browser, or when active browser billing should end. Use browser_list_sessions first if you need to recover the session_id.',\n inputSchema: BrowserSessionInputSchema,\n outputSchema: BrowserCloseOutputSchema,\n annotations: { title: 'Close Browser Session', readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },\n },\n async input => {\n const res = await req('DELETE', `/agent/sessions/${input.session_id}`)\n if (!res.ok) return errorResult('browser_close', res.data, input.session_id)\n return structuredResult({\n ok: true,\n tool: 'browser_close',\n session_id: input.session_id,\n closed: true,\n raw: res.data,\n })\n },\n )\n\n server.registerTool(\n 'browser_list_sessions',\n {\n title: 'List Browser Sessions',\n description: 'List browser sessions and their status, with a watch_url for each. Use this to recover a session_id, find an active browser, or decide which session to close. Use browser_open to create a new session.',\n inputSchema: BrowserListInputSchema,\n outputSchema: BrowserListSessionsOutputSchema,\n annotations: annotations('List Browser Sessions', true),\n },\n async input => {\n const res = await req('GET', `/agent/sessions${input.include_closed ? '?all=1' : ''}`)\n if (!res.ok) return errorResult('browser_list_sessions', res.data)\n const sessions = (res.data.sessions ?? []).map((s: any) => ({ ...s, watch_url: `${consoleBase}/console/${s.session_id}` }))\n return structuredResult({\n ok: true,\n tool: 'browser_list_sessions',\n session_id: null,\n sessions,\n count: sessions.length,\n })\n },\n )\n\n server.registerTool(\n 'query_fanout_workflow',\n {\n title: 'Capture AI Search Fan-Out',\n description:\n 'Capture the query fan-out behind a ChatGPT or Claude web-search answer for Answer Engine Optimization (AEO): the exact sub-queries the model issued, every researched URL split into cited vs browsed-only (with citation frequency and snippet), each source tagged by category (First-party/vendor, News/media, Reddit, Social/video, Encyclopedia, Review site, Docs, Blog), plus top sourced sites and citation order. Set export=true for durable JSON, CSV, TSV, and HTML artifacts; export paths are returned relative to MCP_SCRAPER_OUTPUT_DIR. This returns the raw structured data; YOU analyze it — classify each sub-query by funnel stage (Problem-aware, Solution-aware, Decision-aware, Retention) and type (BoFu, Branded, Comparison, How-to, Search operator), name the brands the model researched, and give AEO insights. Sample asks: \"capture the fan-out for this ChatGPT answer\", \"what did Claude search and cite for best CRM\", \"show the sub-queries and sources behind this AI answer\". WRITE NOTE: passing prompt submits a real message in the user\\'s logged-in account (a new conversation turn) — only send when the user wants that; omit prompt to capture a prompt the user just ran. Setup, if not already connected or if the profile disconnected: call browser_profile_connect, give the user the watch_url, let them complete login, then poll browser_profile_list until status is AUTHENTICATED. After that, browser_open the saved direct no-proxy profile and go to chatgpt.com or claude.ai. Fan-out is captured only as it streams, so the session must be open when the prompt runs. NOT for Google AI Overview citations — use harvest_paa for those; this tool is ChatGPT and Claude only.',\n inputSchema: BrowserCaptureFanoutInputSchema,\n outputSchema: BrowserCaptureFanoutOutputSchema,\n annotations: annotations('Capture AI Search Fan-Out'),\n },\n async input => {\n const emit = (result: Record<string, unknown>, exports: unknown) => structuredResult({\n ok: true,\n tool: 'query_fanout_workflow',\n session_id: input.session_id,\n platform: result.platform,\n captured_at: result.capturedAt,\n prompt: result.prompt,\n meta: result.meta,\n queries: result.queries,\n browsed_urls: result.browsedUrls,\n cited_urls: result.citedUrls,\n browsed_only: result.browsedOnly,\n snippets: result.snippets,\n counts: result.counts,\n aggregates: result.aggregates,\n first_party_domain: result.firstPartyDomain,\n exports: exports ?? null,\n ...(result.debug ? { debug: result.debug } : {}),\n })\n const res = await req('POST', `/agent/sessions/${input.session_id}/capture-fanout`, {\n prompt: input.prompt,\n wait_ms: input.wait_ms,\n first_party_domain: input.first_party_domain,\n reset: input.reset,\n export: input.export,\n }, Math.max(timeoutMs, (input.wait_ms ?? (input.prompt ? 90_000 : 8_000)) + 30_000))\n if (!res.ok) return errorResult('query_fanout_workflow', res.data, input.session_id)\n const hosted = (res.data?.result ?? res.data) as Record<string, unknown>\n let exports = res.data?.exports ?? null\n if (input.export && !exports && isEnrichedFanout(hosted)) {\n try {\n exports = exportFanout(hosted)\n } catch (err) {\n return errorResult(\n 'query_fanout_workflow',\n {\n error: `Fan-out captured but local export failed: ${err instanceof Error ? err.message : String(err)}`,\n result: hosted,\n },\n input.session_id,\n )\n }\n }\n return emit(hosted, exports)\n },\n )\n\n}\n","import { mkdirSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport Papa from 'papaparse'\nimport type { EnrichedFanout } from './classify.js'\n\nexport interface FanoutExportPaths {\n relativeTo: string\n dir: string\n json: string\n queriesCsv: string\n queriesTsv: string\n citationsCsv: string\n sourcesCsv: string\n browsedOnlyCsv: string\n snippetsCsv: string\n domainsCsv: string\n report: string\n}\n\nfunction outputBaseDir(): string {\n return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || join(homedir(), 'Downloads', 'mcp-scraper')\n}\n\nfunction safe(value: string): string {\n return value.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 80) || 'capture'\n}\n\nfunction writeTable(path: string, rows: Array<Record<string, unknown>>, delimiter: ','): void\nfunction writeTable(path: string, rows: Array<Record<string, unknown>>, delimiter: '\\t'): void\nfunction writeTable(path: string, rows: Array<Record<string, unknown>>, delimiter: string): void {\n writeFileSync(path, Papa.unparse(rows.length ? rows : [{}], { delimiter }))\n}\n\nexport function exportFanout(enriched: EnrichedFanout): FanoutExportPaths {\n const stamp = safe(enriched.capturedAt.replace(/[:.]/g, '-'))\n const outputDir = outputBaseDir()\n const relativeDir = join('fanout', `${stamp}-${safe(enriched.platform)}`)\n const dir = join(outputDir, relativeDir)\n mkdirSync(dir, { recursive: true })\n\n const queryRows = enriched.queries.map((q, i) => ({ index: i + 1, query: q }))\n const citationRows = enriched.aggregates.citationOrder.map((c) => {\n const src = enriched.citedUrls.find((s) => s.url === c.url)\n return { rank: c.rank, domain: c.domain, url: c.url, timesCited: c.timesCited, siteType: src?.siteType ?? '', title: src?.title ?? '' }\n })\n const sourceRows = enriched.browsedUrls.map((s) => ({ domain: s.domain, url: s.url, cited: s.cited, timesCited: s.timesCited, siteType: s.siteType, title: s.title, round: s.round ?? '' }))\n const browsedOnlyRows = enriched.browsedOnly.map((s) => ({ domain: s.domain, url: s.url, cited: s.cited, timesCited: s.timesCited, siteType: s.siteType, title: s.title, round: s.round ?? '' }))\n const snippetRows = enriched.snippets.map((s) => ({ domain: s.domain, url: s.url, title: s.title, text: s.text }))\n const domainRows = enriched.aggregates.topSites.map((d) => ({ domain: d.domain, count: d.count, cited: d.cited, timesCited: d.timesCited, siteType: d.siteType }))\n\n const relativePaths: FanoutExportPaths = {\n relativeTo: 'MCP_SCRAPER_OUTPUT_DIR or ~/Downloads/mcp-scraper',\n dir: relativeDir,\n json: join(relativeDir, 'fanout.json'),\n queriesCsv: join(relativeDir, 'queries.csv'),\n queriesTsv: join(relativeDir, 'queries.tsv'),\n citationsCsv: join(relativeDir, 'citations.csv'),\n sourcesCsv: join(relativeDir, 'sources.csv'),\n browsedOnlyCsv: join(relativeDir, 'browsed-only.csv'),\n snippetsCsv: join(relativeDir, 'snippets.csv'),\n domainsCsv: join(relativeDir, 'domains.csv'),\n report: join(relativeDir, 'report.html'),\n }\n\n writeFileSync(join(outputDir, relativePaths.json), JSON.stringify(enriched, null, 2))\n writeTable(join(outputDir, relativePaths.queriesCsv), queryRows, ',')\n writeTable(join(outputDir, relativePaths.queriesTsv), queryRows, '\\t')\n writeTable(join(outputDir, relativePaths.citationsCsv), citationRows, ',')\n writeTable(join(outputDir, relativePaths.sourcesCsv), sourceRows, ',')\n writeTable(join(outputDir, relativePaths.browsedOnlyCsv), browsedOnlyRows, ',')\n writeTable(join(outputDir, relativePaths.snippetsCsv), snippetRows, ',')\n writeTable(join(outputDir, relativePaths.domainsCsv), domainRows, ',')\n writeFileSync(join(outputDir, relativePaths.report), renderReportHtml(enriched))\n\n return relativePaths\n}\n\nfunction esc(s: string): string {\n return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;')\n}\n\nexport function renderReportHtml(enriched: EnrichedFanout): string {\n const data = JSON.stringify(enriched).replace(/</g, '\\\\u003c')\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>AI Search Fan-Out — ${esc(enriched.platform)}</title>\n<style>\n:root{--bg:#0b0d12;--panel:#151922;--line:#252b38;--ink:#e8ecf3;--mut:#8b95a7;--acc:#5b9dff;--cite:#39d98a;--browse:#5a6677}\n*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.5 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}\n.wrap{max-width:980px;margin:0 auto;padding:28px 20px 80px}\nh1{font-size:20px;margin:0 0 2px}.sub{color:var(--mut);margin:0 0 20px;font-size:13px}\n.stat{font-size:30px;font-weight:700}.stat small{font-size:13px;font-weight:400;color:var(--mut)}\n.cards{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin:18px 0}\n.card{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:12px 14px}\n.card b{font-size:22px;display:block}.card span{color:var(--mut);font-size:12px}\n.bars{margin:8px 0 22px}.bar{display:flex;align-items:center;gap:8px;margin:4px 0}\n.bar .lab{width:150px;color:var(--mut);font-size:12px;text-align:right}.bar .track{flex:1;background:#10141c;border-radius:5px;overflow:hidden}\n.bar .fill{background:var(--acc);height:16px}.bar .n{width:34px;font-size:12px;color:var(--mut)}\n.tabs{display:flex;gap:8px;margin:22px 0 12px}.tab{background:var(--panel);border:1px solid var(--line);color:var(--ink);padding:7px 14px;border-radius:8px;cursor:pointer}\n.tab.on{background:var(--acc);border-color:var(--acc);color:#04101f;font-weight:600}\n.chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px}\n.chip{background:var(--panel);border:1px solid var(--line);color:var(--mut);padding:4px 10px;border-radius:20px;cursor:pointer;font-size:12px}\n.chip.on{border-color:var(--acc);color:var(--ink)}.chip b{color:var(--ink)}\n.row{background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:10px 12px;margin:6px 0;display:flex;gap:10px;align-items:flex-start}\n.row .idx{color:var(--mut);min-width:22px}.row .main{flex:1}\n.tag{font-size:11px;padding:2px 7px;border-radius:6px;border:1px solid var(--line);color:var(--mut);margin-right:5px}\n.dom{font-weight:600}.url{color:var(--mut);font-size:12px;word-break:break-all}\n.pill{font-size:11px;padding:2px 7px;border-radius:6px}.pill.cite{background:rgba(57,217,138,.15);color:var(--cite)}.pill.brow{background:rgba(90,102,119,.2);color:#aeb8c8}\n.copy{background:none;border:1px solid var(--line);color:var(--mut);border-radius:6px;cursor:pointer;font-size:11px;padding:2px 8px}\n.hide{display:none}\n</style>\n</head>\n<body><div class=\"wrap\">\n<h1>AI Search Fan-Out</h1>\n<p class=\"sub\" id=\"sub\"></p>\n<div class=\"stat\" id=\"stat\"></div>\n<div class=\"cards\" id=\"cards\"></div>\n<div id=\"charts\"></div>\n<div class=\"tabs\"><button class=\"tab on\" data-tab=\"q\">Queries</button><button class=\"tab\" data-tab=\"u\">URLs</button></div>\n<div class=\"chips\" id=\"chips\"></div>\n<div id=\"list\"></div>\n</div>\n<script>\nconst D=${data};\nconst el=(t,c,h)=>{const e=document.createElement(t);if(c)e.className=c;if(h!=null)e.innerHTML=h;return e};\ndocument.getElementById('sub').textContent=D.platform+' · '+(D.meta.model||'model n/a')+' · '+D.meta.rounds+' search round(s) · prompt: '+(D.prompt||'');\ndocument.getElementById('stat').innerHTML='Total Fan-Out: '+D.counts.subQueries+' <small>sub-queries · '+D.counts.browsed+' URLs researched · '+D.counts.cited+' cited</small>';\nconst cards=[['Sub-queries',D.counts.subQueries],['Researched',D.counts.browsed],['Cited',D.counts.cited],['Browsed-only',D.counts.browsedOnly]];\nconst cc=document.getElementById('cards');cards.forEach(([k,v])=>{const c=el('div','card');c.appendChild(el('b',null,v));c.appendChild(el('span',null,k));cc.appendChild(c)});\nfunction barChart(title,obj){const max=Math.max(1,...Object.values(obj));const box=el('div','bars');box.appendChild(el('div',null,'<b>'+title+'</b>'));Object.entries(obj).forEach(([k,v])=>{const r=el('div','bar');r.appendChild(el('div','lab',k));const t=el('div','track');const f=el('div','fill');f.style.width=(v/max*100)+'%';t.appendChild(f);r.appendChild(t);r.appendChild(el('div','n',v));box.appendChild(r)});return box}\nconst charts=document.getElementById('charts');\ncharts.appendChild(barChart('URL Categories',D.aggregates.byCategory));\nlet tab='q',filter=null;\nconst chips=document.getElementById('chips'),list=document.getElementById('list');\nfunction render(){\n chips.innerHTML='';list.innerHTML='';\n if(tab==='q'){\n D.queries.forEach((q,i)=>{const r=el('div','row');r.appendChild(el('div','idx',i+1));const m=el('div','main');m.appendChild(el('div',null,esc(q)));r.appendChild(m);const b=el('button','copy','copy');b.onclick=()=>navigator.clipboard.writeText(q);r.appendChild(b);list.appendChild(r)});\n } else {\n const counts={};D.browsedUrls.forEach(s=>{counts[s.siteType]=(counts[s.siteType]||0)+1});\n Object.entries(counts).forEach(([k,v])=>{const c=el('button','chip'+(filter===k?' on':''),k+' <b>'+v+'</b>');c.onclick=()=>{filter=filter===k?null:k;render()};chips.appendChild(c)});\n D.browsedUrls.forEach(s=>{if(filter&&s.siteType!==filter)return;const r=el('div','row');const m=el('div','main');m.appendChild(el('div',null,'<span class=\"dom\">'+esc(s.domain)+'</span> <span class=\"pill '+(s.cited?'cite':'brow')+'\">'+(s.cited?'cited '+s.timesCited+'×':'browsed')+'</span> <span class=\"tag\">'+s.siteType+'</span>'));m.appendChild(el('div','url',esc(s.url)));r.appendChild(m);list.appendChild(r)});\n }\n}\nfunction esc(s){return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')}\ndocument.querySelectorAll('.tab').forEach(t=>t.onclick=()=>{document.querySelectorAll('.tab').forEach(x=>x.classList.remove('on'));t.classList.add('on');tab=t.dataset.tab;filter=null;render()});\nrender();\n</script>\n</body></html>`\n}\n","export const PACKAGE_VERSION = '0.3.27'\n","import { z } from 'zod'\n\nconst NullableString = z.string().nullable()\nconst BrowserRawObject = z.record(z.unknown())\n\nconst BrowserElementOutput = z.record(z.unknown())\n\nconst BrowserBaseOutput = {\n ok: z.boolean().describe('Whether the browser-agent action succeeded.'),\n tool: z.string().describe('Browser Agent MCP tool that produced this response.'),\n session_id: NullableString.describe('Browser session id when the response is scoped to a session.'),\n}\n\nconst BrowserReplayBaseOutput = {\n ...BrowserBaseOutput,\n replay_id: NullableString.describe('Replay id when the response is scoped to a replay.'),\n}\n\nexport const BrowserOpenInputSchema = {\n label: z.string().optional().describe('Optional human label for this session, shown in the watch console.'),\n url: z.string().url().optional().describe('Optional URL to navigate to immediately after opening.'),\n profile: z.string().optional().describe('Optional saved hosted profile name to load a logged-in session for a site.'),\n save_profile_changes: z.boolean().optional().describe('Persist cookies and browser storage back to the named profile when the session is closed. Use this for profile setup or intentional auth refreshes; avoid parallel sessions writing to the same profile.'),\n timeout_seconds: z.number().int().min(60).max(259200).optional().describe('How long the direct no-proxy browser session may live before auto-termination. Defaults to 600. The browser idles into a zero-cost standby between actions, so a longer timeout is cheap.'),\n}\nexport type BrowserOpenInput = z.infer<ReturnType<typeof z.object<typeof BrowserOpenInputSchema>>>\n\nexport const BrowserProfileConnectInputSchema = {\n email: z.string().optional().describe('Account email for the login being saved. Used to derive a stable, reusable profile name AND recorded as a note of who is connected. Does NOT import existing cookies — the user signs in fresh via the returned watch_url.'),\n profile: z.string().optional().describe('Profile to add this login to. Omit to derive one from email. A single profile holds MANY site logins — pass the same profile name again with a different domain to stack another account (e.g. add claude.ai to a profile that already has chatgpt.com).'),\n domain: z.string().optional().describe('Site to log into, e.g. chatgpt.com, claude.ai, reddit.com. Defaults to chatgpt.com. Each domain is a separate login inside the profile.'),\n login_url: z.string().url().optional().describe('Login page for the domain. Defaults to https://<domain>/ (https://chatgpt.com/ when domain is omitted).'),\n url: z.string().url().optional().describe('Deprecated alias for login_url. Use login_url.'),\n note: z.string().optional().describe('Free-text note describing this login, e.g. \"ChatGPT Plus, work account\". Surfaced by browser_profile_list so you can see what the profile holds.'),\n label: z.string().optional().describe('Optional human label for this sign-in setup session.'),\n timeout_seconds: z.number().int().min(60).max(259200).optional().describe('How long the sign-in setup session may live before auto-termination. Defaults to 600.'),\n}\nexport type BrowserProfileConnectInput = z.infer<ReturnType<typeof z.object<typeof BrowserProfileConnectInputSchema>>>\n\nexport const BrowserProfileListInputSchema = {\n profile: z.string().optional().describe('Profile whose saved logins to list. Omit to derive from email.'),\n email: z.string().optional().describe('Account email used to derive the profile name when profile is not given.'),\n domain: z.string().optional().describe('Restrict to one site login, e.g. chatgpt.com. Use this to poll a single login until its status reads AUTHENTICATED.'),\n connection_id: z.string().optional().describe('A specific login connection id returned by browser_profile_connect, to poll just that one.'),\n}\nexport type BrowserProfileListInput = z.infer<ReturnType<typeof z.object<typeof BrowserProfileListInputSchema>>>\n\nexport const BrowserSessionInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n}\nexport type BrowserSessionInput = z.infer<ReturnType<typeof z.object<typeof BrowserSessionInputSchema>>>\n\nexport const BrowserLocateTargetSchema = z.object({\n name: z.string().optional().describe('Optional label for this target, echoed in the result.'),\n selector: z.string().optional().describe('CSS selector for the exact DOM element to locate, for example h1, input[name=\"q\"], or [data-testid=\"result\"].'),\n text: z.string().optional().describe('Visible text to locate when a selector is not known. The tool returns the text range bounds when possible.'),\n match: z.enum(['contains', 'exact']).default('contains').describe('How to match text targets. Defaults to contains.'),\n index: z.number().int().min(0).default(0).describe('Zero-based match index when multiple elements match.'),\n}).refine(value => Boolean(value.selector || value.text), {\n message: 'target requires selector or text',\n})\n\nexport const BrowserLocateInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n targets: z.array(BrowserLocateTargetSchema).min(1).max(20).describe('DOM targets to locate in the current viewport. Use selectors for exact elements, or text for visible text ranges.'),\n}\nexport type BrowserLocateInput = z.infer<ReturnType<typeof z.object<typeof BrowserLocateInputSchema>>>\n\nexport const BrowserGotoInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n url: z.string().url().describe('URL to navigate the browser to.'),\n}\nexport type BrowserGotoInput = z.infer<ReturnType<typeof z.object<typeof BrowserGotoInputSchema>>>\n\nexport const BrowserClickInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n x: z.number().describe('X coordinate to click, in screenshot pixels. Use only coordinates from the latest browser_screenshot, browser_read, or browser_locate result; do not guess.'),\n y: z.number().describe('Y coordinate to click, in screenshot pixels. Use only coordinates from the latest browser_screenshot, browser_read, or browser_locate result; do not guess.'),\n button: z.enum(['left', 'right', 'middle']).default('left').describe('Mouse button.'),\n num_clicks: z.number().int().min(1).max(3).optional().describe('Number of clicks, e.g. 2 for double-click.'),\n}\nexport type BrowserClickInput = z.infer<ReturnType<typeof z.object<typeof BrowserClickInputSchema>>>\n\nexport const BrowserTypeInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n text: z.string().describe('Text to type at the current focus. Click a field first to focus it.'),\n delay: z.number().int().min(0).max(500).optional().describe('Optional per-keystroke delay in ms for human-like typing.'),\n}\nexport type BrowserTypeInput = z.infer<ReturnType<typeof z.object<typeof BrowserTypeInputSchema>>>\n\nexport const BrowserScrollInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n delta_y: z.number().default(5).describe('Vertical scroll in wheel units. Positive scrolls down, negative up.'),\n delta_x: z.number().default(0).describe('Horizontal scroll in wheel units.'),\n x: z.number().optional().describe('X position to scroll at. Defaults to screen center.'),\n y: z.number().optional().describe('Y position to scroll at. Defaults to screen center.'),\n}\nexport type BrowserScrollInput = z.infer<ReturnType<typeof z.object<typeof BrowserScrollInputSchema>>>\n\nexport const BrowserPressInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n keys: z.array(z.string()).min(1).describe('Keys or combinations to press, e.g. [\"Return\"], [\"Ctrl+a\"], [\"Ctrl+Shift+Tab\"].'),\n}\nexport type BrowserPressInput = z.infer<ReturnType<typeof z.object<typeof BrowserPressInputSchema>>>\n\nexport const BrowserReplayStopInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n replay_id: z.string().describe('The replay id returned by browser_replay_start or browser_list_replays. Use only a returned replay_id; do not construct one yourself.'),\n}\nexport type BrowserReplayStopInput = z.infer<ReturnType<typeof z.object<typeof BrowserReplayStopInputSchema>>>\n\nexport const BrowserReplayDownloadInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n replay_id: z.string().describe('The replay id returned by browser_replay_start or browser_list_replays. Use only a returned replay_id; do not construct one yourself.'),\n filename: z.string().optional().describe('Optional local MP4 filename. Defaults to a timestamped replay filename.'),\n}\nexport type BrowserReplayDownloadInput = z.infer<ReturnType<typeof z.object<typeof BrowserReplayDownloadInputSchema>>>\n\nexport const BrowserReplayAnnotationSchema = z.object({\n type: z.enum(['box', 'circle', 'underline', 'arrow', 'label']).default('box').describe('Annotation style to draw over the replay.'),\n start_seconds: z.number().min(0).default(0).describe('When the annotation should appear in the replay.'),\n end_seconds: z.number().min(0).optional().describe('When the annotation should disappear. Defaults to two seconds after start_seconds.'),\n left: z.number().optional().describe('Target left edge in browser screenshot pixels. Use element.left from browser_screenshot/browser_read.'),\n top: z.number().optional().describe('Target top edge in browser screenshot pixels. Use element.top from browser_screenshot/browser_read.'),\n width: z.number().positive().optional().describe('Target width in browser screenshot pixels. Use element.width from browser_screenshot/browser_read.'),\n height: z.number().positive().optional().describe('Target height in browser screenshot pixels. Use element.height from browser_screenshot/browser_read.'),\n x: z.number().optional().describe('Point target x coordinate in browser screenshot pixels when no box is available.'),\n y: z.number().optional().describe('Point target y coordinate in browser screenshot pixels when no box is available.'),\n from_x: z.number().optional().describe('Arrow start x coordinate in browser screenshot pixels. Defaults near the target.'),\n from_y: z.number().optional().describe('Arrow start y coordinate in browser screenshot pixels. Defaults near the target.'),\n to_x: z.number().optional().describe('Arrow target x coordinate in browser screenshot pixels. Defaults to the target box center.'),\n to_y: z.number().optional().describe('Arrow target y coordinate in browser screenshot pixels. Defaults to the target box center.'),\n label: z.string().max(120).optional().describe('Optional text callout to render near the annotation.'),\n color: z.string().regex(/^#?[0-9a-fA-F]{6}$/).optional().describe('Annotation color as hex, for example #ff3b30.'),\n thickness: z.number().min(1).max(24).optional().describe('Stroke thickness in pixels. Defaults to 5.'),\n})\n\nexport const BrowserReplayMarkInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself. A replay must already be recording.'),\n target: BrowserLocateTargetSchema.describe('The exact DOM element or text range to mark in the current viewport.'),\n type: z.enum(['box', 'circle', 'underline', 'arrow']).default('box').describe('Annotation style to generate. Labels are included on the returned annotation when label is provided.'),\n label: z.string().max(120).optional().describe('Optional callout text to render near the target.'),\n color: z.string().regex(/^#?[0-9a-fA-F]{6}$/).optional().describe('Annotation color as hex, for example #ff3b30.'),\n thickness: z.number().min(1).max(24).optional().describe('Stroke thickness in pixels. Defaults to 5.'),\n padding: z.number().min(0).max(80).default(8).describe('Pixels to expand the DOM bounds so the highlight does not touch the text edge.'),\n start_offset_seconds: z.number().min(-5).max(10).default(-0.25).describe('Offset from the current replay time. Negative values make the callout appear just before the mark action is captured.'),\n duration_seconds: z.number().min(0.5).max(30).default(4).describe('How long the generated annotation should remain visible.'),\n}\nexport type BrowserReplayMarkInput = z.infer<ReturnType<typeof z.object<typeof BrowserReplayMarkInputSchema>>>\n\nexport const BrowserReplayAnnotateInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n replay_id: z.string().describe('The replay id returned by browser_replay_start or browser_list_replays. Use only a returned replay_id; do not construct one yourself.'),\n annotations: z.array(BrowserReplayAnnotationSchema).min(1).max(50).describe('Timed overlay annotations to render on the replay. Prefer annotations returned by browser_replay_mark; otherwise use exact DOM bounds from browser_locate/browser_screenshot/browser_read.'),\n filename: z.string().optional().describe('Optional output MP4 filename. Defaults to a timestamped annotated replay filename.'),\n source_width: z.number().positive().optional().describe('Width of the screenshot coordinate space used for annotations. Defaults to the replay video width.'),\n source_height: z.number().positive().optional().describe('Height of the coordinate space used for annotations. When this is a page viewport height smaller than the replay video height, the annotator infers the browser chrome top offset.'),\n source_left_offset: z.number().min(0).optional().describe('Optional explicit X offset from annotation coordinates to replay video coordinates. Usually omitted.'),\n source_top_offset: z.number().min(0).optional().describe('Optional explicit Y offset from annotation coordinates to replay video coordinates. Usually omitted because browser chrome offset is inferred when source_height is a page viewport height.'),\n}\nexport type BrowserReplayAnnotateInput = z.infer<ReturnType<typeof z.object<typeof BrowserReplayAnnotateInputSchema>>>\n\nexport const BrowserListInputSchema = {\n include_closed: z.boolean().default(false).describe('Include closed sessions in the list.'),\n}\nexport type BrowserListInput = z.infer<ReturnType<typeof z.object<typeof BrowserListInputSchema>>>\n\nexport const BrowserCaptureFanoutInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. The session must be on chatgpt.com or claude.ai and logged in through a saved hosted profile. Use only a returned session_id; do not construct one yourself.'),\n prompt: z.string().optional().describe('Optional prompt to type into the chat composer and submit before capturing. Omit to passively capture the fan-out of a prompt the user just ran in the visible browser. The prompt must trigger web search for there to be a fan-out.'),\n wait_ms: z.number().int().min(0).max(180000).optional().describe('How long to wait for the answer stream to finish before parsing. Defaults to 90000 when a prompt is sent, 8000 for passive capture. Capture ends as soon as the answer stream finishes.'),\n first_party_domain: z.string().optional().describe('The brand/site being researched, for example example.com. Sources on this domain are tagged First-party/vendor. Set this when the prompt is about a specific business.'),\n reset: z.boolean().default(false).describe('Clear any previously buffered stream for this page before capturing. Use when re-running to avoid mixing turns.'),\n export: z.boolean().default(false).describe('When true, write JSON, CSV, TSV exports (queries, citations, all sources, browsed-only sources, snippets, domains) and a self-contained HTML report to MCP_SCRAPER_OUTPUT_DIR/fanout, returning paths relative to MCP_SCRAPER_OUTPUT_DIR.'),\n}\nexport type BrowserCaptureFanoutInput = z.infer<ReturnType<typeof z.object<typeof BrowserCaptureFanoutInputSchema>>>\n\nconst FanoutSourceOutput = z.object({\n url: z.string(),\n domain: z.string(),\n title: z.string(),\n cited: z.boolean(),\n timesCited: z.number().int().min(0),\n snippet: z.string(),\n round: z.number().int().nullable(),\n siteType: z.string().describe('URL category: First-party/vendor, News/media, Reddit, Social/video, Encyclopedia, Review site, Docs, or Blog.'),\n})\n\nexport const BrowserCaptureFanoutOutputSchema = {\n ...BrowserBaseOutput,\n tool: z.literal('query_fanout_workflow'),\n platform: z.enum(['ChatGPT', 'Claude']).describe('Which AI-search surface the fan-out was captured from.'),\n captured_at: z.string(),\n prompt: z.string().describe('The user prompt that triggered the captured fan-out, when recoverable.'),\n meta: z.object({\n model: z.string(),\n finishType: z.string(),\n title: z.string(),\n rounds: z.number().int().min(0),\n }),\n queries: z.array(z.string()).describe('Every web-search sub-query the model issued, in capture order. Classify these by funnel stage and type yourself from the text.'),\n browsed_urls: z.array(FanoutSourceOutput).describe('Every researched URL (cited and browsed-only), cited first.'),\n cited_urls: z.array(FanoutSourceOutput).describe('The subset of researched URLs actually cited in the final answer.'),\n browsed_only: z.array(FanoutSourceOutput).describe('Researched URLs the model pulled but did not cite.'),\n snippets: z.array(z.object({ url: z.string(), domain: z.string(), title: z.string(), text: z.string() })),\n counts: z.object({\n subQueries: z.number().int().min(0),\n browsed: z.number().int().min(0),\n cited: z.number().int().min(0),\n browsedOnly: z.number().int().min(0),\n }),\n aggregates: z.object({\n topSites: z.array(z.object({ domain: z.string(), count: z.number().int(), cited: z.boolean(), timesCited: z.number().int(), siteType: z.string() })),\n citationOrder: z.array(z.object({ rank: z.number().int(), domain: z.string(), url: z.string(), timesCited: z.number().int() })),\n byCategory: z.record(z.number().int()),\n }).describe('Objective aggregates: top sourced sites by frequency, citation order, and URL-category counts.'),\n first_party_domain: z.string().nullable(),\n exports: z.object({\n relativeTo: z.string(),\n dir: z.string(),\n json: z.string(),\n queriesCsv: z.string(),\n queriesTsv: z.string(),\n citationsCsv: z.string(),\n sourcesCsv: z.string(),\n browsedOnlyCsv: z.string(),\n snippetsCsv: z.string(),\n domainsCsv: z.string(),\n report: z.string(),\n }).nullable().describe('Relative export paths when export=true, otherwise null. Paths are relative to MCP_SCRAPER_OUTPUT_DIR, or ~/Downloads/mcp-scraper when that env var is not set.'),\n debug: z.object({\n interceptorReady: z.boolean(),\n rawBytes: z.number().int().min(0),\n unmappedKeys: z.array(z.string()),\n note: z.string(),\n }).optional(),\n}\n\nexport const BrowserOpenOutputSchema = {\n ok: z.boolean(),\n tool: z.literal('browser_open'),\n session_id: z.string().describe('Session id returned by browser_open. Use only this exact value in later browser_* calls; do not construct one yourself.'),\n watch_url: z.string().describe('Human watch/takeover URL for this browser session on mcpscraper.dev.'),\n live_view_url: NullableString.describe('Deprecated; always null. Open watch_url to view the live session.'),\n url: NullableString.describe('Initial URL requested by the caller, when provided.'),\n hint: z.string(),\n raw: BrowserRawObject.optional(),\n}\n\nconst BrowserProfileLogin = z.object({\n connection_id: NullableString.describe('Auth connection id for this login.'),\n domain: z.string().describe('Site this login is for, e.g. chatgpt.com.'),\n status: z.string().describe('Auth status, e.g. NEEDS_AUTH or AUTHENTICATED.'),\n account_email: NullableString.describe('Account email recorded for this login, when known.'),\n note: NullableString.describe('Free-text note describing this login.'),\n watch_url: NullableString.describe('mcpscraper.dev sign-in link when this login still needs the user to authenticate.'),\n last_connected_at: NullableString.describe('When this login was last saved or refreshed.'),\n})\n\nexport const BrowserProfileConnectOutputSchema = {\n ok: z.boolean(),\n tool: z.literal('browser_profile_connect'),\n session_id: NullableString,\n auth_connection_id: z.string(),\n watch_url: z.string().describe('mcpscraper.dev sign-in link to give the user so they can complete this login.'),\n live_view_url: NullableString.describe('Deprecated; always null. Open watch_url to view the sign-in.'),\n profile: z.string().describe('Profile this login was added to. Reuse it to stack more logins or to open a session.'),\n domain: z.string(),\n setup_url: z.string(),\n account_email: NullableString,\n note: NullableString,\n status: z.string(),\n flow_status: NullableString,\n flow_step: NullableString,\n flow_expires_at: NullableString,\n post_login_url: NullableString,\n connected_logins: z.array(BrowserProfileLogin).describe('Every login currently saved in this profile, so you can see what else is connected.'),\n next_steps: z.array(z.string()),\n raw: BrowserRawObject.optional(),\n}\n\nexport const BrowserProfileListOutputSchema = {\n ok: z.boolean(),\n tool: z.literal('browser_profile_list'),\n session_id: z.null(),\n profile: z.string().describe('Profile these logins belong to.'),\n connections: z.array(BrowserProfileLogin).describe('All site logins saved in this profile, each with its current auth status and note.'),\n count: z.number().int().min(0),\n}\n\nexport const BrowserScreenshotOutputSchema = {\n ...BrowserBaseOutput,\n tool: z.literal('browser_screenshot'),\n url: NullableString,\n title: NullableString,\n text: z.string(),\n elements: z.array(BrowserElementOutput),\n screenshot: z.object({\n mime_type: z.string(),\n inline: z.boolean(),\n }).nullable(),\n}\n\nexport const BrowserReadOutputSchema = {\n ...BrowserBaseOutput,\n tool: z.literal('browser_read'),\n url: NullableString,\n title: NullableString,\n text: z.string(),\n elements: z.array(BrowserElementOutput),\n raw: BrowserRawObject.optional(),\n}\n\nexport const BrowserLocateOutputSchema = {\n ...BrowserBaseOutput,\n tool: z.literal('browser_locate'),\n url: NullableString,\n title: NullableString,\n viewport: BrowserRawObject.nullable(),\n replay: BrowserRawObject.nullable(),\n targets: z.array(BrowserRawObject),\n raw: BrowserRawObject.optional(),\n}\n\nexport const BrowserActionOutputSchema = {\n ...BrowserBaseOutput,\n result: BrowserRawObject.describe('Provider action result. Check ok and follow with browser_screenshot/browser_read when page state matters.'),\n nextRecommendedTool: z.string().nullable(),\n}\n\nexport const BrowserReplayStartOutputSchema = {\n ...BrowserReplayBaseOutput,\n tool: z.literal('browser_replay_start'),\n view_url: NullableString,\n download_url: NullableString,\n raw: BrowserRawObject.optional(),\n}\n\nexport const BrowserReplayStopOutputSchema = {\n ...BrowserReplayBaseOutput,\n tool: z.literal('browser_replay_stop'),\n view_url: NullableString,\n download_url: NullableString,\n raw: BrowserRawObject.optional(),\n}\n\nexport const BrowserListReplaysOutputSchema = {\n ...BrowserBaseOutput,\n tool: z.literal('browser_list_replays'),\n replays: z.array(BrowserRawObject),\n count: z.number().int().min(0),\n}\n\nexport const BrowserReplayDownloadOutputSchema = {\n ...BrowserReplayBaseOutput,\n tool: z.literal('browser_replay_download'),\n file_path: NullableString,\n bytes: z.number().int().min(0).nullable(),\n mime_type: NullableString,\n download_url: NullableString,\n}\n\nexport const BrowserReplayMarkOutputSchema = {\n ...BrowserReplayBaseOutput,\n tool: z.literal('browser_replay_mark'),\n annotation: BrowserRawObject,\n source_width: z.number().nullable(),\n source_height: z.number().nullable(),\n target: BrowserRawObject.nullable(),\n hint: z.string(),\n}\n\nexport const BrowserReplayAnnotateOutputSchema = {\n ...BrowserReplayBaseOutput,\n tool: z.literal('browser_replay_annotate'),\n source_file_path: NullableString,\n annotated_file_path: NullableString,\n bytes: z.number().int().min(0).nullable(),\n width: z.number().int().min(0).nullable(),\n height: z.number().int().min(0).nullable(),\n annotation_count: z.number().int().min(0).nullable(),\n mime_type: NullableString,\n}\n\nexport const BrowserCloseOutputSchema = {\n ...BrowserBaseOutput,\n tool: z.literal('browser_close'),\n closed: z.boolean(),\n raw: BrowserRawObject.optional(),\n}\n\nexport const BrowserListSessionsOutputSchema = {\n ok: z.boolean(),\n tool: z.literal('browser_list_sessions'),\n session_id: z.null(),\n sessions: z.array(BrowserRawObject),\n count: z.number().int().min(0),\n}\n","import { execFile } from 'node:child_process'\nimport { mkdtemp, rm, stat, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { promisify } from 'node:util'\n\nconst execFileAsync = promisify(execFile)\n\nexport type ReplayAnnotationType = 'box' | 'circle' | 'underline' | 'arrow' | 'label'\n\nexport interface ReplayAnnotation {\n type?: ReplayAnnotationType\n start_seconds?: number\n end_seconds?: number\n left?: number\n top?: number\n width?: number\n height?: number\n x?: number\n y?: number\n from_x?: number\n from_y?: number\n to_x?: number\n to_y?: number\n label?: string\n color?: string\n thickness?: number\n}\n\nexport interface AnnotateReplayOptions {\n annotations: ReplayAnnotation[]\n sourceWidth?: number\n sourceHeight?: number\n sourceLeftOffset?: number\n sourceTopOffset?: number\n}\n\ninterface Size {\n width: number\n height: number\n}\n\ninterface Rect {\n left: number\n top: number\n width: number\n height: number\n}\n\ninterface CoordinateTransform {\n scaleX: number\n scaleY: number\n offsetX: number\n offsetY: number\n}\n\nexport interface AnnotatedReplayResult {\n filePath: string\n bytes: number\n width: number\n height: number\n annotationCount: number\n}\n\nfunction finiteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value)\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value))\n}\n\nfunction formatAssTime(seconds: number): string {\n const safe = Math.max(0, seconds)\n const hours = Math.floor(safe / 3600)\n const minutes = Math.floor((safe % 3600) / 60)\n const wholeSeconds = Math.floor(safe % 60)\n const centiseconds = Math.floor((safe - Math.floor(safe)) * 100)\n return `${hours}:${String(minutes).padStart(2, '0')}:${String(wholeSeconds).padStart(2, '0')}.${String(centiseconds).padStart(2, '0')}`\n}\n\nfunction cssHexToAssColor(color?: string): string {\n const normalized = color?.trim().match(/^#?([0-9a-fA-F]{6})$/)?.[1] ?? 'ff3b30'\n const red = normalized.slice(0, 2)\n const green = normalized.slice(2, 4)\n const blue = normalized.slice(4, 6)\n return `&H${blue}${green}${red}&`\n}\n\nfunction escapeAssText(value: string): string {\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\\{/g, '\\\\{')\n .replace(/\\}/g, '\\\\}')\n .replace(/\\r?\\n/g, '\\\\N')\n}\n\nfunction resolveCoordinateTransform(video: Size, source: Size, options: AnnotateReplayOptions): CoordinateTransform {\n const explicitOffsetX = finiteNumber(options.sourceLeftOffset) ? options.sourceLeftOffset : null\n const explicitOffsetY = finiteNumber(options.sourceTopOffset) ? options.sourceTopOffset : null\n const inferredTopOffset =\n explicitOffsetY == null &&\n Math.round(source.width) === Math.round(video.width) &&\n source.height < video.height &&\n video.height - source.height <= 220\n ? video.height - source.height\n : 0\n const offsetX = explicitOffsetX ?? 0\n const offsetY = explicitOffsetY ?? inferredTopOffset\n return {\n scaleX: (video.width - offsetX) / source.width,\n scaleY: (video.height - offsetY) / source.height,\n offsetX,\n offsetY,\n }\n}\n\nfunction transformPoint(x: number, y: number, transform: CoordinateTransform): { x: number; y: number } {\n return {\n x: x * transform.scaleX + transform.offsetX,\n y: y * transform.scaleY + transform.offsetY,\n }\n}\n\nfunction scaleRect(annotation: ReplayAnnotation, transform: CoordinateTransform): Rect {\n if (\n finiteNumber(annotation.left) &&\n finiteNumber(annotation.top) &&\n finiteNumber(annotation.width) &&\n finiteNumber(annotation.height)\n ) {\n const origin = transformPoint(annotation.left, annotation.top, transform)\n return {\n left: origin.x,\n top: origin.y,\n width: annotation.width * transform.scaleX,\n height: annotation.height * transform.scaleY,\n }\n }\n if (finiteNumber(annotation.x) && finiteNumber(annotation.y)) {\n const radius = finiteNumber(annotation.width) ? annotation.width / 2 : 28\n const point = transformPoint(annotation.x, annotation.y, transform)\n return {\n left: point.x - radius * transform.scaleX,\n top: point.y - radius * transform.scaleY,\n width: radius * 2 * transform.scaleX,\n height: radius * 2 * transform.scaleY,\n }\n }\n throw new Error('annotation needs either left/top/width/height or x/y')\n}\n\nfunction rectPath(rect: Rect): string {\n const x1 = Math.round(rect.left)\n const y1 = Math.round(rect.top)\n const x2 = Math.round(rect.left + rect.width)\n const y2 = Math.round(rect.top + rect.height)\n return `m ${x1} ${y1} l ${x2} ${y1} l ${x2} ${y2} l ${x1} ${y2} l ${x1} ${y1}`\n}\n\nfunction ellipsePath(rect: Rect): string {\n const cx = rect.left + rect.width / 2\n const cy = rect.top + rect.height / 2\n const rx = Math.max(4, rect.width / 2)\n const ry = Math.max(4, rect.height / 2)\n const points: string[] = []\n for (let i = 0; i <= 32; i += 1) {\n const t = (Math.PI * 2 * i) / 32\n const x = Math.round(cx + Math.cos(t) * rx)\n const y = Math.round(cy + Math.sin(t) * ry)\n points.push(`${i === 0 ? 'm' : 'l'} ${x} ${y}`)\n }\n return points.join(' ')\n}\n\nfunction filledRectPath(left: number, top: number, width: number, height: number): string {\n return rectPath({ left, top, width, height })\n}\n\nfunction arrowPath(fromX: number, fromY: number, toX: number, toY: number, thickness: number): string {\n const dx = toX - fromX\n const dy = toY - fromY\n const length = Math.max(1, Math.hypot(dx, dy))\n const ux = dx / length\n const uy = dy / length\n const px = -uy\n const py = ux\n const half = thickness / 2\n const head = Math.max(14, thickness * 4)\n const baseX = toX - ux * head\n const baseY = toY - uy * head\n const p1x = Math.round(fromX + px * half)\n const p1y = Math.round(fromY + py * half)\n const p2x = Math.round(baseX + px * half)\n const p2y = Math.round(baseY + py * half)\n const p3x = Math.round(baseX + px * head * 0.55)\n const p3y = Math.round(baseY + py * head * 0.55)\n const p4x = Math.round(toX)\n const p4y = Math.round(toY)\n const p5x = Math.round(baseX - px * head * 0.55)\n const p5y = Math.round(baseY - py * head * 0.55)\n const p6x = Math.round(baseX - px * half)\n const p6y = Math.round(baseY - py * half)\n const p7x = Math.round(fromX - px * half)\n const p7y = Math.round(fromY - py * half)\n return `m ${p1x} ${p1y} l ${p2x} ${p2y} l ${p3x} ${p3y} l ${p4x} ${p4y} l ${p5x} ${p5y} l ${p6x} ${p6y} l ${p7x} ${p7y} l ${p1x} ${p1y}`\n}\n\nfunction eventLine(start: number, end: number, body: string): string {\n return `Dialogue: 0,${formatAssTime(start)},${formatAssTime(end)},Default,,0,0,0,,${body}`\n}\n\nfunction labelLine(start: number, end: number, x: number, y: number, label: string): string {\n const safeX = Math.round(x)\n const safeY = Math.round(y)\n return eventLine(\n start,\n end,\n `{\\\\an7\\\\pos(${safeX},${safeY})\\\\fs30\\\\bord4\\\\shad0\\\\c&HFFFFFF&\\\\3c&H000000&}${escapeAssText(label)}`,\n )\n}\n\nfunction shapeLine(start: number, end: number, path: string, color: string, thickness: number, filled = false): string {\n const fillAlpha = filled ? '&H00&' : '&HFF&'\n const border = filled ? 0 : thickness\n return eventLine(\n start,\n end,\n `{\\\\an7\\\\pos(0,0)\\\\p1\\\\bord${border}\\\\shad0\\\\1a${fillAlpha}\\\\1c${color}\\\\3c${color}}${path}`,\n )\n}\n\nexport function buildAssSubtitle(options: AnnotateReplayOptions, video: Size): string {\n const source = {\n width: options.sourceWidth && options.sourceWidth > 0 ? options.sourceWidth : video.width,\n height: options.sourceHeight && options.sourceHeight > 0 ? options.sourceHeight : video.height,\n }\n const transform = resolveCoordinateTransform(video, source, options)\n const lines: string[] = []\n for (const annotation of options.annotations) {\n const start = Math.max(0, annotation.start_seconds ?? 0)\n const end = annotation.end_seconds && annotation.end_seconds > start ? annotation.end_seconds : start + 2\n const type = annotation.type ?? 'box'\n const color = cssHexToAssColor(annotation.color)\n const thickness = Math.round(clamp(annotation.thickness ?? 5, 2, 24))\n if (type === 'label') {\n if (!annotation.label) throw new Error('label annotation needs label')\n const rect = scaleRect(annotation, transform)\n lines.push(labelLine(start, end, rect.left, Math.max(8, rect.top), annotation.label))\n continue\n }\n if (type === 'arrow') {\n const rect = finiteNumber(annotation.to_x) && finiteNumber(annotation.to_y)\n ? null\n : scaleRect(annotation, transform)\n const toPoint = finiteNumber(annotation.to_x) && finiteNumber(annotation.to_y)\n ? transformPoint(annotation.to_x, annotation.to_y, transform)\n : null\n const toX = toPoint ? toPoint.x : rect!.left + rect!.width / 2\n const toY = toPoint ? toPoint.y : rect!.top + rect!.height / 2\n const fromPoint = finiteNumber(annotation.from_x) && finiteNumber(annotation.from_y)\n ? transformPoint(annotation.from_x, annotation.from_y, transform)\n : null\n const fromX = fromPoint ? fromPoint.x : clamp(toX - 120, 12, video.width - 12)\n const fromY = fromPoint ? fromPoint.y : clamp(toY - 90, 12, video.height - 12)\n lines.push(shapeLine(start, end, arrowPath(fromX, fromY, toX, toY, thickness), color, thickness, true))\n if (annotation.label) lines.push(labelLine(start, end, fromX + 8, Math.max(96, fromY - 36), annotation.label))\n continue\n }\n const rect = scaleRect(annotation, transform)\n if (type === 'underline') {\n const underlineTop = rect.top + rect.height + thickness\n lines.push(shapeLine(start, end, filledRectPath(rect.left, underlineTop, rect.width, thickness), color, 0, true))\n } else if (type === 'circle') {\n lines.push(shapeLine(start, end, ellipsePath(rect), color, thickness))\n } else {\n lines.push(shapeLine(start, end, rectPath(rect), color, thickness))\n }\n if (annotation.label) lines.push(labelLine(start, end, rect.left, Math.max(8, rect.top - 38), annotation.label))\n }\n\n return [\n '[Script Info]',\n 'ScriptType: v4.00+',\n `PlayResX: ${Math.round(video.width)}`,\n `PlayResY: ${Math.round(video.height)}`,\n 'ScaledBorderAndShadow: yes',\n '',\n '[V4+ Styles]',\n 'Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding',\n 'Style: Default,Arial,30,&H00FFFFFF,&H000000FF,&H00000000,&H90000000,0,0,0,0,100,100,0,0,1,2,0,7,0,0,0,1',\n '',\n '[Events]',\n 'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text',\n ...lines,\n '',\n ].join('\\n')\n}\n\nasync function videoSize(inputFilePath: string): Promise<Size> {\n const { stdout } = await execFileAsync('ffprobe', [\n '-v',\n 'error',\n '-select_streams',\n 'v:0',\n '-show_entries',\n 'stream=width,height',\n '-of',\n 'json',\n inputFilePath,\n ], { maxBuffer: 1024 * 1024 })\n const parsed = JSON.parse(stdout) as { streams?: Array<{ width?: number; height?: number }> }\n const stream = parsed.streams?.[0]\n if (!stream?.width || !stream.height) throw new Error('could not read replay video dimensions')\n return { width: stream.width, height: stream.height }\n}\n\nfunction ffmpegFilterPath(path: string): string {\n return path.replace(/\\\\/g, '\\\\\\\\').replace(/:/g, '\\\\:')\n}\n\nexport async function annotateReplayVideo(\n inputFilePath: string,\n outputFilePath: string,\n options: AnnotateReplayOptions,\n): Promise<AnnotatedReplayResult> {\n if (!options.annotations.length) throw new Error('annotations must include at least one item')\n const size = await videoSize(inputFilePath)\n const tmp = await mkdtemp(join(tmpdir(), 'mcp-scraper-ass-'))\n const assPath = join(tmp, 'annotations.ass')\n try {\n await writeFile(assPath, buildAssSubtitle(options, size), 'utf8')\n await execFileAsync('ffmpeg', [\n '-y',\n '-i',\n inputFilePath,\n '-vf',\n `ass=${ffmpegFilterPath(assPath)}`,\n '-c:v',\n 'libx264',\n '-pix_fmt',\n 'yuv420p',\n '-movflags',\n '+faststart',\n '-c:a',\n 'copy',\n outputFilePath,\n ], { maxBuffer: 1024 * 1024 * 20 })\n const out = await stat(outputFilePath)\n return {\n filePath: outputFilePath,\n bytes: out.size,\n width: size.width,\n height: size.height,\n annotationCount: options.annotations.length,\n }\n } finally {\n await rm(tmp, { recursive: true, force: true })\n }\n}\n","export const RECAPTCHA_INSTRUCTIONS = 'Google returned a CAPTCHA. Run with --headless=false to re-warm the browser profile, then retry.'\n\nexport function sanitizeVendorName(message: string): string {\n return message\n .replace(/kernel\\.sh\\s+sessions?/gi, 'sessions')\n .replace(/kernel\\.sh\\s+session/gi, 'this session')\n .replace(/kernel\\.sh/gi, 'the service')\n .replace(/kernel\\s+sessions?/gi, 'sessions')\n .replace(/kernel\\s+session/gi, 'this session')\n .replace(/\\bkernel\\b/gi, 'the service')\n .replace(/ +/g, ' ')\n .trim()\n}\n\nexport class CaptchaError extends Error {\n readonly name = 'CaptchaError'\n constructor(public readonly instructions: string) {\n super(`CAPTCHA detected. ${instructions}`)\n }\n}\n\nexport class ExtractionError extends Error {\n readonly name = 'ExtractionError'\n constructor(message: string, public readonly cause?: unknown) {\n super(message)\n }\n}\n\nexport class RequestAbortedError extends Error {\n readonly name = 'RequestAbortedError'\n constructor(message = 'Request aborted before harvest completed') {\n super(message)\n }\n}\n\nexport class LocationMismatchError extends Error {\n readonly name = 'LocationMismatchError'\n constructor(message = 'Google returned results for a different location than requested') {\n super(message)\n }\n}\n","import { sanitizeVendorName } from '../errors.js'\n\nconst KEY_RENAMES: Record<string, string> = {\n kernel: 'browserRuntime',\n kernel_session_id: 'browser_session_id',\n kernel_delete_started: 'session_cleanup_started',\n kernel_delete_succeeded: 'session_cleanup_succeeded',\n kernel_delete_error: 'session_cleanup_error',\n kernelSessionId: 'browserSessionId',\n kernelDeleteStarted: 'sessionCleanupStarted',\n kernelDeleteSucceeded: 'sessionCleanupSucceeded',\n kernelDeleteError: 'sessionCleanupError',\n kernelProxyId: 'proxyId',\n}\n\nconst SANITIZED_VALUE_KEYS = /error|message/i\n\nconst VENDOR_URL_KEYS = new Set([\n 'hosted_url',\n 'hostedUrl',\n 'live_view_url',\n 'liveViewUrl',\n 'cdp_ws_url',\n 'cdpWsUrl',\n 'browser_live_view_url',\n])\nconst VENDOR_URL_RE = /\\b(?:wss?|https?):\\/\\/[^\\s\"'<>]*\\bonkernel\\.com[^\\s\"'<>]*/gi\n\nfunction redactVendorUrls(value: string): string {\n return value.replace(VENDOR_URL_RE, '[browser-service]')\n}\n\nexport function sanitizeOutboundDiagnostics<T>(value: T, parentKey = ''): T {\n if (typeof value === 'string') {\n let out = redactVendorUrls(value)\n if (SANITIZED_VALUE_KEYS.test(parentKey) && /kernel/i.test(out)) {\n out = sanitizeVendorName(out)\n }\n return out as T\n }\n if (Array.isArray(value)) return value.map(v => sanitizeOutboundDiagnostics(v, parentKey)) as T\n if (value !== null && typeof value === 'object') {\n const out: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n const renamed = KEY_RENAMES[key] ?? key\n if (VENDOR_URL_KEYS.has(key)) {\n out[renamed] = null\n continue\n }\n out[renamed] = sanitizeOutboundDiagnostics(val, key)\n }\n return out as T\n }\n return value\n}\n\nexport function sanitizeAttempts<T>(attempts: T[]): T[] {\n return attempts.map(a => sanitizeOutboundDiagnostics(a))\n}\n\nexport function sanitizeHarvestResult<T extends Record<string, unknown>>(result: T): T {\n const diagnostics = result?.diagnostics as Record<string, unknown> | undefined\n if (!diagnostics?.debug) return result\n return {\n ...result,\n diagnostics: {\n ...diagnostics,\n debug: sanitizeOutboundDiagnostics(diagnostics.debug),\n },\n }\n}\n","import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { readdirSync, readFileSync, statSync } from 'node:fs'\nimport { basename, join } from 'node:path'\nimport type { IMcpToolExecutor } from './IMcpToolExecutor.js'\nimport { PACKAGE_VERSION } from '../version.js'\nimport { outputBaseDir } from './mcp-response-formatter.js'\nimport { SERVER_INSTRUCTIONS } from './server-instructions.js'\nimport {\n HarvestPaaInputSchema,\n SearchSerpInputSchema,\n ExtractUrlInputSchema,\n HarvestPaaOutputSchema,\n SearchSerpOutputSchema,\n ExtractUrlOutputSchema,\n ExtractSiteOutputSchema,\n AuditSiteOutputSchema,\n MapsPlaceIntelOutputSchema,\n CreditsInfoOutputSchema,\n MapSiteUrlsInputSchema,\n MapSiteUrlsOutputSchema,\n ExtractSiteInputSchema,\n AuditSiteInputSchema,\n YoutubeHarvestInputSchema,\n YoutubeHarvestOutputSchema,\n YoutubeTranscribeInputSchema,\n YoutubeTranscribeOutputSchema,\n FacebookPageIntelInputSchema,\n FacebookPageIntelOutputSchema,\n FacebookAdSearchInputSchema,\n FacebookAdSearchOutputSchema,\n RedditThreadInputSchema,\n RedditThreadOutputSchema,\n FacebookAdTranscribeInputSchema,\n FacebookAdTranscribeOutputSchema,\n FacebookVideoTranscribeInputSchema,\n FacebookVideoTranscribeOutputSchema,\n InstagramProfileContentInputSchema,\n InstagramProfileContentOutputSchema,\n InstagramMediaDownloadInputSchema,\n InstagramMediaDownloadOutputSchema,\n MapsPlaceIntelInputSchema,\n MapsSearchInputSchema,\n MapsSearchOutputSchema,\n DirectoryWorkflowInputSchema,\n DirectoryWorkflowOutputSchema,\n WorkflowListInputSchema,\n WorkflowListOutputSchema,\n WorkflowSuggestInputSchema,\n WorkflowSuggestOutputSchema,\n WorkflowRunInputSchema,\n WorkflowRunOutputSchema,\n WorkflowStepInputSchema,\n WorkflowStepOutputSchema,\n WorkflowStatusInputSchema,\n WorkflowStatusOutputSchema,\n WorkflowArtifactReadInputSchema,\n WorkflowArtifactReadOutputSchema,\n RankTrackerBlueprintInputSchema,\n RankTrackerBlueprintOutputSchema,\n CreditsInfoInputSchema,\n} from './mcp-tool-schemas.js'\nimport { buildRankTrackerBlueprint } from './rank-tracker-blueprint.js'\nimport {\n formatHarvestPaa,\n formatSearchSerp,\n formatExtractUrl,\n formatMapSiteUrls,\n formatExtractSite,\n formatAuditSite,\n formatYoutubeHarvest,\n formatYoutubeTranscribe,\n formatFacebookPageIntel,\n formatFacebookAdSearch,\n formatRedditThread,\n formatFacebookAdTranscribe,\n formatFacebookVideoTranscribe,\n formatInstagramProfileContent,\n formatInstagramMediaDownload,\n formatMapsPlaceIntel,\n formatMapsSearch,\n formatDirectoryWorkflow,\n formatWorkflowList,\n formatWorkflowSuggest,\n formatWorkflowRun,\n formatWorkflowStep,\n formatWorkflowStatus,\n formatWorkflowArtifactRead,\n formatCreditsInfo,\n} from './mcp-response-formatter.js'\n\nexport interface BuildMcpServerOptions {\n savesReportsLocally?: boolean\n}\n\nexport function liveWebToolAnnotations(title: string) {\n return {\n title,\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n }\n}\n\nfunction localPlanningToolAnnotations(title: string) {\n return {\n title,\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n }\n}\n\nfunction listSavedReports(): Array<{ filename: string; mtimeMs: number }> {\n try {\n const dir = outputBaseDir()\n return readdirSync(dir)\n .filter(f => f.endsWith('.md'))\n .map(f => ({ filename: f, mtimeMs: statSync(join(dir, f)).mtimeMs }))\n .sort((a, b) => b.mtimeMs - a.mtimeMs)\n .slice(0, 100)\n } catch {\n return []\n }\n}\n\nfunction registerSavedReportResources(server: McpServer): void {\n server.registerResource(\n 'saved-report',\n new ResourceTemplate('report://{filename}', {\n list: () => ({\n resources: listSavedReports().map(r => ({\n uri: `report://${encodeURIComponent(r.filename)}`,\n name: r.filename,\n mimeType: 'text/markdown',\n })),\n }),\n }),\n {\n title: 'Saved MCP Scraper Reports',\n description: 'Markdown research reports saved by previous MCP Scraper tool calls. Read a report to reuse prior research without re-scraping or spending credits.',\n mimeType: 'text/markdown',\n },\n async (uri, variables) => {\n const requested = Array.isArray(variables.filename) ? variables.filename[0] : variables.filename\n const filename = basename(decodeURIComponent(String(requested ?? '')))\n if (!filename.endsWith('.md')) throw new Error('Only saved .md reports can be read')\n const text = readFileSync(join(outputBaseDir(), filename), 'utf8')\n return { contents: [{ uri: uri.href, mimeType: 'text/markdown', text }] }\n },\n )\n}\n\nexport function buildPaaExtractorMcpServer(\n executor: IMcpToolExecutor,\n options: BuildMcpServerOptions = {},\n): McpServer {\n const server = new McpServer({ name: 'mcp-scraper', version: PACKAGE_VERSION }, { instructions: SERVER_INSTRUCTIONS })\n registerPaaExtractorMcpTools(server, executor, options)\n return server\n}\n\nexport function registerPaaExtractorMcpTools(\n server: McpServer,\n executor: IMcpToolExecutor,\n options: BuildMcpServerOptions = {},\n): void {\n const savesReports = options.savesReportsLocally !== false\n const reportNote = savesReports\n ? ' Saves a full Markdown report to disk.'\n : ' Reports are returned inline; no files are saved on this hosted endpoint.'\n const withReportNote = (description: string) => `${description}${reportNote}`\n\n if (savesReports) registerSavedReportResources(server)\n\n server.registerTool('harvest_paa', {\n title: 'Google PAA + SERP Harvest',\n description: withReportNote('Best default tool for Google search research. Extracts People Also Ask questions plus answers/source URLs, organic SERP, local pack when present, entity IDs (CID/GCID/KG MID), and AI Overview. Infer the user language: split topic from location (e.g. \"best hvac company in Denver CO\" => query \"best hvac company\", location \"Denver, CO\", gl \"us\", hl \"en\"). Routing is automatic — leave proxyMode unset. If a deep harvest exceeds the time budget it returns the questions gathered so far (partial), billed per returned question. Use maxQuestions 30 normally, 100-200 for \"full\", \"deep\", \"all\", or comprehensive research. Deep harvests above 100 questions can run for several minutes with no interim progress — warn the user before starting one and keep maxQuestions at or below 100 unless they explicitly want a deep harvest. Credits are charged by extracted question; unused request hold is refunded.'),\n inputSchema: HarvestPaaInputSchema,\n outputSchema: HarvestPaaOutputSchema,\n annotations: liveWebToolAnnotations('Google PAA + SERP Harvest'),\n }, async (input) => formatHarvestPaa(await executor.harvestPaa(input), input))\n\n server.registerTool('search_serp', {\n title: 'Google SERP Lookup',\n description: withReportNote('Fast Google SERP lookup without PAA expansion. Use when the user asks for rankings, organic results, local pack, quick SERP, or positions. Split topic from location and infer gl/hl from the user request. Routing is automatic — leave proxyMode unset; set location only to force local-pack targeting.'),\n inputSchema: SearchSerpInputSchema,\n outputSchema: SearchSerpOutputSchema,\n annotations: liveWebToolAnnotations('Google SERP Lookup'),\n }, async (input) => formatSearchSerp(await executor.searchSerp(input), input))\n\n server.registerTool('extract_url', {\n title: 'Single URL Extract',\n description: withReportNote('Extract structured data from one public URL when the user provides one page, asks to inspect/scrape a page, or needs page content, schema, headings, metadata, screenshots, branding, or media assets. Returns structured page fields plus artifact handles for saved reports/screenshots/media when requested. Set depositToVault:true to also save the full page into the user\\'s MCP Memory vault server-side (the full body is NOT returned to chat). Use map_site_urls before extracting a site inventory; use extract_site for multi-page crawling.'),\n inputSchema: ExtractUrlInputSchema,\n outputSchema: ExtractUrlOutputSchema,\n annotations: liveWebToolAnnotations('Single URL Extract'),\n }, async (input) => formatExtractUrl(await executor.extractUrl(input), input))\n\n server.registerTool('map_site_urls', {\n title: 'Site URL Map',\n description: withReportNote('Map/crawl a public website when the user asks for a sitemap, URL inventory, broken-link scan, redirect scan, or crawl planning. Returns internal URLs with HTTP status and truncation metadata. Supports up to maxUrls=10000; maps over 500 URLs write the complete inventory to a local CSV file and return a summary plus the file path instead of the full list inline. Use this before extract_site when choosing pages for an audit; use extract_url for one known page.'),\n inputSchema: MapSiteUrlsInputSchema,\n outputSchema: MapSiteUrlsOutputSchema,\n annotations: liveWebToolAnnotations('Site URL Map'),\n }, async (input) => formatMapSiteUrls(await executor.mapSiteUrls(input), input))\n\n server.registerTool('extract_site', {\n title: 'Multi-Page Site Content Crawl',\n description: withReportNote('Crawl a public website and return the page CONTENT across multiple pages (map + scrape). Returns per-page titles and Markdown content. Supports up to maxPages=10000; bulk crawls over 25 pages switch to folder mode: each page is saved as its own Markdown file in a local folder and the response returns a summary plus the folder path instead of inlining all content. This tool returns content only — for a technical SEO audit (issues, internal link graph, indexability, heading breakdown, image sizes/formats) use audit_site. Use map_site_urls first when URL selection matters; use extract_url for one page.'),\n inputSchema: ExtractSiteInputSchema,\n outputSchema: ExtractSiteOutputSchema,\n annotations: liveWebToolAnnotations('Multi-Page Site Content Crawl'),\n }, async (input) => formatExtractSite(await executor.extractSite(input), input))\n\n server.registerTool('audit_site', {\n title: 'Technical SEO Audit',\n description: withReportNote('Run a full technical SEO audit (Screaming-Frog-style) on a public website. Crawls up to maxPages and produces a complete on-page + crawl analysis: per-page title/meta lengths, heading breakdown, indexability and canonical status, schema, an internal link graph (inlinks/orphans/crawl-depth), a link analysis (top internal pages by inlinks, top external domains by link count, broken/orphan counts), an issues report, and an image audit (byte size, format, over-100KB and legacy-format flags). Writes everything to a local folder (report.md, issues.json, pages.jsonl, links.jsonl, link-metrics.jsonl, link-report.md, links-summary.json, external-domains.json, images.jsonl) plus per-page content, and returns a headline summary plus the folder path. Use this when the user wants an audit or analysis; use extract_site when they just want page content.'),\n inputSchema: AuditSiteInputSchema,\n outputSchema: AuditSiteOutputSchema,\n annotations: liveWebToolAnnotations('Technical SEO Audit'),\n }, async (input) => formatAuditSite(await executor.auditSite(input), input))\n\n server.registerTool('youtube_harvest', {\n title: 'YouTube Video Harvest',\n description: withReportNote('Harvest YouTube video metadata when the user wants to find videos by topic, inspect a channel library, compare video angles, or get videoIds for later transcription. Use mode \"search\" for keyword/topic requests and mode \"channel\" for @handles, channel IDs, or channel URLs. Returns titles, views, durations, URLs, and videoIds for follow-up transcription. Use youtube_transcribe after selecting one video.'),\n inputSchema: YoutubeHarvestInputSchema,\n outputSchema: YoutubeHarvestOutputSchema,\n annotations: liveWebToolAnnotations('YouTube Video Harvest'),\n }, async (input) => formatYoutubeHarvest(await executor.youtubeHarvest(input), input))\n\n server.registerTool('youtube_transcribe', {\n title: 'YouTube Transcription',\n description: withReportNote('Fetch and transcribe captions from a YouTube video. Use this when the user asks what was said in a YouTube video, wants claims/offers/lessons extracted from a video, or provides a YouTube URL for transcript work. Returns full transcript, timestamped chunks, word count, and resolvedInputs. Pass videoId from youtube_harvest results, or pass url when the user pasted a YouTube URL. Use youtube_harvest first when you need to discover videos by topic/channel.'),\n inputSchema: YoutubeTranscribeInputSchema,\n outputSchema: YoutubeTranscribeOutputSchema,\n annotations: liveWebToolAnnotations('YouTube Transcription'),\n }, async (input) => formatYoutubeTranscribe(await executor.youtubeTranscribe(input), input))\n\n server.registerTool('facebook_page_intel', {\n title: 'Facebook Advertiser Ad Intel',\n description: withReportNote('Harvest ads from a Facebook advertiser when the user wants current ad copy, creative angles, CTAs, video URLs, or competitive ad intelligence for one brand/page. Returns ad copy, headlines, CTAs, creative type, status, landing URLs, and direct ad video URLs ready for facebook_ad_transcribe. Accepts pageId, libraryId, or a brand/advertiser name as query. Use facebook_ad_search first when the advertiser handle is unknown. For normal public Facebook reels/posts/watch/share URLs, use facebook_video_transcribe instead.'),\n inputSchema: FacebookPageIntelInputSchema,\n outputSchema: FacebookPageIntelOutputSchema,\n annotations: liveWebToolAnnotations('Facebook Advertiser Ad Intel'),\n }, async (input) => formatFacebookPageIntel(await executor.facebookPageIntel(input), input))\n\n server.registerTool('facebook_ad_search', {\n title: 'Facebook Ad Library Search',\n description: withReportNote('Search Facebook Ad Library when the user wants to find advertisers by brand, competitor, niche, or keyword. Returns advertisers with ad counts and library IDs. Use this to discover competitor/page handles, then pass libraryId or pageId to facebook_page_intel for ad details.'),\n inputSchema: FacebookAdSearchInputSchema,\n outputSchema: FacebookAdSearchOutputSchema,\n annotations: liveWebToolAnnotations('Facebook Ad Library Search'),\n }, async (input) => formatFacebookAdSearch(await executor.facebookAdSearch(input), input))\n\n server.registerTool('reddit_thread', {\n title: 'Reddit Thread + Comments',\n description: withReportNote('Capture a Reddit post and its comment tree from any reddit.com thread URL. Use this when the user wants Reddit comments, opinions, discussion, or audience voice from a specific thread (find threads first with search_serp, which surfaces reddit.com/comments links). Returns the post title, author, score, body, and a list of comments with author, score, nesting depth, and text. Handles Reddit\\'s bot protection automatically (fetches via old.reddit through a residential proxy with retries); pass maxComments to cap the list.'),\n inputSchema: RedditThreadInputSchema,\n outputSchema: RedditThreadOutputSchema,\n annotations: liveWebToolAnnotations('Reddit Thread + Comments'),\n }, async (input) => formatRedditThread(await executor.redditThread(input), input))\n\n server.registerTool('facebook_ad_transcribe', {\n title: 'Facebook Ad Transcription',\n description: 'Transcribe audio from a Facebook ad video CDN URL. Use this when facebook_page_intel returned a direct videoUrl and the user asks what the ad says, what claims it makes, or wants ad-message extraction. Returns full transcript, timestamped chunks, word count, and resolvedInputs. Use only with the direct videoUrl value from facebook_page_intel results; do not pass public Facebook post/reel/share URLs. Use facebook_video_transcribe for organic Facebook URLs, and facebook_page_intel first when you only have a brand/page/ad library handle.',\n inputSchema: FacebookAdTranscribeInputSchema,\n outputSchema: FacebookAdTranscribeOutputSchema,\n annotations: liveWebToolAnnotations('Facebook Ad Transcription'),\n }, async (input) => formatFacebookAdTranscribe(await executor.facebookAdTranscribe(input), input))\n\n server.registerTool('facebook_video_transcribe', {\n title: 'Facebook Organic Video Transcription',\n description: withReportNote('Transcribe audio from an organic Facebook reel, video, watch, post, or share URL, including fb.watch links. Use this when the user pastes a normal Facebook video page URL and wants the transcript or downloadable MP4. Renders the Facebook page in a browser, selects the best matching public Facebook CDN MP4 URL from page state, then returns sourceUrl, resolved pageUrl, videoId, ownerName, selectedQuality, bitrate, videoDurationSec, extracted MP4 URL, full transcript, and timestamped chunks.'),\n inputSchema: FacebookVideoTranscribeInputSchema,\n outputSchema: FacebookVideoTranscribeOutputSchema,\n annotations: liveWebToolAnnotations('Facebook Organic Video Transcription'),\n }, async (input) => formatFacebookVideoTranscribe(await executor.facebookVideoTranscribe(input), input))\n\n server.registerTool('instagram_profile_content', {\n title: 'Instagram Profile Content Discovery',\n description: withReportNote('Discover Instagram profile grid content links for a handle or profile URL. Use this when the user wants a person or brand account content inventory before selecting posts/reels to download. Returns profile stats, collected post/reel/tv URLs, shortcodes, type counts, browser details, pagination attempts, stop reason, and limitations.'),\n inputSchema: InstagramProfileContentInputSchema,\n outputSchema: InstagramProfileContentOutputSchema,\n annotations: liveWebToolAnnotations('Instagram Profile Content Discovery'),\n }, async (input) => formatInstagramProfileContent(await executor.instagramProfileContent(input), input))\n\n server.registerTool('instagram_media_download', {\n title: 'Instagram Post/Reel Media Download',\n description: withReportNote('Extract and download media from one Instagram post, reel, or tv URL. Use after instagram_profile_content or when the user gives a specific Instagram URL and wants the image, caption/text, reel audio/video tracks, optional muxed MP4, or optional transcript. Reels commonly expose separate video-only and audio-only MP4 tracks; this tool selects the best video and audio tracks and attempts muxing when ffmpeg is available.'),\n inputSchema: InstagramMediaDownloadInputSchema,\n outputSchema: InstagramMediaDownloadOutputSchema,\n annotations: liveWebToolAnnotations('Instagram Post/Reel Media Download'),\n }, async (input) => formatInstagramMediaDownload(await executor.instagramMediaDownload(input), input))\n\n server.registerTool('maps_place_intel', {\n title: 'Google Maps Business Profile Details',\n description: withReportNote('Extract Google Maps business intelligence for one known/named business: rating, review count, category, address, phone, website, hours, booking URL, review histogram, review topics, about attributes, entity IDs, and optional review cards. Do not use this for category searches, local market prospect lists, or requests for multiple GMB/GBP profiles; use maps_search first for those. Split business name from location (e.g. \"Elite Roofing Denver CO\" => businessName \"Elite Roofing\", location \"Denver, CO\"). Pass includeReviews true when the user asks for reviews/customer pain.'),\n inputSchema: MapsPlaceIntelInputSchema,\n outputSchema: MapsPlaceIntelOutputSchema,\n annotations: liveWebToolAnnotations('Google Maps Business Profile Details'),\n }, async (input) => formatMapsPlaceIntel(await executor.mapsPlaceIntel(input), input))\n\n server.registerTool('maps_search', {\n title: 'Google Maps Business Search',\n description: withReportNote('Search Google Maps for multiple businesses/profiles by category, niche, keyword, or local market. Use this when the user asks for several Google Business Profiles, GMBs, GBPs, leads, prospects, competitors, or \"more than the 3-pack.\" Routing is automatic and location-aware — leave proxyMode unset; pass proxyZip only to force a specific ZIP. Returns up to 50 candidates with names, place URLs, CIDs when available, ratings, review counts, profile metadata, and sanitized attempt telemetry. Default maxResults is 10; maximum is 50. Use maps_place_intel afterward only when a selected business needs full details and reviews.'),\n inputSchema: MapsSearchInputSchema,\n outputSchema: MapsSearchOutputSchema,\n annotations: liveWebToolAnnotations('Google Maps Business Search'),\n }, async (input) => formatMapsSearch(await executor.mapsSearch(input), input))\n\n server.registerTool('directory_workflow', {\n title: 'Directory Workflow: Markets + Maps',\n description: withReportNote('Build directory/prospecting datasets by selecting US city markets from the free Census Population Estimates city/place dataset, optionally joining configured US ZIPS/Lead Magician ZIP groups, then running Google Maps business searches for each city in parallel. Use this when the user wants \"all cities over 100k population in a state\", \"build a directory CSV\", \"find markets then get Maps data\", or similar location-database + Maps workflows. Set minPopulation, state, query, maxResultsPerCity, and concurrency. Routing is automatic per city. Saved CSV rows include source_location, result_position, business_name, review_stars, review_count, category, address, phone, hours_status, website_url, directions_url, place_url, cid, cid_decimal, city population, and ZIP groups. Structured city results include sanitized attempt telemetry. Use maps_place_intel only when a selected profile needs deeper review topics, profile review count confirmation, or review cards. For local Lead Magician ZIP enrichment, set MCP_SCRAPER_USZIPS_CSV_PATH on the API server or pass usZipsCsvPath only in local/test mode.'),\n inputSchema: DirectoryWorkflowInputSchema,\n outputSchema: DirectoryWorkflowOutputSchema,\n annotations: liveWebToolAnnotations('Directory Workflow: Markets + Maps'),\n }, async (input) => formatDirectoryWorkflow(await executor.directoryWorkflow(input), input))\n\n server.registerTool('workflow_list', {\n title: 'Workflow Catalog',\n description: 'List MCP Scraper higher-level workflows and AI-facing recipes. Use this when the user asks what MCP Scraper can do beyond single tools, or asks for market analysis, ICP research, forum/review acquisition, full brand design briefings, CRO audits, competitive positioning, content gap briefs, or AI search visibility audits. Returns runnable workflow ids plus recipe guidance for the best tool chain.',\n inputSchema: WorkflowListInputSchema,\n outputSchema: WorkflowListOutputSchema,\n annotations: localPlanningToolAnnotations('Workflow Catalog'),\n }, async (input) => formatWorkflowList(await executor.workflowList(input), input))\n\n server.registerTool('workflow_suggest', {\n title: 'Workflow Intent Router',\n description: 'Route a high-level business or research goal to the right MCP Scraper workflow/tool chain. Use before running work when the user says things like \"do market analysis\", \"research my ICP\", \"acquire forum and review language\", \"build a brand design brief\", \"run a CRO audit\", \"compare competitors\", \"make a content gap brief\", or \"audit AI search visibility\". This tool does not spend credits; it tells the AI exactly which workflow/tool chain to run next.',\n inputSchema: WorkflowSuggestInputSchema,\n outputSchema: WorkflowSuggestOutputSchema,\n annotations: localPlanningToolAnnotations('Workflow Intent Router'),\n }, async (input) => formatWorkflowSuggest(input))\n\n server.registerTool('workflow_run', {\n title: 'Run Workflow',\n description: withReportNote('Start a higher-level MCP Scraper workflow. Use after workflow_suggest or workflow_list. Runnable workflow ids: directory, agent-packet, local-competitive-audit, map-comparison, serp-comparison, paa-expansion-brief, ai-overview-language. This is the main MCP tool for market analysis, ICP evidence packets, local competitive audits, Maps/SERP comparisons, content gap briefs, and AI Overview language guidance. Stepwise workflows (e.g. agent-packet) run ONE leg per call and return runId, the step output, and nextStep — when nextStep is present, call workflow_step with the runId to run the next leg, and keep calling it until done is true. This keeps each call short instead of one long blocking run, so report each step result to the user as it arrives.'),\n inputSchema: WorkflowRunInputSchema,\n outputSchema: WorkflowRunOutputSchema,\n annotations: liveWebToolAnnotations('Run Workflow'),\n }, async (input) => formatWorkflowRun(await executor.workflowRun(input), input))\n\n server.registerTool('workflow_step', {\n title: 'Advance Workflow Step',\n description: withReportNote('Run the next leg of a stepwise MCP Scraper workflow started with workflow_run. Pass the runId. Each call executes exactly one logical step (typically one live harvest), persists that step\\'s artifacts, and returns the step output plus nextStep. Keep calling workflow_step with the same runId until done is true, reporting each step result to the user as it lands. Use this instead of waiting on one long workflow call — it avoids client timeouts on long multi-step jobs.'),\n inputSchema: WorkflowStepInputSchema,\n outputSchema: WorkflowStepOutputSchema,\n annotations: liveWebToolAnnotations('Advance Workflow Step'),\n }, async (input) => formatWorkflowStep(await executor.workflowStep(input), input))\n\n server.registerTool('workflow_status', {\n title: 'Workflow Status',\n description: 'Fetch a hosted workflow run by id and list its current status and artifacts. Use when a workflow may still be running, when the model needs to re-open a run, inspect artifact ids, recover from a long workflow, or decide whether to call workflow_step or workflow_artifact_read next. Use only a runId returned by workflow_run/workflow_step/workflow_status; do not construct one yourself.',\n inputSchema: WorkflowStatusInputSchema,\n outputSchema: WorkflowStatusOutputSchema,\n annotations: liveWebToolAnnotations('Workflow Status'),\n }, async (input) => formatWorkflowStatus(await executor.workflowStatus(input), input))\n\n server.registerTool('workflow_artifact_read', {\n title: 'Read Workflow Artifact',\n description: 'Read a workflow artifact back into MCP context by run id and artifact id. Use this before writing final deliverables so the answer is grounded in generated evidence.json, CSVs, Markdown briefs, reports, and task files instead of memory. Use workflow_status first when artifact ids are unknown. Use only artifactId values returned by workflow_run/workflow_step/workflow_status; do not construct one yourself. Use maxBytes to limit large CSV/JSON artifacts.',\n inputSchema: WorkflowArtifactReadInputSchema,\n outputSchema: WorkflowArtifactReadOutputSchema,\n annotations: liveWebToolAnnotations('Read Workflow Artifact'),\n }, async (input) => formatWorkflowArtifactRead(await executor.workflowArtifactRead(input), input))\n\n server.registerTool('rank_tracker_workflow', {\n title: 'Rank Tracker Blueprint Builder',\n description: 'Generate a build-ready database, cron/heartbeat, ingestion, metrics, and AI implementation prompt for a rank tracker powered by MCP Scraper. Supports Maps rankings through directory_workflow/maps_search, organic rankings through search_serp, AI Overview citation tracking, and People Also Ask source presence tracking. This tool is local planning only; it does not call the web or spend credits.',\n inputSchema: RankTrackerBlueprintInputSchema,\n outputSchema: RankTrackerBlueprintOutputSchema,\n annotations: localPlanningToolAnnotations('Rank Tracker Blueprint Builder'),\n }, async (input) => buildRankTrackerBlueprint(input))\n\n server.registerTool('credits_info', {\n title: 'MCP Scraper Credits & Costs',\n description: 'Answer questions about MCP Scraper credits, usage limits, and concurrency upgrades: current credit balance, what a specific tool/action costs, the full cost table, current concurrency limit, the extra-slot price, billing URL, and the terminal checkout command. Does not expose payment methods or credit card information.',\n inputSchema: CreditsInfoInputSchema,\n outputSchema: CreditsInfoOutputSchema,\n annotations: {\n title: 'MCP Scraper Credits & Costs',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n }, async (input) => formatCreditsInfo(await executor.creditsInfo(input), input))\n\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { sanitizeVendorName } from '../errors.js'\nimport { WORKFLOW_RECIPES, suggestWorkflowRecipes, type WorkflowRecipe } from './workflow-catalog.js'\nimport { buildLinkGraph } from '../api/seo-link-graph.js'\nimport { buildLinkReport, renderLinkReport, type LinkReport } from '../api/seo-link-report.js'\nimport { computeIssues, renderIssueReport } from '../api/seo-issues.js'\nimport { auditImages, renderImageSection, type ImageAudit } from '../api/image-audit.js'\nimport type { PageData } from '../api/site-extractor.js'\n\nlet reportSavingEnabled = true\n\nexport function configureReportSaving(enabled: boolean): void {\n reportSavingEnabled = enabled\n}\n\nfunction sanitizeVendorText(text: string): string {\n return sanitizeVendorName(\n text\n .replace(/kernel_session_id/gi, 'browser_session_id')\n .replace(/kernel_delete_succeeded/gi, 'session_cleanup_succeeded')\n .replace(/kernel_delete_started/gi, 'session_cleanup_started')\n .replace(/kernel_delete_error/gi, 'session_cleanup_error')\n .replace(/kernelSessionId/g, 'browserSessionId')\n .replace(/kernelProxyId/g, 'proxyId')\n .replace(/KERNEL_API_KEY/g, 'BROWSER_SERVICE_API_KEY')\n .replace(/\"kernel\"\\s*:/gi, '\"browserRuntime\":'),\n )\n}\n\nfunction slugifyReportName(input: string): string {\n return input\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 80) || 'mcp-scraper-report'\n}\n\nfunction reportTitle(full: string): string {\n const title = full.split('\\n').find(line => line.startsWith('# '))\n return title?.replace(/^#\\s+/, '').trim() || 'MCP Scraper Report'\n}\n\nexport function outputBaseDir(): string {\n return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || join(homedir(), 'Downloads', 'mcp-scraper')\n}\n\nfunction saveFullReport(full: string): string | null {\n if (!reportSavingEnabled || process.env.MCP_SCRAPER_SAVE_REPORTS === 'false') return null\n const outDir = outputBaseDir()\n try {\n mkdirSync(outDir, { recursive: true })\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const file = join(outDir, `${stamp}-${slugifyReportName(reportTitle(full))}.md`)\n writeFileSync(file, full, 'utf8')\n return file\n } catch {\n return null\n }\n}\n\nconst BULK_PAGE_THRESHOLD = 25\nconst BULK_URL_THRESHOLD = 500\n\nfunction reportSavingActive(): boolean {\n return reportSavingEnabled && process.env.MCP_SCRAPER_SAVE_REPORTS !== 'false'\n}\n\ninterface BulkPage { url: string; title?: string | null; bodyMarkdown?: string | null; metaDescription?: string | null; schemaTypes?: string[] }\n\ninterface SeoExport {\n pageRows: Array<Record<string, unknown>>\n edges: Array<Record<string, unknown>>\n metrics: Array<Record<string, unknown>>\n issues: Record<string, { count: number; urls: string[] }>\n reportMd: string\n linkReport: LinkReport\n branding?: unknown\n}\n\nfunction saveBulkSite(siteUrl: string, pages: BulkPage[], seo?: SeoExport, imageAudit?: ImageAudit | null): { dir: string; indexFile: string; fileCount: number; seoFiles?: string[] } | null {\n if (!reportSavingActive()) return null\n try {\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const dir = join(outputBaseDir(), `extract-${slugifyReportName(siteUrl)}-${stamp}`)\n const pagesDir = join(dir, 'pages')\n mkdirSync(pagesDir, { recursive: true })\n\n const indexRows = pages.map((p, i) => {\n const num = String(i + 1).padStart(4, '0')\n const slug = slugifyReportName(p.url.replace(/^https?:\\/\\//, '')).slice(0, 60) || 'page'\n const fname = `${num}-${slug}.md`\n const body = (p.bodyMarkdown ?? '').trim()\n const content = [\n `# ${p.title ?? 'Untitled'}`,\n `- **URL:** ${p.url}`,\n p.metaDescription ? `- **Description:** ${p.metaDescription}` : '',\n p.schemaTypes?.length ? `- **Schema:** ${p.schemaTypes.join(', ')}` : '',\n '',\n body || '_(no content extracted)_',\n ].filter(Boolean).join('\\n')\n writeFileSync(join(pagesDir, fname), content, 'utf8')\n return `| ${i + 1} | ${cell(p.title ?? 'Untitled')} | ${p.url} | pages/${fname} |`\n })\n\n const dataFilesSection = seo ? [\n `\\n## Data files (in this folder)`,\n `- \\`report.md\\` — SEO issues summary (counts + example URLs)`,\n `- \\`issues.json\\` — every finding with the full list of offender URLs`,\n `- \\`pages.jsonl\\` — per-page SEO fields, one JSON object per page`,\n `- \\`links.jsonl\\` — internal/external link edges (anchor, rel, target status)`,\n `- \\`link-metrics.jsonl\\` — inlinks, crawl depth, orphan flags per page`,\n `- \\`link-report.md\\` — link analysis: top internal pages by inlinks, top external domains, distribution`,\n `- \\`links-summary.json\\` — link totals + top-20 internal pages + top-20 external domains`,\n `- \\`external-domains.json\\` — every external domain linked to, ordered by link count`,\n ...(imageAudit ? [\n `- \\`images.jsonl\\` — every image with byte size, format, over-100KB and legacy-format flags`,\n `- \\`images-summary.json\\` — image totals (count, total weight, over-100KB, legacy)`,\n ] : []),\n ...(seo.branding ? [`- \\`branding.json\\` — site logo, colors, fonts`] : []),\n ].join('\\n') : ''\n\n const index = [\n `# Site Extract: ${siteUrl}`,\n `**${pages.length} pages** crawled. Everything is in this folder.`,\n `- Page content: one Markdown file per page under \\`pages/\\` (listed in the table below).`,\n seo ? `- SEO crawl data: the data files listed below.` : '',\n dataFilesSection,\n `\\n## Pages\\n| # | Title | URL | File |\\n|---|-------|-----|------|\\n${indexRows.join('\\n')}`,\n ].filter(Boolean).join('\\n')\n const indexFile = join(dir, 'index.md')\n writeFileSync(indexFile, index, 'utf8')\n\n let seoFiles: string[] | undefined\n if (seo) {\n const toJsonl = (rows: Array<Record<string, unknown>>) => rows.map(r => JSON.stringify(r)).join('\\n')\n const pagesJsonl = join(dir, 'pages.jsonl')\n const linksJsonl = join(dir, 'links.jsonl')\n const metricsJsonl = join(dir, 'link-metrics.jsonl')\n const issuesFile = join(dir, 'issues.json')\n const reportFile = join(dir, 'report.md')\n writeFileSync(pagesJsonl, toJsonl(seo.pageRows), 'utf8')\n writeFileSync(linksJsonl, toJsonl(seo.edges), 'utf8')\n writeFileSync(metricsJsonl, toJsonl(seo.metrics), 'utf8')\n writeFileSync(issuesFile, JSON.stringify(seo.issues, null, 2), 'utf8')\n writeFileSync(reportFile, seo.reportMd + (imageAudit ? `\\n\\n${renderImageSection(imageAudit)}` : ''), 'utf8')\n const linkReportFile = join(dir, 'link-report.md')\n const linksSummaryFile = join(dir, 'links-summary.json')\n const externalDomainsFile = join(dir, 'external-domains.json')\n writeFileSync(linkReportFile, renderLinkReport(seo.linkReport), 'utf8')\n writeFileSync(linksSummaryFile, JSON.stringify(seo.linkReport.summary, null, 2), 'utf8')\n writeFileSync(externalDomainsFile, JSON.stringify(seo.linkReport.externalDomains, null, 2), 'utf8')\n seoFiles = [pagesJsonl, linksJsonl, metricsJsonl, issuesFile, reportFile, linkReportFile, linksSummaryFile, externalDomainsFile]\n if (imageAudit) {\n const imagesJsonl = join(dir, 'images.jsonl')\n const imagesSummary = join(dir, 'images-summary.json')\n writeFileSync(imagesJsonl, imageAudit.rows.map(r => JSON.stringify(r)).join('\\n'), 'utf8')\n writeFileSync(imagesSummary, JSON.stringify(imageAudit.summary, null, 2), 'utf8')\n seoFiles.push(imagesJsonl, imagesSummary)\n }\n if (seo.branding) {\n const brandingFile = join(dir, 'branding.json')\n writeFileSync(brandingFile, JSON.stringify(seo.branding, null, 2), 'utf8')\n seoFiles.push(brandingFile)\n }\n }\n\n return { dir, indexFile, fileCount: pages.length, seoFiles }\n } catch {\n return null\n }\n}\n\nfunction saveUrlInventory(siteUrl: string, urls: Array<{ url: string; status: number | null }>): string | null {\n if (!reportSavingActive()) return null\n try {\n const outDir = outputBaseDir()\n mkdirSync(outDir, { recursive: true })\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const file = join(outDir, `${stamp}-urlmap-${slugifyReportName(siteUrl.replace(/^https?:\\/\\//, ''))}.csv`)\n const csv = (v: string) => /[\",\\n]/.test(v) ? `\"${v.replace(/\"/g, '\"\"')}\"` : v\n const rows = ['url,status', ...urls.map(u => `${csv(u.url)},${u.status ?? ''}`)]\n writeFileSync(file, rows.join('\\n'), 'utf8')\n return file\n } catch {\n return null\n }\n}\n\nfunction persistScreenshotLocally(base64: string, url: string): string | null {\n if (!reportSavingEnabled || process.env.MCP_SCRAPER_SAVE_REPORTS === 'false') return null\n try {\n const dir = join(outputBaseDir(), 'screenshots')\n mkdirSync(dir, { recursive: true })\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const slug = url.replace(/^https?:\\/\\//, '').replace(/[^a-z0-9]+/gi, '-').replace(/^-+|-+$/g, '').slice(0, 60)\n const filePath = join(dir, `${stamp}-${slug}.png`)\n writeFileSync(filePath, Buffer.from(base64, 'base64'))\n return filePath\n } catch {\n return null\n }\n}\n\nfunction oneBlock(content: string, diskContent?: string): CallToolResult {\n const filePath = saveFullReport(diskContent ?? content)\n const text = filePath ? `${content}\\n\\n📄 Saved: \\`${filePath}\\`` : content\n return { content: [{ type: 'text', text }] }\n}\n\nexport function passthrough(raw: CallToolResult): CallToolResult {\n return raw\n}\n\nfunction workflowRecipeTable(recipes: WorkflowRecipe[]): string {\n if (!recipes.length) return ''\n return [\n '| Recipe | Best workflow | What it produces |',\n '|---|---|---|',\n ...recipes.map(recipe => `| ${cell(recipe.title)} | ${recipe.primaryWorkflowId ? `\\`${recipe.primaryWorkflowId}\\`` : 'tool chain'} | ${cell(recipe.produces.slice(0, 4).join(', '))} |`),\n ].join('\\n')\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 formatStructuredError(body: Record<string, unknown>, fallback: string): string {\n if (body.error === 'insufficient_balance') {\n return `Insufficient credits. Balance: ${body.balance_credits} credits. This call requires ${body.required_credits} credits. Top up at ${body.topup_url}`\n }\n if (body.error === 'mcp_request_timeout') {\n return typeof body.message === 'string' ? body.message : 'MCP Scraper request timed out and was cancelled.'\n }\n if (typeof body.error_code === 'string') {\n const message = typeof body.error === 'string'\n ? body.error\n : typeof body.message === 'string'\n ? body.message\n : fallback\n const retryable = body.retryable === true ? ' Retryable: yes.' : ''\n return `${body.error_code}: ${message}${retryable}${errorAttemptsSection(body)}`\n }\n if (typeof body.error === 'string') return body.error\n return fallback || 'Tool error'\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 (raw.isError || parsed.error || parsed.error_code) return { error: sanitizeVendorText(formatStructuredError(parsed, text)) }\n const data = (parsed.result as Record<string, unknown>) ?? parsed\n return { data }\n } catch {\n if (raw.isError) return { error: sanitizeVendorText(text || 'Tool error') }\n return { error: 'Failed to parse tool response' }\n }\n}\n\ninterface EntityIdRecord { name: string; kgId: string | null; cid: string | null; gcid: string | null }\ninterface EntityIdsData { entities?: EntityIdRecord[]; kgIds?: string[]; cids?: string[]; gcids?: string[] }\n\nfunction entityIdsSection(ids?: EntityIdsData): string {\n if (!ids) return ''\n const lines: string[] = []\n if (ids.entities?.length) {\n for (const e of ids.entities) {\n const idParts = [e.kgId && `MID ${e.kgId}`, e.cid && `CID ${e.cid}`, e.gcid && `GCID ${e.gcid}`].filter(Boolean)\n if (idParts.length) lines.push(`- **${e.name}** — ${idParts.join(', ')}`)\n }\n }\n const linkedNames = new Set((ids.entities ?? []).map(e => e.name))\n if (!linkedNames.size) {\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 }\n return lines.length ? `\\n## Entity IDs\\n${lines.join('\\n')}` : ''\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\nexport function cell(s: string | null | undefined): string {\n return String(s ?? '')\n .replace(/\\r?\\n+/g, ' ')\n .replace(/\\|/g, '\\\\|')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\nfunction debugSection(debug: any): string {\n if (!debug || typeof debug !== 'object') return ''\n const request = debug.request ?? {}\n const browser = debug.browser ?? {}\n const kernel = browser.browserRuntime ?? browser.kernel ?? {}\n const network = browser.networkLocation ?? {}\n const nav = browser.serpNavigation ?? {}\n const proxyResolution = kernel.proxyResolution ?? {}\n const locationEvidence = debug.locationEvidence\n const candidates = Array.isArray(locationEvidence?.candidates)\n ? locationEvidence.candidates.slice(0, 4).map((c: any) => `${c.city}, ${c.regionCode} (${c.count})`).join(', ')\n : ''\n const lines = [\n '\\n## Debug',\n `- Proxy mode: ${request.proxyMode ?? kernel.proxyMode ?? 'unknown'} · requested proxy: ${kernel.requestedProxyIdPresent === true ? `yes (${kernel.requestedProxyIdSuffix ?? 'redacted'})` : 'no'}`,\n `- Proxy resolution: ${proxyResolution.source ?? 'unknown'}${proxyResolution.target ? ` · ${proxyResolution.target.level ?? 'city'} ${proxyResolution.target.city}, ${proxyResolution.target.state}` : ''}${proxyResolution.error ? ` · ${truncate(proxyResolution.error, 180)}` : ''}`,\n `- Browser session: ${kernel.sessionId ?? 'unknown'} · retrieved proxy: ${kernel.retrievedProxyIdPresent === true ? `yes (${kernel.retrievedProxyIdSuffix ?? 'redacted'})` : kernel.retrievedProxyIdPresent === false ? 'no' : 'unknown'}`,\n `- Browser IP geo: ${[network.ip, network.city, network.region, network.country].filter(Boolean).join(' · ') || network.error || 'unknown'}`,\n `- Google URL: ${truncate(nav.requestedUrl, 240) || 'unknown'}`,\n `- Final URL: ${truncate(nav.finalUrl, 240) || 'unknown'} · CAPTCHA: ${nav.captchaDetected === true ? 'yes' : nav.captchaDetected === false ? 'no' : 'unknown'} · redirected: ${nav.redirected === true ? 'yes' : nav.redirected === false ? 'no' : 'unknown'}`,\n ]\n if (locationEvidence) {\n lines.push(`- Location evidence: ${locationEvidence.status}${locationEvidence.expected ? ` · expected ${locationEvidence.expected.city}${locationEvidence.expected.regionCode ? `, ${locationEvidence.expected.regionCode}` : ''}` : ''}${candidates ? ` · candidates ${candidates}` : ''}`)\n }\n return sanitizeVendorText(lines.join('\\n'))\n}\n\nfunction errorAttemptsSection(body: Record<string, unknown>): string {\n const attempts = Array.isArray(body.attempts) ? body.attempts as Array<Record<string, any>> : []\n if (attempts.length === 0) return ''\n const lines = attempts.slice(0, 5).map((attempt) => {\n const debug = attempt.debug ?? {}\n const browser = debug.browser ?? {}\n const kernel = browser.browserRuntime ?? browser.kernel ?? {}\n const proxyResolution = kernel.proxyResolution ?? {}\n const network = browser.networkLocation ?? {\n ip: attempt.observedIp ?? attempt.observed_ip,\n city: attempt.observedCity ?? attempt.observed_city,\n region: attempt.observedRegion ?? attempt.observed_region,\n }\n const nav = browser.serpNavigation ?? {}\n const geo = [network.ip, network.city, network.region].filter(Boolean).join(' / ') || 'geo unknown'\n const sessionId = attempt.browser_session_id ?? attempt.browserSessionIdSuffix ?? attempt.kernel_session_id ?? kernel.sessionId ?? 'unknown'\n const cleanupSucceeded = attempt.session_cleanup_succeeded ?? attempt.kernel_delete_succeeded\n const proxySource = proxyResolution.source ?? attempt.proxyResolutionSource\n return `- Attempt ${attempt.attempt_number ?? attempt.attemptNumber ?? '?'}: ${attempt.outcome ?? attempt.status ?? 'unknown'} · session ${sessionId} · proxy ${debug.request?.proxyMode ?? kernel.proxyMode ?? attempt.proxyMode ?? 'unknown'}${proxySource ? `/${proxySource}` : ''} · ${geo} · CAPTCHA ${nav.captchaDetected === true ? 'yes' : nav.captchaDetected === false ? 'no' : 'unknown'} · cleanup ${cleanupSucceeded === true ? 'yes' : cleanupSucceeded === false ? 'no' : 'unknown'}`\n })\n return `\\n\\nAttempts:\\n${lines.join('\\n')}`\n}\n\ninterface FlatRow { question: string; answer?: string; source_site?: string; source_title?: string }\ninterface OrganicResult { position: number; title: string; url: string; domain: string; snippet?: string | null }\ninterface AIOverview { detected: boolean; text?: string | null }\ninterface HarvestDiagnostics { completionStatus?: string; debug?: unknown }\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 EntityIdsData | undefined\n const aiOvw = d.aiOverview as AIOverview | undefined\n const diagnostics = d.diagnostics as HarvestDiagnostics | undefined\n const durationMs = (d.stats as { durationMs?: number } | undefined)?.durationMs\n\n const paaRows = flat.map((r, i) =>\n `| ${i + 1} | ${cell(r.question)} | ${cell(truncate(r.answer, 120))} | ${cell(r.source_title || 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*Google did not return a People Also Ask block for this query/location. SERP data was extracted successfully when available.*'\n\n const serpRows = organic.map(r =>\n `| ${r.position} | ${cell(r.title)} | [${cell(r.domain)}](${r.url}) | ${cell(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- Status: ${diagnostics?.completionStatus ?? (flat.length ? 'paa_found' : 'no_paa')} · Questions: ${flat.length} · Duration: ${(durationMs / 1000).toFixed(1)}s`\n : ''\n\n const tips = `\\n---\\n💡 **Tips**\\n- Max questions: \\`maxQuestions: 200\\` (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 = `# PAA Report: \"${input.query}\"${input.location ? ` · ${input.location}` : ''}\\n\\n${paaTable}${serpTable}${entityIdsSection(entityIds)}${aiSection}${statsLine}${debugSection(diagnostics?.debug)}${tips}`\n\n return {\n ...oneBlock(full),\n structuredContent: {\n query: input.query,\n location: input.location ?? null,\n questionCount: flat.length,\n completionStatus: diagnostics?.completionStatus ?? null,\n questions: flat.map(r => ({\n question: String(r.question ?? ''),\n answer: r.answer ?? null,\n sourceTitle: r.source_title ?? null,\n sourceSite: r.source_site ?? null,\n })),\n organicResults: organic.map(r => ({\n position: Number(r.position) || 0,\n title: String(r.title ?? ''),\n url: String(r.url ?? ''),\n domain: String(r.domain ?? ''),\n snippet: r.snippet ?? null,\n })),\n aiOverview: aiOvw ? { detected: aiOvw.detected === true, text: aiOvw.text ?? null } : null,\n entityIds: entityIds\n ? { entities: entityIds.entities ?? [], kgIds: entityIds.kgIds ?? [], cids: entityIds.cids ?? [], gcids: entityIds.gcids ?? [] }\n : null,\n durationMs: durationMs ?? null,\n },\n }\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 EntityIdsData | undefined\n const aiOvw = d.aiOverview as AIOverview | undefined\n const diagnostics = d.diagnostics as HarvestDiagnostics | undefined\n\n const serpRows = organic.map(r =>\n `| ${r.position} | ${cell(r.title)} | [${cell(r.domain)}](${r.url}) | ${cell(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} | ${cell(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 = `# SERP Report: \"${input.query}\"${input.location ? ` · ${input.location}` : ''}\\n\\n${serpTable}${localSection}${entityIdsSection(entityIds)}${aiSection}${debugSection(diagnostics?.debug)}${tips}`\n\n return {\n ...oneBlock(full),\n structuredContent: {\n query: input.query,\n location: input.location ?? null,\n organicResults: organic.map(r => ({\n position: Number(r.position) || 0,\n title: String(r.title ?? ''),\n url: String(r.url ?? ''),\n domain: String(r.domain ?? ''),\n snippet: r.snippet ?? null,\n })),\n localPack: localPack.map(b => ({\n position: Number(b.position) || 0,\n name: String(b.name ?? ''),\n rating: b.rating ?? null,\n reviewCount: b.reviewCount ?? null,\n websiteUrl: b.websiteUrl ?? null,\n })),\n aiOverview: aiOvw ? { detected: aiOvw.detected === true, text: aiOvw.text ?? null } : null,\n entityIds: entityIds\n ? { entities: entityIds.entities ?? [], kgIds: entityIds.kgIds ?? [], cids: entityIds.cids ?? [], gcids: entityIds.gcids ?? [] }\n : null,\n },\n }\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 const screenshotMeta = d.screenshot as { base64: string; sizeBytes: number; device: string } | null | undefined\n const screenshotPath = screenshotMeta?.base64 ? persistScreenshotLocally(screenshotMeta.base64, url) : null\n const branding = d.branding as { colorScheme: string | null; colors: Record<string, string | null>; fonts: Record<string, string | null>; assets: Record<string, string | null> } | null | undefined\n const media = d.media as { outputDir: string | null; assets: unknown[]; filteredCount: number; totalFound: number } | null | undefined\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 to 3,000 of ${bodyMd.length.toLocaleString()} chars — full content in the saved report)*` : ''}`\n : ''\n const bodySectionFull = bodyMd ? `\\n## Page Content\\n${bodyMd}` : ''\n\n const mem = (d.memory as { deposited?: boolean; vault?: string; noteId?: string; chunks?: number; fileUrl?: string; fileExpiresAt?: string; error?: string } | null | undefined) ?? null\n const memSection = mem?.deposited\n ? `\\n## ✅ Saved to memory\\nFull content stored in vault \\`${mem.vault ?? '—'}\\` as note \\`${mem.noteId ?? '—'}\\`${mem.chunks !== undefined ? ` (${mem.chunks} chunks indexed)` : ''}. Recall it later with memory search — no need to re-scrape.`\n : mem?.fileUrl\n ? `\\n## 📄 Saved as a temporary file\\nMemory vault was unavailable${mem.error ? ` (${mem.error})` : ''}, so the full content was saved to a download link instead:\\n- **Link:** ${mem.fileUrl}\\n- **Expires:** ${mem.fileExpiresAt ?? 'in 24 hours'} (auto-deleted)`\n : mem\n ? `\\n## ⚠️ Memory deposit skipped\\n${mem.error ?? 'unknown error'} — the page content is still in the truncated preview above.`\n : ''\n\n const screenshotSection = screenshotMeta\n ? `\\n## Screenshot\\n- **File:** ${screenshotPath ?? '(returned inline only — disk write unavailable in this environment)'}\\n- **Size:** ${(screenshotMeta.sizeBytes / 1024).toFixed(1)} KB\\n- **Device:** ${screenshotMeta.device}`\n : ''\n\n const brandingSection = branding\n ? [\n `\\n## Branding`,\n branding.colorScheme ? `- **Color scheme:** ${branding.colorScheme}` : '',\n `- **Colors:**${Object.entries(branding.colors ?? {}).filter(([,v]) => v).map(([k,v]) => ` ${k}=${v}`).join(',') || ' (none extracted)'}`,\n `- **Fonts:**${Object.entries(branding.fonts ?? {}).filter(([,v]) => v).map(([k,v]) => ` ${k}=${v}`).join(',') || ' (none extracted)'}`,\n branding.assets?.logo ? `- **Logo:** ${branding.assets.logo}` : '',\n branding.assets?.favicon ? `- **Favicon:** ${branding.assets.favicon}` : '',\n ].filter(Boolean).join('\\n')\n : ''\n\n const mediaSection = media\n ? [\n `\\n## Media Assets`,\n `- **Found:** ${media.totalFound} total, ${media.filteredCount} filtered (ads/noise), ${media.assets.length} downloaded`,\n media.outputDir ? `- **Saved to:** ${media.outputDir}` : '',\n ].filter(Boolean).join('\\n')\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 = `# URL Extract: ${url}\\n**${title}**\\n${headingSection}${kpoSection}${brandingSection}${bodySection}${memSection}${screenshotSection}${mediaSection}${tips}`\n const diskReport = `# URL Extract: ${url}\\n**${title}**\\n${headingSection}${kpoSection}${brandingSection}${bodySectionFull}${memSection}${screenshotSection}${mediaSection}${tips}`\n\n const textResult = oneBlock(full, diskReport)\n const structuredContent = {\n url,\n title: (d.title as string | null) ?? null,\n headings: headings.map(h => ({ level: Number(h.level) || 0, text: String(h.text ?? '') })),\n schemaBlockCount: schemaCount,\n entityName: kpo?.entityName ?? null,\n entityTypes: kpo?.type ?? [],\n napScore: kpo?.napScore ?? null,\n missingSchemaFields: kpo?.missingFields ?? [],\n screenshotSaved: screenshotPath ?? null,\n branding: branding ?? null,\n mediaAssets: media?.assets ?? null,\n memory: mem ?? undefined,\n }\n\n if (screenshotMeta?.base64) {\n return {\n content: [\n ...(textResult.content),\n { type: 'image', data: screenshotMeta.base64, mimeType: 'image/png' },\n ],\n structuredContent,\n }\n }\n\n return { ...textResult, structuredContent }\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 isBulk = urls.length > BULK_URL_THRESHOLD\n const inventoryFile = isBulk ? saveUrlInventory(input.url, urls.map(u => ({ url: u.url, status: u.status ?? null }))) : null\n const inlineCount = isBulk ? BULK_URL_THRESHOLD : 200\n const urlRows = urls.slice(0, inlineCount).map((u, i) => `| ${i + 1} | ${u.url} | ${u.status ?? '—'} |`).join('\\n')\n\n const inventoryNote = isBulk\n ? inventoryFile\n ? `\\n## 📁 Full inventory saved\\n- **File:** \\`${inventoryFile}\\` (CSV: url, status — all ${urls.length} URLs)\\nShowing the first ${inlineCount} below; read the file for the complete list.`\n : `\\n## ⚠️ Full inventory not saved\\nReport saving is disabled, so only the first ${inlineCount} of ${urls.length} URLs are shown. Enable \\`MCP_SCRAPER_SAVE_REPORTS\\` to capture the full inventory.`\n : ''\n\n const full = [\n `# 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 inventoryNote,\n `\\n## URL Inventory${isBulk ? ` (first ${inlineCount} of ${urls.length})` : ''}\\n| # | URL | Status |\\n|---|-----|--------|\\n${urlRows}`,\n !isBulk && 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 return {\n ...oneBlock(full),\n structuredContent: {\n startUrl: d.startUrl ?? input.url,\n totalFound: d.totalFound ?? urls.length,\n truncated: d.truncated === true,\n okCount: ok.length,\n redirectCount: redirects.length,\n brokenCount: broken.length,\n inventoryFile: inventoryFile ?? null,\n urls: urls.map(u => ({ url: u.url, status: u.status ?? null })),\n durationMs: d.durationMs ?? 0,\n },\n }\n}\n\ninterface SitePageResult { url: string; title?: string | null; kpo?: KpoResult; schema?: unknown[]; bodyMarkdown?: string | null; metaDescription?: string | null }\ninterface ExtractSiteResult { pages: SitePageResult[]; durationMs?: number; branding?: unknown }\n\nfunction buildSeoExport(siteUrl: string, pages: PageData[], branding?: unknown): SeoExport {\n const { edges, metrics } = buildLinkGraph(pages, siteUrl)\n const pageRows = pages.map(p => {\n const { bodyMarkdown: _b, schema: _s, outlinks: _o, ...rest } = p\n const m = metrics.get(p.url)\n return { ...rest, inlinks: m?.inlinks ?? 0, crawlDepth: m?.crawlDepth ?? null, orphan: m?.orphan ?? false }\n })\n const issues = computeIssues(pages, metrics)\n return {\n pageRows: pageRows as unknown as Array<Record<string, unknown>>,\n edges: edges as unknown as Array<Record<string, unknown>>,\n metrics: [...metrics.values()] as unknown as Array<Record<string, unknown>>,\n issues,\n reportMd: renderIssueReport(siteUrl, pages, issues, metrics),\n linkReport: buildLinkReport(edges, [...metrics.values()], siteUrl),\n branding: branding ?? undefined,\n }\n}\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 schemaTypesOf = (p: SitePageResult) =>\n p.kpo?.type ?? (Array.isArray(p.schema) && p.schema.length ? [`${p.schema.length} block(s)`] : [])\n\n const pageRow = (p: SitePageResult, i: number) => {\n const schemaInfo = schemaTypesOf(p).join(', ') || '—'\n return `| ${i + 1} | ${cell(p.title ?? 'Untitled')} | ${p.url} | ${schemaInfo} |`\n }\n\n const tips = `\\n---\\n💡 **Tips**\\n- Map URLs first: use \\`map_site_urls\\`\\n- Inspect a single page: use \\`extract_url\\``\n const durationLine = `**${pages.length} pages** · ${(((d.durationMs ?? 0)) / 1000).toFixed(1)}s`\n\n const structuredContent = {\n url: input.url,\n pageCount: pages.length,\n pages: pages.map(p => ({\n url: String(p.url ?? ''),\n title: p.title ?? null,\n schemaTypes: schemaTypesOf(p),\n })),\n durationMs: d.durationMs ?? 0,\n }\n\n if (pages.length > BULK_PAGE_THRESHOLD) {\n const bulk = saveBulkSite(input.url, pages.map(p => ({\n url: String(p.url ?? ''),\n title: p.title ?? null,\n bodyMarkdown: p.bodyMarkdown ?? null,\n metaDescription: p.metaDescription ?? null,\n schemaTypes: schemaTypesOf(p),\n })))\n const preview = pages.slice(0, BULK_PAGE_THRESHOLD).map(pageRow).join('\\n')\n const location = bulk\n ? `\\n## 📁 Bulk scrape saved\\n- **Folder:** \\`${bulk.dir}\\` ← all scraped page content is here\\n- **Start here:** \\`${bulk.indexFile}\\` — lists every page and its file\\n- **Page content:** ${bulk.fileCount} Markdown files under \\`pages/\\` (one per page)\\n\\nThe page content is NOT inlined here to keep the context window clear — it is saved to disk. Open \\`index.md\\`, then open the page file you need from \\`pages/\\`.\\n\\n💡 Want the full technical SEO audit (headings, link graph, indexability, image sizes/formats, issues)? Run \\`audit_site\\` on this URL instead.`\n : `\\n## ⚠️ Bulk scrape not saved\\nReport saving is disabled in this environment, so the ${pages.length} pages of content could not be written to disk and are omitted to protect the context window. Enable \\`MCP_SCRAPER_SAVE_REPORTS\\` to capture bulk crawls.`\n const full = [\n `# Site Extract: ${input.url}`,\n durationLine,\n location,\n `\\n## Pages (first ${Math.min(BULK_PAGE_THRESHOLD, pages.length)} of ${pages.length})\\n| # | Title | URL | Schema |\\n|---|-------|-----|--------|\\n${preview}`,\n tips,\n ].join('\\n')\n return { content: [{ type: 'text', text: full }], structuredContent: { ...structuredContent, bulkFolder: bulk?.dir ?? null } }\n }\n\n const header = [\n `# Site Extract: ${input.url}`,\n durationLine,\n `\\n## Pages\\n| # | Title | URL | Schema |\\n|---|-------|-----|--------|\\n${pages.map(pageRow).join('\\n')}`,\n ].join('\\n')\n\n const full = `${header}${tips}`\n\n const pageDetails = pages.map((p, i) => {\n const body = (p.bodyMarkdown ?? '').trim()\n return [\n `\\n## ${i + 1}. ${p.title ?? 'Untitled'}`,\n `- **URL:** ${p.url}`,\n p.metaDescription ? `- **Description:** ${p.metaDescription}` : '',\n body ? `\\n${body}` : '_(no content extracted)_',\n ].filter(Boolean).join('\\n')\n }).join('\\n')\n\n const diskReport = `${header}\\n\\n---\\n# Full Page Content\\n${pageDetails}${tips}`\n\n return { ...oneBlock(full, diskReport), structuredContent }\n}\n\nexport async function formatAuditSite(raw: CallToolResult, input: { url: string }): Promise<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 const pages = d.pages ?? []\n const schemaTypesOf = (p: SitePageResult) =>\n p.kpo?.type ?? (Array.isArray(p.schema) && p.schema.length ? [`${p.schema.length} block(s)`] : [])\n\n const seo = buildSeoExport(input.url, pages as unknown as PageData[], d.branding)\n const imageAudit = await auditImages(pages as unknown as PageData[], { concurrency: 12 })\n const bulk = saveBulkSite(input.url, pages.map(p => ({\n url: String(p.url ?? ''),\n title: p.title ?? null,\n bodyMarkdown: p.bodyMarkdown ?? null,\n metaDescription: p.metaDescription ?? null,\n schemaTypes: schemaTypesOf(p),\n })), seo, imageAudit)\n\n const topIssues = Object.entries(seo.issues).sort((a, b) => b[1].count - a[1].count).slice(0, 8)\n .map(([k, v]) => `- \\`${k}\\` — ${v.count}`).join('\\n')\n const img = imageAudit.summary\n const imgLine = `${img.unique} images · ${img.totalSize} total · ${img.over100kb} over 100 KB · ${img.legacyFormat} legacy format`\n const lr = seo.linkReport.summary\n const topExt = lr.external.topDomains.slice(0, 3).map(dm => `${dm.domain} (${dm.links})`).join(', ') || '—'\n const linkLine = `${lr.internal.totalLinks} internal / ${lr.external.totalLinks} external links · ${lr.internal.orphans} orphans · ${lr.internal.brokenInternal} broken · avg ${lr.internal.avgInlinks} inlinks/page · top external: ${topExt}`\n const durationLine = `**${pages.length} pages** · ${(((d.durationMs ?? 0)) / 1000).toFixed(1)}s`\n\n const structuredContent = {\n url: input.url,\n pageCount: pages.length,\n durationMs: d.durationMs ?? 0,\n bulkFolder: bulk?.dir ?? null,\n issues: Object.fromEntries(Object.entries(seo.issues).map(([k, v]) => [k, v.count])),\n images: { unique: img.unique, totalBytes: img.totalBytes, over100kb: img.over100kb, legacyFormat: img.legacyFormat },\n links: { internal: lr.internal.totalLinks, external: lr.external.totalLinks, orphans: lr.internal.orphans, brokenInternal: lr.internal.brokenInternal, externalDomains: lr.external.uniqueDomains },\n }\n\n const location = bulk\n ? `\\n## 📁 Technical audit saved\\n- **Folder:** \\`${bulk.dir}\\` ← full audit + page content here\\n- **Start here:** \\`${bulk.indexFile}\\` — maps every file in the folder\\n- **Data:** \\`report.md\\` (issues + image audit), \\`issues.json\\`, \\`pages.jsonl\\` (per-page fields), \\`links.jsonl\\`, \\`link-metrics.jsonl\\`, \\`images.jsonl\\`\\n\\nDetail is saved to disk, not inlined. Open \\`report.md\\` for the audit, \\`pages.jsonl\\` for per-page fields (headings, canonical, indexability), \\`images.jsonl\\` for image sizes/formats.`\n : `\\n## ⚠️ Audit not saved\\nReport saving is disabled in this environment. Enable \\`MCP_SCRAPER_SAVE_REPORTS\\` to capture the technical audit.`\n\n const full = [\n `# Technical SEO Audit: ${input.url}`,\n durationLine,\n location,\n `\\n## Top issues\\n${topIssues || '_none found_'}`,\n `\\n## Links\\n${linkLine}`,\n `\\n## Images\\n${imgLine}`,\n ].join('\\n')\n return { content: [{ type: 'text', text: full }], structuredContent }\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} | ${cell(truncate(v.title, 70))} | ${cell(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 `# 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 return {\n ...oneBlock(full),\n structuredContent: {\n mode: input.mode,\n videoCount: videos.length,\n channel: d.channelMeta\n ? { title: d.channelMeta.title ?? null, subscriberCount: d.channelMeta.subscriberCount ?? null }\n : null,\n videos: videos.map(v => ({\n videoId: String(v.videoId ?? ''),\n title: String(v.title ?? ''),\n channelName: v.channelName ?? null,\n views: v.views ?? null,\n duration: v.duration ?? null,\n url: v.url ?? null,\n })),\n },\n }\n}\n\ninterface TranscriptChunk { timestamp: [number, number]; text: string }\ninterface TranscriptResult { videoId?: string | null; text: string; chunks?: TranscriptChunk[]; durationMs?: number }\n\nfunction structuredTranscriptChunks(chunks: TranscriptChunk[]): Array<{ startSec: number; endSec: number; text: string }> {\n return chunks.map(c => ({\n startSec: Number.isFinite(c.timestamp?.[0]) ? c.timestamp[0] : 0,\n endSec: Number.isFinite(c.timestamp?.[1]) ? c.timestamp[1] : 0,\n text: c.text,\n }))\n}\n\nfunction wordCount(text: string): number {\n return text.trim() ? text.trim().split(/\\s+/).length : 0\n}\n\nexport function formatYoutubeTranscribe(raw: CallToolResult, input: { videoId?: string; 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 TranscriptResult\n\n const text = d.text ?? ''\n const chunks = d.chunks ?? []\n const videoId = d.videoId ?? input.videoId ?? null\n const durSec = d.durationMs ? (d.durationMs / 1000).toFixed(0) : '—'\n const words = wordCount(text)\n\n const chunkRows = chunks.slice(0, 50).map(c => {\n const sec = Number.isFinite(c.timestamp[0]) ? Math.floor(c.timestamp[0]) : 0\n const mm = String(Math.floor(sec / 60)).padStart(2, '0')\n const ss = String(sec % 60).padStart(2, '0')\n return `| ${mm}:${ss} | ${cell(truncate(c.text, 120))} |`\n }).join('\\n')\n\n const full = [\n `# YouTube Transcript: \\`${videoId ?? input.url ?? 'video'}\\``,\n `**Duration:** ${durSec}s · **${words} 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 return {\n ...oneBlock(full),\n structuredContent: {\n videoId,\n url: videoId ? `https://www.youtube.com/watch?v=${videoId}` : input.url ?? null,\n wordCount: words,\n chunkCount: chunks.length,\n durationMs: typeof d.durationMs === 'number' ? d.durationMs : null,\n transcriptText: text,\n chunks: structuredTranscriptChunks(chunks),\n resolvedInputs: {\n videoId,\n url: input.url ?? null,\n },\n },\n }\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; started?: string | null\n landingUrl?: string | null; domain?: string | null\n videoUrl?: string | null; videoSrc?: string | null\n imageUrl?: string | null; imageSrc?: string | null; videoPoster?: string | null\n variations?: number; clusterCount?: number | null\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 ?? ad.started ?? '—'}`,\n ad.headline ? `**Headline:** ${ad.headline}` : '',\n ad.primaryText ? `**Copy:** ${truncate(ad.primaryText, 200)}` : '',\n ad.cta ? `**CTA:** ${ad.cta}` : '',\n ad.landingUrl ? `**Landing URL:** ${ad.landingUrl}` : '',\n (ad.videoUrl ?? ad.videoSrc) ? `**Video URL:** \\`${ad.videoUrl ?? ad.videoSrc}\\`` : '',\n (ad.variations ?? ad.clusterCount) ? `**Variations:** ${ad.variations ?? ad.clusterCount}` : '',\n ].filter(Boolean).join('\\n')).join('\\n\\n---\\n\\n')\n\n const full = [\n `# 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 direct \\`videoUrl\\` above\\n- Transcribe organic Facebook reels/posts: use \\`facebook_video_transcribe\\` with the public Facebook URL\\n- Find other advertisers: use \\`facebook_ad_search\\``,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n advertiserName: d.advertiserName ?? null,\n totalAds: s.totalAds ?? 0,\n activeCount: s.activeCount ?? 0,\n videoCount: s.videoCount ?? 0,\n imageCount: s.imageCount ?? 0,\n ads: ads.map(ad => ({\n libraryId: ad.libraryId ?? null,\n status: ad.status ?? null,\n creativeType: ad.creativeType ?? null,\n primaryText: ad.primaryText ?? null,\n headline: ad.headline ?? null,\n cta: ad.cta ?? null,\n startDate: ad.startDate ?? ad.started ?? null,\n landingUrl: ad.landingUrl ?? null,\n domain: ad.domain ?? null,\n videoUrl: ad.videoUrl ?? ad.videoSrc ?? null,\n imageUrl: ad.imageUrl ?? ad.imageSrc ?? null,\n videoPoster: ad.videoPoster ?? null,\n variations: typeof ad.variations === 'number'\n ? ad.variations\n : typeof ad.clusterCount === 'number'\n ? ad.clusterCount\n : null,\n })),\n },\n }\n}\n\ninterface FbAdvertiserResult { name?: string; pageName?: string; pageId?: string; pageUrl?: string; adCount?: number; libraryId?: string; sampleLibraryId?: string }\ninterface FbSearchResult { results?: FbAdvertiserResult[]; advertisers?: FbAdvertiserResult[] }\n\nexport function formatRedditThread(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 {\n title?: string; author?: string; score?: string; postBody?: string; numComments?: number\n comments?: Array<{ author?: string; score?: string; depth?: number; body?: string }>\n sourceUrl?: string; oldRedditUrl?: string\n }\n const comments = d.comments ?? []\n const commentMd = comments.map(cm => {\n const indent = ' '.repeat(Math.min(Number(cm.depth ?? 0), 6))\n return `${indent}- **u/${cm.author || '[unknown]'}** (${cm.score || '—'}): ${(cm.body || '').replace(/\\s+/g, ' ').trim()}`\n }).join('\\n')\n const full = [\n `# ${d.title || 'Reddit thread'}`,\n `**u/${d.author || '[unknown]'}** · ${d.score || '—'} · ${comments.length} comments captured`,\n d.postBody ? `\\n${d.postBody}` : '',\n `\\n## Comments\\n${commentMd || '_No comments captured._'}`,\n ].join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n sourceUrl: d.sourceUrl ?? input.url ?? null,\n oldRedditUrl: d.oldRedditUrl ?? null,\n title: d.title ?? null,\n author: d.author ?? null,\n score: d.score ?? null,\n postBody: d.postBody ?? null,\n numComments: comments.length,\n comments: comments.map(cm => ({ author: cm.author ?? null, score: cm.score ?? null, depth: Number(cm.depth ?? 0), body: cm.body ?? '' })),\n },\n }\n}\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} | ${cell(a.pageName ?? a.name)} | ${a.adCount ?? '—'} | \\`${a.sampleLibraryId ?? a.libraryId ?? '—'}\\` |`,\n ).join('\\n')\n\n const full = [\n `# 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 return {\n ...oneBlock(full),\n structuredContent: {\n query: input.query,\n advertiserCount: advertisers.length,\n advertisers: advertisers.map(a => ({\n name: a.pageName ?? a.name ?? null,\n pageId: a.pageId ?? null,\n pageUrl: a.pageUrl ?? null,\n adCount: typeof a.adCount === 'number' ? a.adCount : null,\n libraryId: a.sampleLibraryId ?? a.libraryId ?? null,\n sampleLibraryId: a.sampleLibraryId ?? null,\n })),\n },\n }\n}\n\ninterface MapsReviewCard { author: string | null; stars: string | null; date: string | null; text: string | null }\ntype ReviewsStatus = 'collected' | 'none_exist' | 'unavailable' | 'not_requested'\ninterface MapsHistogramEntry { stars: number; count: string }\ninterface MapsTopicEntry { label: string; count: string }\ninterface MapsAboutEntry { section: string; attribute: string }\ninterface MapsSearchBusiness {\n position: number\n name: string\n placeUrl: string\n cid: string | null\n cidDecimal: string | null\n rating: string | null\n reviewCount: string | null\n category: string | null\n address: string | null\n phone: string | null\n hoursStatus: string | null\n websiteUrl: string | null\n directionsUrl: string | null\n metadata: string[]\n}\ninterface MapsSearchAttempt {\n attemptNumber?: number\n attempt_number?: number\n maxAttempts?: number\n max_attempts?: number\n status?: 'ok' | 'failed'\n outcome?: string\n willRetry?: boolean\n will_retry?: boolean\n durationMs?: number\n duration_ms?: number\n resultCount?: number\n result_count?: number\n error?: string | null\n proxyMode?: 'location' | 'configured' | 'none'\n proxy_mode?: 'location' | 'configured' | 'none'\n proxyResolutionSource?: string | null\n proxy_resolution_source?: string | null\n proxyIdSuffix?: string | null\n proxy_id_suffix?: string | null\n proxyTargetLevel?: 'zip' | 'city' | 'state' | null\n proxy_target_level?: 'zip' | 'city' | 'state' | null\n proxyTargetLocation?: string | null\n proxy_target_location?: string | null\n proxyTargetZip?: string | null\n proxy_target_zip?: string | null\n browserSessionIdSuffix?: string | null\n browser_session_id?: string | null\n observedIp?: string | null\n observed_ip?: string | null\n observedCity?: string | null\n observed_city?: string | null\n observedRegion?: string | null\n observed_region?: string | null\n}\ninterface DirectoryWorkflowCity {\n city: string\n state: string\n location: string\n cityKey: string\n censusName: string\n population: number\n populationYear: number\n zips: string[]\n counties: string[]\n status: 'ok' | 'empty' | 'failed'\n error: string | null\n resultCount: number\n durationMs: number\n attempts?: MapsSearchAttempt[]\n results: MapsSearchBusiness[]\n}\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\nfunction normalizeMapsAttempts(value: unknown): Array<{\n attemptNumber: number\n maxAttempts: number\n status: 'ok' | 'failed'\n outcome: string\n willRetry: boolean\n durationMs: number\n resultCount: number\n error: string | null\n proxyMode: 'location' | 'configured' | 'none'\n proxyResolutionSource: string | null\n proxyIdSuffix: string | null\n proxyTargetLevel: 'zip' | 'city' | 'state' | null\n proxyTargetLocation: string | null\n proxyTargetZip: string | null\n browserSessionIdSuffix: string | null\n observedIp: string | null\n observedCity: string | null\n observedRegion: string | null\n}> {\n const attempts = Array.isArray(value) ? value as MapsSearchAttempt[] : []\n return attempts.map((attempt, index) => ({\n attemptNumber: attempt.attemptNumber ?? attempt.attempt_number ?? index + 1,\n maxAttempts: attempt.maxAttempts ?? attempt.max_attempts ?? attempts.length,\n status: attempt.status === 'ok' ? 'ok' : 'failed',\n outcome: attempt.outcome ?? attempt.status ?? 'unknown',\n willRetry: attempt.willRetry ?? attempt.will_retry ?? false,\n durationMs: attempt.durationMs ?? attempt.duration_ms ?? 0,\n resultCount: attempt.resultCount ?? attempt.result_count ?? 0,\n error: attempt.error ? sanitizeVendorText(attempt.error) : null,\n proxyMode: attempt.proxyMode ?? attempt.proxy_mode ?? 'location',\n proxyResolutionSource: attempt.proxyResolutionSource ?? attempt.proxy_resolution_source ?? null,\n proxyIdSuffix: attempt.proxyIdSuffix ?? attempt.proxy_id_suffix ?? null,\n proxyTargetLevel: attempt.proxyTargetLevel ?? attempt.proxy_target_level ?? null,\n proxyTargetLocation: attempt.proxyTargetLocation ?? attempt.proxy_target_location ?? null,\n proxyTargetZip: attempt.proxyTargetZip ?? attempt.proxy_target_zip ?? null,\n browserSessionIdSuffix: attempt.browserSessionIdSuffix ?? attempt.browser_session_id ?? null,\n observedIp: attempt.observedIp ?? attempt.observed_ip ?? null,\n observedCity: attempt.observedCity ?? attempt.observed_city ?? null,\n observedRegion: attempt.observedRegion ?? attempt.observed_region ?? null,\n }))\n}\n\nfunction workflowArtifactsFrom(run: Record<string, unknown> | undefined): Array<Record<string, unknown>> {\n return Array.isArray(run?.artifacts) ? run.artifacts as Array<Record<string, unknown>> : []\n}\n\nfunction workflowArtifactRows(artifacts: Array<Record<string, unknown>>): string {\n if (!artifacts.length) return ''\n return [\n '| Artifact | Type | ID | Rows/Bytes |',\n '|---|---|---|---|',\n ...artifacts.map(artifact => {\n const rows = artifact.rows_count ?? artifact.rows ?? ''\n const bytes = artifact.bytes ?? ''\n const size = [rows ? `${rows} rows` : '', bytes ? `${bytes} bytes` : ''].filter(Boolean).join(' / ')\n return `| ${cell(String(artifact.label ?? artifact.path ?? 'artifact'))} | ${cell(String(artifact.kind ?? artifact.content_type ?? 'file'))} | \\`${String(artifact.id ?? '')}\\` | ${cell(size || '—')} |`\n }),\n ].join('\\n')\n}\n\nexport function formatWorkflowList(raw: CallToolResult, input: { includeRecipes?: boolean }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const workflows = Array.isArray(parsed.data.workflows) ? parsed.data.workflows as Array<Record<string, unknown>> : []\n const workflowRows = [\n '| Workflow ID | Title | Use |',\n '|---|---|---|',\n ...workflows.map(workflow => `| \\`${String(workflow.id ?? '')}\\` | ${cell(String(workflow.title ?? ''))} | ${cell(String(workflow.description ?? ''))} |`),\n ].join('\\n')\n const recipes = input.includeRecipes === false ? [] : WORKFLOW_RECIPES\n const full = [\n '# MCP Scraper Workflows',\n 'Use `workflow_suggest` when the user describes a high-level job. Use `workflow_run` when the workflow id and input are known. Use `workflow_status` and `workflow_artifact_read` to inspect completed runs and pull evidence back into context.',\n workflows.length ? `\\n## Runnable Workflows\\n${workflowRows}` : '',\n recipes.length ? `\\n## High-Level Recipes\\n${workflowRecipeTable(recipes)}` : '',\n recipes.length ? '\\nThese recipes cover market analysis, ICP research, forum and review acquisition, brand design briefings, CRO audits, competitive positioning, content gaps, and AI search visibility audits.' : '',\n ].filter(Boolean).join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n workflows: workflows.map(workflow => ({\n id: String(workflow.id ?? ''),\n title: String(workflow.title ?? ''),\n description: String(workflow.description ?? ''),\n })),\n recipes,\n },\n }\n}\n\nexport function formatWorkflowSuggest(input: { goal: string; maxSuggestions?: number }): CallToolResult {\n const suggestions = suggestWorkflowRecipes(input.goal, input.maxSuggestions ?? 3)\n const full = [\n `# Workflow Suggestions`,\n `**Goal:** ${input.goal}`,\n '',\n workflowRecipeTable(suggestions),\n '',\n '## How To Execute',\n '1. Pick the closest recipe.',\n '2. If it has a `primaryWorkflowId`, call `workflow_run` with that id and the required inputs.',\n '3. After the run completes, use `workflow_artifact_read` on the most relevant CSV/JSON/Markdown artifacts before writing the final answer.',\n ].join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n goal: input.goal,\n suggestions,\n },\n }\n}\n\nfunction workflowStepLines(data: Record<string, unknown>): string[] {\n const step = data.step as Record<string, unknown> | undefined\n const nextStep = data.nextStep as Record<string, unknown> | null | undefined\n const done = data.done === true\n const lines: string[] = []\n if (step) {\n const index = Number(step.index ?? 0)\n const totalSteps = step.totalSteps != null ? Number(step.totalSteps) : undefined\n const stepLabel = totalSteps ? `${index + 1}/${totalSteps}` : `${index + 1}`\n lines.push(`\\n## Step ${stepLabel}: ${step.title ?? step.id ?? ''}`)\n const output = step.output as Record<string, unknown> | undefined\n if (output && Object.keys(output).length) {\n lines.push(Object.entries(output).map(([k, v]) => `- ${k}: ${typeof v === 'object' ? JSON.stringify(v) : String(v)}`).join('\\n'))\n }\n const warnings = Array.isArray(step.warnings) ? step.warnings as string[] : []\n if (warnings.length) lines.push(`\\n**Warnings:**\\n${warnings.map(w => `- ${w}`).join('\\n')}`)\n }\n if (done) {\n lines.push('\\n**Done.** All steps complete.')\n } else if (nextStep && typeof nextStep === 'object') {\n lines.push(`\\n**Next step:** \\`${nextStep.id ?? nextStep.index}\\` — call \\`workflow_step\\` with this run id to continue.`)\n }\n return lines\n}\n\nexport function formatWorkflowRun(raw: CallToolResult, input: { workflowId: string; input?: Record<string, unknown> }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const run = parsed.data.run as Record<string, unknown> | undefined\n const summary = parsed.data.summary as Record<string, unknown> | undefined\n const artifacts = workflowArtifactsFrom(run)\n const runId = String(run?.id ?? '')\n const status = String(run?.status ?? summary?.status ?? 'unknown')\n const full = [\n `# Workflow Run: ${input.workflowId}`,\n `**Run ID:** \\`${runId || 'unknown'}\\``,\n `**Status:** ${status}`,\n summary?.title ? `**Title:** ${summary.title}` : '',\n ...workflowStepLines(parsed.data),\n summary?.summary ? `\\n## Summary\\n${summary.summary}` : '',\n artifacts.length ? `\\n## Artifacts\\n${workflowArtifactRows(artifacts)}` : '',\n artifacts.length ? '\\nUse `workflow_artifact_read` with the run id and artifact id to pull CSV, JSON, Markdown, or report content into context.' : '',\n ].filter(Boolean).join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n workflowId: input.workflowId,\n input: input.input ?? {},\n run,\n summary,\n step: parsed.data.step,\n nextStep: parsed.data.nextStep ?? null,\n done: parsed.data.done === true,\n artifacts,\n },\n }\n}\n\nexport function formatWorkflowStep(raw: CallToolResult, input: { runId: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const run = parsed.data.run as Record<string, unknown> | undefined\n const summary = parsed.data.summary as Record<string, unknown> | undefined\n const artifacts = workflowArtifactsFrom(run)\n const done = parsed.data.done === true\n const full = [\n `# Workflow Step`,\n `**Run ID:** \\`${input.runId}\\``,\n `**Status:** ${run?.status ?? (done ? 'done' : 'running')}`,\n ...workflowStepLines(parsed.data),\n done && summary?.summary ? `\\n## Summary\\n${summary.summary}` : '',\n artifacts.length ? `\\n## Artifacts\\n${workflowArtifactRows(artifacts)}` : '',\n done && artifacts.length ? '\\nUse `workflow_artifact_read` with the run id and artifact id to pull CSV, JSON, Markdown, or report content into context.' : '',\n ].filter(Boolean).join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n runId: input.runId,\n run,\n summary: summary ?? null,\n step: parsed.data.step,\n nextStep: parsed.data.nextStep ?? null,\n done,\n artifacts,\n },\n }\n}\n\nexport function formatWorkflowStatus(raw: CallToolResult, input: { runId: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const run = parsed.data.run as Record<string, unknown> | undefined\n const artifacts = workflowArtifactsFrom(run)\n const full = [\n `# Workflow Status`,\n `**Run ID:** \\`${input.runId}\\``,\n `**Workflow:** ${run?.workflow_id ?? 'unknown'}`,\n `**Status:** ${run?.status ?? 'unknown'}`,\n run?.error_message ? `\\n## Error\\n${run.error_message}` : '',\n artifacts.length ? `\\n## Artifacts\\n${workflowArtifactRows(artifacts)}` : '',\n ].filter(Boolean).join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n run,\n artifacts,\n },\n }\n}\n\nexport function formatWorkflowArtifactRead(raw: CallToolResult, input: { runId: string; artifactId: string; maxBytes?: number }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const text = typeof parsed.data.text === 'string' ? parsed.data.text : ''\n const contentType = String(parsed.data.contentType ?? 'text/plain')\n const bytes = Number(parsed.data.bytes ?? 0)\n const truncated = parsed.data.truncated === true\n const full = [\n `# Workflow Artifact`,\n `**Run ID:** \\`${input.runId}\\``,\n `**Artifact ID:** \\`${input.artifactId}\\``,\n `**Content-Type:** ${contentType}`,\n `**Bytes:** ${bytes}${truncated ? ` (truncated to ${input.maxBytes ?? 200000})` : ''}`,\n '',\n '```',\n text,\n '```',\n ].join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n runId: input.runId,\n artifactId: input.artifactId,\n contentType,\n bytes,\n truncated,\n text,\n },\n }\n}\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 const concurrencyRaw = d.concurrency as Record<string, unknown> | undefined\n const upgradeRaw = concurrencyRaw?.upgrade as Record<string, unknown> | 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 concurrencySection = concurrencyRaw\n ? [\n `\\n## Concurrency`,\n `**Current limit:** ${concurrencyRaw.current_limit ?? 'unknown'} concurrent operation${concurrencyRaw.current_limit === 1 ? '' : 's'}`,\n `**Extra slots:** ${concurrencyRaw.current_extra_slots ?? 'unknown'}`,\n `**Extra concurrency slot:** ${upgradeRaw?.price_label ?? '$5/month'}`,\n `**Upgrade in terminal:** \\`${upgradeRaw?.terminal_command ?? 'npx -y -p mcp-scraper@latest mcp-scraper-cli billing concurrency checkout'}\\``,\n `**Billing URL:** ${upgradeRaw?.billing_url ?? 'https://mcpscraper.dev/billing'}`,\n ].join('\\n')\n : ''\n\n const full = [\n `# Credits`,\n `**Balance:** ${balance ?? 'unknown'} credits`,\n matchedSection,\n concurrencySection,\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 return {\n ...oneBlock(full),\n structuredContent: {\n balanceCredits: typeof balance === 'number' ? balance : null,\n matchedCost: matched\n ? { label: matched.label, credits: matched.credits, unit: matched.unit, notes: matched.notes ?? null }\n : null,\n costs: costs.map(c => ({\n key: c.key,\n label: c.label,\n credits: c.credits,\n unit: c.unit,\n notes: c.notes ?? null,\n })),\n ledger: ledger.map(row => ({\n createdAt: String(row.created_at ?? ''),\n operation: String(row.operation ?? ''),\n credits: row.amount_mc / 1000,\n description: row.description ?? null,\n })),\n concurrency: concurrencyRaw && upgradeRaw\n ? {\n currentExtraSlots: Number(concurrencyRaw.current_extra_slots ?? 0),\n currentLimit: Number(concurrencyRaw.current_limit ?? 1),\n hasSubscription: concurrencyRaw.has_subscription === true,\n upgrade: {\n product: String(upgradeRaw.product ?? 'Extra concurrency slot'),\n priceLabel: String(upgradeRaw.price_label ?? '$5/month'),\n unitAmountUsd: Number(upgradeRaw.unit_amount_usd ?? 5),\n currency: String(upgradeRaw.currency ?? 'usd'),\n interval: String(upgradeRaw.interval ?? 'month'),\n billingUrl: String(upgradeRaw.billing_url ?? 'https://mcpscraper.dev/billing'),\n terminalCommand: String(upgradeRaw.terminal_command ?? 'npx -y -p mcp-scraper@latest mcp-scraper-cli billing concurrency checkout'),\n terminalCommandWithApiKeyEnv: String(upgradeRaw.terminal_command_with_api_key_env ?? 'MCP_SCRAPER_API_KEY=sk_live_your_key npx -y -p mcp-scraper@latest mcp-scraper-cli billing concurrency checkout'),\n },\n }\n : null,\n },\n }\n}\n\nexport function formatMapsSearch(\n raw: CallToolResult,\n input: { query: string; location?: string; maxResults?: number },\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 const results = (d.results as MapsSearchBusiness[]) ?? []\n const normalizedResults = results.map(result => ({\n ...result,\n phone: result.phone ?? null,\n hoursStatus: result.hoursStatus ?? null,\n }))\n const searchQuery = (d.searchQuery as string | undefined) ?? [input.query, input.location].filter(Boolean).join(' ')\n const requestedMax = (d.requestedMaxResults as number | undefined) ?? input.maxResults ?? 10\n const durationMs = d.durationMs as number | undefined\n const attempts = normalizeMapsAttempts(d.attempts)\n const lastAttempt = attempts.at(-1)\n\n const rows = results.map((r) => {\n const rating = [r.rating, r.reviewCount ? `(${r.reviewCount})` : null].filter(Boolean).join(' ')\n return `| ${r.position} | ${cell(r.name)} | ${cell(r.category)} | ${cell(rating)} | ${cell(r.address)} | ${r.cidDecimal ? `\\`${r.cidDecimal}\\`` : '—'} | ${r.websiteUrl ? `[site](${r.websiteUrl})` : '—'} | [maps](${r.placeUrl}) |`\n }).join('\\n')\n\n const metadataSection = results.length\n ? `\\n## Candidate Metadata\\n${results.map(r => {\n const meta = r.metadata?.length ? r.metadata.slice(0, 8).map(m => ` - ${m}`).join('\\n') : ' - none'\n return `### ${r.position}. ${r.name}\\n${meta}`\n }).join('\\n\\n')}`\n : ''\n\n const full = [\n `# Google Maps Search: \"${searchQuery}\"`,\n `**Returned:** ${results.length} profile candidate${results.length === 1 ? '' : 's'} · **Requested max:** ${requestedMax} · **Limit:** 50`,\n attempts.length ? `**Attempts:** ${attempts.length}/${lastAttempt?.maxAttempts ?? attempts.length} · **Proxy:** ${lastAttempt?.proxyMode ?? 'unknown'}${lastAttempt?.proxyResolutionSource ? `/${lastAttempt.proxyResolutionSource}` : ''} · **Observed:** ${[lastAttempt?.observedCity, lastAttempt?.observedRegion].filter(Boolean).join(', ') || 'unknown'}` : null,\n `\\n## Results\\n| # | Name | Category | Rating | Address | CID | Website | Maps |\\n|---|------|----------|--------|---------|-----|---------|------|\\n${rows}`,\n metadataSection,\n `\\n---\\n💡 **Next step:** use \\`maps_place_intel\\` with a selected business name and location to hydrate full hours, phone, review topics, and optional review cards.`,\n durationMs != null ? `\\n*Extracted in ${(durationMs / 1000).toFixed(1)}s*` : null,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n query: d.query,\n location: d.location ?? null,\n searchQuery: d.searchQuery,\n searchUrl: d.searchUrl,\n extractedAt: d.extractedAt,\n requestedMaxResults: requestedMax,\n resultCount: results.length,\n results: normalizedResults,\n attempts,\n durationMs: durationMs ?? 0,\n },\n }\n}\n\nexport function formatDirectoryWorkflow(\n raw: CallToolResult,\n input: { query: string; state?: string; minPopulation?: number; maxResultsPerCity?: number },\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 const cities = ((d.cities as DirectoryWorkflowCity[]) ?? []).map(city => ({\n ...city,\n attempts: normalizeMapsAttempts(city.attempts),\n results: city.results.map(result => ({\n ...result,\n phone: result.phone ?? null,\n hoursStatus: result.hoursStatus ?? null,\n })),\n }))\n const warnings = (d.warnings as string[] | undefined) ?? []\n const csvPath = (d.csvPath as string | null | undefined) ?? null\n const totalResultCount = (d.totalResultCount as number | undefined) ?? cities.reduce((sum, city) => sum + city.resultCount, 0)\n const durationMs = d.durationMs as number | undefined\n\n const marketRows = cities.map((city) => {\n const zips = city.zips?.length ? city.zips.slice(0, 8).join(' ') + (city.zips.length > 8 ? ` +${city.zips.length - 8}` : '') : '—'\n return `| ${cell(city.city)} | ${city.population.toLocaleString()} | ${city.zips?.length ?? 0} | ${city.resultCount} | ${city.status} | ${cell(zips)} |`\n }).join('\\n')\n\n const businessRows = cities\n .flatMap(city => city.results.slice(0, 3).map(result => ({ city, result })))\n .map(({ city, result }) => {\n const rating = [result.rating, result.reviewCount ? `(${result.reviewCount})` : null].filter(Boolean).join(' ')\n return `| ${cell(city.city)} | ${result.position} | ${cell(result.name)} | ${cell(result.category)} | ${cell(rating)} | ${result.websiteUrl ? `[site](${result.websiteUrl})` : '—'} | [maps](${result.placeUrl}) |`\n }).join('\\n')\n\n const warningText = warnings.length ? `\\n## Warnings\\n${warnings.map(w => `- ${w}`).join('\\n')}` : ''\n const csvText = csvPath ? `\\n**CSV:** \\`${csvPath}\\`` : ''\n const full = [\n `# Directory Workflow: ${input.query}`,\n `**Markets:** ${cities.length} · **Maps results:** ${totalResultCount} · **State:** ${d.state ?? input.state ?? 'US'} · **Population threshold:** ${d.minPopulation ?? input.minPopulation ?? 100000}`,\n csvText,\n `\\n## Markets\\n| City | Population | ZIPs | Maps Results | Status | ZIP Sample |\\n|---|---:|---:|---:|---|---|\\n${marketRows}`,\n businessRows ? `\\n## Top Candidates By City\\n| City | # | Name | Category | Rating | Website | Maps |\\n|---|---:|---|---|---|---|---|\\n${businessRows}` : null,\n warningText,\n `\\n## Sources\\n- Population: ${d.censusSourceUrl ?? 'Census Population Estimates Program'}\\n- ZIP groups: ${d.usZipsSourcePath ?? 'not configured'}`,\n durationMs != null ? `\\n*Completed in ${(durationMs / 1000).toFixed(1)}s*` : null,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n query: d.query,\n state: d.state,\n minPopulation: d.minPopulation,\n populationYear: d.populationYear,\n maxResultsPerCity: d.maxResultsPerCity,\n concurrency: d.concurrency,\n censusSourceUrl: d.censusSourceUrl,\n usZipsSourcePath: d.usZipsSourcePath ?? null,\n warnings,\n extractedAt: d.extractedAt,\n selectedCityCount: d.selectedCityCount,\n totalResultCount,\n csvPath,\n cities,\n durationMs: durationMs ?? 0,\n },\n }\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 const reviewsStatus = (d.reviewsStatus as ReviewsStatus | undefined) ?? 'not_requested'\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 = (() => {\n if (reviewsStatus === 'not_requested') return ''\n if (reviewsStatus === 'unavailable') return '\\n## Reviews\\n> Reviews could not be retrieved this run — retry with `includeReviews: true`.'\n if (reviewsStatus === 'none_exist') return '\\n## Reviews\\n*This business has no reviews on Google Maps.*'\n if (reviews.length === 0) return '\\n## Reviews\\n*0 reviews collected.*'\n return `\\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 `# ${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 return {\n ...oneBlock(full),\n structuredContent: {\n name,\n rating: rating ?? null,\n reviewCount: reviewCount ?? null,\n category: category ?? null,\n address: address ?? null,\n phone: phone ?? null,\n website: website ?? null,\n hoursSummary: hoursSummary ?? null,\n bookingUrl: bookingUrl ?? null,\n kgmid: kgmid ?? null,\n cidDecimal: cidDecimal ?? null,\n cidUrl: cidUrl ?? null,\n lat: lat ?? null,\n lng: lng ?? null,\n reviewsStatus,\n reviewsCollected: reviews.length,\n reviewTopics: topics.map(t => ({ label: String(t.label ?? ''), count: String(t.count ?? '') })),\n },\n }\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 const words = wordCount(text)\n\n const chunkRows = chunks.slice(0, 50).map(c => {\n const sec = Number.isFinite(c.timestamp[0]) ? Math.floor(c.timestamp[0]) : 0\n const mm = String(Math.floor(sec / 60)).padStart(2, '0')\n const ss = String(sec % 60).padStart(2, '0')\n return `| ${mm}:${ss} | ${cell(truncate(c.text, 120))} |`\n }).join('\\n')\n\n const full = [\n `# Facebook Ad Transcript`,\n `**Duration:** ${durSec}s · **${words} 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\\`. For public Facebook reel/post URLs, use \\`facebook_video_transcribe\\`.`,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n videoUrl: input.videoUrl,\n wordCount: words,\n chunkCount: chunks.length,\n durationMs: typeof d.durationMs === 'number' ? d.durationMs : null,\n transcriptText: text,\n chunks: structuredTranscriptChunks(chunks),\n resolvedInputs: {\n videoUrl: input.videoUrl,\n },\n },\n }\n}\n\ninterface FacebookVideoTranscriptResult extends TranscriptResult {\n sourceUrl?: string\n pageUrl?: string\n videoId?: string | null\n ownerName?: string | null\n selectedQuality?: string\n bitrate?: number | null\n videoDurationSec?: number | null\n videoUrl?: string\n}\n\nexport function formatFacebookVideoTranscribe(raw: CallToolResult, input: { url: string; quality?: 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 FacebookVideoTranscriptResult\n\n const text = d.text ?? ''\n const chunks = d.chunks ?? []\n const wordCount = text.trim() ? text.trim().split(/\\s+/).length : 0\n const durSec = d.durationMs ? (d.durationMs / 1000).toFixed(0) : '—'\n const videoDuration = typeof d.videoDurationSec === 'number' ? `${Math.round(d.videoDurationSec)}s` : '—'\n const label = d.videoId ? `Facebook Organic Video \\`${d.videoId}\\`` : 'Facebook Organic Video'\n\n const chunkRows = chunks.slice(0, 50).map(c => {\n const sec = Number.isFinite(c.timestamp[0]) ? Math.floor(c.timestamp[0]) : 0\n const mm = String(Math.floor(sec / 60)).padStart(2, '0')\n const ss = String(sec % 60).padStart(2, '0')\n return `| ${mm}:${ss} | ${cell(truncate(c.text, 120))} |`\n }).join('\\n')\n\n const full = [\n `# ${label} Transcript`,\n d.ownerName ? `**Owner:** ${d.ownerName}` : '',\n `**Video duration:** ${videoDuration} · **Transcribed in:** ${durSec}s · **${wordCount} words**`,\n d.pageUrl ? `**Page URL:** ${d.pageUrl}` : `**Page URL:** ${input.url}`,\n d.videoUrl ? `**Extracted MP4:** \\`${d.videoUrl}\\`` : '',\n `\\n## Full Transcript\\n${text}`,\n chunks.length ? `\\n## Timestamped Chunks\\n| Time | Text |\\n|------|------|\\n${chunkRows}` : '',\n `\\n---\\n💡 Use \\`videoUrl\\` as the extracted MP4 for download or follow-up processing. Use \\`facebook_ad_transcribe\\` only for Ad Library videoUrl values.`,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n sourceUrl: d.sourceUrl ?? input.url,\n pageUrl: d.pageUrl ?? input.url,\n videoId: d.videoId ?? null,\n ownerName: d.ownerName ?? null,\n selectedQuality: d.selectedQuality ?? input.quality ?? 'best',\n bitrate: typeof d.bitrate === 'number' ? d.bitrate : null,\n videoDurationSec: typeof d.videoDurationSec === 'number' ? d.videoDurationSec : null,\n videoUrl: d.videoUrl ?? '',\n wordCount,\n chunkCount: chunks.length,\n transcriptText: text,\n chunks: chunks.map(c => ({\n startSec: Number.isFinite(c.timestamp[0]) ? c.timestamp[0] : 0,\n endSec: Number.isFinite(c.timestamp[1]) ? c.timestamp[1] : 0,\n text: c.text,\n })),\n },\n }\n}\n\ninterface InstagramProfileItem {\n url: string\n type: 'post' | 'reel' | 'tv'\n shortcode: string\n anchorText?: string | null\n firstSeenStage?: string\n}\n\ninterface InstagramMediaTrack {\n url: string\n streamType: 'video' | 'audio' | 'unknown'\n bitrate?: number | null\n durationSec?: number | null\n vencodeTag?: string | null\n width?: number | null\n height?: number | null\n}\n\ninterface InstagramDownload {\n kind: 'text' | 'image' | 'video' | 'audio' | 'muxed_video'\n url: string | null\n savedPath: string | null\n sizeBytes: number | null\n mimeType: string | null\n error: string | null\n}\n\ninterface StructuredInstagramBrowser {\n mode: 'hosted'\n requestedMode: 'hosted'\n profileName: string | null\n profileSource: 'hosted'\n profileDirConfigured: boolean\n executablePathConfigured: boolean\n}\n\ninterface StructuredInstagramPagination {\n maxItems: number\n maxScrolls: number\n attemptedScrolls: number\n stableScrolls: number\n stableScrollLimit: number\n scrollDelayMs: number\n reachedMaxItems: boolean\n reachedReportedPostCount: boolean\n finalScrollHeight: number | null\n stoppedReason: 'max_items' | 'reported_post_count' | 'stable_scrolls' | 'max_scrolls' | 'no_scrolls'\n stages: Array<{\n stage: string\n itemCount: number\n addedCount: number\n scrollY: number | null\n scrollHeight: number | null\n }>\n}\n\nfunction structuredInstagramBrowser(raw: unknown): StructuredInstagramBrowser {\n const browser = raw && typeof raw === 'object' ? raw as Record<string, unknown> : {}\n return {\n mode: 'hosted',\n requestedMode: 'hosted',\n profileName: typeof browser.profileName === 'string' ? browser.profileName : null,\n profileSource: 'hosted',\n profileDirConfigured: false,\n executablePathConfigured: false,\n }\n}\n\nfunction structuredInstagramPagination(raw: unknown, input: { maxItems?: number; maxScrolls?: number; scrollDelayMs?: number; stableScrollLimit?: number }): StructuredInstagramPagination {\n const pagination = raw && typeof raw === 'object' ? raw as Record<string, unknown> : {}\n const stages = Array.isArray(pagination.stages) ? pagination.stages : []\n const stoppedReason = (typeof pagination.stoppedReason === 'string'\n && ['max_items', 'reported_post_count', 'stable_scrolls', 'max_scrolls', 'no_scrolls'].includes(pagination.stoppedReason)\n ? pagination.stoppedReason\n : 'no_scrolls') as StructuredInstagramPagination['stoppedReason']\n return {\n maxItems: typeof pagination.maxItems === 'number' ? pagination.maxItems : Number(input.maxItems ?? 50),\n maxScrolls: typeof pagination.maxScrolls === 'number' ? pagination.maxScrolls : Number(input.maxScrolls ?? 10),\n attemptedScrolls: typeof pagination.attemptedScrolls === 'number' ? pagination.attemptedScrolls : 0,\n stableScrolls: typeof pagination.stableScrolls === 'number' ? pagination.stableScrolls : 0,\n stableScrollLimit: typeof pagination.stableScrollLimit === 'number' ? pagination.stableScrollLimit : Number(input.stableScrollLimit ?? 4),\n scrollDelayMs: typeof pagination.scrollDelayMs === 'number' ? pagination.scrollDelayMs : Number(input.scrollDelayMs ?? 1200),\n reachedMaxItems: pagination.reachedMaxItems === true,\n reachedReportedPostCount: pagination.reachedReportedPostCount === true,\n finalScrollHeight: typeof pagination.finalScrollHeight === 'number' ? pagination.finalScrollHeight : null,\n stoppedReason,\n stages: stages.map((stage) => {\n const row = stage && typeof stage === 'object' ? stage as Record<string, unknown> : {}\n return {\n stage: String(row.stage ?? ''),\n itemCount: typeof row.itemCount === 'number' ? row.itemCount : 0,\n addedCount: typeof row.addedCount === 'number' ? row.addedCount : 0,\n scrollY: typeof row.scrollY === 'number' ? row.scrollY : null,\n scrollHeight: typeof row.scrollHeight === 'number' ? row.scrollHeight : null,\n }\n }),\n }\n}\n\nexport function formatInstagramProfileContent(\n raw: CallToolResult,\n input: { handle?: string; url?: string; maxItems?: number; maxScrolls?: number; scrollDelayMs?: number; stableScrollLimit?: number },\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 const items = (Array.isArray(d.items) ? d.items : []) as InstagramProfileItem[]\n const typeCounts = d.typeCounts as Record<string, number> | undefined\n const limitations = Array.isArray(d.limitations) ? d.limitations.map(String) : []\n const browser = structuredInstagramBrowser(d.browser)\n const pagination = structuredInstagramPagination(d.pagination, input)\n const itemRows = items.slice(0, 100).map((item, i) =>\n `| ${i + 1} | ${item.type} | \\`${item.shortcode}\\` | ${item.url} | ${cell(item.firstSeenStage ?? '')} |`,\n ).join('\\n')\n const browserLabel = browser.profileName ? `hosted browser profile ${browser.profileName}` : 'hosted browser'\n\n const full = [\n `# Instagram Profile Content: ${d.handle ?? input.handle ?? input.url ?? 'profile'}`,\n `**Collected:** ${items.length} items · posts ${typeCounts?.post ?? 0} · reels ${typeCounts?.reel ?? 0} · tv ${typeCounts?.tv ?? 0}`,\n `**Browser:** ${browserLabel}`,\n `**Pagination:** ${pagination.attemptedScrolls} scrolls · stopped: ${pagination.stoppedReason}`,\n d.reportedPostCountText ? `**Profile count:** ${d.reportedPostCountText}` : '',\n d.followerCountText ? `**Followers:** ${d.followerCountText}` : '',\n `\\n## Content Links\\n| # | Type | Shortcode | URL | First Seen |\\n|---|------|-----------|-----|------------|\\n${itemRows || '| — | — | — | — | — |'}`,\n limitations.length ? `\\n## Limits\\n${limitations.map(l => `- ${l}`).join('\\n')}` : '',\n `\\n---\\n💡 Use \\`instagram_media_download\\` with one of these URLs to download text, image, reel tracks, and optional transcript.`,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n handle: String(d.handle ?? input.handle ?? ''),\n profileUrl: String(d.profileUrl ?? input.url ?? ''),\n pageUrl: String(d.pageUrl ?? d.profileUrl ?? input.url ?? ''),\n browser,\n profileName: typeof d.profileName === 'string' ? d.profileName : null,\n reportedPostCount: typeof d.reportedPostCount === 'number' ? d.reportedPostCount : null,\n reportedPostCountText: typeof d.reportedPostCountText === 'string' ? d.reportedPostCountText : null,\n followerCountText: typeof d.followerCountText === 'string' ? d.followerCountText : null,\n followingCountText: typeof d.followingCountText === 'string' ? d.followingCountText : null,\n collectedContentCount: items.length,\n typeCounts: {\n post: Number(typeCounts?.post ?? 0),\n reel: Number(typeCounts?.reel ?? 0),\n tv: Number(typeCounts?.tv ?? 0),\n },\n pagination,\n limited: d.limited === true,\n limitations,\n items: items.map(item => ({\n url: String(item.url ?? ''),\n type: item.type,\n shortcode: String(item.shortcode ?? ''),\n anchorText: item.anchorText ?? null,\n firstSeenStage: String(item.firstSeenStage ?? ''),\n })),\n },\n }\n}\n\nfunction structuredInstagramTrack(track: InstagramMediaTrack | null | undefined): Record<string, unknown> | null {\n if (!track) return null\n return {\n url: String(track.url ?? ''),\n streamType: track.streamType ?? 'unknown',\n bitrate: typeof track.bitrate === 'number' ? track.bitrate : null,\n durationSec: typeof track.durationSec === 'number' ? track.durationSec : null,\n vencodeTag: track.vencodeTag ?? null,\n width: typeof track.width === 'number' ? track.width : null,\n height: typeof track.height === 'number' ? track.height : null,\n }\n}\n\nexport function formatInstagramMediaDownload(\n raw: CallToolResult,\n input: { url: string; includeTranscript?: 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\n const tracks = (Array.isArray(d.tracks) ? d.tracks : []) as InstagramMediaTrack[]\n const downloads = (Array.isArray(d.downloads) ? d.downloads : []) as InstagramDownload[]\n const warnings = Array.isArray(d.warnings) ? d.warnings.map(String) : []\n const limitations = Array.isArray(d.limitations) ? d.limitations.map(String) : []\n const transcript = d.transcript as TranscriptResult | null | undefined\n const transcriptText = transcript?.text ?? ''\n const chunks = transcript?.chunks ?? []\n const browser = structuredInstagramBrowser(d.browser)\n const browserLabel = browser.profileName ? `hosted browser profile ${browser.profileName}` : 'hosted browser'\n\n const downloadRows = downloads.map((download, i) => {\n const status = download.error ? `error: ${cell(download.error)}` : `${download.sizeBytes ?? 0} bytes`\n return `| ${i + 1} | ${download.kind} | ${download.savedPath ? `\\`${download.savedPath}\\`` : '—'} | ${status} |`\n }).join('\\n')\n const trackRows = tracks.slice(0, 20).map((track, i) =>\n `| ${i + 1} | ${track.streamType} | ${track.bitrate ?? '—'} | ${track.durationSec ?? '—'} | ${cell(track.vencodeTag ?? '')} |`,\n ).join('\\n')\n\n const full = [\n `# Instagram Media Download`,\n `**URL:** ${d.pageUrl ?? input.url}`,\n `**Browser:** ${browserLabel}`,\n d.ownerName ? `**Owner:** ${d.ownerName}` : '',\n d.shortcode ? `**Shortcode:** \\`${d.shortcode}\\`` : '',\n d.caption ? `\\n## Caption\\n${truncate(String(d.caption), 1200)}` : '',\n d.imageUrl ? `\\n## Image\\n${d.imageUrl}` : '',\n tracks.length ? `\\n## Media Tracks\\n| # | Type | Bitrate | Duration | Tag |\\n|---|------|---------|----------|-----|\\n${trackRows}` : '\\n## Media Tracks\\n*None captured.*',\n downloads.length ? `\\n## Downloads\\n| # | Kind | File | Status |\\n|---|------|------|--------|\\n${downloadRows}` : '',\n d.outputDir ? `\\n**Output directory:** \\`${d.outputDir}\\`` : '',\n transcript ? `\\n## Transcript\\n**${wordCount(transcriptText)} words** · ${chunks.length} chunks\\n\\n${transcriptText}` : '',\n warnings.length ? `\\n## Warnings\\n${warnings.map(w => `- ${w}`).join('\\n')}` : '',\n limitations.length ? `\\n## Limits\\n${limitations.map(l => `- ${l}`).join('\\n')}` : '',\n `\\n---\\n💡 Reels may expose separate video-only and audio-only MP4 tracks. Use the muxed file when present; otherwise use the selected video/audio track URLs or saved files.`,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n sourceUrl: String(d.sourceUrl ?? input.url),\n pageUrl: String(d.pageUrl ?? input.url),\n browser,\n type: d.type === 'post' || d.type === 'reel' || d.type === 'tv' ? d.type : null,\n shortcode: typeof d.shortcode === 'string' ? d.shortcode : null,\n ownerName: typeof d.ownerName === 'string' ? d.ownerName : null,\n caption: typeof d.caption === 'string' ? d.caption : null,\n imageUrl: typeof d.imageUrl === 'string' ? d.imageUrl : null,\n trackCount: tracks.length,\n selectedVideoTrack: structuredInstagramTrack(d.selectedVideoTrack as InstagramMediaTrack | null | undefined),\n selectedAudioTrack: structuredInstagramTrack(d.selectedAudioTrack as InstagramMediaTrack | null | undefined),\n downloads: downloads.map(download => ({\n kind: download.kind,\n url: download.url ?? null,\n savedPath: download.savedPath ?? null,\n sizeBytes: typeof download.sizeBytes === 'number' ? download.sizeBytes : null,\n mimeType: download.mimeType ?? null,\n error: download.error ?? null,\n })),\n outputDir: typeof d.outputDir === 'string' ? d.outputDir : null,\n warnings,\n limitations,\n transcript: transcript ? {\n wordCount: wordCount(transcriptText),\n chunkCount: chunks.length,\n durationMs: typeof transcript.durationMs === 'number' ? transcript.durationMs : null,\n transcriptText,\n chunks: structuredTranscriptChunks(chunks),\n } : null,\n },\n }\n}\n\nexport function formatCaptureSerpSnapshot(\n raw: CallToolResult,\n input: Record<string, unknown>,\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 const providerPayload = d\n const organic = Array.isArray(d.organicResults) ? d.organicResults : Array.isArray(d.organic) ? d.organic : []\n const localPack = Array.isArray(d.localPack) ? d.localPack : []\n const artifacts = Array.isArray(d.artifacts) ? d.artifacts as Array<Record<string, unknown>> : []\n const status = String(d.status ?? d.captureStatus ?? 'captured')\n const query = typeof d.query === 'string' ? d.query : typeof input.query === 'string' ? input.query : null\n const location = typeof d.location === 'string' ? d.location : typeof input.location === 'string' ? input.location : null\n const capturedAt = typeof d.capturedAt === 'string'\n ? d.capturedAt\n : typeof d.extractedAt === 'string'\n ? d.extractedAt\n : null\n const resultCount = organic.length + localPack.length\n\n const full = [\n `# SERP Intelligence Snapshot: ${query ?? 'query'}`,\n `**Status:** ${status}`,\n location ? `**Location:** ${location}` : '',\n `**Result count:** ${resultCount}`,\n artifacts.length ? `**Artifacts:** ${artifacts.length}` : '',\n '',\n 'Use `capture_serp_page_snapshots` when you need page-level evidence for ranking URLs.',\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n schemaVersion: 'serp-intelligence.capture.v1',\n status,\n query,\n location,\n capturedAt,\n resultCount,\n snapshotId: typeof d.snapshotId === 'string'\n ? d.snapshotId\n : typeof d.snapshot_id === 'string'\n ? d.snapshot_id\n : typeof d.id === 'string'\n ? d.id\n : null,\n resolvedInputs: {\n query: input.query ?? null,\n location: input.location ?? null,\n gl: input.gl ?? null,\n hl: input.hl ?? null,\n device: input.device ?? null,\n proxyMode: input.proxyMode ?? null,\n proxyZip: input.proxyZip ?? null,\n pages: input.pages ?? null,\n },\n artifacts,\n diagnostics: d.diagnostics && typeof d.diagnostics === 'object' ? d.diagnostics as Record<string, unknown> : null,\n providerPayload,\n },\n }\n}\n\nexport function formatCaptureSerpPageSnapshots(\n raw: CallToolResult,\n input: Record<string, unknown>,\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 const captures = Array.isArray(d.captures)\n ? d.captures as Array<Record<string, unknown>>\n : Array.isArray(d.results)\n ? d.results as Array<Record<string, unknown>>\n : []\n const failedCount = captures.filter(c => c.status === 'failed' || c.error).length\n const status = String(d.status ?? (failedCount ? 'partial' : 'captured'))\n\n const rows = captures.slice(0, 25).map((capture, i) => {\n const url = typeof capture.url === 'string' ? capture.url : ''\n const sourceKind = typeof capture.sourceKind === 'string' ? capture.sourceKind : typeof capture.source_kind === 'string' ? capture.source_kind : 'configured_target'\n return `| ${i + 1} | ${cell(url)} | ${cell(sourceKind)} | ${cell(String(capture.status ?? (capture.error ? 'failed' : 'ok')))} |`\n }).join('\\n')\n\n const full = [\n '# SERP Intelligence Page Snapshots',\n `**Status:** ${status}`,\n `**Captured:** ${captures.length}`,\n `**Failed:** ${failedCount}`,\n captures.length ? `\\n| # | URL | Source | Status |\\n|---|-----|--------|--------|\\n${rows}` : '',\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n schemaVersion: 'serp-intelligence.page-snapshots.v1',\n status,\n count: captures.length,\n failedCount,\n captures,\n resolvedInputs: {\n urls: input.urls ?? null,\n targets: input.targets ?? null,\n maxConcurrency: input.maxConcurrency ?? null,\n timeoutMs: input.timeoutMs ?? null,\n debug: input.debug ?? null,\n },\n diagnostics: d.diagnostics && typeof d.diagnostics === 'object' ? d.diagnostics as Record<string, unknown> : null,\n providerPayload: d,\n },\n }\n}\n","export type WorkflowRecipe = {\n id: string\n title: string\n description: string\n primaryWorkflowId: string | null\n recommendedTools: string[]\n requiredInputs: string[]\n optionalInputs: string[]\n produces: string[]\n runHint: string\n}\n\nexport const WORKFLOW_RECIPES: WorkflowRecipe[] = [\n {\n id: 'market_analysis',\n title: 'Market Analysis',\n description: 'Compare a niche across a city, state, or market set using Google Maps competitors, SERP evidence, review counts, categories, and opportunity signals.',\n primaryWorkflowId: 'local-competitive-audit',\n recommendedTools: ['workflow_run', 'directory_workflow', 'maps_search', 'maps_place_intel', 'search_serp', 'harvest_paa'],\n requiredInputs: ['query', 'state or location'],\n optionalInputs: ['domain', 'minPopulation', 'maxCities', 'maxResultsPerCity', 'hydrateTop', 'maxReviews'],\n produces: ['city summary', 'competitor CSV', 'review insight CSV', 'market difficulty/opportunity notes', 'HTML report'],\n runHint: 'Use workflow_run with workflowId local-competitive-audit for state-wide market batches, or map-comparison for one city/location comparison.',\n },\n {\n id: 'lead_generation',\n title: 'Lead Generation',\n description: 'Build an outreach-ready local lead list for a niche in one market: Google Maps businesses with confirmed review counts and booking URLs, enriched with email and social links scraped from each business website (proxy/browser-backed so blocked sites still resolve).',\n primaryWorkflowId: 'get-leads',\n recommendedTools: ['workflow_run', 'maps_search', 'maps_place_intel', 'extract_url'],\n requiredInputs: ['query', 'location'],\n optionalInputs: ['maxResults', 'enrichWebsites', 'hydrateReviewCounts', 'concurrency', 'proxyMode'],\n produces: ['leads CSV (name, phone, website, email, socials, review count, booking URL)', 'evidence JSON', 'HTML report', 'outreach task list'],\n runHint: 'Use workflow_run with workflowId get-leads. Put the niche in query (e.g. \"roofers\") and the market in location (e.g. \"Houston, TX\"); do not combine them.',\n },\n {\n id: 'icp_research',\n title: 'ICP Research',\n description: 'Build an evidence packet for ideal-customer-profile research from real search demand, PAA language, competing pages, AI Overview citations, and source domains.',\n primaryWorkflowId: 'agent-packet',\n recommendedTools: ['workflow_run', 'harvest_paa', 'search_serp', 'extract_url', 'youtube_harvest', 'facebook_ad_search'],\n requiredInputs: ['keyword or audience problem'],\n optionalInputs: ['domain', 'location', 'maxQuestions'],\n produces: ['evidence JSON', 'sources CSV', 'competitor CSV', 'brief markdown', 'agent task list'],\n runHint: 'Use workflow_run with workflowId agent-packet. Treat keyword as the buyer problem, job-to-be-done, niche, or service category.',\n },\n {\n id: 'forum_review_research',\n title: 'Forum And Review Research',\n description: 'Acquire customer language from Google PAA, forum/Perspectives SERP surfaces, Google Maps reviews, review topics, Facebook ads, and video transcripts.',\n primaryWorkflowId: 'local-competitive-audit',\n recommendedTools: ['workflow_run', 'harvest_paa', 'maps_search', 'maps_place_intel', 'facebook_page_intel', 'facebook_video_transcribe', 'youtube_transcribe'],\n requiredInputs: ['query', 'state or location'],\n optionalInputs: ['maxReviews', 'maxQuestions', 'competitors', 'facebookUrl', 'youtubeVideoId'],\n produces: ['review insight CSV', 'PAA/source language', 'competitor review topics', 'transcripts where supplied', 'pain/theme summary'],\n runHint: 'Use local-competitive-audit for review acquisition, then harvest_paa for forum/Perspectives language and transcript tools for supplied videos.',\n },\n {\n id: 'brand_design_brief',\n title: 'Brand Design Brief',\n description: 'Create a design briefing grounded in a brand site, competitor pages, SERP language, audience pains, visual assets, colors, fonts, screenshots, and positioning evidence.',\n primaryWorkflowId: 'serp-comparison',\n recommendedTools: ['workflow_run', 'extract_url', 'extract_site', 'capture_serp_page_snapshots', 'search_serp', 'harvest_paa', 'browser_open'],\n requiredInputs: ['url or domain', 'keyword or market category'],\n optionalInputs: ['competitorUrls', 'location', 'extractTop'],\n produces: ['page comparison CSV', 'content gaps', 'branding/asset evidence', 'SERP positioning evidence', 'designer-ready brief'],\n runHint: 'Use workflow_run with workflowId serp-comparison for market/page evidence, then extract_url with extractBranding:true for brand assets and colors.',\n },\n {\n id: 'cro_audit',\n title: 'CRO Audit',\n description: 'Audit conversion clarity using page extraction, screenshots, browser DOM inspection, competitor SERP/page comparisons, forms/buttons, proof, offer, trust, and friction evidence.',\n primaryWorkflowId: 'serp-comparison',\n recommendedTools: ['workflow_run', 'extract_url', 'extract_site', 'capture_serp_page_snapshots', 'browser_open', 'browser_screenshot', 'browser_locate'],\n requiredInputs: ['url'],\n optionalInputs: ['keyword', 'domain', 'location', 'competitorUrls'],\n produces: ['page extraction', 'SERP/page comparison', 'screenshot evidence', 'friction checklist', 'CRO recommendations'],\n runHint: 'Use workflow_run with workflowId serp-comparison when a keyword/domain is known; use extract_url and browser tools for page-level CRO evidence.',\n },\n {\n id: 'competitive_positioning_brief',\n title: 'Competitive Positioning Brief',\n description: 'Compare competitors across SERP, PAA, AI Overview citations, page headings, Facebook ads, YouTube angles, Maps proof, and website claims.',\n primaryWorkflowId: 'serp-comparison',\n recommendedTools: ['workflow_run', 'facebook_ad_search', 'facebook_page_intel', 'youtube_harvest', 'youtube_transcribe', 'maps_search', 'extract_url'],\n requiredInputs: ['keyword or query', 'domain or url'],\n optionalInputs: ['location', 'extractTop', 'competitorUrls', 'brandNames'],\n produces: ['SERP comparison', 'content gap CSV', 'AI Overview citation table', 'competitor message map', 'positioning brief'],\n runHint: 'Use workflow_run with workflowId serp-comparison, then enrich with Facebook, YouTube, and Maps tools when the user asks for campaign or offer positioning.',\n },\n {\n id: 'content_gap_brief',\n title: 'Content Gap Brief',\n description: 'Turn live SERP, page extraction, PAA questions, AI Overview citations, and source-domain evidence into a writer-ready content brief.',\n primaryWorkflowId: 'serp-comparison',\n recommendedTools: ['workflow_run', 'paa-expansion-brief', 'harvest_paa', 'extract_url'],\n requiredInputs: ['keyword'],\n optionalInputs: ['domain', 'url', 'location', 'maxQuestions', 'extractTop'],\n produces: ['content gaps', 'page comparison CSV', 'PAA questions CSV', 'section map', 'writer brief'],\n runHint: 'Use workflow_run with workflowId serp-comparison for competitor gaps or paa-expansion-brief when the user mainly wants a section map from PAA data.',\n },\n {\n id: 'ai_search_visibility_audit',\n title: 'AI Search Visibility Audit',\n description: 'Audit whether a brand/domain appears in AI Overview citations, PAA sources, organic results, local pack, and source pages, then produce language guidance.',\n primaryWorkflowId: 'ai-overview-language',\n recommendedTools: ['workflow_run', 'search_serp', 'harvest_paa', 'extract_url', 'capture_serp_snapshot'],\n requiredInputs: ['keyword', 'domain or url'],\n optionalInputs: ['location', 'maxQuestions', 'extractTop'],\n produces: ['AI Overview citations CSV', 'claim patterns', 'language guidance', 'citation hooks', 'visibility gaps'],\n runHint: 'Use workflow_run with workflowId ai-overview-language. Use serp-comparison when the user also wants ranking-page gaps.',\n },\n]\n\nfunction normalize(value: string): string {\n return value.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim()\n}\n\nexport function suggestWorkflowRecipes(goal: string, limit = 3): WorkflowRecipe[] {\n const normalized = normalize(goal)\n const scored = WORKFLOW_RECIPES.map(recipe => {\n const haystack = normalize([\n recipe.id,\n recipe.title,\n recipe.description,\n recipe.requiredInputs.join(' '),\n recipe.optionalInputs.join(' '),\n recipe.produces.join(' '),\n ].join(' '))\n let score = 0\n for (const token of normalized.split(/\\s+/).filter(Boolean)) {\n if (haystack.includes(token)) score += 1\n }\n if (haystack.includes(normalized)) score += 5\n return { recipe, score }\n })\n return scored\n .sort((a, b) => b.score - a.score || a.recipe.title.localeCompare(b.recipe.title))\n .slice(0, Math.max(1, limit))\n .map(item => item.recipe)\n}\n","import type { PageData } from './site-extractor.js'\n\nexport interface LinkEdge {\n from: string\n to: string\n anchor: string\n rel: string | null\n internal: boolean\n nofollow: boolean\n targetStatus: number | null\n}\n\nexport interface PageLinkMetrics {\n url: string\n inlinks: number\n uniqueInlinks: number\n outlinksInternal: number\n outlinksExternal: number\n crawlDepth: number | null\n orphan: boolean\n topAnchors: string[]\n}\n\nfunction normalize(u: string): string {\n return u.split('#')[0].replace(/\\/$/, '')\n}\n\nexport function buildLinkGraph(\n pages: PageData[],\n startUrl: string,\n): { edges: LinkEdge[]; metrics: Map<string, PageLinkMetrics> } {\n const statusByUrl = new Map<string, number | null>()\n for (const p of pages) statusByUrl.set(normalize(p.url), p.status)\n\n const edges: LinkEdge[] = []\n for (const p of pages) {\n for (const l of p.outlinks ?? []) {\n const nofollow = (l.rel ?? '').split(/\\s+/).includes('nofollow')\n edges.push({\n from: p.url,\n to: l.href,\n anchor: l.anchor,\n rel: l.rel,\n internal: l.internal,\n nofollow,\n targetStatus: statusByUrl.get(normalize(l.href)) ?? null,\n })\n }\n }\n\n const inboundFrom = new Map<string, Set<string>>()\n const inboundAnchors = new Map<string, string[]>()\n const adjacency = new Map<string, Set<string>>()\n for (const e of edges) {\n if (!e.internal) continue\n const to = normalize(e.to)\n const from = normalize(e.from)\n if (!inboundFrom.has(to)) inboundFrom.set(to, new Set())\n inboundFrom.get(to)!.add(from)\n if (e.anchor) {\n if (!inboundAnchors.has(to)) inboundAnchors.set(to, [])\n inboundAnchors.get(to)!.push(e.anchor)\n }\n if (!e.nofollow && (statusByUrl.get(to) === 200 || !statusByUrl.has(to))) {\n if (!adjacency.has(from)) adjacency.set(from, new Set())\n adjacency.get(from)!.add(to)\n }\n }\n\n const depth = new Map<string, number>()\n const start = normalize(startUrl)\n const queue: string[] = [start]\n depth.set(start, 0)\n while (queue.length > 0) {\n const cur = queue.shift()!\n const d = depth.get(cur)!\n for (const next of adjacency.get(cur) ?? []) {\n if (!depth.has(next)) { depth.set(next, d + 1); queue.push(next) }\n }\n }\n\n const topAnchorsFor = (url: string): string[] => {\n const counts = new Map<string, number>()\n for (const a of inboundAnchors.get(url) ?? []) counts.set(a, (counts.get(a) ?? 0) + 1)\n return [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3).map(e => e[0])\n }\n\n const metrics = new Map<string, PageLinkMetrics>()\n for (const p of pages) {\n const key = normalize(p.url)\n const inbound = inboundFrom.get(key) ?? new Set()\n metrics.set(p.url, {\n url: p.url,\n inlinks: inbound.size,\n uniqueInlinks: inbound.size,\n outlinksInternal: (p.outlinks ?? []).filter(l => l.internal).length,\n outlinksExternal: (p.outlinks ?? []).filter(l => !l.internal).length,\n crawlDepth: depth.has(key) ? depth.get(key)! : null,\n orphan: inbound.size === 0 && key !== start,\n topAnchors: topAnchorsFor(key),\n })\n }\n\n return { edges, metrics }\n}\n","import type { LinkEdge, PageLinkMetrics } from './seo-link-graph.js'\n\nexport interface ExtDomainRow { domain: string; links: number; nofollow: number; pages: number }\n\nexport interface LinkReportSummary {\n internal: {\n totalLinks: number\n pages: number\n orphans: number\n brokenInternal: number\n avgInlinks: number\n avgOutlinks: number\n distribution: { zero: number; oneToTwo: number; threeToTen: number; elevenPlus: number }\n topByInlinks: Array<{ url: string; inlinks: number; outlinksInternal: number; outlinksExternal: number }>\n }\n external: {\n totalLinks: number\n uniqueDomains: number\n topDomains: ExtDomainRow[]\n }\n}\n\nexport interface LinkReport {\n summary: LinkReportSummary\n externalDomains: ExtDomainRow[]\n}\n\nfunction registrableDomain(host: string): string {\n const h = host.replace(/^www\\./, '').toLowerCase()\n const parts = h.split('.')\n return parts.length <= 2 ? h : parts.slice(-2).join('.')\n}\n\nexport function buildLinkReport(edges: LinkEdge[], metrics: PageLinkMetrics[], siteUrl: string): LinkReport {\n let siteReg = ''\n try { siteReg = registrableDomain(new URL(siteUrl).hostname) } catch { siteReg = '' }\n const internalEdges = edges.filter(e => e.internal)\n const pages = metrics.length\n const orphans = metrics.filter(m => m.orphan).length\n const brokenInternal = internalEdges.filter(e => e.targetStatus != null && e.targetStatus >= 400).length\n const sumInlinks = metrics.reduce((a, m) => a + m.inlinks, 0)\n const sumOutlinks = metrics.reduce((a, m) => a + m.outlinksInternal + m.outlinksExternal, 0)\n\n const distribution = { zero: 0, oneToTwo: 0, threeToTen: 0, elevenPlus: 0 }\n for (const m of metrics) {\n if (m.inlinks === 0) distribution.zero++\n else if (m.inlinks <= 2) distribution.oneToTwo++\n else if (m.inlinks <= 10) distribution.threeToTen++\n else distribution.elevenPlus++\n }\n\n const topByInlinks = [...metrics].sort((a, b) => b.inlinks - a.inlinks).slice(0, 20)\n .map(m => ({ url: m.url, inlinks: m.inlinks, outlinksInternal: m.outlinksInternal, outlinksExternal: m.outlinksExternal }))\n\n const domMap = new Map<string, { links: number; nofollow: number; pages: Set<string> }>()\n let externalTotal = 0\n for (const e of edges) {\n let domain: string\n try { domain = registrableDomain(new URL(e.to).hostname) } catch { continue }\n if (!domain || domain === siteReg) continue\n externalTotal++\n const d = domMap.get(domain) ?? { links: 0, nofollow: 0, pages: new Set<string>() }\n d.links++\n if (e.nofollow) d.nofollow++\n d.pages.add(e.from)\n domMap.set(domain, d)\n }\n const externalDomains: ExtDomainRow[] = [...domMap.entries()]\n .map(([domain, d]) => ({ domain, links: d.links, nofollow: d.nofollow, pages: d.pages.size }))\n .sort((a, b) => b.links - a.links)\n\n const round = (n: number) => Math.round(n * 10) / 10\n return {\n summary: {\n internal: {\n totalLinks: internalEdges.length,\n pages, orphans, brokenInternal,\n avgInlinks: pages ? round(sumInlinks / pages) : 0,\n avgOutlinks: pages ? round(sumOutlinks / pages) : 0,\n distribution,\n topByInlinks,\n },\n external: {\n totalLinks: externalTotal,\n uniqueDomains: externalDomains.length,\n topDomains: externalDomains.slice(0, 20),\n },\n },\n externalDomains,\n }\n}\n\nexport function renderLinkReport(r: LinkReport): string {\n const s = r.summary\n const lines = [\n `## Link analysis`,\n `**Internal:** ${s.internal.totalLinks} links · ${s.internal.pages} pages · avg ${s.internal.avgInlinks} inlinks/page · ${s.internal.orphans} orphans · ${s.internal.brokenInternal} broken`,\n `**External:** ${s.external.totalLinks} links to ${s.external.uniqueDomains} domains`,\n ``,\n `### Inlink distribution`,\n `- 0 inlinks (orphans): ${s.internal.distribution.zero}`,\n `- 1–2: ${s.internal.distribution.oneToTwo}`,\n `- 3–10: ${s.internal.distribution.threeToTen}`,\n `- 11+: ${s.internal.distribution.elevenPlus}`,\n ``,\n `### Top 20 internal pages by inlinks`,\n `| inlinks | out (int/ext) | URL |`,\n `|---|---|---|`,\n ...s.internal.topByInlinks.map(p => `| ${p.inlinks} | ${p.outlinksInternal}/${p.outlinksExternal} | ${p.url} |`),\n ``,\n `### Top 20 external domains by links`,\n `| links | nofollow | from pages | domain |`,\n `|---|---|---|---|`,\n ...s.external.topDomains.map(d => `| ${d.links} | ${d.nofollow} | ${d.pages} | ${d.domain} |`),\n ]\n return lines.join('\\n')\n}\n","import type { PageData } from './site-extractor.js'\nimport type { PageLinkMetrics } from './seo-link-graph.js'\n\nexport interface IssueGroup { count: number; urls: string[] }\nexport type IssueReport = Record<string, IssueGroup>\n\nconst THIN_WORDS = 200\nconst TITLE_MAX = 60\nconst TITLE_PX_MAX = 561\nconst TITLE_MIN = 30\nconst META_MAX = 155\nconst META_MIN = 70\nconst H1_MAX = 70\nconst URL_MAX = 115\n\nfunction dupes<T>(pages: PageData[], key: (p: PageData) => T | null | undefined): string[] {\n const groups = new Map<string, string[]>()\n for (const p of pages) {\n const k = key(p)\n if (k === null || k === undefined || k === '') continue\n const ks = String(k)\n if (!groups.has(ks)) groups.set(ks, [])\n groups.get(ks)!.push(p.url)\n }\n return [...groups.values()].filter(g => g.length > 1).flat()\n}\n\nexport function computeIssues(pages: PageData[], metrics: Map<string, PageLinkMetrics>): IssueReport {\n const group = (urls: string[]): IssueGroup => ({ count: urls.length, urls: urls.slice(0, 200) })\n const where = (fn: (p: PageData) => boolean) => pages.filter(fn).map(p => p.url)\n const ok = (p: PageData) => p.status === 200\n const pathname = (u: string) => { try { return new URL(u).pathname } catch { return '' } }\n\n const report: IssueReport = {\n 'title.missing': group(where(p => ok(p) && !p.title)),\n 'title.duplicate': group(dupes(pages.filter(ok), p => p.title)),\n 'title.tooLong': group(where(p => (p.titleLength ?? 0) > TITLE_MAX || (p.titlePixels ?? 0) > TITLE_PX_MAX)),\n 'title.tooShort': group(where(p => p.title != null && (p.titleLength ?? 0) < TITLE_MIN)),\n 'title.sameAsH1': group(where(p => !!p.title && !!p.h1 && p.title.trim() === p.h1.trim())),\n 'meta.missing': group(where(p => ok(p) && !p.metaDescription)),\n 'meta.duplicate': group(dupes(pages.filter(ok), p => p.metaDescription)),\n 'meta.tooLong': group(where(p => (p.metaDescLength ?? 0) > META_MAX)),\n 'meta.tooShort': group(where(p => p.metaDescription != null && (p.metaDescLength ?? 0) < META_MIN)),\n 'h1.missing': group(where(p => ok(p) && !p.h1)),\n 'h1.multiple': group(where(p => !!p.h1_2)),\n 'h1.duplicate': group(dupes(pages.filter(ok), p => p.h1)),\n 'h1.tooLong': group(where(p => (p.h1?.length ?? 0) > H1_MAX)),\n 'h2.missing': group(where(p => ok(p) && p.h2Count === 0)),\n 'indexability.nonIndexable': group(where(p => !p.indexable)),\n 'indexability.noindex': group(where(p => p.indexabilityReason === 'noindex')),\n 'canonical.missing': group(where(p => ok(p) && !p.canonicalUrl)),\n 'canonical.canonicalised': group(where(p => p.indexabilityReason === 'canonicalised')),\n 'response.broken4xx': group(where(p => (p.status ?? 0) >= 400 && (p.status ?? 0) < 500)),\n 'response.error5xx': group(where(p => (p.status ?? 0) >= 500)),\n 'response.redirect3xx': group(where(p => (p.status ?? 0) >= 300 && (p.status ?? 0) < 400)),\n 'response.noResponse': group(where(p => p.status === null)),\n 'content.thin': group(where(p => ok(p) && p.wordCount > 0 && p.wordCount < THIN_WORDS)),\n 'content.exactDuplicate': group(dupes(pages.filter(p => ok(p) && p.contentHash), p => p.contentHash)),\n 'images.missingAlt': group(where(p => p.imagesMissingAlt > 0)),\n 'schema.missing': group(where(p => ok(p) && p.schemaTypes.length === 0)),\n 'url.tooLong': group(where(p => p.url.length > URL_MAX)),\n 'url.uppercase': group(where(p => /[A-Z]/.test(pathname(p.url)))),\n 'url.underscores': group(where(p => pathname(p.url).includes('_'))),\n 'links.orphan': group([...metrics.values()].filter(m => m.orphan).map(m => m.url)),\n }\n\n const normUrl = (u: string) => { try { const x = new URL(u); x.hash = ''; return (x.origin + x.pathname).replace(/\\/+$/, '') + x.search } catch { return u.replace(/#.*$/, '').replace(/\\/+$/, '') } }\n const statusByUrl = new Map(pages.map(p => [normUrl(p.url), p.status]))\n const brokenLinkPages = new Set<string>()\n for (const p of pages) {\n for (const l of p.outlinks ?? []) {\n if (!l.internal) continue\n const st = statusByUrl.get(normUrl(l.href))\n if (st != null && st >= 400) brokenLinkPages.add(p.url)\n }\n }\n report['links.brokenInternal'] = group([...brokenLinkPages])\n\n return report\n}\n\nexport function renderIssueReport(siteUrl: string, pages: PageData[], report: IssueReport, metrics: Map<string, PageLinkMetrics>): string {\n const total = pages.length\n const sev = (key: string): string => (\n key.startsWith('response.broken') || key.startsWith('response.error') || key.startsWith('links.broken') ? '🔴'\n : key.startsWith('title.missing') || key.startsWith('h1.missing') || key.startsWith('indexability') || key.startsWith('canonical.missing') ? '🟠'\n : '🟡'\n )\n const rows = Object.entries(report)\n .filter(([, g]) => g.count > 0)\n .sort((a, b) => b[1].count - a[1].count)\n .map(([k, g]) => `| ${sev(k)} | \\`${k}\\` | ${g.count} | ${g.urls.slice(0, 3).join(' · ')}${g.urls.length > 3 ? ' …' : ''} |`)\n\n const depths = [...metrics.values()].map(m => m.crawlDepth).filter((d): d is number => d != null)\n const maxDepth = depths.length ? Math.max(...depths) : 0\n const orphans = [...metrics.values()].filter(m => m.orphan).length\n const topLinked = [...metrics.values()].sort((a, b) => b.inlinks - a.inlinks).slice(0, 5)\n\n return [\n `# SEO Crawl Report: ${siteUrl}`,\n `**${total} pages crawled** · max crawl depth ${maxDepth} · ${orphans} orphan page(s)`,\n `\\n## Issues\\n| | Issue | Count | Examples |\\n|---|-------|-------|----------|\\n${rows.join('\\n') || '| ✅ | none | 0 | — |'}`,\n `\\n## Most-linked pages\\n${topLinked.map(m => `- ${m.inlinks} inlinks · depth ${m.crawlDepth ?? '—'} · ${m.url}`).join('\\n')}`,\n `\\n_Thresholds: title ${TITLE_MAX}ch/${TITLE_PX_MAX}px, meta ${META_MAX}ch, H1 ${H1_MAX}ch, thin <${THIN_WORDS} words, URL ${URL_MAX}ch. Pixel widths are estimates._`,\n ].join('\\n')\n}\n","import type { PageData } from './site-extractor.js'\n\nexport interface ImageRow {\n url: string\n status: number | null\n bytes: number | null\n size: string | null\n contentType: string | null\n format: string\n over100kb: boolean\n legacyFormat: boolean\n error?: string\n}\n\nexport interface ImageAuditSummary {\n unique: number\n sized: number\n totalBytes: number\n totalSize: string\n avgSize: string\n over100kb: number\n legacyFormat: number\n formatCounts: Record<string, number>\n}\n\nexport interface ImageAudit {\n rows: ImageRow[]\n summary: ImageAuditSummary\n}\n\nconst OVER_BYTES = 100 * 1024\nconst MODERN = new Set(['webp', 'avif', 'svg', 'svg+xml'])\n\nexport function formatBytes(n: number | null): string | null {\n if (n == null) return null\n if (n < 1024) return `${n} B`\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`\n return `${(n / (1024 * 1024)).toFixed(2)} MB`\n}\n\nconst decodeEntities = (u: string): string =>\n u.replace(/&amp;/g, '&').replace(/&#0?38;/g, '&').replace(/&#x26;/gi, '&').trim()\n\nconst dedupKey = (u: string): string => u.replace(/^https?:\\/\\//i, '//').replace(/\\/$/, '')\n\nconst formatOf = (ct: string | null, url: string): string => {\n if (ct) { const m = ct.split(';')[0].trim().toLowerCase(); if (m.startsWith('image/')) return m.replace('image/', '') }\n return (url.split('?')[0].match(/\\.([a-z0-9]+)$/i)?.[1] || 'unknown').toLowerCase()\n}\n\nfunction collectUrls(pages: PageData[]): string[] {\n const byKey = new Map<string, string>()\n for (const p of pages) for (const raw of (p.imageLinks || [])) {\n const u = decodeEntities(raw)\n if (!/^https?:\\/\\//i.test(u)) continue\n if (/[{}]|%7[bd]/i.test(u)) continue\n const k = dedupKey(u)\n const prev = byKey.get(k)\n if (!prev || (/^https:/i.test(u) && /^http:/i.test(prev))) byKey.set(k, u)\n }\n return [...byKey.values()]\n}\n\nasync function sizeAndType(url: string, timeoutMs: number): Promise<Omit<ImageRow, 'size' | 'format' | 'over100kb' | 'legacyFormat'>> {\n const ctrl = new AbortController()\n const t = setTimeout(() => ctrl.abort(), timeoutMs)\n const read = (res: Response) => ({\n len: res.headers.get('content-length'),\n cr: res.headers.get('content-range'),\n ct: res.headers.get('content-type'),\n status: res.status,\n })\n try {\n let bytes: number | null = null\n let ct: string | null = null\n let status: number | null = null\n try {\n const h = read(await fetch(url, { method: 'HEAD', redirect: 'follow', signal: ctrl.signal }))\n status = h.status; ct = h.ct\n if (h.len) bytes = Number(h.len)\n } catch { /* fall through to ranged GET */ }\n if (bytes == null) {\n const g = await fetch(url, { method: 'GET', headers: { Range: 'bytes=0-0' }, redirect: 'follow', signal: ctrl.signal })\n const r = read(g)\n status = status ?? r.status; ct = ct ?? r.ct\n if (r.cr && r.cr.includes('/')) { const tail = r.cr.split('/')[1]; if (tail && tail !== '*') bytes = Number(tail) }\n else if (r.len) bytes = Number(r.len)\n try { await g.body?.cancel() } catch { /* ignore */ }\n }\n return { url, status, bytes: Number.isFinite(bytes as number) ? bytes : null, contentType: ct }\n } catch (e) {\n return { url, status: null, bytes: null, contentType: null, error: String((e as Error).message || e) }\n } finally {\n clearTimeout(t)\n }\n}\n\nasync function pool<T, R>(items: T[], n: number, fn: (item: T) => Promise<R>): Promise<R[]> {\n const out = new Array<R>(items.length)\n let i = 0\n await Promise.all(Array.from({ length: Math.min(n, items.length) }, async () => {\n while (i < items.length) { const idx = i++; out[idx] = await fn(items[idx]) }\n }))\n return out\n}\n\nexport async function auditImages(\n pages: PageData[],\n opts: { concurrency?: number; timeoutMs?: number; max?: number } = {},\n): Promise<ImageAudit> {\n const concurrency = opts.concurrency ?? 12\n const timeoutMs = opts.timeoutMs ?? 12_000\n const urls = collectUrls(pages).slice(0, opts.max ?? 5000)\n\n const heads = await pool(urls, concurrency, (u) => sizeAndType(u, timeoutMs))\n const rows: ImageRow[] = heads.map(r => {\n const format = formatOf(r.contentType, r.url)\n return {\n ...r,\n size: formatBytes(r.bytes),\n format,\n over100kb: r.bytes != null && r.bytes > OVER_BYTES,\n legacyFormat: format !== 'unknown' && !MODERN.has(format),\n }\n })\n\n const sized = rows.filter(r => r.bytes != null)\n const totalBytes = sized.reduce((a, r) => a + (r.bytes as number), 0)\n const formatCounts: Record<string, number> = {}\n for (const r of rows) formatCounts[r.format] = (formatCounts[r.format] || 0) + 1\n\n return {\n rows: rows.sort((a, b) => (b.bytes ?? 0) - (a.bytes ?? 0)),\n summary: {\n unique: rows.length,\n sized: sized.length,\n totalBytes,\n totalSize: formatBytes(totalBytes) ?? '0 B',\n avgSize: formatBytes(Math.round(totalBytes / (sized.length || 1))) ?? '0 B',\n over100kb: rows.filter(r => r.over100kb).length,\n legacyFormat: rows.filter(r => r.legacyFormat).length,\n formatCounts,\n },\n }\n}\n\nexport function renderImageSection(audit: ImageAudit): string {\n const s = audit.summary\n const fmt = Object.entries(s.formatCounts).sort((a, b) => b[1] - a[1]).map(([k, v]) => `${k}:${v}`).join(' ')\n const heaviest = audit.rows.filter(r => r.over100kb).slice(0, 15)\n const lines = [\n `## Images`,\n `**${s.unique} unique images** · ${s.totalSize} total · ${s.avgSize} avg · ${s.over100kb} over 100 KB · ${s.legacyFormat} legacy format`,\n `Formats: ${fmt}`,\n ]\n if (heaviest.length) {\n lines.push('', '| Size | Format | URL |', '|------|--------|-----|')\n for (const r of heaviest) lines.push(`| ${r.size} | ${r.format} | ${r.url} |`)\n }\n return lines.join('\\n')\n}\n","export const SERVER_INSTRUCTIONS = `\n# MCP Scraper\n\nScrapes and analyzes web, search, maps, social, and site data. **Pick a tool by NAME from the map\nbelow, then load its schema before calling.** Where a tool needs a value another tool produces, the\nseam is noted so you can chain them.\n\n## Search & research\n- Organic Google results, rankings, local pack -> **search_serp**.\n- Full SERP plus People-Also-Ask and AI-Overview detail -> **harvest_paa**.\n- \\`search_serp\\` returns \\`organicResults[].url\\` (often including reddit.com threads) — feed those into\n \\`extract_url\\` or \\`reddit_thread\\`.\n\n## Pages & sites\n- One page -> **extract_url** (takes a url).\n- Whole site, crawl + SEO report -> **extract_site** (takes a url).\n- Just the URL list/inventory -> **map_site_urls** (takes a url).\n- \\`map_site_urls\\` returns urls you can feed straight into \\`extract_url\\`.\n\n## Google Maps\n- Find multiple places/competitors/prospects -> **maps_search** (returns \\`results[]\\` with name,\n placeUrl, cid).\n- One business deep-dive + reviews -> **maps_place_intel** (takes businessName + location, NOT an id —\n call it directly with a name from a \\`maps_search\\` result or from the user).\n\n## YouTube\n- Find or list videos -> **youtube_harvest** (returns \\`videos[].videoId\\`).\n- Transcribe one video -> **youtube_transcribe** (takes a videoId from \\`youtube_harvest\\`, or a url).\n\n## Facebook\n- Find advertisers -> **facebook_ad_search** (returns \\`advertisers[]\\` with pageId, libraryId).\n- One advertiser's ads -> **facebook_page_intel** (takes pageId, libraryId, or query; returns\n \\`ads[].videoUrl\\`).\n- Transcribe an ad video -> **facebook_ad_transcribe** (takes a videoUrl from \\`facebook_page_intel\\`).\n- Transcribe an organic reel/video/post -> **facebook_video_transcribe** (takes the Facebook url directly).\n\n## Instagram\n- Profile inventory -> **instagram_profile_content** (returns post/reel/tv urls).\n- One post or reel -> **instagram_media_download** (takes a url from \\`instagram_profile_content\\`, or a\n url the user gives).\n\n## Reddit\n- A reddit.com thread/post URL -> **reddit_thread**. Returns the post plus its comment tree and handles\n Reddit's bot wall itself (no login needed). Find threads first with \\`search_serp\\`.\n\n## Other sites & logins (browser agent)\nFor an arbitrary site or a logged-in dashboard with no dedicated tool, use the browser_* agent. **First\ndecide whether the site needs a login:**\n- **Needs a login** (ChatGPT, Claude, any account) -> save it first: **browser_profile_connect** returns\n an mcpscraper.dev sign-in link for the user; one profile holds MANY logins (call it again with the same\n profile + a new domain to add accounts). Poll **browser_profile_list** until AUTHENTICATED, then\n **browser_open** with that profile.\n- **No login** -> **browser_open**, then navigate/read.\n\n## Workflows\nMulti-step orchestrations — prefer these over hand-chaining primitives when the whole job is one of these:\n- Build a local business directory for a niche across a state/region -> **directory_workflow**.\n- Stand up a rank-tracking blueprint (database + cron + ingestion plan) -> **rank_tracker_workflow**.\n- Find which sources an AI answer cites for a query (AEO) -> **query_fanout_workflow** (open a browser\n session on chatgpt.com or claude.ai FIRST, then run it against that session).\n\n## Notes\n- Bulk / full-site crawls: call \\`extract_site\\` with \\`rotateProxies:true\\` for blocked or rate-limited\n sites. It returns a saved folder/artifact plus a summary, not the full content inline.\n- Browser sessions and media transcription cost credits and take longer — prefer the cheapest tool that\n answers the question (plain search/extract before browser agents).\n- Large results are saved to disk or an artifact and returned as a summary plus a path; read the path for\n full detail rather than expecting the whole payload inline.\n`.trim()\n","import { z } from 'zod'\nimport { DEFAULT_MAPS_PROXY_MODE, DEFAULT_PROXY_MODE } from '../schemas.js'\n\nexport const HarvestPaaInputSchema = {\n query: z.string().min(1).describe('Core search topic only. If the user says \"best hvac company in Denver CO\", use query=\"best hvac company\" and location=\"Denver, CO\". Do not include the location in query when it can be separated.'),\n location: z.string().optional().describe('City, region, or country for geo-targeted results, inferred from the user request when present, e.g. \"Denver, CO\", \"Tokyo, Japan\", \"London, UK\".'),\n maxQuestions: z.number().int().min(1).max(200).default(30).describe('Number of PAA questions to extract. Default 30. Maximum 200. Use 10 for quick probes, 30 for normal research, 100-200 when the user asks for everything/full/deep research. Larger harvests get a longer server time budget (151-200 questions → up to 280s). Credits are charged by extracted question; unused request hold is refunded.'),\n gl: z.string().length(2).default('us').describe('Google country code inferred from location or user language. Examples: United States us, United Kingdom gb, Japan jp, Canada ca, Australia au.'),\n hl: z.string().default('en').describe('Google interface/content language inferred from the user request. Use en unless the user asks for another language or locale.'),\n device: z.enum(['desktop', 'mobile']).default('desktop').describe('SERP device context. Use desktop by default; use mobile only when the user asks for mobile rankings.'),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_PROXY_MODE).describe('Leave unset — routing is automatic (clean egress by default; residential only when a location is given, with fallback). Set \"location\" only to force local-pack targeting.'),\n proxyZip: z.string().regex(/^\\d{5}$/).optional().describe('Optional US ZIP override for residential location proxy targeting. Use only with proxyMode location when the user gives a specific ZIP or city-center targeting needs to be forced.'),\n debug: z.boolean().default(false).describe('Include sanitized browser/session/location diagnostics in the response. Use true when debugging localization, CAPTCHA, or proxy behavior.'),\n}\nexport type HarvestPaaInput = z.infer<ReturnType<typeof z.object<typeof HarvestPaaInputSchema>>>\n\nexport const ExtractUrlInputSchema = {\n url: z.string().url().describe('Public http/https URL to extract. Use this when the user provides one specific page URL.'),\n screenshot: z.boolean().default(false).describe('Also capture a full-page screenshot of the URL. Saved to ~/Downloads/mcp-scraper/screenshots/ and returned inline. Use when the user asks to see or capture the page visually.'),\n screenshotDevice: z.enum(['desktop', 'mobile']).default('desktop').describe('Viewport for screenshot. desktop = 1440×900. mobile = 390×844. Default desktop.'),\n extractBranding: z.boolean().default(false).describe('Extract brand colors, fonts, logo, and favicon using a rendered browser session. Returns colorScheme (light/dark), colors (primary/accent/background/text/heading as hex), fonts (heading/body family names), and assets (logo URL, favicon URL). Use when the user asks about brand colors, site theme, or brand assets.'),\n downloadMedia: z.boolean().default(false).describe('Extract and download all page media (images, video, audio) to ~/Downloads/mcp-scraper/media/. Ad networks, tracking pixels, and noise URLs are filtered automatically. Use when the user asks to download or harvest assets from a page.'),\n mediaTypes: z.array(z.enum(['image', 'video', 'audio'])).default(['image', 'video', 'audio']).describe('Which media types to download. Default all three.'),\n allowLocal: z.boolean().default(false).describe('Allow localhost and private-network URLs. For local development only.'),\n depositToVault: z.boolean().default(false).describe('Also save the full page content into the user\\'s MCP Memory Library vault, server-side. The complete body is stored and embedded for semantic recall WITHOUT passing through this conversation — the tool result only confirms the saved note. Use when the user asks to save/remember/store a page, or to build a knowledge base from scrapes.'),\n vaultName: z.string().trim().min(1).max(120).optional().describe('Optional vault to deposit into. Defaults to the user\\'s personal vault.'),\n}\nexport type ExtractUrlInput = z.infer<ReturnType<typeof z.object<typeof ExtractUrlInputSchema>>>\n\nexport const MapSiteUrlsInputSchema = {\n url: z.string().url().describe('Public website URL or domain to crawl for internal URLs. Use before extract_site when the user asks to audit/map/crawl a site.'),\n maxUrls: z.number().int().min(1).max(10000).optional().describe('Maximum URLs to discover. Use 100 for normal maps, up to 10000 for a full inventory. Large maps (over 500 URLs) write the complete inventory to a local file and return only a summary plus the file path instead of the full list inline.'),\n}\nexport type MapSiteUrlsInput = z.infer<ReturnType<typeof z.object<typeof MapSiteUrlsInputSchema>>>\n\nexport const ExtractSiteInputSchema = {\n url: z.string().url().describe('Public website URL or domain to crawl for page CONTENT across multiple pages (map + scrape). Use when the user wants the content/text/markdown of a site\\'s pages. For a technical SEO audit (issues, link graph, indexability, headings, image weights) use audit_site instead — extract_site returns content only, not analysis.'),\n maxPages: z.number().int().min(1).max(10000).optional().describe('Maximum pages to extract. Use 50 for a normal crawl, up to 10000 for a full-site bulk scrape. Bulk crawls (over 25 pages) switch to folder mode: every page is saved as its own Markdown file in a local folder and the response returns only a summary plus the folder path, so the full content never floods the context window.'),\n rotateProxies: z.boolean().optional().describe('Route page fetches through rotating residential proxies in headful browsers to defeat rate-limiting and bot blocks (403/429). Discovers URLs from the sitemap, fetches in batches with a fresh proxy per batch, retries failures on a new proxy, and automatically parallelizes across the account\\'s concurrency slots. Slower and pricier than the default fetch path, so use only when a site blocks normal crawling.'),\n rotateProxyEvery: z.number().int().min(1).max(100).optional().describe('When rotateProxies is on, how many pages to fetch per browser/proxy before discarding it and minting a fresh one. Default 30. Lower values rotate IPs more aggressively against strict rate limits.'),\n formats: z.array(z.enum(['markdown', 'links', 'json', 'images', 'branding'])).optional().describe('Which data formats to include in the per-page output. markdown=page content as Markdown, links=internal/external link graph, json=structured data/schema, images=per-page image URLs (links only, no downloads), branding=site-level logo/colors/fonts captured once from the homepage (requires a browser, adds time). markdown, links, json, and images are always captured cheaply from the HTML; branding is the only opt-in capture. Defaults to markdown+links when omitted.'),\n}\nexport type ExtractSiteInput = z.infer<ReturnType<typeof z.object<typeof ExtractSiteInputSchema>>>\n\nexport const AuditSiteInputSchema = {\n url: z.string().url().describe('Public website URL or domain to run a full technical SEO audit on. Use when the user asks for a technical audit, SEO audit, site health check, or a Screaming-Frog-style crawl — i.e. they want ANALYSIS (issues, internal link graph, indexability, heading breakdown, image sizes/formats), not just page content. For plain content scraping use extract_site instead.'),\n maxPages: z.number().int().min(1).max(10000).optional().describe('Maximum pages to crawl and audit. Use 50 for a normal audit, up to 10000 for a full-site audit. The audit always writes a folder of analysis files (report.md, issues.json, pages.jsonl, links.jsonl, link-metrics.jsonl, images.jsonl) plus per-page content, and returns a headline summary plus the folder path.'),\n rotateProxies: z.boolean().optional().describe('Route page fetches through rotating residential proxies to defeat rate-limiting and bot blocks (403/429). Slower and pricier than the default fetch path, so use only when a site blocks normal crawling.'),\n rotateProxyEvery: z.number().int().min(1).max(100).optional().describe('When rotateProxies is on, how many pages to fetch per browser/proxy before discarding it and minting a fresh one. Default 30.'),\n}\nexport type AuditSiteInput = z.infer<ReturnType<typeof z.object<typeof AuditSiteInputSchema>>>\n\nexport const YoutubeHarvestInputSchema = {\n mode: z.enum(['search', 'channel']).describe('Use search for topic/keyword requests. Use channel when the user provides @handle, channel ID, or channel URL.'),\n query: z.string().optional().describe('Required when mode is search. The YouTube search topic in the user’s words.'),\n channelHandle: z.string().optional().describe('YouTube channel handle, channel ID, or URL. Examples: @mkbhd, UC..., https://youtube.com/@mkbhd.'),\n maxVideos: z.number().int().min(1).max(500).default(50).describe('Number of videos to return. Default 50, maximum 500. Use 10-25 for quick topic discovery, 50 for normal channel/search harvests, and larger values only when the user asks for full channel/history because large responses consume more context.'),\n}\nexport type YoutubeHarvestInput = z.infer<ReturnType<typeof z.object<typeof YoutubeHarvestInputSchema>>>\n\nexport const YoutubeTranscribeInputSchema = {\n videoId: z.string().min(1).optional().describe('YouTube video ID, e.g. dQw4w9WgXcQ. Use only an ID returned by youtube_harvest or visible in a YouTube URL; do not invent one.'),\n url: z.string().url().optional().describe('Full YouTube URL, e.g. https://www.youtube.com/watch?v=dQw4w9WgXcQ or https://youtu.be/dQw4w9WgXcQ. Use this when the user pasted a URL instead of an ID. Provide videoId or url.'),\n}\nexport type YoutubeTranscribeInput = z.infer<ReturnType<typeof z.object<typeof YoutubeTranscribeInputSchema>>>\n\nexport const FacebookPageIntelInputSchema = {\n pageId: z.string().optional().describe('Facebook advertiser/page ID. Use only a pageId returned by facebook_ad_search/facebook_page_intel or copied from Facebook Ad Library; do not construct one yourself.'),\n libraryId: z.string().optional().describe('Facebook Ad Library archive ID for a known ad or advertiser sample. Use a libraryId returned by facebook_ad_search, or a libraryId/adArchiveId visible in Ad Library.'),\n query: z.string().optional().describe('Advertiser or brand name when pageId/libraryId is not known. One of pageId, libraryId, or query is required.'),\n maxAds: z.number().int().min(1).max(200).default(50).describe('Maximum ads to inspect. Default 50, maximum 200. Prefer 25-50 for focused advertiser scans; use 100-200 only when the user asks for a broad ad archive sweep.'),\n country: z.string().length(2).default('US').describe('Two-letter Ad Library country code. Default US. Examples: US, CA, GB, AU. Infer from the user request when they name a country.'),\n}\nexport type FacebookPageIntelInput = z.infer<ReturnType<typeof z.object<typeof FacebookPageIntelInputSchema>>>\n\nexport const FacebookAdSearchInputSchema = {\n query: z.string().min(1).describe('Advertiser, brand, competitor, niche, or keyword to search in Facebook Ad Library.'),\n country: z.string().length(2).default('US').describe('Two-letter Ad Library country code. Default US. Examples: US, CA, GB, AU.'),\n maxResults: z.number().int().min(1).max(20).default(10).describe('Maximum advertisers to return. Default 10, maximum 20. Prefer tighter search terms over maxing this out.'),\n}\nexport type FacebookAdSearchInput = z.infer<ReturnType<typeof z.object<typeof FacebookAdSearchInputSchema>>>\n\nexport const RedditThreadInputSchema = {\n url: z.string().min(1).describe('A reddit.com thread/post URL (www, old, or new Reddit, or a redd.it link). The service fetches it via old.reddit through a residential proxy and returns the post plus its comment tree.'),\n maxComments: z.number().int().min(1).max(2000).optional().describe('Optional cap on comments returned. Omit to return all captured comments.'),\n}\nexport type RedditThreadInput = z.infer<ReturnType<typeof z.object<typeof RedditThreadInputSchema>>>\n\nexport const FacebookAdTranscribeInputSchema = {\n videoUrl: z.string().url().describe('Direct Facebook CDN video URL from a facebook_page_intel ad result. Do not pass a public Facebook reel/post/share URL here; use facebook_video_transcribe for organic Facebook URLs.'),\n}\nexport type FacebookAdTranscribeInput = z.infer<ReturnType<typeof z.object<typeof FacebookAdTranscribeInputSchema>>>\n\nexport const FacebookVideoTranscribeInputSchema = {\n url: z.string().url().describe('Organic Facebook reel, video, watch, post, or share URL from facebook.com, m.facebook.com, or fb.watch. The tool renders the page, extracts the best matching public Facebook CDN MP4 URL, then transcribes it. Use this when the user pastes a normal Facebook video page URL and asks for the transcript or downloadable MP4.'),\n quality: z.enum(['best', 'hd', 'sd']).default('best').describe('Preferred progressive MP4 quality. Use best by default; hd prefers the highest HD progressive URL; sd forces the SD URL.'),\n}\nexport type FacebookVideoTranscribeInput = z.infer<ReturnType<typeof z.object<typeof FacebookVideoTranscribeInputSchema>>>\n\nexport const InstagramProfileContentInputSchema = {\n handle: z.string().min(1).optional().describe('Instagram handle, with or without @. Provide handle or url.'),\n url: z.string().url().optional().describe('Instagram profile URL, e.g. https://www.instagram.com/nasaartemis/. Provide handle or url.'),\n profile: z.string().min(1).optional().describe('Optional saved hosted browser profile name to load authenticated Instagram access. If omitted, the server uses its configured default profile when present.'),\n saveProfileChanges: z.boolean().optional().describe('Whether to save browser changes back to the hosted profile. Leave unset unless intentionally updating the saved login session.'),\n maxItems: z.number().int().min(1).max(2000).default(50).describe('Maximum profile grid post/reel/tv URLs to collect. Default 50, maximum 2000. Use higher values only when the user asks for a fuller archive.'),\n maxScrolls: z.number().int().min(0).max(250).default(10).describe('Maximum pagination scroll attempts. Default 10, maximum 250. Increase for long profiles when Instagram continues loading more grid links.'),\n scrollDelayMs: z.number().int().min(250).max(5000).default(1200).describe('Delay after each pagination scroll before collecting newly loaded links. Default 1200ms. Increase to 2000-3000ms when Instagram loads slowly.'),\n stableScrollLimit: z.number().int().min(1).max(10).default(4).describe('Stop after this many consecutive scrolls with no new links or scroll progress. Default 4.'),\n}\nexport type InstagramProfileContentInput = z.infer<ReturnType<typeof z.object<typeof InstagramProfileContentInputSchema>>>\n\nexport const InstagramMediaDownloadInputSchema = {\n url: z.string().url().describe('Instagram post, reel, or tv URL, e.g. https://www.instagram.com/reel/SHORTCODE/. The tool renders the page, extracts text, image metadata, and Instagram CDN media tracks.'),\n profile: z.string().min(1).optional().describe('Optional saved hosted browser profile name to load authenticated Instagram access. If omitted, the server uses its configured default profile when present.'),\n saveProfileChanges: z.boolean().optional().describe('Whether to save browser changes back to the hosted profile. Leave unset unless intentionally updating the saved login session.'),\n mediaTypes: z.array(z.enum(['image', 'video', 'audio'])).default(['image', 'video', 'audio']).describe('Which media types to download when downloadMedia is true. Reels commonly expose separate video-only and audio-only MP4 tracks.'),\n downloadMedia: z.boolean().default(true).describe('Download extracted text/media files to the MCP Scraper output directory when the API server can write files. Always returns extracted media URLs even when false.'),\n downloadAllTracks: z.boolean().default(false).describe('Download every captured Instagram MP4 track instead of only the selected best video and audio tracks. Use false by default to avoid duplicate bitrates.'),\n includeTranscript: z.boolean().default(false).describe('Transcribe the selected audio track when available. This adds transcription cost and may take longer.'),\n mux: z.boolean().default(true).describe('When video and audio tracks are downloaded separately, try to mux them into a single MP4 if ffmpeg is available. Returns separate tracks when muxing is unavailable.'),\n}\nexport type InstagramMediaDownloadInput = z.infer<ReturnType<typeof z.object<typeof InstagramMediaDownloadInputSchema>>>\n\nexport const MapsPlaceIntelInputSchema = {\n businessName: z.string().min(1).describe('Business name only. If user says \"Elite Roofing Denver CO\", use businessName=\"Elite Roofing\" and location=\"Denver, CO\".'),\n location: z.string().min(1).describe('City/region/country where the business should be searched, e.g. \"Denver, CO\". Infer from the user request when possible.'),\n gl: z.string().length(2).default('us').describe('Google country code inferred from location.'),\n hl: z.string().length(2).default('en').describe('Language inferred from user request.'),\n includeReviews: z.boolean().default(false).describe('Whether to fetch individual review cards. Use true when the user asks for reviews, customer pain, complaints, praise, themes, or review evidence.'),\n maxReviews: z.number().int().min(1).max(500).default(50).describe('Max review cards to return when includeReviews is true. Default 50, maximum 500. Use 50 for normal review analysis and larger values only for deep review mining.'),\n}\nexport type MapsPlaceIntelInput = z.infer<ReturnType<typeof z.object<typeof MapsPlaceIntelInputSchema>>>\n\nexport const MapsSearchInputSchema = {\n query: z.string().min(1).describe('Business category, niche, keyword, or search term. If the user says \"roofers in Denver CO\", use query=\"roofers\" and location=\"Denver, CO\". Do not put the location here when it can be separated.'),\n location: z.string().optional().describe('City, region, country, or service area for the Maps search, e.g. \"Denver, CO\". Infer from the user request when present.'),\n gl: z.string().length(2).default('us').describe('Google country code inferred from location.'),\n hl: z.string().length(2).default('en').describe('Language inferred from user request.'),\n maxResults: z.number().int().min(1).max(50).default(10).describe('Number of Google Maps business/profile candidates to return. Default 10. Maximum 50. Use 10 unless the user asks for more.'),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_MAPS_PROXY_MODE).describe('Proxy targeting mode. Maps defaults to location so local market searches get city/state residential proxy targeting and rotation. Use configured to force the service proxy without city/ZIP targeting, and none only for local direct-network debugging.'),\n proxyZip: z.string().regex(/^\\d{5}$/).optional().describe('Optional US ZIP override for residential location proxy targeting. Use when the user gives a specific ZIP or city-center ZIP.'),\n debug: z.boolean().default(false).describe('Include sanitized browser/proxy diagnostics when debugging Maps localization, CAPTCHA, or proxy behavior.'),\n}\nexport type MapsSearchInput = z.infer<ReturnType<typeof z.object<typeof MapsSearchInputSchema>>>\n\nexport const DirectoryWorkflowInputSchema = {\n query: z.string().min(1).describe('Business category, niche, or keyword to search on Google Maps for every selected market, e.g. roofers, dentists, med spas. Do not include the city here.'),\n state: z.string().min(2).default('TN').describe('US state abbreviation or state name used to select Census places, e.g. TN or Tennessee.'),\n minPopulation: z.number().int().min(0).default(100000).describe('Minimum Census place population for market selection. Use 100000 for \"cities above 100k population\".'),\n populationYear: z.number().int().min(2020).max(2025).default(2025).describe('Census population estimate year from the 2020-2025 Population Estimates Program city/place dataset.'),\n maxCities: z.number().int().min(1).max(100).default(25).describe('Maximum number of markets to process after sorting by population descending.'),\n maxResultsPerCity: z.number().int().min(1).max(50).default(50).describe('Google Maps business/profile candidates to collect for each city. Maximum 50.'),\n concurrency: z.number().int().min(1).max(5).default(5).describe('How many city Maps searches to run in parallel. Use 5 for broad directory batches unless debugging.'),\n includeZipGroups: z.boolean().default(true).describe('Attach ZIP groups from a configured US ZIPS CSV when available. Set MCP_SCRAPER_USZIPS_CSV_PATH on the API server or pass usZipsCsvPath in local/test mode.'),\n usZipsCsvPath: z.string().optional().describe('Local/test-only path to a US ZIPS CSV with state_abbr, zipcode, county, city columns, such as Lead Magician tools/analytics/data/uszips.csv. Deployed APIs should use MCP_SCRAPER_USZIPS_CSV_PATH instead.'),\n saveCsv: z.boolean().default(true).describe('Save a directory-ready CSV to the MCP Scraper output directory and return its path. CSV rows include source_location, result_position, business_name, review_stars, review_count, category, address, phone, hours_status, website_url, directions_url, place_url, CID fields, population, and ZIP groups.'),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_MAPS_PROXY_MODE).describe('Proxy targeting mode for every city Maps search. Maps workflows default to location so each city can use city/state or ZIP-group residential proxy targeting. Use configured to force the service proxy without city/ZIP targeting, and none only for local direct-network debugging.'),\n proxyZip: z.string().regex(/^\\d{5}$/).optional().describe('Optional ZIP override for proxy targeting. Normally omit it so each city can use its ZIP group or city/state location.'),\n debug: z.boolean().default(false).describe('Include sanitized browser/proxy diagnostics in each Maps browser session when supported.'),\n}\nexport type DirectoryWorkflowInput = z.infer<ReturnType<typeof z.object<typeof DirectoryWorkflowInputSchema>>>\n\nexport const RankTrackerModeSchema = z.enum(['maps', 'organic', 'ai_overview', 'paa'])\nexport type RankTrackerMode = z.infer<typeof RankTrackerModeSchema>\n\nexport const RankTrackerBlueprintInputSchema = {\n projectName: z.string().min(1).optional().describe('Optional name for the rank tracker project, client, or campaign.'),\n targetDomain: z.string().min(1).optional().describe('Primary domain to track in organic results, AI Overview citations, and PAA sources, e.g. example.com.'),\n targetBusinessName: z.string().min(1).optional().describe('Primary Google Business Profile or brand/business name to match in Maps results. Required for reliable Maps rank tracking.'),\n trackingModes: z.array(RankTrackerModeSchema).min(1).max(4).default(['maps', 'organic', 'ai_overview', 'paa']).describe('Rank tracker surfaces to build. maps uses directory_workflow/maps_search. organic uses search_serp. ai_overview uses search_serp/harvest_paa. paa uses harvest_paa source presence.'),\n keywords: z.array(z.string().min(1)).max(200).default([]).describe('Seed keywords or service queries to track. Leave empty when the downstream AI should create the keyword table from user input.'),\n locations: z.array(z.string().min(1)).max(100).default([]).describe('Markets, cities, ZIPs, or service areas to track. Use city/state strings like Denver, CO for localized SERP and Maps checks.'),\n competitors: z.array(z.string().min(1)).max(100).default([]).describe('Optional competitor domains or business names to persist as comparison targets.'),\n database: z.enum(['postgres', 'neon', 'supabase', 'sqlite', 'mysql']).default('postgres').describe('Database family the downstream AI should target when generating migrations.'),\n scheduleCadence: z.enum(['daily', 'weekly', 'monthly', 'custom']).default('weekly').describe('Default recurring rank check cadence for the generated cron/heartbeat plan.'),\n customCron: z.string().min(1).optional().describe('Cron expression to use when scheduleCadence is custom.'),\n timezone: z.string().min(1).default('UTC').describe('IANA timezone for scheduled rank checks, e.g. America/Denver.'),\n includeCron: z.boolean().default(true).describe('Include a cron or heartbeat worker plan. Keep true for production rank trackers.'),\n includeDashboard: z.boolean().default(true).describe('Include dashboard/reporting requirements in the generated prompt.'),\n includeAlerts: z.boolean().default(true).describe('Include alert rules for rank movement and SERP feature gains/losses.'),\n notes: z.string().max(4000).optional().describe('Extra product, client, stack, or hosting requirements to include in the implementation prompt.'),\n}\nexport type RankTrackerBlueprintInput = z.infer<ReturnType<typeof z.object<typeof RankTrackerBlueprintInputSchema>>>\n\nconst NullableString = z.string().nullable()\n\nconst MapsSearchAttemptOutput = z.object({\n attemptNumber: z.number().int().min(1),\n maxAttempts: z.number().int().min(1),\n status: z.enum(['ok', 'failed']),\n outcome: z.string(),\n willRetry: z.boolean(),\n durationMs: z.number().int().min(0),\n resultCount: z.number().int().min(0),\n error: NullableString,\n proxyMode: z.enum(['location', 'configured', 'none']),\n proxyResolutionSource: z.enum(['disabled', 'location_reused', 'location_created', 'configured_fallback', 'unavailable']).nullable(),\n proxyIdSuffix: NullableString,\n proxyTargetLevel: z.enum(['zip', 'city', 'state']).nullable(),\n proxyTargetLocation: NullableString,\n proxyTargetZip: NullableString,\n browserSessionIdSuffix: NullableString,\n observedIp: NullableString,\n observedCity: NullableString,\n observedRegion: NullableString,\n})\n\nexport const MapsSearchOutputSchema = {\n query: z.string(),\n location: z.string().nullable(),\n searchQuery: z.string(),\n searchUrl: z.string().url(),\n extractedAt: z.string(),\n requestedMaxResults: z.number().int().min(1).max(50),\n resultCount: z.number().int().min(0).max(50),\n results: z.array(z.object({\n position: z.number().int().min(1),\n name: z.string(),\n placeUrl: z.string().url(),\n cid: NullableString,\n cidDecimal: NullableString,\n rating: NullableString,\n reviewCount: NullableString,\n category: NullableString,\n address: NullableString,\n phone: NullableString,\n hoursStatus: NullableString,\n websiteUrl: NullableString,\n directionsUrl: NullableString,\n metadata: z.array(z.string()),\n })),\n attempts: z.array(MapsSearchAttemptOutput),\n durationMs: z.number().int().min(0),\n}\n\nconst DirectoryMapsBusinessOutput = z.object({\n position: z.number().int().min(1),\n name: z.string(),\n placeUrl: z.string().url(),\n cid: NullableString,\n cidDecimal: NullableString,\n rating: NullableString,\n reviewCount: NullableString,\n category: NullableString,\n address: NullableString,\n phone: NullableString,\n hoursStatus: NullableString,\n websiteUrl: NullableString,\n directionsUrl: NullableString,\n metadata: z.array(z.string()),\n})\n\nexport const DirectoryWorkflowOutputSchema = {\n query: z.string(),\n state: z.string(),\n minPopulation: z.number().int().min(0),\n populationYear: z.number().int().min(2020).max(2025),\n maxResultsPerCity: z.number().int().min(1).max(50),\n concurrency: z.number().int().min(1).max(5),\n censusSourceUrl: z.string().url(),\n usZipsSourcePath: NullableString,\n warnings: z.array(z.string()),\n extractedAt: z.string(),\n selectedCityCount: z.number().int().min(0),\n totalResultCount: z.number().int().min(0),\n csvPath: NullableString,\n cities: z.array(z.object({\n city: z.string(),\n state: z.string(),\n location: z.string(),\n cityKey: z.string(),\n censusName: z.string(),\n population: z.number().int().min(0),\n populationYear: z.number().int().min(2020).max(2025),\n zips: z.array(z.string()),\n counties: z.array(z.string()),\n status: z.enum(['ok', 'empty', 'failed']),\n error: NullableString,\n resultCount: z.number().int().min(0),\n durationMs: z.number().int().min(0),\n attempts: z.array(MapsSearchAttemptOutput),\n results: z.array(DirectoryMapsBusinessOutput),\n })),\n durationMs: z.number().int().min(0),\n}\n\nconst RankTrackerToolPlanOutput = z.object({\n tool: z.string(),\n purpose: z.string(),\n})\n\nconst RankTrackerTableOutput = z.object({\n name: z.string(),\n purpose: z.string(),\n keyColumns: z.array(z.string()),\n})\n\nconst RankTrackerCronJobOutput = z.object({\n name: z.string(),\n purpose: z.string(),\n modes: z.array(RankTrackerModeSchema),\n recommendedTools: z.array(z.string()),\n})\n\nexport const RankTrackerBlueprintOutputSchema = {\n projectName: z.string(),\n targetDomain: NullableString,\n targetBusinessName: NullableString,\n trackingModes: z.array(RankTrackerModeSchema),\n database: z.string(),\n recommendedTools: z.array(RankTrackerToolPlanOutput),\n tables: z.array(RankTrackerTableOutput),\n cron: z.object({\n enabled: z.boolean(),\n cadence: z.string(),\n expression: z.string(),\n timezone: z.string(),\n jobs: z.array(RankTrackerCronJobOutput),\n }),\n metrics: z.array(z.string()),\n implementationPrompt: z.string(),\n}\n\nconst OrganicResultOutput = z.object({\n position: z.number().int(),\n title: z.string(),\n url: z.string(),\n domain: z.string(),\n snippet: NullableString,\n})\n\nconst AiOverviewOutput = z.object({\n detected: z.boolean(),\n text: NullableString,\n}).nullable()\n\nconst EntityIdsOutput = z.object({\n entities: z.array(z.object({\n name: z.string(),\n kgId: z.string().nullable(),\n cid: z.string().nullable(),\n gcid: z.string().nullable(),\n })).describe('Each entity actually named on the page, with whichever of its kgId/cid/gcid were found — the linked view. kgIds/cids/gcids below are the same IDs as flat deduplicated lists, without the name link, kept for backward compatibility.'),\n kgIds: z.array(z.string()),\n cids: z.array(z.string()),\n gcids: z.array(z.string()),\n}).nullable()\n\nexport const HarvestPaaOutputSchema = {\n query: z.string(),\n location: NullableString,\n questionCount: z.number().int().min(0),\n completionStatus: NullableString,\n questions: z.array(z.object({\n question: z.string(),\n answer: NullableString,\n sourceTitle: NullableString,\n sourceSite: NullableString,\n })),\n organicResults: z.array(OrganicResultOutput),\n aiOverview: AiOverviewOutput,\n entityIds: EntityIdsOutput,\n durationMs: z.number().min(0).nullable(),\n}\n\nexport const SearchSerpOutputSchema = {\n query: z.string(),\n location: NullableString,\n organicResults: z.array(OrganicResultOutput),\n localPack: z.array(z.object({\n position: z.number().int(),\n name: z.string(),\n rating: NullableString,\n reviewCount: NullableString,\n websiteUrl: NullableString,\n })),\n aiOverview: AiOverviewOutput,\n entityIds: EntityIdsOutput,\n}\n\nexport const ExtractUrlOutputSchema = {\n url: z.string(),\n title: NullableString,\n headings: z.array(z.object({\n level: z.number().int(),\n text: z.string(),\n })),\n schemaBlockCount: z.number().int().min(0),\n entityName: NullableString,\n entityTypes: z.array(z.string()),\n napScore: z.number().nullable(),\n missingSchemaFields: z.array(z.string()),\n screenshotSaved: NullableString,\n memory: z.object({\n deposited: z.boolean(),\n vault: z.string().optional(),\n noteId: z.string().optional(),\n path: z.string().optional(),\n chunks: z.number().int().optional(),\n fileUrl: z.string().optional(),\n fileExpiresAt: z.string().optional(),\n error: z.string().optional(),\n }).optional(),\n}\n\nexport const ExtractSiteOutputSchema = {\n url: z.string(),\n pageCount: z.number().int().min(0),\n pages: z.array(z.object({\n url: z.string(),\n title: NullableString,\n schemaTypes: z.array(z.string()),\n })),\n durationMs: z.number().min(0),\n}\n\nexport const AuditSiteOutputSchema = {\n url: z.string(),\n pageCount: z.number().int().min(0),\n durationMs: z.number().min(0),\n bulkFolder: z.string().nullable(),\n issues: z.record(z.string(), z.number()),\n images: z.object({\n unique: z.number().int().min(0),\n totalBytes: z.number().min(0),\n over100kb: z.number().int().min(0),\n legacyFormat: z.number().int().min(0),\n }),\n links: z.object({\n internal: z.number().int().min(0),\n external: z.number().int().min(0),\n orphans: z.number().int().min(0),\n brokenInternal: z.number().int().min(0),\n externalDomains: z.number().int().min(0),\n }),\n}\n\nexport const MapsPlaceIntelOutputSchema = {\n name: z.string(),\n rating: NullableString,\n reviewCount: NullableString,\n category: NullableString,\n address: NullableString,\n phone: NullableString,\n website: NullableString,\n hoursSummary: NullableString,\n bookingUrl: NullableString,\n kgmid: NullableString,\n cidDecimal: NullableString,\n cidUrl: NullableString,\n lat: z.number().nullable(),\n lng: z.number().nullable(),\n reviewsStatus: z.string(),\n reviewsCollected: z.number().int().min(0),\n reviewTopics: z.array(z.object({\n label: z.string(),\n count: z.string(),\n })),\n}\n\nexport const CreditsInfoOutputSchema = {\n balanceCredits: z.number().nullable(),\n matchedCost: z.object({\n label: z.string(),\n credits: z.number(),\n unit: z.string(),\n notes: NullableString,\n }).nullable(),\n costs: z.array(z.object({\n key: z.string(),\n label: z.string(),\n credits: z.number(),\n unit: z.string(),\n notes: NullableString,\n })),\n ledger: z.array(z.object({\n createdAt: z.string(),\n operation: z.string(),\n credits: z.number(),\n description: NullableString,\n })),\n concurrency: z.object({\n currentExtraSlots: z.number().int().min(0),\n currentLimit: z.number().int().min(1),\n hasSubscription: z.boolean(),\n upgrade: z.object({\n product: z.string(),\n priceLabel: z.string(),\n unitAmountUsd: z.number(),\n currency: z.string(),\n interval: z.string(),\n billingUrl: z.string().url(),\n terminalCommand: z.string(),\n terminalCommandWithApiKeyEnv: z.string(),\n }),\n }).nullable(),\n}\n\nexport const MapSiteUrlsOutputSchema = {\n startUrl: z.string(),\n totalFound: z.number().int().min(0),\n truncated: z.boolean(),\n okCount: z.number().int().min(0),\n redirectCount: z.number().int().min(0),\n brokenCount: z.number().int().min(0),\n urls: z.array(z.object({\n url: z.string(),\n status: z.number().int().nullable(),\n })),\n durationMs: z.number().min(0),\n}\n\nexport const YoutubeHarvestOutputSchema = {\n mode: z.string(),\n videoCount: z.number().int().min(0),\n channel: z.object({\n title: NullableString,\n subscriberCount: NullableString,\n }).nullable(),\n videos: z.array(z.object({\n videoId: z.string(),\n title: z.string(),\n channelName: NullableString,\n views: NullableString,\n duration: NullableString,\n url: NullableString,\n })),\n}\n\nexport const FacebookAdSearchOutputSchema = {\n query: z.string(),\n advertiserCount: z.number().int().min(0),\n advertisers: z.array(z.object({\n name: NullableString,\n pageId: NullableString,\n pageUrl: NullableString,\n adCount: z.number().int().nullable(),\n libraryId: NullableString,\n sampleLibraryId: NullableString,\n })),\n}\n\nexport const RedditThreadOutputSchema = {\n sourceUrl: NullableString,\n oldRedditUrl: NullableString,\n title: NullableString,\n author: NullableString,\n score: NullableString,\n postBody: NullableString,\n numComments: z.number().int().min(0),\n comments: z.array(z.object({\n author: NullableString,\n score: NullableString,\n depth: z.number().int().min(0),\n body: z.string(),\n })),\n}\n\nexport const FacebookPageIntelOutputSchema = {\n advertiserName: NullableString,\n totalAds: z.number().int().min(0),\n activeCount: z.number().int().min(0),\n videoCount: z.number().int().min(0),\n imageCount: z.number().int().min(0),\n ads: z.array(z.object({\n libraryId: NullableString,\n status: NullableString,\n creativeType: NullableString,\n primaryText: NullableString,\n headline: NullableString,\n cta: NullableString,\n startDate: NullableString,\n landingUrl: NullableString,\n domain: NullableString,\n videoUrl: NullableString,\n imageUrl: NullableString,\n videoPoster: NullableString,\n variations: z.number().int().nullable(),\n })),\n}\n\nexport const FacebookVideoTranscribeOutputSchema = {\n sourceUrl: z.string().url(),\n pageUrl: z.string().url(),\n videoId: NullableString,\n ownerName: NullableString,\n selectedQuality: z.string(),\n bitrate: z.number().int().nullable(),\n videoDurationSec: z.number().nullable(),\n videoUrl: z.string().url(),\n wordCount: z.number().int().min(0),\n chunkCount: z.number().int().min(0),\n transcriptText: z.string(),\n chunks: z.array(z.object({\n startSec: z.number(),\n endSec: z.number(),\n text: z.string(),\n })),\n}\n\nconst TranscriptChunkOutput = z.object({\n startSec: z.number(),\n endSec: z.number(),\n text: z.string(),\n})\n\nconst InstagramBrowserOutput = z.object({\n mode: z.literal('hosted'),\n requestedMode: z.literal('hosted'),\n profileName: NullableString,\n profileSource: z.literal('hosted'),\n profileDirConfigured: z.boolean(),\n executablePathConfigured: z.boolean(),\n})\n\nconst InstagramPaginationOutput = z.object({\n maxItems: z.number().int().min(1).max(2000),\n maxScrolls: z.number().int().min(0).max(250),\n attemptedScrolls: z.number().int().min(0),\n stableScrolls: z.number().int().min(0),\n stableScrollLimit: z.number().int().min(1).max(10),\n scrollDelayMs: z.number().int().min(250).max(5000),\n reachedMaxItems: z.boolean(),\n reachedReportedPostCount: z.boolean(),\n finalScrollHeight: z.number().int().nullable(),\n stoppedReason: z.enum(['max_items', 'reported_post_count', 'stable_scrolls', 'max_scrolls', 'no_scrolls']),\n stages: z.array(z.object({\n stage: z.string(),\n itemCount: z.number().int().min(0),\n addedCount: z.number().int().min(0),\n scrollY: z.number().nullable(),\n scrollHeight: z.number().nullable(),\n })),\n})\n\nexport const InstagramProfileContentOutputSchema = {\n handle: z.string(),\n profileUrl: z.string().url(),\n pageUrl: z.string().url(),\n browser: InstagramBrowserOutput,\n profileName: NullableString,\n reportedPostCount: z.number().int().nullable(),\n reportedPostCountText: NullableString,\n followerCountText: NullableString,\n followingCountText: NullableString,\n collectedContentCount: z.number().int().min(0),\n typeCounts: z.object({\n post: z.number().int().min(0),\n reel: z.number().int().min(0),\n tv: z.number().int().min(0),\n }),\n pagination: InstagramPaginationOutput,\n limited: z.boolean(),\n limitations: z.array(z.string()),\n items: z.array(z.object({\n url: z.string().url(),\n type: z.enum(['post', 'reel', 'tv']),\n shortcode: z.string(),\n anchorText: NullableString,\n firstSeenStage: z.string(),\n })),\n}\n\nconst InstagramMediaTrackOutput = z.object({\n url: z.string().url(),\n streamType: z.enum(['video', 'audio', 'unknown']),\n bitrate: z.number().int().nullable(),\n durationSec: z.number().nullable(),\n vencodeTag: NullableString,\n width: z.number().int().nullable(),\n height: z.number().int().nullable(),\n})\n\nconst InstagramDownloadOutput = z.object({\n kind: z.enum(['text', 'image', 'video', 'audio', 'muxed_video']),\n url: z.string().url().nullable(),\n savedPath: NullableString,\n sizeBytes: z.number().int().nullable(),\n mimeType: NullableString,\n error: NullableString,\n})\n\nexport const InstagramMediaDownloadOutputSchema = {\n sourceUrl: z.string().url(),\n pageUrl: z.string().url(),\n browser: InstagramBrowserOutput,\n type: z.enum(['post', 'reel', 'tv']).nullable(),\n shortcode: NullableString,\n ownerName: NullableString,\n caption: NullableString,\n imageUrl: z.string().url().nullable(),\n trackCount: z.number().int().min(0),\n selectedVideoTrack: InstagramMediaTrackOutput.nullable(),\n selectedAudioTrack: InstagramMediaTrackOutput.nullable(),\n downloads: z.array(InstagramDownloadOutput),\n outputDir: NullableString,\n warnings: z.array(z.string()),\n limitations: z.array(z.string()),\n transcript: z.object({\n wordCount: z.number().int().min(0),\n chunkCount: z.number().int().min(0),\n durationMs: z.number().nullable(),\n transcriptText: z.string(),\n chunks: z.array(TranscriptChunkOutput),\n }).nullable(),\n}\n\nexport const YoutubeTranscribeOutputSchema = {\n videoId: NullableString,\n url: NullableString,\n wordCount: z.number().int().min(0),\n chunkCount: z.number().int().min(0),\n durationMs: z.number().nullable(),\n transcriptText: z.string(),\n chunks: z.array(TranscriptChunkOutput),\n resolvedInputs: z.object({\n videoId: NullableString,\n url: NullableString,\n }),\n}\n\nexport const FacebookAdTranscribeOutputSchema = {\n videoUrl: z.string().url(),\n wordCount: z.number().int().min(0),\n chunkCount: z.number().int().min(0),\n durationMs: z.number().nullable(),\n transcriptText: z.string(),\n chunks: z.array(TranscriptChunkOutput),\n resolvedInputs: z.object({\n videoUrl: z.string().url(),\n }),\n}\n\nexport const CaptureSerpSnapshotOutputSchema = {\n schemaVersion: z.literal('serp-intelligence.capture.v1'),\n status: z.string(),\n query: NullableString,\n location: NullableString,\n capturedAt: NullableString,\n resultCount: z.number().int().min(0).nullable(),\n snapshotId: NullableString,\n resolvedInputs: z.record(z.unknown()),\n artifacts: z.array(z.record(z.unknown())),\n diagnostics: z.record(z.unknown()).nullable(),\n providerPayload: z.record(z.unknown()),\n}\n\nexport const CaptureSerpPageSnapshotsOutputSchema = {\n schemaVersion: z.literal('serp-intelligence.page-snapshots.v1'),\n status: z.string(),\n count: z.number().int().min(0),\n failedCount: z.number().int().min(0),\n captures: z.array(z.record(z.unknown())),\n resolvedInputs: z.record(z.unknown()),\n diagnostics: z.record(z.unknown()).nullable(),\n providerPayload: z.record(z.unknown()),\n}\n\nexport const CreditsInfoInputSchema = {\n item: z.string().optional().describe('Optional tool, action, or feature to look up, e.g. \"maps reviews\", \"extract_url\", \"YouTube transcription\", or \"concurrency\"'),\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 WorkflowIdSchema = z.enum([\n 'directory',\n 'get-leads',\n 'agent-packet',\n 'local-competitive-audit',\n 'map-comparison',\n 'serp-comparison',\n 'paa-expansion-brief',\n 'ai-overview-language',\n])\nexport type WorkflowId = z.infer<typeof WorkflowIdSchema>\n\nexport const WorkflowListInputSchema = {\n includeRecipes: z.boolean().default(true).describe('Include high-level AI-facing recipes such as market analysis, ICP research, forum/review research, brand design briefings, CRO audits, positioning briefs, content gaps, and AI search visibility audits.'),\n}\nexport type WorkflowListInput = z.infer<ReturnType<typeof z.object<typeof WorkflowListInputSchema>>>\n\nexport const WorkflowSuggestInputSchema = {\n goal: z.string().min(1).describe('The user goal or job to route, e.g. \"market analysis for roofers in Tennessee\", \"ICP research for med spas\", \"CRO audit for this URL\", or \"brand design briefing\".'),\n query: z.string().optional().describe('Business category, niche, or Maps query when known.'),\n keyword: z.string().optional().describe('Search keyword, audience problem, or content topic when known.'),\n domain: z.string().optional().describe('Target domain or brand domain when known.'),\n url: z.string().url().optional().describe('Target URL when the workflow should inspect a specific page.'),\n location: z.string().optional().describe('City/region/country for localized research, e.g. Denver, CO.'),\n state: z.string().optional().describe('US state abbreviation or name for state-wide market research.'),\n maxSuggestions: z.number().int().min(1).max(8).default(3).describe('Number of matching workflow recipes to return.'),\n}\nexport type WorkflowSuggestInput = z.infer<ReturnType<typeof z.object<typeof WorkflowSuggestInputSchema>>>\n\nexport const WorkflowRunInputSchema = {\n workflowId: WorkflowIdSchema.describe('Workflow to run: directory, get-leads, agent-packet, local-competitive-audit, map-comparison, serp-comparison, paa-expansion-brief, ai-overview-language. Use only these values; call workflow_list or workflow_suggest first when unsure.'),\n input: z.record(z.unknown()).default({}).describe('Workflow-specific input object. Examples: get-leads uses {query, location, maxResults?, enrichWebsites?, hydrateReviewCounts?}; agent-packet uses {keyword, domain?, location?, maxQuestions?}; local-competitive-audit uses {query, state, minPopulation?, maxCities?, maxResultsPerCity?, hydrateTop?, maxReviews?}; serp-comparison uses {keyword, domain?, url?, location?, extractTop?}.'),\n webhookUrl: z.string().url().optional().describe('Optional HTTPS webhook to receive the completed hosted workflow run event.'),\n}\nexport type WorkflowRunInput = z.infer<ReturnType<typeof z.object<typeof WorkflowRunInputSchema>>>\n\nexport const WorkflowStepInputSchema = {\n runId: z.string().min(1).describe('Workflow run id returned by workflow_run, workflow_step, or workflow_status. Use only a returned runId; do not construct one yourself. Advances the run by exactly one step (one logical leg, e.g. one live harvest).'),\n}\nexport type WorkflowStepInput = z.infer<ReturnType<typeof z.object<typeof WorkflowStepInputSchema>>>\n\nexport const WorkflowStatusInputSchema = {\n runId: z.string().min(1).describe('Workflow run id returned by workflow_run, workflow_step, or workflow_status. Use only a returned runId; do not construct one yourself.'),\n}\nexport type WorkflowStatusInput = z.infer<ReturnType<typeof z.object<typeof WorkflowStatusInputSchema>>>\n\nexport const WorkflowArtifactReadInputSchema = {\n runId: z.string().min(1).describe('Workflow run id returned by workflow_run, workflow_step, or workflow_status. Use only a returned runId; do not construct one yourself.'),\n artifactId: z.string().min(1).describe('Artifact id from the run artifact list returned by workflow_run, workflow_step, or workflow_status. Use only a returned artifactId; do not construct one yourself.'),\n maxBytes: z.number().int().min(1_000).max(1_000_000).default(200_000).describe('Maximum bytes of artifact text to return inline. Use lower values for large CSV/JSON artifacts; call again with the downloadUrl if needed outside MCP.'),\n}\nexport type WorkflowArtifactReadInput = z.infer<ReturnType<typeof z.object<typeof WorkflowArtifactReadInputSchema>>>\n\nconst WorkflowRecipeOutput = z.object({\n id: z.string(),\n title: z.string(),\n description: z.string(),\n primaryWorkflowId: z.string().nullable(),\n recommendedTools: z.array(z.string()),\n requiredInputs: z.array(z.string()),\n optionalInputs: z.array(z.string()),\n produces: z.array(z.string()),\n runHint: z.string(),\n})\n\nconst WorkflowDefinitionOutput = z.object({\n id: z.string(),\n title: z.string(),\n description: z.string(),\n})\n\nconst WorkflowArtifactOutput = z.record(z.unknown())\n\nexport const WorkflowListOutputSchema = {\n workflows: z.array(WorkflowDefinitionOutput),\n recipes: z.array(WorkflowRecipeOutput),\n}\n\nexport const WorkflowSuggestOutputSchema = {\n goal: z.string(),\n suggestions: z.array(WorkflowRecipeOutput),\n}\n\nexport const WorkflowRunOutputSchema = {\n workflowId: z.string(),\n input: z.record(z.unknown()),\n run: z.record(z.unknown()).optional(),\n summary: z.record(z.unknown()).optional(),\n step: z.record(z.unknown()).optional(),\n nextStep: z.record(z.unknown()).nullable().optional(),\n done: z.boolean().optional(),\n artifacts: z.array(WorkflowArtifactOutput),\n}\n\nexport const WorkflowStepOutputSchema = {\n runId: z.string(),\n run: z.record(z.unknown()).optional(),\n summary: z.record(z.unknown()).nullable().optional(),\n step: z.record(z.unknown()).optional(),\n nextStep: z.record(z.unknown()).nullable().optional(),\n done: z.boolean(),\n artifacts: z.array(WorkflowArtifactOutput),\n}\n\nexport const WorkflowStatusOutputSchema = {\n run: z.record(z.unknown()).optional(),\n artifacts: z.array(WorkflowArtifactOutput),\n}\n\nexport const WorkflowArtifactReadOutputSchema = {\n runId: z.string(),\n artifactId: z.string(),\n contentType: z.string(),\n bytes: z.number().int().min(0),\n truncated: z.boolean(),\n text: z.string(),\n}\n\nexport const SearchSerpInputSchema = {\n query: z.string().min(1).describe('Core search topic only. Separate location when possible. If user says \"best dentist in Brooklyn NY serp\", use query=\"best dentist\" and location=\"Brooklyn, NY\".'),\n location: z.string().optional().describe('City, region, or country for geo-targeted results, inferred from user request when present.'),\n gl: z.string().length(2).default('us').describe('Google country code inferred from location or user language.'),\n hl: z.string().default('en').describe('Google interface/content language inferred from user request.'),\n device: z.enum(['desktop', 'mobile']).default('desktop').describe('SERP device context. Use desktop by default; use mobile only when the user asks for mobile rankings.'),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_PROXY_MODE).describe('Leave unset — routing is automatic. Set \"location\" only to force local-pack targeting.'),\n proxyZip: z.string().regex(/^\\d{5}$/).optional().describe('Optional US ZIP override for residential location proxy targeting. Use only with proxyMode location when the user gives a specific ZIP or city-center targeting needs to be forced.'),\n debug: z.boolean().default(false).describe('Include sanitized browser/session/location diagnostics in the response. Use true when debugging localization, CAPTCHA, or proxy behavior.'),\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\nexport const CaptureSerpSnapshotInputSchema = {\n query: z.string().min(1).describe('Core search query to capture as a structured SERP Intelligence snapshot. Separate the place into location when the user gives a city, region, country, or ZIP.'),\n location: z.string().optional().describe('City, region, country, or service area used for localized Google results. MCP Scraper records location evidence; UULE alone is not proof of localization.'),\n gl: z.string().length(2).default('us').describe('Google country code inferred from the requested market, e.g. us, gb, ca, au.'),\n hl: z.string().default('en').describe('Google interface/content language inferred from the user request.'),\n device: z.enum(['desktop', 'mobile']).default('desktop').describe('SERP device context. Use mobile only when the user asks for mobile rankings or mobile SERP evidence.'),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_PROXY_MODE).describe('Leave unset — routing is automatic. Set \"location\" only to force city/ZIP targeting.'),\n proxyZip: z.string().regex(/^\\d{5}$/).optional().describe('Optional US ZIP override for residential location proxy targeting. Use only with proxyMode location when a precise city-center or ZIP proxy is needed.'),\n pages: z.number().int().min(1).max(2).default(1).describe('Number of Google result pages to capture. Use 1 normally and 2 only when the user needs deeper ranking evidence.'),\n debug: z.boolean().default(false).describe('Include sanitized browser, proxy, and location diagnostics. Use true when debugging localization, CAPTCHA, proxy selection, or capture reliability.'),\n includePageSnapshots: z.boolean().default(false).describe('Also capture ranking-page snapshots for selected SERP URLs through the same product capture path.'),\n pageSnapshotLimit: z.number().int().min(0).max(10).default(0).describe('Maximum ranking-page snapshots to capture when includePageSnapshots is true. Use 0 when only SERP evidence is needed.'),\n}\nexport type CaptureSerpSnapshotInput = z.infer<ReturnType<typeof z.object<typeof CaptureSerpSnapshotInputSchema>>>\n\nexport const ScreenshotInputSchema = {\n url: z.string().url().describe('URL to capture as a full-page screenshot. Use http or https. Pass allowLocal: true to capture localhost or private-network URLs during development.'),\n device: z.enum(['desktop', 'mobile']).default('desktop').describe('Viewport profile. desktop = 1440×900. mobile = 390×844. Use desktop by default; use mobile when the user asks for a mobile view.'),\n allowLocal: z.boolean().default(false).describe('Allow localhost and private-network URLs (127.x, 192.168.x, 10.x, etc.). For local development only — not for production use.'),\n}\nexport type ScreenshotInput = z.infer<ReturnType<typeof z.object<typeof ScreenshotInputSchema>>>\n\nexport const CaptureSerpPageSnapshotsInputSchema = {\n urls: z.array(z.string().url()).min(1).max(25).describe('Public HTTP/HTTPS URLs to capture as SERP Intelligence page snapshots. Do not pass localhost, private IPs, file URLs, or internal admin URLs.'),\n targets: z.array(z.object({\n url: z.string().url().describe('Public HTTP/HTTPS URL to capture.'),\n sourceKind: z.enum(['organic', 'ai_citation', 'local_pack_website', 'configured_target', 'site_subject']).default('configured_target').describe('Why this page is being captured for SERP Intelligence evidence.'),\n sourcePosition: z.number().int().min(1).optional().describe('Ranking or citation position when the page came from SERP evidence.'),\n }).strict()).min(1).max(25).optional().describe('Structured page snapshot targets. Use this instead of urls when source kind or position should be preserved.'),\n maxConcurrency: z.number().int().min(1).max(5).default(2).describe('Parallel page captures. Use 2 normally; higher values can increase proxy/browser pressure.'),\n timeoutMs: z.number().int().min(1_000).max(60_000).default(15_000).describe('Per-page capture timeout in milliseconds. Increase for slow pages; timeout artifacts are returned as structured capture failures.'),\n debug: z.boolean().default(false).describe('Include sanitized browser/proxy diagnostics for page snapshot debugging. Use true for capture, network, or proxy troubleshooting.'),\n}\nexport type CaptureSerpPageSnapshotsInput = z.infer<ReturnType<typeof z.object<typeof CaptureSerpPageSnapshotsInputSchema>>>\n","import { z } from 'zod'\n\nexport const DEFAULT_PROXY_MODE = 'none' as const\nexport const DEFAULT_MAPS_PROXY_MODE = 'location' as const\n\nexport const HarvestOptionsSchema = z.object({\n query: z.string().min(1),\n location: z.string().optional(),\n gl: z.string().length(2).default('us'),\n hl: z.string().length(2).default('en'),\n device: z.enum(['desktop', 'mobile']).default('desktop'),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_PROXY_MODE),\n proxyZip: z.string().regex(/^\\d{5}$/).optional(),\n debug: z.boolean().default(false),\n depth: z.number().int().min(1).max(30).default(3),\n maxQuestions: z.number().int().min(1).max(1000).default(100),\n headless: z.boolean().default(false),\n profileDir: z.string().optional(),\n proxy: z.string().url().optional(),\n kernelApiKey: z.string().optional(),\n kernelProxyId: z.string().optional(),\n kernelProxyResolution: z.unknown().optional(),\n outputDir: z.string().default('./paa-output'),\n format: z.enum(['json', 'csv', 'both']).default('both'),\n serpOnly: z.boolean().default(false),\n pages: z.number().int().min(1).max(2).default(1),\n softDeadlineMs: z.number().optional(),\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 MapsSearchOptionsSchema = 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 maxResults: z.number().int().min(1).max(50).default(10),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_MAPS_PROXY_MODE),\n proxyZip: z.string().regex(/^\\d{5}$/).optional(),\n debug: z.boolean().default(false),\n kernelApiKey: z.string().optional(),\n kernelProxyId: z.string().optional(),\n kernelProxyResolution: z.unknown().optional(),\n headless: z.boolean().default(true),\n})\n\nexport const RawPAAItemSchema = z.object({\n question: z.string().min(1),\n answer: z.string().optional(),\n sourceTitle: z.string().optional(),\n sourceSite: z.string().optional(),\n sourceCite: z.string().optional(),\n})\n\nexport const RawMapsOverviewSchema = z.object({\n name: z.string().nullable(),\n rating: z.string().nullable(),\n reviewCount: z.string().nullable(),\n category: z.string().nullable(),\n address: z.string().nullable(),\n hoursSummary: z.string().nullable(),\n phone: z.string().nullable(),\n phoneDisplay: z.string().nullable(),\n website: z.string().nullable(),\n plusCode: z.string().nullable(),\n bookingUrl: z.string().nullable(),\n})\n\nexport const RawMapsHoursRowSchema = z.object({\n day: z.string(),\n hours: z.string(),\n})\n\nexport const RawMapsReviewStatsSchema = z.object({\n reviewHistogram: z.array(z.object({\n stars: z.number(),\n count: z.string(),\n })),\n reviewTopics: z.array(z.object({\n label: z.string(),\n count: z.string(),\n })),\n})\n\nexport const RawMapsReviewCardSchema = z.object({\n reviewId: z.string(),\n author: z.string().nullable(),\n stars: z.string().nullable(),\n date: z.string().nullable(),\n text: z.string().nullable(),\n ownerResponse: z.string().nullable(),\n})\n\nexport const RawMapsAboutAttributeSchema = z.object({\n section: z.string(),\n attribute: z.string(),\n})\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { RankTrackerBlueprintInput, RankTrackerMode } from './mcp-tool-schemas.js'\n\ntype ToolPlan = {\n tool: string\n purpose: string\n}\n\ntype TablePlan = {\n name: string\n purpose: string\n keyColumns: string[]\n}\n\ntype CronJobPlan = {\n name: string\n purpose: string\n modes: RankTrackerMode[]\n recommendedTools: string[]\n}\n\ntype RankTrackerBlueprint = {\n projectName: string\n targetDomain: string | null\n targetBusinessName: string | null\n trackingModes: RankTrackerMode[]\n database: string\n recommendedTools: ToolPlan[]\n tables: TablePlan[]\n cron: {\n enabled: boolean\n cadence: string\n expression: string\n timezone: string\n jobs: CronJobPlan[]\n }\n metrics: string[]\n implementationPrompt: string\n}\n\nconst DEFAULT_MODES: RankTrackerMode[] = ['maps', 'organic', 'ai_overview', 'paa']\n\nfunction normalizeDomain(value?: string): string | null {\n const trimmed = value?.trim()\n if (!trimmed) return null\n try {\n const url = new URL(trimmed.includes('://') ? trimmed : `https://${trimmed}`)\n return url.hostname.replace(/^www\\./, '').toLowerCase()\n } catch {\n return trimmed.replace(/^https?:\\/\\//, '').replace(/^www\\./, '').split('/')[0]?.toLowerCase() || trimmed\n }\n}\n\nfunction uniqueModes(input?: RankTrackerMode[]): RankTrackerMode[] {\n const modes = input?.length ? input : DEFAULT_MODES\n return [...new Set(modes)]\n}\n\nfunction cronExpression(cadence: RankTrackerBlueprintInput['scheduleCadence'], customCron?: string): string {\n if (cadence === 'daily') return '15 6 * * *'\n if (cadence === 'monthly') return '15 6 1 * *'\n if (cadence === 'custom') return customCron?.trim() || 'CUSTOM_CRON_EXPRESSION_REQUIRED'\n return '15 6 * * 1'\n}\n\nfunction includes(modes: RankTrackerMode[], mode: RankTrackerMode): boolean {\n return modes.includes(mode)\n}\n\nfunction buildToolPlan(modes: RankTrackerMode[]): ToolPlan[] {\n const plans: ToolPlan[] = []\n const push = (tool: string, purpose: string) => {\n if (!plans.some((plan) => plan.tool === tool)) plans.push({ tool, purpose })\n }\n\n push('credits_info', 'Check account balance and rates before scheduling recurring rank checks.')\n\n if (includes(modes, 'maps')) {\n push('directory_workflow', 'Seed or refresh city-by-city Maps datasets when building local market coverage.')\n push('maps_search', 'Run recurring Google Maps category checks for each keyword and location.')\n push('maps_place_intel', 'Hydrate selected target or competitor GBP details when profile-level evidence is needed.')\n }\n if (includes(modes, 'organic')) {\n push('search_serp', 'Capture localized organic rankings, local pack data, and AI Overview status without PAA expansion.')\n }\n if (includes(modes, 'ai_overview')) {\n push('search_serp', 'Capture quick AI Overview detection and organic context for each tracked query.')\n push('harvest_paa', 'Use when AI Overview text, PAA context, or source-level evidence needs deeper capture.')\n }\n if (includes(modes, 'paa')) {\n push('harvest_paa', 'Capture People Also Ask questions, answers, and source sites for PAA presence tracking.')\n }\n\n return plans\n}\n\nfunction buildTables(modes: RankTrackerMode[], includeDashboard: boolean, includeAlerts: boolean, hasCompetitors: boolean): TablePlan[] {\n const tables: TablePlan[] = [\n {\n name: 'rank_tracker_projects',\n purpose: 'One row per client, campaign, or tracked property.',\n keyColumns: ['id', 'name', 'target_domain', 'target_business_name', 'database_mode', 'timezone', 'created_at'],\n },\n {\n name: 'rank_tracker_targets',\n purpose: 'Normalized target identities and match rules for domains, URLs, business names, CIDs, and competitors.',\n keyColumns: ['id', 'project_id', 'kind', 'value', 'display_name', 'match_rules_json', 'active'],\n },\n {\n name: 'rank_tracker_keywords',\n purpose: 'Tracked keywords or service queries, separated from location so calls can localize correctly.',\n keyColumns: ['id', 'project_id', 'keyword', 'intent', 'tags_json', 'active'],\n },\n {\n name: 'rank_tracker_locations',\n purpose: 'Markets, cities, ZIPs, country/language settings, and proxy targeting hints.',\n keyColumns: ['id', 'project_id', 'label', 'gl', 'hl', 'proxy_zip', 'device', 'active'],\n },\n {\n name: 'rank_tracker_runs',\n purpose: 'Heartbeat table for every scheduled or manual rank check batch.',\n keyColumns: ['id', 'project_id', 'scheduled_for', 'started_at', 'completed_at', 'status', 'idempotency_key', 'error_message'],\n },\n ]\n\n if (includes(modes, 'organic')) {\n tables.push({\n name: 'rank_tracker_organic_results',\n purpose: 'SERP organic result rows from search_serp, including target-domain matches and competitor rows.',\n keyColumns: ['id', 'run_id', 'keyword_id', 'location_id', 'device', 'position', 'title', 'url', 'domain', 'is_target'],\n })\n }\n\n if (includes(modes, 'maps')) {\n tables.push({\n name: 'rank_tracker_maps_results',\n purpose: 'Google Maps result rows from maps_search and directory_workflow, including GBP identity fields.',\n keyColumns: ['id', 'run_id', 'keyword_id', 'location_id', 'position', 'business_name', 'place_url', 'cid', 'website_url', 'rating', 'review_count', 'is_target'],\n })\n tables.push({\n name: 'rank_tracker_market_seeds',\n purpose: 'Directory workflow city, population, ZIP-group, and market seed records used to build local tracking coverage.',\n keyColumns: ['id', 'project_id', 'query', 'city', 'state', 'population', 'zip_group_json', 'last_seeded_run_id'],\n })\n }\n\n if (includes(modes, 'ai_overview')) {\n tables.push({\n name: 'rank_tracker_ai_overviews',\n purpose: 'AI Overview detection, text snapshot, citation domains, and target citation status per query/location.',\n keyColumns: ['id', 'run_id', 'keyword_id', 'location_id', 'detected', 'target_cited', 'cited_domains_json', 'overview_text'],\n })\n }\n\n if (includes(modes, 'paa')) {\n tables.push({\n name: 'rank_tracker_paa_sources',\n purpose: 'People Also Ask questions, answers, and source sites, with target source presence flags.',\n keyColumns: ['id', 'run_id', 'keyword_id', 'location_id', 'question', 'answer', 'source_title', 'source_site', 'target_present'],\n })\n }\n\n if (hasCompetitors) {\n tables.push({\n name: 'rank_tracker_competitor_snapshots',\n purpose: 'Per-run competitor visibility summaries across organic, Maps, AI Overview, and PAA surfaces.',\n keyColumns: ['id', 'run_id', 'target_id', 'surface', 'best_position', 'presence_count', 'share_of_surface'],\n })\n }\n\n if (includeDashboard) {\n tables.push({\n name: 'rank_tracker_daily_metrics',\n purpose: 'Rollup table for dashboard charts, trend lines, and share-of-visibility summaries.',\n keyColumns: ['id', 'project_id', 'metric_date', 'keyword_id', 'location_id', 'surface', 'metric_name', 'metric_value'],\n })\n }\n\n if (includeAlerts) {\n tables.push({\n name: 'rank_tracker_alert_events',\n purpose: 'Deduplicated gain/loss events for rank movement, Maps top 3, AI Overview citations, and PAA source presence.',\n keyColumns: ['id', 'project_id', 'run_id', 'surface', 'severity', 'event_key', 'message', 'created_at', 'acknowledged_at'],\n })\n }\n\n return tables\n}\n\nfunction buildCronJobs(modes: RankTrackerMode[], includeDashboard: boolean, includeAlerts: boolean): CronJobPlan[] {\n const jobs: CronJobPlan[] = [\n {\n name: 'rank-tracker-dispatch',\n purpose: 'Find due keyword/location/mode combinations, create a rank_tracker_runs row, and enqueue idempotent work items.',\n modes,\n recommendedTools: ['credits_info'],\n },\n ]\n\n if (includes(modes, 'maps')) {\n jobs.push({\n name: 'maps-rank-check',\n purpose: 'Run maps_search per keyword/location and optionally directory_workflow for market seed refreshes.',\n modes: ['maps'],\n recommendedTools: ['maps_search', 'directory_workflow', 'maps_place_intel'],\n })\n }\n\n if (includes(modes, 'organic') || includes(modes, 'ai_overview')) {\n jobs.push({\n name: 'serp-rank-check',\n purpose: 'Run search_serp per keyword/location/device and persist organic ranks, local pack, and AI Overview status.',\n modes: modes.filter((mode) => mode === 'organic' || mode === 'ai_overview'),\n recommendedTools: ['search_serp'],\n })\n }\n\n if (includes(modes, 'paa') || includes(modes, 'ai_overview')) {\n jobs.push({\n name: 'paa-ai-evidence-check',\n purpose: 'Run harvest_paa for PAA source presence and deeper AI Overview/PAA evidence where needed.',\n modes: modes.filter((mode) => mode === 'paa' || mode === 'ai_overview'),\n recommendedTools: ['harvest_paa'],\n })\n }\n\n if (includeDashboard) {\n jobs.push({\n name: 'rank-tracker-rollups',\n purpose: 'Aggregate raw rows into daily metrics for charts, comparison tables, and trend lines.',\n modes,\n recommendedTools: [],\n })\n }\n\n if (includeAlerts) {\n jobs.push({\n name: 'rank-tracker-alerts',\n purpose: 'Compare latest run against prior snapshots and emit deduplicated visibility gain/loss events.',\n modes,\n recommendedTools: [],\n })\n }\n\n return jobs\n}\n\nfunction buildMetrics(modes: RankTrackerMode[], includeDashboard: boolean, includeAlerts: boolean): string[] {\n const metrics: string[] = ['run_success_rate', 'last_successful_run_at', 'stale_keyword_location_count']\n\n if (includes(modes, 'maps')) {\n metrics.push('maps_best_position', 'maps_top_3_presence', 'maps_target_found', 'maps_competitor_count_above_target')\n }\n if (includes(modes, 'organic')) {\n metrics.push('organic_best_position', 'organic_top_3_presence', 'organic_top_10_presence', 'organic_best_url')\n }\n if (includes(modes, 'ai_overview')) {\n metrics.push('ai_overview_detected', 'target_ai_overview_cited', 'ai_overview_citation_domain_count')\n }\n if (includes(modes, 'paa')) {\n metrics.push('paa_question_count', 'target_paa_source_count', 'paa_presence_rate', 'paa_source_domains')\n }\n if (includeDashboard) metrics.push('share_of_visibility', 'position_delta_7d', 'position_delta_30d')\n if (includeAlerts) metrics.push('visibility_gain_events', 'visibility_loss_events')\n\n return metrics\n}\n\nfunction listOrPlaceholder(values: string[] | undefined, fallback: string): string {\n const clean = values?.map((value) => value.trim()).filter(Boolean) ?? []\n if (!clean.length) return fallback\n return clean.map((value) => `- ${value}`).join('\\n')\n}\n\nfunction buildPrompt(\n input: RankTrackerBlueprintInput,\n modes: RankTrackerMode[],\n tools: ToolPlan[],\n tables: TablePlan[],\n jobs: CronJobPlan[],\n metrics: string[],\n expression: string,\n targetDomain: string | null,\n targetBusinessName: string | null,\n): string {\n const keywords = listOrPlaceholder(input.keywords, '- TODO: add tracked keywords')\n const locations = listOrPlaceholder(input.locations, '- TODO: add tracked markets/locations')\n const competitors = listOrPlaceholder(input.competitors, '- Optional: add competitor domains or GBP names')\n const notes = input.notes?.trim() || 'No extra implementation notes.'\n\n return [\n 'You are building a production rank tracker powered by MCP Scraper. Create the database migrations, scheduled worker, ingestion functions, and dashboard/query layer described below.',\n '',\n `Project: ${input.projectName || 'MCP Scraper Rank Tracker'}`,\n `Target domain: ${targetDomain || 'TODO_TARGET_DOMAIN'}`,\n `Target business/GBP name: ${targetBusinessName || 'TODO_TARGET_BUSINESS_NAME'}`,\n `Database target: ${input.database || 'postgres'}`,\n `Tracking modes: ${modes.join(', ')}`,\n '',\n 'Seed keywords:',\n keywords,\n '',\n 'Seed locations:',\n locations,\n '',\n 'Competitors:',\n competitors,\n '',\n 'MCP Scraper calls to use:',\n tools.map((tool) => `- ${tool.tool}: ${tool.purpose}`).join('\\n'),\n '',\n 'Database tables to create:',\n tables.map((table) => `- ${table.name}: ${table.keyColumns.join(', ')}`).join('\\n'),\n '',\n 'Scheduler and heartbeat requirements:',\n `- Use cron expression \"${expression}\" in timezone \"${input.timezone || 'UTC'}\" unless the user changes cadence.`,\n '- Every scheduled batch must insert or update rank_tracker_runs before calling MCP tools.',\n '- Use idempotency_key = project_id + keyword_id + location_id + mode + device + scheduled_date.',\n '- Mark runs as running, succeeded, failed, or skipped; persist error_message on failures.',\n '- Call credits_info first to read the account\\'s real concurrency_limit (most paid accounts have 3, 10, or 20, not 1), then run up to that many MCP calls in parallel — never sequential-by-default and never more than the limit, or calls start failing with 429s.',\n '- Retry retryable upstream failures with backoff, but do not duplicate rows for the same idempotency key.',\n '',\n 'Mode-specific ingestion rules:',\n '- maps: Use directory_workflow to seed/refresh market coverage and maps_search for recurring keyword/location rank checks. Match the target by targetBusinessName, website domain, CID, and place URL when available.',\n '- organic: Use search_serp and persist every organic result row. Compute the best targetDomain position and best ranking URL per keyword/location/device.',\n '- ai_overview: Use search_serp for quick detection and harvest_paa when deeper text/source evidence is needed. Track detected, overview_text, cited domains, and whether targetDomain is cited.',\n '- paa: Use harvest_paa and persist each question/source pair. Track whether sourceSite or answer/source evidence matches targetDomain, then compute PAA presence rate.',\n '',\n 'Metrics to expose:',\n metrics.map((metric) => `- ${metric}`).join('\\n'),\n '',\n 'Alert requirements:',\n input.includeAlerts\n ? '- Emit deduplicated alert_events when target gains/loses Maps top 3, organic top 10, AI Overview citation, or PAA source presence.'\n : '- Alerts are out of scope for this build unless the user asks for them.',\n '',\n 'Dashboard requirements:',\n input.includeDashboard\n ? '- Build views for latest position by keyword/location, trend deltas, competitors above target, AI Overview citations, and PAA source wins/losses.'\n : '- Dashboard is out of scope for this build unless the user asks for it.',\n '',\n 'Extra notes:',\n notes,\n ].join('\\n')\n}\n\nexport function buildRankTrackerBlueprint(input: RankTrackerBlueprintInput): CallToolResult {\n const trackingModes = uniqueModes(input.trackingModes)\n const targetDomain = normalizeDomain(input.targetDomain)\n const targetBusinessName = input.targetBusinessName?.trim() || null\n const projectName = input.projectName?.trim() || 'MCP Scraper Rank Tracker'\n const database = input.database || 'postgres'\n const expression = cronExpression(input.scheduleCadence || 'weekly', input.customCron)\n const tools = buildToolPlan(trackingModes)\n const tables = buildTables(trackingModes, input.includeDashboard !== false, input.includeAlerts !== false, Boolean(input.competitors?.length))\n const jobs = input.includeCron === false ? [] : buildCronJobs(trackingModes, input.includeDashboard !== false, input.includeAlerts !== false)\n const metrics = buildMetrics(trackingModes, input.includeDashboard !== false, input.includeAlerts !== false)\n const implementationPrompt = buildPrompt(input, trackingModes, tools, tables, jobs, metrics, expression, targetDomain, targetBusinessName)\n\n const blueprint: RankTrackerBlueprint = {\n projectName,\n targetDomain,\n targetBusinessName,\n trackingModes,\n database,\n recommendedTools: tools,\n tables,\n cron: {\n enabled: input.includeCron !== false,\n cadence: input.scheduleCadence || 'weekly',\n expression: input.includeCron === false ? 'disabled' : expression,\n timezone: input.timezone || 'UTC',\n jobs,\n },\n metrics,\n implementationPrompt,\n }\n\n const text = [\n `# ${projectName}`,\n '',\n 'Rank tracker build blueprint generated from MCP Scraper tool capabilities.',\n '',\n '## Modes',\n trackingModes.map((mode) => `- ${mode}`).join('\\n'),\n '',\n '## Recommended MCP Tools',\n tools.map((tool) => `- \\`${tool.tool}\\` - ${tool.purpose}`).join('\\n'),\n '',\n '## Database Tables',\n tables.map((table) => `- \\`${table.name}\\` - ${table.purpose}`).join('\\n'),\n '',\n '## Cron / Heartbeat',\n blueprint.cron.enabled\n ? `- Cadence: ${blueprint.cron.cadence}\\n- Cron: \\`${blueprint.cron.expression}\\`\\n- Timezone: ${blueprint.cron.timezone}\\n- Jobs: ${jobs.map((job) => job.name).join(', ')}`\n : '- Disabled by input. Still create rank_tracker_runs for manual runs.',\n '',\n '## Implementation Prompt',\n '```text',\n implementationPrompt,\n '```',\n ].join('\\n')\n\n return {\n content: [{ type: 'text', text }],\n structuredContent: blueprint,\n }\n}\n","export interface InstallTerminalOptions {\n color?: boolean\n version: string\n apiKeyConfigured?: boolean\n}\n\ntype Tone = 'cyan' | 'lime' | 'amber' | 'red' | 'muted' | 'bold'\n\nconst CODES: Record<Tone | 'reset', string> = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n lime: '\\x1b[32m',\n amber: '\\x1b[33m',\n red: '\\x1b[31m',\n muted: '\\x1b[90m',\n bold: '\\x1b[1m',\n}\n\nfunction colorize(value: string, tone: Tone, enabled: boolean): string {\n if (!enabled) return value\n return `${CODES[tone]}${value}${CODES.reset}`\n}\n\nfunction toolRow(label: string, tools: string[], enabled: boolean): string {\n const padded = label.padEnd(9, ' ')\n return ` ${colorize(padded, 'muted', enabled)} ${tools.join(colorize(' . ', 'muted', enabled))}`\n}\n\nexport function renderInstallTerminal(options: InstallTerminalOptions): string {\n const color = options.color ?? true\n const apiKeyValue = options.apiKeyConfigured ? '$MCP_SCRAPER_API_KEY' : 'sk_live_your_key'\n const ascii = String.raw`\n __ __ ____ ____ \n| \\/ |/ ___| _ \\\n| |\\/| | | | |_) |\n| | | | |___| __/\n|_| |_|\\____|_|\n\n ____ ____ ____ _ ____ _____ ____\n/ ___| / ___| _ \\ / \\ | _ \\| ____| _ \\\n\\___ \\| | | |_) | / _ \\ | |_) | _| | |_) |\n ___) | |___| _ < / ___ \\| __/| |___| _ <\n|____/ \\____|_| \\_\\/_/ \\_\\_| |_____|_| \\_\\\n`\n\n const claudeCommand = [\n `MCP_SCRAPER_API_KEY=${apiKeyValue} npx -y -p mcp-scraper@latest \\\\`,\n ' mcp-scraper-cli agent install claude --apply',\n ].join('\\n')\n\n const codexConfig = [\n '[mcp_servers.mcp-scraper]',\n 'command = \"npx\"',\n 'args = [\"-y\", \"-p\", \"mcp-scraper@latest\", \"mcp-scraper\"]',\n `env = { MCP_SCRAPER_API_KEY = \"${apiKeyValue}\" }`,\n ].join('\\n')\n\n return [\n colorize(`mcp-scraper v${options.version}`, 'bold', color),\n colorize('> mcp-scraper-install', 'muted', color),\n colorize(ascii, 'amber', color),\n `${colorize('MCP Scraper Agent', 'cyan', color)} . v${options.version} . mcpscraper.dev`,\n '1/1 install surfaces ready',\n colorize('Newest: saved browser profiles that hold MANY site logins. Share the watch_url, user signs in, then verify with browser_profile_list. Browser sessions are direct/no-proxy by default.', 'lime', color),\n '',\n `${colorize('Tools', 'cyan', color)} ${colorize('(48 MCP tools)', 'muted', color)}`,\n toolRow('search', ['harvest_paa', 'search_serp', 'maps_search', 'maps_place_intel'], color),\n toolRow('extract', ['extract_url', 'map_site_urls', 'extract_site', 'audit_site', 'directory_workflow'], color),\n toolRow('build', ['rank_tracker_workflow', 'cron plan', 'database prompt'], color),\n toolRow('media', ['youtube_harvest', 'youtube_transcribe', 'facebook_ad_search', 'facebook_page_intel', 'facebook_ad_transcribe', 'facebook_video_transcribe', 'instagram_profile_content', 'instagram_media_download', 'reddit_thread'], color),\n toolRow('browser', ['browser_open', 'browser_profile_connect', 'browser_profile_list', 'browser_close', 'browser_screenshot', 'browser_read', 'browser_locate', 'browser_replay_mark', 'browser_replay_annotate'], color),\n toolRow('account', ['credits_info', 'reports', 'MCP resources'], color),\n `${colorize('Workflows', 'cyan', color)} ${colorize('(MCP + CLI + API)', 'muted', color)}`,\n toolRow('route', ['workflow_list', 'workflow_suggest', 'workflow_run', 'workflow_step', 'workflow_status', 'workflow_artifact_read'], color),\n toolRow('seo', ['directory', 'agent-packet', 'competitive audit', 'map/serp comparison', 'PAA/AIO briefs', 'scheduled runs'], color),\n '',\n colorize('Usage tips:', 'amber', color),\n 'Run mcp-scraper-install for this visible card. Run mcp-scraper-cli for setup utilities and subcommands.',\n 'Run mcp-scraper in a human terminal to print this card; MCP clients get the same command as a silent stdio server.',\n 'Explicit card command: npx -y -p mcp-scraper@latest mcp-scraper-install',\n 'Customer auth setup: run browser_profile_connect, send the watch_url, let the user sign in, then call browser_profile_list until AUTHENTICATED.',\n 'Stack logins / reconnect: run browser_profile_connect again with the same profile name and another domain to add accounts or refresh a login.',\n 'Start with workflow_suggest for broad jobs like market analysis, ICP research, CRO audits, brand briefs, content gaps, and AI visibility.',\n 'For MCP clients, use mcp-scraper so one install can mix SERP, Maps, browser, reports, and saved MCP resources.',\n 'If you hit the concurrency limit, add an extra slot for $5/month with mcp-scraper-cli billing concurrency checkout.',\n '',\n `${colorize('Ready.', 'lime', color)} Install the combined MCP server with one command:`,\n '',\n colorize('Setup doctor', 'amber', color),\n 'npx -y -p mcp-scraper@latest mcp-scraper-cli doctor',\n '',\n colorize('Hosted profile setup', 'amber', color),\n 'In your MCP client, call browser_profile_connect with email=\"seo@example.com\" and domain=\"chatgpt.com\".',\n 'Give the returned watch_url to the user. After they sign in, call browser_profile_list, then browser_open with the returned profile. Add more logins by calling browser_profile_connect again with the same profile and a new domain.',\n '',\n colorize('Claude Code one-command setup', 'amber', color),\n claudeCommand,\n 'Then fully exit Claude Code and open a new Claude terminal. Check with: claude mcp list',\n '',\n colorize('Codex config', 'amber', color),\n codexConfig,\n '',\n colorize('Claude Desktop Extension', 'amber', color),\n 'Download: https://mcpscraper.dev/downloads/mcp-scraper.mcpb',\n '',\n colorize('Safety note:', 'muted', color),\n 'mcp-scraper prints this card only when stdin/stdout are an interactive TTY. In MCP clients it writes only JSON-RPC to stdout.',\n 'Use --stdio or MCP_SCRAPER_FORCE_STDIO=1 to force server mode from a terminal.',\n '',\n ].join('\\n')\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AACA,IAAAA,kBAA6B;AAC7B,IAAAC,kBAAwB;AACxB,IAAAC,oBAAqB;AACrB,IAAAC,cAA0B;AAC1B,mBAAqC;;;ACL9B,IAAM,yBAAyB;AAE/B,IAAM,+BAA+B;AAOrC,SAAS,qBAAqB,cAAsB,WAAW,OAA6B;AACjG,QAAM,YAAY,OAAO,SAAS,YAAY,KAAK,eAAe,IAAI,KAAK,MAAM,YAAY,IAAI;AACjG,MAAI;AACJ,MAAI,SAAU,YAAW;AAAA,WAChB,aAAa,GAAI,YAAW;AAAA,WAC5B,aAAa,IAAK,YAAW;AAAA,MACjC,YAAW;AAChB,QAAM,WAAW,KAAK,IAAI,WAAW,8BAA8B,yBAAyB,GAAK;AACjG,SAAO,EAAE,UAAU,SAAS;AAC9B;;;ACTO,SAAS,4BAAgD;AAC9D,QAAM,SACJ,QAAQ,IAAI,8BACZ,QAAQ,IAAI,gCACZ,QAAQ,IAAI,+BACZ,QAAQ,IAAI,sBACX,KAAK;AACR,SAAO,SAAS;AAClB;AAEO,SAAS,mCAAwD;AACtE,QAAM,SACJ,QAAQ,IAAI,sCACZ,QAAQ,IAAI,wCACZ,QAAQ,IAAI,uCACZ,QAAQ,IAAI,8BACX,KAAK,EAAE,YAAY;AACtB,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,CAAC,KAAK,QAAQ,OAAO,IAAI,EAAE,SAAS,KAAK,EAAG,QAAO;AACvD,MAAI,CAAC,KAAK,SAAS,MAAM,KAAK,EAAE,SAAS,KAAK,EAAG,QAAO;AACxD,SAAO;AACT;;;ACMA,SAAS,sBAAsB,KAAwC;AACrE,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,UAAM,OAAO,OAAO,SAAS,QAAQ,UAAU,EAAE,EAAE,QAAQ,QAAQ,EAAE;AACrE,QAAI,SAAS,YAAY;AACvB,YAAM,KAAK,OAAO,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,CAAC;AACvD,aAAO,MAAM;AAAA,IACf;AACA,QAAI,SAAS,iBAAiB,SAAS,qBAAqB;AAC1D,YAAM,UAAU,OAAO,aAAa,IAAI,GAAG;AAC3C,UAAI,QAAS,QAAO;AACpB,YAAM,QAAQ,OAAO,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AACvD,YAAM,cAAc,MAAM,UAAU,UAAQ,CAAC,UAAU,SAAS,MAAM,EAAE,SAAS,IAAI,CAAC;AACtF,UAAI,eAAe,KAAK,MAAM,cAAc,CAAC,EAAG,QAAO,MAAM,cAAc,CAAC;AAAA,IAC9E;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,eAAe,iBAAiB,KAAiC;AAC/D,QAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,MAAI,CAAC,KAAK,KAAK,EAAG,QAAO;AACzB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iBAAiB,MAAc,KAAe,MAAwC;AAC7F,QAAM,aAAa,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,IACtE,OACA;AACJ,QAAM,cAAc,aAChB,WAAW,WAAW,WAAW,SAAS,WAAW,aACrD;AACJ,SAAO;AAAA,IACL,GAAI,cAAc,EAAE,MAAM,KAAK;AAAA,IAC/B,OAAO,YAAY,SAAS,YAAY,cAAc;AAAA,IACtD,YAAY;AAAA,IACZ,WAAW,IAAI,WAAW,OAAO,IAAI,UAAU;AAAA,IAC/C,QAAQ,IAAI;AAAA,IACZ,YAAY,IAAI;AAAA,IAChB;AAAA,IACA,SAAS,OAAO,gBAAgB,YAAY,YAAY,KAAK,IACzD,cACA,oBAAoB,IAAI,MAAM,GAAG,IAAI,aAAa,IAAI,IAAI,UAAU,KAAK,EAAE,QAAQ,IAAI;AAAA,EAC7F;AACF;AAEA,SAAS,yBAAuF,OAAa;AAC3G,QAAM,UAAU,MAAM,SAAS,KAAK,KAAK,0BAA0B;AACnE,QAAM,qBAAqB,MAAM,sBAAsB,iCAAiC;AACxF,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7B,GAAI,OAAO,uBAAuB,YAAY,EAAE,mBAAmB,IAAI,CAAC;AAAA,EAC1E;AACF;AAEO,IAAM,sBAAN,MAAqF;AAAA,EACzE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAYC,UAAiBC,SAAgB;AAC3C,SAAK,UAAUD,SAAQ,QAAQ,OAAO,EAAE;AACxC,SAAK,SAASC;AACd,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,iBAAiB,gBAAgB,SAAY,MAAM,OAAO,WAAW;AAC3E,SAAK,wBAAwB,OAAO,SAAS,cAAc,KAAK,iBAAiB,IAAI,iBAAiB;AACtG,SAAK,YAAY,KAAK,yBAAyB;AAC/C,UAAM,sCAAsC,OAAO,QAAQ,IAAI,iDAAiD,KAAK,SAAS;AAC9H,SAAK,4BAA4B,OAAO,SAAS,mCAAmC,KAAK,sCAAsC,IAC3H,sCACA,KAAK;AAAA,EACX;AAAA,EAEA,MAAc,KAAK,MAAc,MAA+B,YAAY,KAAK,WAAoC;AACnH,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,SAAS;AAAA,MACvC,CAAC;AACD,YAAM,OAAO,MAAM,iBAAiB,GAAG;AACvC,UAAI,CAAC,IAAI,IAAI;AACX,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,iBAAiB,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC,GAAG,SAAS,KAAK;AAAA,MAC/G;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,UAAI,eAAe,gBAAgB,IAAI,SAAS,gBAAgB;AAC9D,eAAO;AAAA,UACL,SAAS,CAAC;AAAA,YACR,MAAM;AAAA,YACN,MAAM,KAAK,UAAU;AAAA,cACnB,OAAO;AAAA,cACP,YAAY;AAAA,cACZ,WAAW;AAAA,cACX;AAAA,cACA;AAAA,cACA,SAAS,gCAAgC,KAAK,MAAM,YAAY,GAAI,CAAC;AAAA,YACvE,CAAC;AAAA,UACH,CAAC;AAAA,UACD,SAAS;AAAA,QACX;AAAA,MACF;AACA,aAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,IAAI,CAAC,GAAG,SAAS,KAAK;AAAA,IACjE;AAAA,EACF;AAAA,EAEA,MAAc,QAAQ,MAAc,YAAY,KAAK,WAAoC;AACvF,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,QAChD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,aAAa,KAAK;AAAA,QACpB;AAAA,QACA,QAAQ,YAAY,QAAQ,SAAS;AAAA,MACvC,CAAC;AACD,YAAM,OAAO,MAAM,iBAAiB,GAAG;AACvC,UAAI,CAAC,IAAI,IAAI;AACX,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,iBAAiB,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC,GAAG,SAAS,KAAK;AAAA,MAC/G;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,MAAc,gBAAgB,MAAc,UAAkB,YAAY,KAAK,WAAoC;AACjH,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,QAChD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,aAAa,KAAK;AAAA,QACpB;AAAA,QACA,QAAQ,YAAY,QAAQ,SAAS;AAAA,MACvC,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,aAAa,EAAE,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,QAAQ,IAAI,MAAM,EAAE,EAAE,EAAE;AAC/G,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,IAAI,EAAE,CAAC,GAAG,SAAS,KAAK;AAAA,MAClF;AACA,YAAM,QAAQ,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC;AACjD,YAAM,SAAS,MAAM,SAAS,GAAG,KAAK,IAAI,UAAU,MAAM,MAAM,CAAC;AACjE,aAAO;AAAA,QACL,SAAS,CAAC;AAAA,UACR,MAAM;AAAA,UACN,MAAM,KAAK,UAAU;AAAA,YACnB,aAAa,IAAI,QAAQ,IAAI,cAAc,KAAK;AAAA,YAChD,OAAO,MAAM;AAAA,YACb,WAAW,OAAO,SAAS,MAAM;AAAA,YACjC;AAAA,YACA,MAAM,OAAO,SAAS,MAAM;AAAA,UAC9B,CAAC;AAAA,QACH,CAAC;AAAA,MACH;AAAA,IACF,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,UAAM,YAAY,KAAK,yBAAyB,qBAAqB,MAAM,gBAAgB,EAAE,EAAE;AAC/F,WAAO,KAAK,KAAK,iBAAiB,OAAkC,SAAS;AAAA,EAC/E;AAAA,EAEA,WAAW,OAAiD;AAC1D,UAAM,YAAY,KAAK,yBAAyB,qBAAqB,GAAG,IAAI,EAAE;AAC9E,WAAO,KAAK,KAAK,iBAAiB,EAAE,GAAG,OAAO,UAAU,KAAK,GAA8B,SAAS;AAAA,EACtG;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,UAAU,OAAgD;AACxD,WAAO,KAAK,KAAK,iBAAiB,KAAgC;AAAA,EACpE;AAAA,EAEA,eAAe,OAAqD;AAClE,WAAO,KAAK,KAAK,oBAAoB,KAAgC;AAAA,EACvE;AAAA,EAEA,kBAAkB,OAAwD;AACxE,UAAM,UAAU,MAAM,SAAS,KAAK,KAAK,sBAAsB,MAAM,GAAG;AACxE,QAAI,CAAC,SAAS;AACZ,aAAO,QAAQ,QAAQ;AAAA,QACrB,SAAS,CAAC;AAAA,UACR,MAAM;AAAA,UACN,MAAM,KAAK,UAAU;AAAA,YACnB,YAAY;AAAA,YACZ,OAAO;AAAA,YACP,WAAW;AAAA,UACb,CAAC;AAAA,QACH,CAAC;AAAA,QACD,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AACA,WAAO,KAAK,KAAK,uBAAuB,EAAE,QAAQ,CAAC;AAAA,EACrD;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,aAAa,OAAmD;AAC9D,WAAO,KAAK,KAAK,kBAAkB,OAAkC,KAAK,yBAAyB,IAAO;AAAA,EAC5G;AAAA,EAEA,qBAAqB,OAA2D;AAC9E,WAAO,KAAK,KAAK,wBAAwB,KAAgC;AAAA,EAC3E;AAAA,EAEA,wBAAwB,OAA8D;AACpF,WAAO,KAAK,KAAK,8BAA8B,OAAkC,KAAK,yBAAyB,IAAO;AAAA,EACxH;AAAA,EAEA,wBAAwB,OAA8D;AACpF,WAAO,KAAK,KAAK,8BAA8B,yBAAyB,KAAK,GAA8B,KAAK,yBAAyB,IAAO;AAAA,EAClJ;AAAA,EAEA,uBAAuB,OAA6D;AAClF,WAAO,KAAK,KAAK,6BAA6B,yBAAyB,KAAK,GAA8B,KAAK,yBAAyB,GAAO;AAAA,EACjJ;AAAA,EAEA,eAAe,OAAqD;AAClE,WAAO,KAAK,KAAK,eAAe,KAAgC;AAAA,EAClE;AAAA,EAEA,WAAW,OAAiD;AAC1D,WAAO,KAAK,KAAK,gBAAgB,KAAgC;AAAA,EACnE;AAAA,EAEA,kBAAkB,OAAwD;AACxE,UAAM,YAAY,OAAO,MAAM,cAAc,WAAW,MAAM,YAAY;AAC1E,UAAM,cAAc,OAAO,MAAM,gBAAgB,YAAY,MAAM,cAAc,IAAI,MAAM,cAAc;AACzG,UAAM,YAAY,KAAK,yBAAyB,KAAK,IAAI,KAAS,KAAK,IAAI,MAAS,KAAK,KAAK,YAAY,WAAW,IAAI,IAAO,CAAC;AACjI,WAAO,KAAK,KAAK,kBAAkB,OAAkC,SAAS;AAAA,EAChF;AAAA,EAEA,aAAa,QAAoD;AAC/D,WAAO,KAAK,QAAQ,wBAAwB;AAAA,EAC9C;AAAA,EAEA,YAAY,OAAkD;AAC5D,UAAM,YAAY,KAAK,yBAAyB,OAAO,QAAQ,IAAI,mCAAmC,GAAO;AAC7G,WAAO,KAAK,KAAK,kBAAkB;AAAA,MACjC,YAAY,MAAM;AAAA,MAClB,OAAO,MAAM,SAAS,CAAC;AAAA,MACvB,YAAY,MAAM;AAAA,IACpB,GAAG,OAAO,SAAS,SAAS,KAAK,YAAY,IAAI,YAAY,GAAO;AAAA,EACtE;AAAA,EAEA,aAAa,OAAmD;AAC9D,UAAM,YAAY,KAAK,yBAAyB,OAAO,QAAQ,IAAI,mCAAmC,GAAO;AAC7G,WAAO,KAAK,KAAK,mBAAmB,mBAAmB,MAAM,KAAK,CAAC,SAAS,CAAC,GAAG,OAAO,SAAS,SAAS,KAAK,YAAY,IAAI,YAAY,GAAO;AAAA,EACnJ;AAAA,EAEA,eAAe,OAAqD;AAClE,WAAO,KAAK,QAAQ,mBAAmB,mBAAmB,MAAM,KAAK,CAAC,EAAE;AAAA,EAC1E;AAAA,EAEA,qBAAqB,OAA2D;AAC9E,WAAO,KAAK;AAAA,MACV,mBAAmB,mBAAmB,MAAM,KAAK,CAAC,cAAc,mBAAmB,MAAM,UAAU,CAAC;AAAA,MACpG,MAAM,YAAY;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,YAAY,OAAkD;AAC5D,WAAO,KAAK,KAAK,oBAAoB,KAAgC;AAAA,EACvE;AAAA,EAEA,oBAAoB,OAA0D;AAC5E,WAAO,KAAK,KAAK,8BAA8B,OAAkC,KAAK,yBAAyB;AAAA,EACjH;AAAA,EAEA,yBAAyB,OAA+D;AACtF,WAAO,KAAK,KAAK,qCAAqC,OAAkC,KAAK,yBAAyB;AAAA,EACxH;AAEF;;;ACtVA,iBAA0B;AAE1B,IAAAC,kBAAyC;AACzC,IAAAC,kBAAwB;AACxB,IAAAC,oBAAqB;;;ACJrB,qBAAyC;AACzC,qBAAwB;AACxB,uBAAqB;AACrB,uBAAiB;AAiBjB,SAAS,gBAAwB;AAC/B,SAAO,QAAQ,IAAI,wBAAwB,KAAK,SAAK,2BAAK,wBAAQ,GAAG,aAAa,aAAa;AACjG;AAEA,SAAS,KAAK,OAAuB;AACnC,SAAO,MAAM,QAAQ,qBAAqB,GAAG,EAAE,QAAQ,YAAY,EAAE,EAAE,MAAM,GAAG,EAAE,KAAK;AACzF;AAIA,SAAS,WAAW,MAAc,MAAsC,WAAyB;AAC/F,oCAAc,MAAM,iBAAAC,QAAK,QAAQ,KAAK,SAAS,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;AAC5E;AAEO,SAAS,aAAa,UAA6C;AACxE,QAAM,QAAQ,KAAK,SAAS,WAAW,QAAQ,SAAS,GAAG,CAAC;AAC5D,QAAM,YAAY,cAAc;AAChC,QAAM,kBAAc,uBAAK,UAAU,GAAG,KAAK,IAAI,KAAK,SAAS,QAAQ,CAAC,EAAE;AACxE,QAAM,UAAM,uBAAK,WAAW,WAAW;AACvC,gCAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAElC,QAAM,YAAY,SAAS,QAAQ,IAAI,CAAC,GAAG,OAAO,EAAE,OAAO,IAAI,GAAG,OAAO,EAAE,EAAE;AAC7E,QAAM,eAAe,SAAS,WAAW,cAAc,IAAI,CAAC,MAAM;AAChE,UAAM,MAAM,SAAS,UAAU,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG;AAC1D,WAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE,QAAQ,KAAK,EAAE,KAAK,YAAY,EAAE,YAAY,UAAU,KAAK,YAAY,IAAI,OAAO,KAAK,SAAS,GAAG;AAAA,EACxI,CAAC;AACD,QAAM,aAAa,SAAS,YAAY,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,KAAK,OAAO,EAAE,OAAO,YAAY,EAAE,YAAY,UAAU,EAAE,UAAU,OAAO,EAAE,OAAO,OAAO,EAAE,SAAS,GAAG,EAAE;AAC3L,QAAM,kBAAkB,SAAS,YAAY,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,KAAK,OAAO,EAAE,OAAO,YAAY,EAAE,YAAY,UAAU,EAAE,UAAU,OAAO,EAAE,OAAO,OAAO,EAAE,SAAS,GAAG,EAAE;AAChM,QAAM,cAAc,SAAS,SAAS,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,KAAK,OAAO,EAAE,OAAO,MAAM,EAAE,KAAK,EAAE;AACjH,QAAM,aAAa,SAAS,WAAW,SAAS,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,OAAO,EAAE,OAAO,OAAO,EAAE,OAAO,YAAY,EAAE,YAAY,UAAU,EAAE,SAAS,EAAE;AAEjK,QAAM,gBAAmC;AAAA,IACvC,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,UAAM,uBAAK,aAAa,aAAa;AAAA,IACrC,gBAAY,uBAAK,aAAa,aAAa;AAAA,IAC3C,gBAAY,uBAAK,aAAa,aAAa;AAAA,IAC3C,kBAAc,uBAAK,aAAa,eAAe;AAAA,IAC/C,gBAAY,uBAAK,aAAa,aAAa;AAAA,IAC3C,oBAAgB,uBAAK,aAAa,kBAAkB;AAAA,IACpD,iBAAa,uBAAK,aAAa,cAAc;AAAA,IAC7C,gBAAY,uBAAK,aAAa,aAAa;AAAA,IAC3C,YAAQ,uBAAK,aAAa,aAAa;AAAA,EACzC;AAEA,wCAAc,uBAAK,WAAW,cAAc,IAAI,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AACpF,iBAAW,uBAAK,WAAW,cAAc,UAAU,GAAG,WAAW,GAAG;AACpE,iBAAW,uBAAK,WAAW,cAAc,UAAU,GAAG,WAAW,GAAI;AACrE,iBAAW,uBAAK,WAAW,cAAc,YAAY,GAAG,cAAc,GAAG;AACzE,iBAAW,uBAAK,WAAW,cAAc,UAAU,GAAG,YAAY,GAAG;AACrE,iBAAW,uBAAK,WAAW,cAAc,cAAc,GAAG,iBAAiB,GAAG;AAC9E,iBAAW,uBAAK,WAAW,cAAc,WAAW,GAAG,aAAa,GAAG;AACvE,iBAAW,uBAAK,WAAW,cAAc,UAAU,GAAG,YAAY,GAAG;AACrE,wCAAc,uBAAK,WAAW,cAAc,MAAM,GAAG,iBAAiB,QAAQ,CAAC;AAE/E,SAAO;AACT;AAEA,SAAS,IAAI,GAAmB;AAC9B,SAAO,OAAO,CAAC,EAAE,QAAQ,MAAM,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,QAAQ;AAC5G;AAEO,SAAS,iBAAiB,UAAkC;AACjE,QAAM,OAAO,KAAK,UAAU,QAAQ,EAAE,QAAQ,MAAM,SAAS;AAC7D,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,kCAKoB,IAAI,SAAS,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAsCzC,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0Bd;;;ACzJO,IAAM,kBAAkB;;;ACA/B,iBAAkB;AAElB,IAAM,iBAAiB,aAAE,OAAO,EAAE,SAAS;AAC3C,IAAM,mBAAmB,aAAE,OAAO,aAAE,QAAQ,CAAC;AAE7C,IAAM,uBAAuB,aAAE,OAAO,aAAE,QAAQ,CAAC;AAEjD,IAAM,oBAAoB;AAAA,EACxB,IAAI,aAAE,QAAQ,EAAE,SAAS,6CAA6C;AAAA,EACtE,MAAM,aAAE,OAAO,EAAE,SAAS,qDAAqD;AAAA,EAC/E,YAAY,eAAe,SAAS,8DAA8D;AACpG;AAEA,IAAM,0BAA0B;AAAA,EAC9B,GAAG;AAAA,EACH,WAAW,eAAe,SAAS,oDAAoD;AACzF;AAEO,IAAM,yBAAyB;AAAA,EACpC,OAAO,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oEAAoE;AAAA,EAC1G,KAAK,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,wDAAwD;AAAA,EAClG,SAAS,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,4EAA4E;AAAA,EACpH,sBAAsB,aAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,0MAA0M;AAAA,EAChQ,iBAAiB,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,MAAM,EAAE,SAAS,EAAE,SAAS,2LAA2L;AACvQ;AAGO,IAAM,mCAAmC;AAAA,EAC9C,OAAO,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,iOAA4N;AAAA,EAClQ,SAAS,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,+PAA0P;AAAA,EAClS,QAAQ,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yIAAyI;AAAA,EAChL,WAAW,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,yGAAyG;AAAA,EACzJ,KAAK,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,gDAAgD;AAAA,EAC1F,MAAM,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kJAAkJ;AAAA,EACvL,OAAO,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sDAAsD;AAAA,EAC5F,iBAAiB,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,MAAM,EAAE,SAAS,EAAE,SAAS,uFAAuF;AACnK;AAGO,IAAM,gCAAgC;AAAA,EAC3C,SAAS,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,gEAAgE;AAAA,EACxG,OAAO,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0EAA0E;AAAA,EAChH,QAAQ,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qHAAqH;AAAA,EAC5J,eAAe,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,4FAA4F;AAC5I;AAGO,IAAM,4BAA4B;AAAA,EACvC,YAAY,aAAE,OAAO,EAAE,SAAS,kIAAkI;AACpK;AAGO,IAAM,4BAA4B,aAAE,OAAO;AAAA,EAChD,MAAM,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uDAAuD;AAAA,EAC5F,UAAU,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,+GAA+G;AAAA,EACxJ,MAAM,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,4GAA4G;AAAA,EACjJ,OAAO,aAAE,KAAK,CAAC,YAAY,OAAO,CAAC,EAAE,QAAQ,UAAU,EAAE,SAAS,kDAAkD;AAAA,EACpH,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,sDAAsD;AAC3G,CAAC,EAAE,OAAO,WAAS,QAAQ,MAAM,YAAY,MAAM,IAAI,GAAG;AAAA,EACxD,SAAS;AACX,CAAC;AAEM,IAAM,2BAA2B;AAAA,EACtC,YAAY,aAAE,OAAO,EAAE,SAAS,kIAAkI;AAAA,EAClK,SAAS,aAAE,MAAM,yBAAyB,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,mHAAmH;AACzL;AAGO,IAAM,yBAAyB;AAAA,EACpC,YAAY,aAAE,OAAO,EAAE,SAAS,kIAAkI;AAAA,EAClK,KAAK,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,iCAAiC;AAClE;AAGO,IAAM,0BAA0B;AAAA,EACrC,YAAY,aAAE,OAAO,EAAE,SAAS,kIAAkI;AAAA,EAClK,GAAG,aAAE,OAAO,EAAE,SAAS,6JAA6J;AAAA,EACpL,GAAG,aAAE,OAAO,EAAE,SAAS,6JAA6J;AAAA,EACpL,QAAQ,aAAE,KAAK,CAAC,QAAQ,SAAS,QAAQ,CAAC,EAAE,QAAQ,MAAM,EAAE,SAAS,eAAe;AAAA,EACpF,YAAY,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,4CAA4C;AAC7G;AAGO,IAAM,yBAAyB;AAAA,EACpC,YAAY,aAAE,OAAO,EAAE,SAAS,kIAAkI;AAAA,EAClK,MAAM,aAAE,OAAO,EAAE,SAAS,qEAAqE;AAAA,EAC/F,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,2DAA2D;AACzH;AAGO,IAAM,2BAA2B;AAAA,EACtC,YAAY,aAAE,OAAO,EAAE,SAAS,kIAAkI;AAAA,EAClK,SAAS,aAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,qEAAqE;AAAA,EAC7G,SAAS,aAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,mCAAmC;AAAA,EAC3E,GAAG,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qDAAqD;AAAA,EACvF,GAAG,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qDAAqD;AACzF;AAGO,IAAM,0BAA0B;AAAA,EACrC,YAAY,aAAE,OAAO,EAAE,SAAS,kIAAkI;AAAA,EAClK,MAAM,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,iFAAiF;AAC7H;AAGO,IAAM,+BAA+B;AAAA,EAC1C,YAAY,aAAE,OAAO,EAAE,SAAS,kIAAkI;AAAA,EAClK,WAAW,aAAE,OAAO,EAAE,SAAS,uIAAuI;AACxK;AAGO,IAAM,mCAAmC;AAAA,EAC9C,YAAY,aAAE,OAAO,EAAE,SAAS,kIAAkI;AAAA,EAClK,WAAW,aAAE,OAAO,EAAE,SAAS,uIAAuI;AAAA,EACtK,UAAU,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yEAAyE;AACpH;AAGO,IAAM,gCAAgC,aAAE,OAAO;AAAA,EACpD,MAAM,aAAE,KAAK,CAAC,OAAO,UAAU,aAAa,SAAS,OAAO,CAAC,EAAE,QAAQ,KAAK,EAAE,SAAS,2CAA2C;AAAA,EAClI,eAAe,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,kDAAkD;AAAA,EACvG,aAAa,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,oFAAoF;AAAA,EACvI,MAAM,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uGAAuG;AAAA,EAC5I,KAAK,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qGAAqG;AAAA,EACzI,OAAO,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,oGAAoG;AAAA,EACrJ,QAAQ,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,sGAAsG;AAAA,EACxJ,GAAG,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kFAAkF;AAAA,EACpH,GAAG,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kFAAkF;AAAA,EACpH,QAAQ,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kFAAkF;AAAA,EACzH,QAAQ,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kFAAkF;AAAA,EACzH,MAAM,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,4FAA4F;AAAA,EACjI,MAAM,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,4FAA4F;AAAA,EACjI,OAAO,aAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,sDAAsD;AAAA,EACrG,OAAO,aAAE,OAAO,EAAE,MAAM,oBAAoB,EAAE,SAAS,EAAE,SAAS,+CAA+C;AAAA,EACjH,WAAW,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,4CAA4C;AACvG,CAAC;AAEM,IAAM,+BAA+B;AAAA,EAC1C,YAAY,aAAE,OAAO,EAAE,SAAS,sKAAsK;AAAA,EACtM,QAAQ,0BAA0B,SAAS,sEAAsE;AAAA,EACjH,MAAM,aAAE,KAAK,CAAC,OAAO,UAAU,aAAa,OAAO,CAAC,EAAE,QAAQ,KAAK,EAAE,SAAS,sGAAsG;AAAA,EACpL,OAAO,aAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,kDAAkD;AAAA,EACjG,OAAO,aAAE,OAAO,EAAE,MAAM,oBAAoB,EAAE,SAAS,EAAE,SAAS,+CAA+C;AAAA,EACjH,WAAW,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,4CAA4C;AAAA,EACrG,SAAS,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,gFAAgF;AAAA,EACvI,sBAAsB,aAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,QAAQ,KAAK,EAAE,SAAS,uHAAuH;AAAA,EAChM,kBAAkB,aAAE,OAAO,EAAE,IAAI,GAAG,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,0DAA0D;AAC9H;AAGO,IAAM,mCAAmC;AAAA,EAC9C,YAAY,aAAE,OAAO,EAAE,SAAS,kIAAkI;AAAA,EAClK,WAAW,aAAE,OAAO,EAAE,SAAS,uIAAuI;AAAA,EACtK,aAAa,aAAE,MAAM,6BAA6B,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,4LAA4L;AAAA,EACxQ,UAAU,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oFAAoF;AAAA,EAC7H,cAAc,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,oGAAoG;AAAA,EAC5J,eAAe,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,oLAAoL;AAAA,EAC7O,oBAAoB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,sGAAsG;AAAA,EAChK,mBAAmB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,6LAA6L;AACxP;AAGO,IAAM,yBAAyB;AAAA,EACpC,gBAAgB,aAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,sCAAsC;AAC5F;AAGO,IAAM,kCAAkC;AAAA,EAC7C,YAAY,aAAE,OAAO,EAAE,SAAS,gOAAgO;AAAA,EAChQ,QAAQ,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uOAAuO;AAAA,EAC9Q,SAAS,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,IAAM,EAAE,SAAS,EAAE,SAAS,yLAAyL;AAAA,EAC1P,oBAAoB,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,wKAAwK;AAAA,EAC3N,OAAO,aAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,iHAAiH;AAAA,EAC5J,QAAQ,aAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,2OAA2O;AACzR;AAGA,IAAM,qBAAqB,aAAE,OAAO;AAAA,EAClC,KAAK,aAAE,OAAO;AAAA,EACd,QAAQ,aAAE,OAAO;AAAA,EACjB,OAAO,aAAE,OAAO;AAAA,EAChB,OAAO,aAAE,QAAQ;AAAA,EACjB,YAAY,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAClC,SAAS,aAAE,OAAO;AAAA,EAClB,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACjC,UAAU,aAAE,OAAO,EAAE,SAAS,+GAA+G;AAC/I,CAAC;AAEM,IAAM,mCAAmC;AAAA,EAC9C,GAAG;AAAA,EACH,MAAM,aAAE,QAAQ,uBAAuB;AAAA,EACvC,UAAU,aAAE,KAAK,CAAC,WAAW,QAAQ,CAAC,EAAE,SAAS,wDAAwD;AAAA,EACzG,aAAa,aAAE,OAAO;AAAA,EACtB,QAAQ,aAAE,OAAO,EAAE,SAAS,wEAAwE;AAAA,EACpG,MAAM,aAAE,OAAO;AAAA,IACb,OAAO,aAAE,OAAO;AAAA,IAChB,YAAY,aAAE,OAAO;AAAA,IACrB,OAAO,aAAE,OAAO;AAAA,IAChB,QAAQ,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAChC,CAAC;AAAA,EACD,SAAS,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,SAAS,gIAAgI;AAAA,EACtK,cAAc,aAAE,MAAM,kBAAkB,EAAE,SAAS,6DAA6D;AAAA,EAChH,YAAY,aAAE,MAAM,kBAAkB,EAAE,SAAS,mEAAmE;AAAA,EACpH,cAAc,aAAE,MAAM,kBAAkB,EAAE,SAAS,oDAAoD;AAAA,EACvG,UAAU,aAAE,MAAM,aAAE,OAAO,EAAE,KAAK,aAAE,OAAO,GAAG,QAAQ,aAAE,OAAO,GAAG,OAAO,aAAE,OAAO,GAAG,MAAM,aAAE,OAAO,EAAE,CAAC,CAAC;AAAA,EACxG,QAAQ,aAAE,OAAO;AAAA,IACf,YAAY,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAClC,SAAS,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAC/B,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAC7B,aAAa,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACrC,CAAC;AAAA,EACD,YAAY,aAAE,OAAO;AAAA,IACnB,UAAU,aAAE,MAAM,aAAE,OAAO,EAAE,QAAQ,aAAE,OAAO,GAAG,OAAO,aAAE,OAAO,EAAE,IAAI,GAAG,OAAO,aAAE,QAAQ,GAAG,YAAY,aAAE,OAAO,EAAE,IAAI,GAAG,UAAU,aAAE,OAAO,EAAE,CAAC,CAAC;AAAA,IACnJ,eAAe,aAAE,MAAM,aAAE,OAAO,EAAE,MAAM,aAAE,OAAO,EAAE,IAAI,GAAG,QAAQ,aAAE,OAAO,GAAG,KAAK,aAAE,OAAO,GAAG,YAAY,aAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AAAA,IAC9H,YAAY,aAAE,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACvC,CAAC,EAAE,SAAS,gGAAgG;AAAA,EAC5G,oBAAoB,aAAE,OAAO,EAAE,SAAS;AAAA,EACxC,SAAS,aAAE,OAAO;AAAA,IAChB,YAAY,aAAE,OAAO;AAAA,IACrB,KAAK,aAAE,OAAO;AAAA,IACd,MAAM,aAAE,OAAO;AAAA,IACf,YAAY,aAAE,OAAO;AAAA,IACrB,YAAY,aAAE,OAAO;AAAA,IACrB,cAAc,aAAE,OAAO;AAAA,IACvB,YAAY,aAAE,OAAO;AAAA,IACrB,gBAAgB,aAAE,OAAO;AAAA,IACzB,aAAa,aAAE,OAAO;AAAA,IACtB,YAAY,aAAE,OAAO;AAAA,IACrB,QAAQ,aAAE,OAAO;AAAA,EACnB,CAAC,EAAE,SAAS,EAAE,SAAS,gKAAgK;AAAA,EACvL,OAAO,aAAE,OAAO;AAAA,IACd,kBAAkB,aAAE,QAAQ;AAAA,IAC5B,UAAU,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAChC,cAAc,aAAE,MAAM,aAAE,OAAO,CAAC;AAAA,IAChC,MAAM,aAAE,OAAO;AAAA,EACjB,CAAC,EAAE,SAAS;AACd;AAEO,IAAM,0BAA0B;AAAA,EACrC,IAAI,aAAE,QAAQ;AAAA,EACd,MAAM,aAAE,QAAQ,cAAc;AAAA,EAC9B,YAAY,aAAE,OAAO,EAAE,SAAS,yHAAyH;AAAA,EACzJ,WAAW,aAAE,OAAO,EAAE,SAAS,sEAAsE;AAAA,EACrG,eAAe,eAAe,SAAS,mEAAmE;AAAA,EAC1G,KAAK,eAAe,SAAS,qDAAqD;AAAA,EAClF,MAAM,aAAE,OAAO;AAAA,EACf,KAAK,iBAAiB,SAAS;AACjC;AAEA,IAAM,sBAAsB,aAAE,OAAO;AAAA,EACnC,eAAe,eAAe,SAAS,oCAAoC;AAAA,EAC3E,QAAQ,aAAE,OAAO,EAAE,SAAS,2CAA2C;AAAA,EACvE,QAAQ,aAAE,OAAO,EAAE,SAAS,gDAAgD;AAAA,EAC5E,eAAe,eAAe,SAAS,oDAAoD;AAAA,EAC3F,MAAM,eAAe,SAAS,uCAAuC;AAAA,EACrE,WAAW,eAAe,SAAS,mFAAmF;AAAA,EACtH,mBAAmB,eAAe,SAAS,8CAA8C;AAC3F,CAAC;AAEM,IAAM,oCAAoC;AAAA,EAC/C,IAAI,aAAE,QAAQ;AAAA,EACd,MAAM,aAAE,QAAQ,yBAAyB;AAAA,EACzC,YAAY;AAAA,EACZ,oBAAoB,aAAE,OAAO;AAAA,EAC7B,WAAW,aAAE,OAAO,EAAE,SAAS,+EAA+E;AAAA,EAC9G,eAAe,eAAe,SAAS,8DAA8D;AAAA,EACrG,SAAS,aAAE,OAAO,EAAE,SAAS,sFAAsF;AAAA,EACnH,QAAQ,aAAE,OAAO;AAAA,EACjB,WAAW,aAAE,OAAO;AAAA,EACpB,eAAe;AAAA,EACf,MAAM;AAAA,EACN,QAAQ,aAAE,OAAO;AAAA,EACjB,aAAa;AAAA,EACb,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,kBAAkB,aAAE,MAAM,mBAAmB,EAAE,SAAS,qFAAqF;AAAA,EAC7I,YAAY,aAAE,MAAM,aAAE,OAAO,CAAC;AAAA,EAC9B,KAAK,iBAAiB,SAAS;AACjC;AAEO,IAAM,iCAAiC;AAAA,EAC5C,IAAI,aAAE,QAAQ;AAAA,EACd,MAAM,aAAE,QAAQ,sBAAsB;AAAA,EACtC,YAAY,aAAE,KAAK;AAAA,EACnB,SAAS,aAAE,OAAO,EAAE,SAAS,iCAAiC;AAAA,EAC9D,aAAa,aAAE,MAAM,mBAAmB,EAAE,SAAS,oFAAoF;AAAA,EACvI,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAC/B;AAEO,IAAM,gCAAgC;AAAA,EAC3C,GAAG;AAAA,EACH,MAAM,aAAE,QAAQ,oBAAoB;AAAA,EACpC,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM,aAAE,OAAO;AAAA,EACf,UAAU,aAAE,MAAM,oBAAoB;AAAA,EACtC,YAAY,aAAE,OAAO;AAAA,IACnB,WAAW,aAAE,OAAO;AAAA,IACpB,QAAQ,aAAE,QAAQ;AAAA,EACpB,CAAC,EAAE,SAAS;AACd;AAEO,IAAM,0BAA0B;AAAA,EACrC,GAAG;AAAA,EACH,MAAM,aAAE,QAAQ,cAAc;AAAA,EAC9B,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM,aAAE,OAAO;AAAA,EACf,UAAU,aAAE,MAAM,oBAAoB;AAAA,EACtC,KAAK,iBAAiB,SAAS;AACjC;AAEO,IAAM,4BAA4B;AAAA,EACvC,GAAG;AAAA,EACH,MAAM,aAAE,QAAQ,gBAAgB;AAAA,EAChC,KAAK;AAAA,EACL,OAAO;AAAA,EACP,UAAU,iBAAiB,SAAS;AAAA,EACpC,QAAQ,iBAAiB,SAAS;AAAA,EAClC,SAAS,aAAE,MAAM,gBAAgB;AAAA,EACjC,KAAK,iBAAiB,SAAS;AACjC;AAEO,IAAM,4BAA4B;AAAA,EACvC,GAAG;AAAA,EACH,QAAQ,iBAAiB,SAAS,2GAA2G;AAAA,EAC7I,qBAAqB,aAAE,OAAO,EAAE,SAAS;AAC3C;AAEO,IAAM,iCAAiC;AAAA,EAC5C,GAAG;AAAA,EACH,MAAM,aAAE,QAAQ,sBAAsB;AAAA,EACtC,UAAU;AAAA,EACV,cAAc;AAAA,EACd,KAAK,iBAAiB,SAAS;AACjC;AAEO,IAAM,gCAAgC;AAAA,EAC3C,GAAG;AAAA,EACH,MAAM,aAAE,QAAQ,qBAAqB;AAAA,EACrC,UAAU;AAAA,EACV,cAAc;AAAA,EACd,KAAK,iBAAiB,SAAS;AACjC;AAEO,IAAM,iCAAiC;AAAA,EAC5C,GAAG;AAAA,EACH,MAAM,aAAE,QAAQ,sBAAsB;AAAA,EACtC,SAAS,aAAE,MAAM,gBAAgB;AAAA,EACjC,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAC/B;AAEO,IAAM,oCAAoC;AAAA,EAC/C,GAAG;AAAA,EACH,MAAM,aAAE,QAAQ,yBAAyB;AAAA,EACzC,WAAW;AAAA,EACX,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACxC,WAAW;AAAA,EACX,cAAc;AAChB;AAEO,IAAM,gCAAgC;AAAA,EAC3C,GAAG;AAAA,EACH,MAAM,aAAE,QAAQ,qBAAqB;AAAA,EACrC,YAAY;AAAA,EACZ,cAAc,aAAE,OAAO,EAAE,SAAS;AAAA,EAClC,eAAe,aAAE,OAAO,EAAE,SAAS;AAAA,EACnC,QAAQ,iBAAiB,SAAS;AAAA,EAClC,MAAM,aAAE,OAAO;AACjB;AAEO,IAAM,oCAAoC;AAAA,EAC/C,GAAG;AAAA,EACH,MAAM,aAAE,QAAQ,yBAAyB;AAAA,EACzC,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACxC,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACxC,QAAQ,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACzC,kBAAkB,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACnD,WAAW;AACb;AAEO,IAAM,2BAA2B;AAAA,EACtC,GAAG;AAAA,EACH,MAAM,aAAE,QAAQ,eAAe;AAAA,EAC/B,QAAQ,aAAE,QAAQ;AAAA,EAClB,KAAK,iBAAiB,SAAS;AACjC;AAEO,IAAM,kCAAkC;AAAA,EAC7C,IAAI,aAAE,QAAQ;AAAA,EACd,MAAM,aAAE,QAAQ,uBAAuB;AAAA,EACvC,YAAY,aAAE,KAAK;AAAA,EACnB,UAAU,aAAE,MAAM,gBAAgB;AAAA,EAClC,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAC/B;;;AC7YA,gCAAyB;AACzB,sBAA6C;AAC7C,IAAAC,kBAAuB;AACvB,IAAAC,oBAAqB;AACrB,uBAA0B;AAE1B,IAAM,oBAAgB,4BAAU,kCAAQ;AA0DxC,SAAS,aAAa,OAAiC;AACrD,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK;AAC3D;AAEA,SAAS,MAAM,OAAe,KAAa,KAAqB;AAC9D,SAAO,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC;AAC3C;AAEA,SAAS,cAAc,SAAyB;AAC9C,QAAMC,QAAO,KAAK,IAAI,GAAG,OAAO;AAChC,QAAM,QAAQ,KAAK,MAAMA,QAAO,IAAI;AACpC,QAAM,UAAU,KAAK,MAAOA,QAAO,OAAQ,EAAE;AAC7C,QAAM,eAAe,KAAK,MAAMA,QAAO,EAAE;AACzC,QAAM,eAAe,KAAK,OAAOA,QAAO,KAAK,MAAMA,KAAI,KAAK,GAAG;AAC/D,SAAO,GAAG,KAAK,IAAI,OAAO,OAAO,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,OAAO,YAAY,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,OAAO,YAAY,EAAE,SAAS,GAAG,GAAG,CAAC;AACvI;AAEA,SAAS,iBAAiB,OAAwB;AAChD,QAAM,aAAa,OAAO,KAAK,EAAE,MAAM,sBAAsB,IAAI,CAAC,KAAK;AACvE,QAAM,MAAM,WAAW,MAAM,GAAG,CAAC;AACjC,QAAM,QAAQ,WAAW,MAAM,GAAG,CAAC;AACnC,QAAM,OAAO,WAAW,MAAM,GAAG,CAAC;AAClC,SAAO,KAAK,IAAI,GAAG,KAAK,GAAG,GAAG;AAChC;AAEA,SAAS,cAAc,OAAuB;AAC5C,SAAO,MACJ,QAAQ,OAAO,MAAM,EACrB,QAAQ,OAAO,KAAK,EACpB,QAAQ,OAAO,KAAK,EACpB,QAAQ,UAAU,KAAK;AAC5B;AAEA,SAAS,2BAA2B,OAAa,QAAc,SAAqD;AAClH,QAAM,kBAAkB,aAAa,QAAQ,gBAAgB,IAAI,QAAQ,mBAAmB;AAC5F,QAAM,kBAAkB,aAAa,QAAQ,eAAe,IAAI,QAAQ,kBAAkB;AAC1F,QAAM,oBACJ,mBAAmB,QACnB,KAAK,MAAM,OAAO,KAAK,MAAM,KAAK,MAAM,MAAM,KAAK,KACnD,OAAO,SAAS,MAAM,UACtB,MAAM,SAAS,OAAO,UAAU,MAC5B,MAAM,SAAS,OAAO,SACtB;AACN,QAAM,UAAU,mBAAmB;AACnC,QAAM,UAAU,mBAAmB;AACnC,SAAO;AAAA,IACL,SAAS,MAAM,QAAQ,WAAW,OAAO;AAAA,IACzC,SAAS,MAAM,SAAS,WAAW,OAAO;AAAA,IAC1C;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,eAAe,GAAW,GAAW,WAA0D;AACtG,SAAO;AAAA,IACL,GAAG,IAAI,UAAU,SAAS,UAAU;AAAA,IACpC,GAAG,IAAI,UAAU,SAAS,UAAU;AAAA,EACtC;AACF;AAEA,SAAS,UAAU,YAA8B,WAAsC;AACrF,MACE,aAAa,WAAW,IAAI,KAC5B,aAAa,WAAW,GAAG,KAC3B,aAAa,WAAW,KAAK,KAC7B,aAAa,WAAW,MAAM,GAC9B;AACA,UAAM,SAAS,eAAe,WAAW,MAAM,WAAW,KAAK,SAAS;AACxE,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,MACb,KAAK,OAAO;AAAA,MACZ,OAAO,WAAW,QAAQ,UAAU;AAAA,MACpC,QAAQ,WAAW,SAAS,UAAU;AAAA,IACxC;AAAA,EACF;AACA,MAAI,aAAa,WAAW,CAAC,KAAK,aAAa,WAAW,CAAC,GAAG;AAC5D,UAAM,SAAS,aAAa,WAAW,KAAK,IAAI,WAAW,QAAQ,IAAI;AACvE,UAAM,QAAQ,eAAe,WAAW,GAAG,WAAW,GAAG,SAAS;AAClE,WAAO;AAAA,MACL,MAAM,MAAM,IAAI,SAAS,UAAU;AAAA,MACnC,KAAK,MAAM,IAAI,SAAS,UAAU;AAAA,MAClC,OAAO,SAAS,IAAI,UAAU;AAAA,MAC9B,QAAQ,SAAS,IAAI,UAAU;AAAA,IACjC;AAAA,EACF;AACA,QAAM,IAAI,MAAM,sDAAsD;AACxE;AAEA,SAAS,SAAS,MAAoB;AACpC,QAAM,KAAK,KAAK,MAAM,KAAK,IAAI;AAC/B,QAAM,KAAK,KAAK,MAAM,KAAK,GAAG;AAC9B,QAAM,KAAK,KAAK,MAAM,KAAK,OAAO,KAAK,KAAK;AAC5C,QAAM,KAAK,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM;AAC5C,SAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;AAC9E;AAEA,SAAS,YAAY,MAAoB;AACvC,QAAM,KAAK,KAAK,OAAO,KAAK,QAAQ;AACpC,QAAM,KAAK,KAAK,MAAM,KAAK,SAAS;AACpC,QAAM,KAAK,KAAK,IAAI,GAAG,KAAK,QAAQ,CAAC;AACrC,QAAM,KAAK,KAAK,IAAI,GAAG,KAAK,SAAS,CAAC;AACtC,QAAM,SAAmB,CAAC;AAC1B,WAAS,IAAI,GAAG,KAAK,IAAI,KAAK,GAAG;AAC/B,UAAM,IAAK,KAAK,KAAK,IAAI,IAAK;AAC9B,UAAM,IAAI,KAAK,MAAM,KAAK,KAAK,IAAI,CAAC,IAAI,EAAE;AAC1C,UAAM,IAAI,KAAK,MAAM,KAAK,KAAK,IAAI,CAAC,IAAI,EAAE;AAC1C,WAAO,KAAK,GAAG,MAAM,IAAI,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE;AAAA,EAChD;AACA,SAAO,OAAO,KAAK,GAAG;AACxB;AAEA,SAAS,eAAe,MAAc,KAAa,OAAe,QAAwB;AACxF,SAAO,SAAS,EAAE,MAAM,KAAK,OAAO,OAAO,CAAC;AAC9C;AAEA,SAAS,UAAU,OAAe,OAAe,KAAa,KAAa,WAA2B;AACpG,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,MAAM;AACjB,QAAM,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,IAAI,EAAE,CAAC;AAC7C,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,CAAC;AACZ,QAAM,KAAK;AACX,QAAM,OAAO,YAAY;AACzB,QAAM,OAAO,KAAK,IAAI,IAAI,YAAY,CAAC;AACvC,QAAM,QAAQ,MAAM,KAAK;AACzB,QAAM,QAAQ,MAAM,KAAK;AACzB,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,IAAI;AACxC,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,IAAI;AACxC,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,IAAI;AACxC,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,IAAI;AACxC,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,OAAO,IAAI;AAC/C,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,OAAO,IAAI;AAC/C,QAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,QAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,OAAO,IAAI;AAC/C,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,OAAO,IAAI;AAC/C,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,IAAI;AACxC,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,IAAI;AACxC,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,IAAI;AACxC,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,IAAI;AACxC,SAAO,KAAK,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG;AACxI;AAEA,SAAS,UAAU,OAAe,KAAa,MAAsB;AACnE,SAAO,eAAe,cAAc,KAAK,CAAC,IAAI,cAAc,GAAG,CAAC,oBAAoB,IAAI;AAC1F;AAEA,SAAS,UAAU,OAAe,KAAa,GAAW,GAAW,OAAuB;AAC1F,QAAM,QAAQ,KAAK,MAAM,CAAC;AAC1B,QAAM,QAAQ,KAAK,MAAM,CAAC;AAC1B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,eAAe,KAAK,IAAI,KAAK,kDAAkD,cAAc,KAAK,CAAC;AAAA,EACrG;AACF;AAEA,SAAS,UAAU,OAAe,KAAa,MAAc,OAAe,WAAmB,SAAS,OAAe;AACrH,QAAM,YAAY,SAAS,UAAU;AACrC,QAAM,SAAS,SAAS,IAAI;AAC5B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,6BAA6B,MAAM,cAAc,SAAS,OAAO,KAAK,OAAO,KAAK,IAAI,IAAI;AAAA,EAC5F;AACF;AAEO,SAAS,iBAAiB,SAAgC,OAAqB;AACpF,QAAM,SAAS;AAAA,IACb,OAAO,QAAQ,eAAe,QAAQ,cAAc,IAAI,QAAQ,cAAc,MAAM;AAAA,IACpF,QAAQ,QAAQ,gBAAgB,QAAQ,eAAe,IAAI,QAAQ,eAAe,MAAM;AAAA,EAC1F;AACA,QAAM,YAAY,2BAA2B,OAAO,QAAQ,OAAO;AACnE,QAAM,QAAkB,CAAC;AACzB,aAAW,cAAc,QAAQ,aAAa;AAC5C,UAAM,QAAQ,KAAK,IAAI,GAAG,WAAW,iBAAiB,CAAC;AACvD,UAAM,MAAM,WAAW,eAAe,WAAW,cAAc,QAAQ,WAAW,cAAc,QAAQ;AACxG,UAAM,OAAO,WAAW,QAAQ;AAChC,UAAM,QAAQ,iBAAiB,WAAW,KAAK;AAC/C,UAAM,YAAY,KAAK,MAAM,MAAM,WAAW,aAAa,GAAG,GAAG,EAAE,CAAC;AACpE,QAAI,SAAS,SAAS;AACpB,UAAI,CAAC,WAAW,MAAO,OAAM,IAAI,MAAM,8BAA8B;AACrE,YAAMC,QAAO,UAAU,YAAY,SAAS;AAC5C,YAAM,KAAK,UAAU,OAAO,KAAKA,MAAK,MAAM,KAAK,IAAI,GAAGA,MAAK,GAAG,GAAG,WAAW,KAAK,CAAC;AACpF;AAAA,IACF;AACA,QAAI,SAAS,SAAS;AACpB,YAAMA,QAAO,aAAa,WAAW,IAAI,KAAK,aAAa,WAAW,IAAI,IACtE,OACA,UAAU,YAAY,SAAS;AACnC,YAAM,UAAU,aAAa,WAAW,IAAI,KAAK,aAAa,WAAW,IAAI,IACzE,eAAe,WAAW,MAAM,WAAW,MAAM,SAAS,IAC1D;AACJ,YAAM,MAAM,UAAU,QAAQ,IAAIA,MAAM,OAAOA,MAAM,QAAQ;AAC7D,YAAM,MAAM,UAAU,QAAQ,IAAIA,MAAM,MAAMA,MAAM,SAAS;AAC7D,YAAM,YAAY,aAAa,WAAW,MAAM,KAAK,aAAa,WAAW,MAAM,IAC/E,eAAe,WAAW,QAAQ,WAAW,QAAQ,SAAS,IAC9D;AACJ,YAAM,QAAQ,YAAY,UAAU,IAAI,MAAM,MAAM,KAAK,IAAI,MAAM,QAAQ,EAAE;AAC7E,YAAM,QAAQ,YAAY,UAAU,IAAI,MAAM,MAAM,IAAI,IAAI,MAAM,SAAS,EAAE;AAC7E,YAAM,KAAK,UAAU,OAAO,KAAK,UAAU,OAAO,OAAO,KAAK,KAAK,SAAS,GAAG,OAAO,WAAW,IAAI,CAAC;AACtG,UAAI,WAAW,MAAO,OAAM,KAAK,UAAU,OAAO,KAAK,QAAQ,GAAG,KAAK,IAAI,IAAI,QAAQ,EAAE,GAAG,WAAW,KAAK,CAAC;AAC7G;AAAA,IACF;AACA,UAAM,OAAO,UAAU,YAAY,SAAS;AAC5C,QAAI,SAAS,aAAa;AACxB,YAAM,eAAe,KAAK,MAAM,KAAK,SAAS;AAC9C,YAAM,KAAK,UAAU,OAAO,KAAK,eAAe,KAAK,MAAM,cAAc,KAAK,OAAO,SAAS,GAAG,OAAO,GAAG,IAAI,CAAC;AAAA,IAClH,WAAW,SAAS,UAAU;AAC5B,YAAM,KAAK,UAAU,OAAO,KAAK,YAAY,IAAI,GAAG,OAAO,SAAS,CAAC;AAAA,IACvE,OAAO;AACL,YAAM,KAAK,UAAU,OAAO,KAAK,SAAS,IAAI,GAAG,OAAO,SAAS,CAAC;AAAA,IACpE;AACA,QAAI,WAAW,MAAO,OAAM,KAAK,UAAU,OAAO,KAAK,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,GAAG,WAAW,KAAK,CAAC;AAAA,EACjH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa,KAAK,MAAM,MAAM,KAAK,CAAC;AAAA,IACpC,aAAa,KAAK,MAAM,MAAM,MAAM,CAAC;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,IACH;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,eAAe,UAAU,eAAsC;AAC7D,QAAM,EAAE,OAAO,IAAI,MAAM,cAAc,WAAW;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG,EAAE,WAAW,OAAO,KAAK,CAAC;AAC7B,QAAM,SAAS,KAAK,MAAM,MAAM;AAChC,QAAM,SAAS,OAAO,UAAU,CAAC;AACjC,MAAI,CAAC,QAAQ,SAAS,CAAC,OAAO,OAAQ,OAAM,IAAI,MAAM,wCAAwC;AAC9F,SAAO,EAAE,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO;AACtD;AAEA,SAAS,iBAAiB,MAAsB;AAC9C,SAAO,KAAK,QAAQ,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAK;AACxD;AAEA,eAAsB,oBACpB,eACA,gBACA,SACgC;AAChC,MAAI,CAAC,QAAQ,YAAY,OAAQ,OAAM,IAAI,MAAM,4CAA4C;AAC7F,QAAM,OAAO,MAAM,UAAU,aAAa;AAC1C,QAAM,MAAM,UAAM,6BAAQ,4BAAK,wBAAO,GAAG,kBAAkB,CAAC;AAC5D,QAAM,cAAU,wBAAK,KAAK,iBAAiB;AAC3C,MAAI;AACF,cAAM,2BAAU,SAAS,iBAAiB,SAAS,IAAI,GAAG,MAAM;AAChE,UAAM,cAAc,UAAU;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,iBAAiB,OAAO,CAAC;AAAA,MAChC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,GAAG,EAAE,WAAW,OAAO,OAAO,GAAG,CAAC;AAClC,UAAM,MAAM,UAAM,sBAAK,cAAc;AACrC,WAAO;AAAA,MACL,UAAU;AAAA,MACV,OAAO,IAAI;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,iBAAiB,QAAQ,YAAY;AAAA,IACvC;AAAA,EACF,UAAE;AACA,cAAM,oBAAG,KAAK,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EAChD;AACF;;;ACrWO,SAAS,mBAAmB,SAAyB;AAC1D,SAAO,QACJ,QAAQ,4BAA4B,UAAU,EAC9C,QAAQ,0BAA0B,cAAc,EAChD,QAAQ,gBAAgB,aAAa,EACrC,QAAQ,wBAAwB,UAAU,EAC1C,QAAQ,sBAAsB,cAAc,EAC5C,QAAQ,gBAAgB,aAAa,EACrC,QAAQ,QAAQ,GAAG,EACnB,KAAK;AACV;;;ACVA,IAAM,cAAsC;AAAA,EAC1C,QAAQ;AAAA,EACR,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB,yBAAyB;AAAA,EACzB,qBAAqB;AAAA,EACrB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,mBAAmB;AAAA,EACnB,eAAe;AACjB;AAEA,IAAM,uBAAuB;AAE7B,IAAM,kBAAkB,oBAAI,IAAI;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,gBAAgB;AAEtB,SAAS,iBAAiB,OAAuB;AAC/C,SAAO,MAAM,QAAQ,eAAe,mBAAmB;AACzD;AAEO,SAAS,4BAA+B,OAAU,YAAY,IAAO;AAC1E,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,MAAM,iBAAiB,KAAK;AAChC,QAAI,qBAAqB,KAAK,SAAS,KAAK,UAAU,KAAK,GAAG,GAAG;AAC/D,YAAM,mBAAmB,GAAG;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,OAAK,4BAA4B,GAAG,SAAS,CAAC;AACzF,MAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;AAC/C,UAAM,MAA+B,CAAC;AACtC,eAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAgC,GAAG;AACzE,YAAM,UAAU,YAAY,GAAG,KAAK;AACpC,UAAI,gBAAgB,IAAI,GAAG,GAAG;AAC5B,YAAI,OAAO,IAAI;AACf;AAAA,MACF;AACA,UAAI,OAAO,IAAI,4BAA4B,KAAK,GAAG;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;ANDA,SAAS,iBAAiB,OAAgC,UAAU,OAAuB;AACzF,QAAMC,QAAO,4BAA4B,KAAK;AAC9C,SAAO;AAAA,IACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAUA,KAAI,EAAE,CAAC;AAAA,IACtD,mBAAmBA;AAAA,IACnB;AAAA,EACF;AACF;AAEA,SAAS,aAAa,OAAwB;AAC5C,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,UAAM,OAAO;AACb,QAAI,OAAO,KAAK,UAAU,SAAU,QAAO,KAAK;AAChD,QAAI,OAAO,KAAK,YAAY,SAAU,QAAO,KAAK;AAAA,EACpD;AACA,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAEA,SAAS,YAAY,MAAc,OAAgB,YAA2B,MAAM,WAA0B,MAAsB;AAClI,SAAO,iBAAiB;AAAA,IACtB,IAAI;AAAA,IACJ;AAAA,IACA,YAAY;AAAA,IACZ,GAAI,aAAa,OAAO,EAAE,WAAW,SAAS,IAAI,CAAC;AAAA,IACnD,OAAO,aAAa,KAAK;AAAA,IACzB,KAAK,SAAS,OAAO,UAAU,WAAW,QAAmC,EAAE,MAAM;AAAA,EACvF,GAAG,IAAI;AACT;AAEA,SAAS,aACP,MACA,WACA,IACA,MACA,sBAAqC,sBACrB;AAChB,MAAI,CAAC,GAAI,QAAO,YAAY,MAAM,MAAM,SAAS;AACjD,SAAO,iBAAiB;AAAA,IACtB,IAAI;AAAA,IACJ;AAAA,IACA,YAAY;AAAA,IACZ,QAAQ,QAAQ,OAAO,SAAS,WAAW,OAAkC,EAAE,OAAO,KAAK;AAAA,IAC3F;AAAA,EACF,CAAC;AACH;AAEA,SAASC,iBAAwB;AAC/B,SAAO,QAAQ,IAAI,wBAAwB,KAAK,SAAK,4BAAK,yBAAQ,GAAG,aAAa,aAAa;AACjG;AAEA,SAAS,aAAa,OAAuB;AAC3C,SAAO,MAAM,QAAQ,qBAAqB,GAAG,EAAE,QAAQ,YAAY,EAAE,EAAE,MAAM,GAAG,GAAG,KAAK;AAC1F;AAEA,SAAS,eAAe,WAAmB,UAAkB,UAA2B;AACtF,QAAM,YAAY,UAAU,KAAK;AACjC,QAAM,SAAQ,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG;AAC3D,QAAM,OAAO,YACT,aAAa,SAAS,EAAE,QAAQ,WAAW,EAAE,IAC7C,GAAG,KAAK,IAAI,aAAa,SAAS,CAAC,IAAI,aAAa,QAAQ,CAAC;AACjE,aAAO,wBAAKA,eAAc,GAAG,mBAAmB,GAAG,IAAI,MAAM;AAC/D;AAEA,SAAS,SAAS,OAA+B;AAC/C,QAAM,UAAU,OAAO,KAAK,EAAE,YAAY;AAC1C,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,QACJ,QAAQ,gBAAgB,EAAE,EAC1B,QAAQ,UAAU,EAAE,EACpB,QAAQ,SAAS,EAAE,EACnB,QAAQ,kBAAkB,GAAG,EAC7B,QAAQ,WAAW,GAAG,EACtB,QAAQ,YAAY,EAAE;AAC3B;AAEA,SAAS,0BAA0B,OAA+B;AAChE,QAAM,QAAQ,SAAS,KAAK;AAC5B,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,MAAM,MAAM,GAAG,EAAE,KAAK;AAC/B;AAEA,SAAS,iBAAiB,OAAyC;AACjE,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,YAAY;AAClB,SACE,OAAO,UAAU,aAAa,YAC9B,OAAO,UAAU,eAAe,YAChC,OAAO,UAAU,WAAW,YAC5B,MAAM,QAAQ,UAAU,OAAO,KAC/B,MAAM,QAAQ,UAAU,WAAW,KACnC,MAAM,QAAQ,UAAU,SAAS,KACjC,MAAM,QAAQ,UAAU,WAAW,KACnC,MAAM,QAAQ,UAAU,QAAQ,KAChC,CAAC,CAAC,UAAU,UACZ,CAAC,CAAC,UAAU;AAEhB;AAEA,SAAS,wBAAwB,WAAmB,UAAkB,UAA2B;AAC/F,QAAM,YAAY,UAAU,KAAK;AACjC,MAAI,UAAW,QAAO,eAAe,WAAW,UAAU,SAAS;AACnE,QAAM,SAAQ,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG;AAC3D,SAAO,eAAe,WAAW,UAAU,GAAG,KAAK,IAAI,aAAa,SAAS,CAAC,IAAI,aAAa,QAAQ,CAAC,YAAY;AACtH;AAEA,SAASC,cAAa,OAAiC;AACrD,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK;AAC3D;AAEA,SAAS,oBACP,SACA,UACA,SACA;AACA,QAAM,cAAcA,cAAa,UAAU,KAAK,KAAK,SAAU,QAAQ,IAAI,SAAU,QAAQ;AAC7F,QAAM,eAAeA,cAAa,UAAU,MAAM,KAAK,SAAU,SAAS,IAAI,SAAU,SAAS;AACjG,QAAM,OAAO,KAAK,IAAI,GAAG,QAAQ,OAAO,OAAO;AAC/C,QAAM,MAAM,KAAK,IAAI,GAAG,QAAQ,MAAM,OAAO;AAC7C,QAAM,QAAQ,KAAK,IAAI,aAAa,QAAQ,OAAO,QAAQ,QAAQ,OAAO;AAC1E,QAAM,SAAS,KAAK,IAAI,cAAc,QAAQ,MAAM,QAAQ,SAAS,OAAO;AAC5E,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,KAAK,IAAI,GAAG,QAAQ,IAAI;AAAA,IAC/B,QAAQ,KAAK,IAAI,GAAG,SAAS,GAAG;AAAA,IAChC;AAAA,IACA;AAAA,EACF;AACF;AAQO,SAAS,6BAA6BC,SAAmB,MAAqC;AACnG,QAAMC,WAAU,KAAK,QAAQ,QAAQ,OAAO,EAAE;AAC9C,QAAM,eAAe,KAAK,kBAAkB,KAAK,SAAS,QAAQ,OAAO,EAAE;AAC3E,QAAM,YAAY,KAAK,aAAa;AAEpC,iBAAe,IACb,QACA,MACA,MACA,mBAAmB,WACkB;AACrC,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAGA,QAAO,GAAG,IAAI,IAAI;AAAA,QAC3C;AAAA,QACA,SAAS,EAAE,gBAAgB,oBAAoB,aAAa,KAAK,OAAO;AAAA,QACxE,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,QACpC,QAAQ,YAAY,QAAQ,gBAAgB;AAAA,MAC9C,CAAC;AACD,YAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC9C,aAAO,EAAE,IAAI,IAAI,IAAI,KAAK;AAAA,IAC5B,SAAS,KAAK;AACZ,aAAO,EAAE,IAAI,OAAO,MAAM,EAAE,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,EAAE;AAAA,IACxF;AAAA,EACF;AAEA,iBAAe,eACb,WACA,UACA,UACqC;AACrC,UAAM,OAAO,mBAAmB,mBAAmB,SAAS,CAAC,YAAY,mBAAmB,QAAQ,CAAC;AACrG,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAGA,QAAO,GAAG,IAAI,IAAI;AAAA,QAC3C,QAAQ;AAAA,QACR,SAAS,EAAE,aAAa,KAAK,OAAO;AAAA,QACpC,QAAQ,YAAY,QAAQ,SAAS;AAAA,MACvC,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,aAAa,EAAE,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,QAAQ,IAAI,MAAM,EAAE,EAAE,EAAE;AAC/G,eAAO,EAAE,IAAI,OAAO,KAAK;AAAA,MAC3B;AACA,YAAM,QAAQ,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC;AACjD,YAAM,WAAW,eAAe,WAAW,UAAU,QAAQ;AAC7D,yCAAU,wBAAKC,eAAc,GAAG,iBAAiB,GAAG,EAAE,WAAW,KAAK,CAAC;AACvE,yCAAc,UAAU,KAAK;AAC7B,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,MAAM;AAAA,UACJ,WAAW;AAAA,UACX,WAAW;AAAA,UACX,OAAO,MAAM;AAAA,UACb,WAAW,IAAI,QAAQ,IAAI,cAAc,KAAK;AAAA,UAC9C,cAAc,GAAGD,QAAO,GAAG,IAAI;AAAA,QACjC;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,aAAO,EAAE,IAAI,OAAO,MAAM,EAAE,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,EAAE;AAAA,IACxF;AAAA,EACF;AAEA,QAAM,cAAc,CAAC,OAAe,WAAW,WAAW;AAAA,IACxD;AAAA,IACA,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,eAAe;AAAA,EACjB;AAEA,WAAS,eAAe,MAAW;AACjC,WAAO;AAAA,MACL,eAAe,KAAK,iBAAiB;AAAA,MACrC,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,eAAe,KAAK,iBAAiB;AAAA,MACrC,MAAM,KAAK,QAAQ;AAAA,MACnB,WAAW,KAAK,iBAAiB,KAAK,WAAW,kBAAkB,GAAG,WAAW,iBAAiB,KAAK,aAAa,KAAK;AAAA,MACzH,mBAAmB,KAAK,qBAAqB;AAAA,IAC/C;AAAA,EACF;AAEA,iBAAe,qBAAqB,SAAqC;AACvE,UAAM,OAAO,MAAM,IAAI,QAAQ,wBAAwB,EAAE,QAAQ,CAAC;AAClE,WAAO,KAAK,MAAM,MAAM,QAAQ,KAAK,MAAM,WAAW,IAAI,KAAK,KAAK,YAAY,IAAI,cAAc,IAAI,CAAC;AAAA,EACzG;AAEA,EAAAD,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,gCAAgC;AAAA,IAC3D;AAAA,IACA,OAAM,UAAS;AACb,YAAM,SAAS,SAAS,MAAM,MAAM,KAAK;AACzC,YAAM,WAAW,MAAM,aAAa,MAAM,QAAQ,WAAW,gBAAgB,yBAAyB,WAAW,MAAM;AACvH,YAAM,UAAU,MAAM,SAAS,KAAK,KAAK,0BAA0B,MAAM,KAAK,KAAK,0BAA0B;AAC7G,UAAI,CAAC,SAAS;AACZ,eAAO,YAAY,2BAA2B;AAAA,UAC5C,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AACA,YAAM,eAAe,MAAM,OAAO,KAAK,KAAK;AAC5C,YAAM,OAAO,MAAM,MAAM,KAAK,KAAK;AACnC,YAAM,OAAO,MAAM,IAAI,QAAQ,2BAA2B;AAAA,QACxD,OAAO,MAAM,SAAS,gBAAgB,MAAM,WAAM,OAAO;AAAA,QACzD;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QACX,GAAI,eAAe,EAAE,eAAe,aAAa,IAAI,CAAC;AAAA,QACtD,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACzB,CAAC;AACD,UAAI,CAAC,KAAK,GAAI,QAAO,YAAY,2BAA2B,KAAK,IAAI;AACrE,YAAM,kBAAkB,MAAM,qBAAqB,OAAO,EAAE,MAAM,MAAM,CAAC,CAAC;AAC1E,aAAO,iBAAiB;AAAA,QACtB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,oBAAoB,KAAK,KAAK;AAAA,QAC9B,WAAW,GAAG,WAAW,iBAAiB,KAAK,KAAK,aAAa;AAAA,QACjE,eAAe;AAAA,QACf;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QACX,eAAe;AAAA,QACf;AAAA,QACA,QAAQ,KAAK,KAAK,UAAU;AAAA,QAC5B,aAAa,KAAK,KAAK,eAAe;AAAA,QACtC,WAAW,KAAK,KAAK,aAAa;AAAA,QAClC,iBAAiB,KAAK,KAAK,mBAAmB;AAAA,QAC9C,gBAAgB,KAAK,KAAK,kBAAkB;AAAA,QAC5C,kBAAkB;AAAA,QAClB,YAAY;AAAA,UACV,kDAAkD,MAAM;AAAA,UACxD;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,KAAK,KAAK;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,kCAAkC,IAAI;AAAA,IACjE;AAAA,IACA,OAAM,UAAS;AACb,YAAM,UAAU,MAAM,SAAS,KAAK,KAAK,0BAA0B,MAAM,KAAK,KAAK,0BAA0B;AAC7G,UAAI,CAAC,SAAS;AACZ,eAAO,YAAY,wBAAwB;AAAA,UACzC,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AACA,YAAM,SAAS,SAAS,MAAM,MAAM,KAAK;AACzC,YAAM,MAAM,MAAM,IAAI,QAAQ,wBAAwB;AAAA,QACpD;AAAA,QACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,QAC3B,GAAI,MAAM,gBAAgB,EAAE,eAAe,MAAM,cAAc,IAAI,CAAC;AAAA,MACtE,CAAC;AACD,UAAI,CAAC,IAAI,GAAI,QAAO,YAAY,wBAAwB,IAAI,IAAI;AAChE,YAAM,eAAe,MAAM,QAAQ,IAAI,MAAM,WAAW,IAAI,IAAI,KAAK,cAAc,CAAC,GAAG,IAAI,cAAc;AACzG,aAAO,iBAAiB;AAAA,QACtB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,QACA,OAAO,YAAY;AAAA,MACrB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,sBAAsB;AAAA,IACjD;AAAA,IACA,OAAM,UAAS;AACb,YAAM,UAAU,MAAM,WAAW,0BAA0B;AAC3D,YAAM,qBAAqB,MAAM,wBAAwB,iCAAiC;AAC1F,YAAM,OAAO,MAAM,IAAI,QAAQ,mBAAmB;AAAA,QAChD,OAAO,MAAM;AAAA,QACb,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,QAC7B,GAAI,WAAW,OAAO,uBAAuB,YAAY,EAAE,sBAAsB,mBAAmB,IAAI,CAAC;AAAA,QACzG,uBAAuB;AAAA,QACvB,iBAAiB,MAAM;AAAA,QACvB,GAAI,MAAM,MAAM,EAAE,KAAK,MAAM,IAAI,IAAI,CAAC;AAAA,MACxC,CAAC;AACD,UAAI,CAAC,KAAK,GAAI,QAAO,YAAY,gBAAgB,KAAK,IAAI;AAC1D,YAAM,UAAU,KAAK;AACrB,aAAO,iBAAiB;AAAA,QACtB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY,QAAQ;AAAA,QACpB,WAAW,GAAG,WAAW,YAAY,QAAQ,UAAU;AAAA,QACvD,eAAe;AAAA,QACf,KAAK,MAAM,OAAO;AAAA,QAClB,MAAM;AAAA,QACN,KAAK;AAAA,MACP,CAAC;AAAA,IACH;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,YAAY,IAAI;AAAA,IAC3C;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,aAAa;AAC9E,UAAI,CAAC,IAAI,GAAI,QAAO,YAAY,sBAAsB,IAAI,MAAM,MAAM,UAAU;AAChF,YAAM,EAAE,cAAc,WAAW,KAAK,OAAO,UAAU,KAAK,IAAI,IAAI;AACpE,YAAM,UAAqC,CAAC;AAC5C,UAAI,aAAc,SAAQ,KAAK,EAAE,MAAM,SAAS,MAAM,cAAc,UAAU,aAAa,YAAY,CAAC;AACxG,YAAM,aAAa;AAAA,QACjB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY,MAAM;AAAA,QAClB,KAAK,OAAO;AAAA,QACZ,OAAO,SAAS;AAAA,QAChB,MAAM,OAAO,SAAS,WAAW,OAAO;AAAA,QACxC,UAAU,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC;AAAA,QAChD,YAAY,eAAe,EAAE,WAAW,aAAa,aAAa,QAAQ,KAAK,IAAI;AAAA,MACrF;AACA,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,MAAM,KAAK,UAAU,UAAU;AAAA,MACjC,CAAC;AACD,aAAO,EAAE,SAAS,mBAAmB,WAAW;AAAA,IAClD;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,aAAa,IAAI;AAAA,IAC5C;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,OAAO;AACxE,UAAI,CAAC,IAAI,GAAI,QAAO,YAAY,gBAAgB,IAAI,MAAM,MAAM,UAAU;AAC1E,aAAO,iBAAiB;AAAA,QACtB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY,MAAM;AAAA,QAClB,KAAK,IAAI,MAAM,OAAO;AAAA,QACtB,OAAO,IAAI,MAAM,SAAS;AAAA,QAC1B,MAAM,OAAO,IAAI,MAAM,SAAS,WAAW,IAAI,KAAK,OAAO;AAAA,QAC3D,UAAU,MAAM,QAAQ,IAAI,MAAM,QAAQ,IAAI,IAAI,KAAK,WAAW,CAAC;AAAA,QACnE,KAAK,IAAI;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,sBAAsB,IAAI;AAAA,IACrD;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,WAAW,EAAE,SAAS,MAAM,QAAQ,CAAC;AACtG,UAAI,CAAC,IAAI,GAAI,QAAO,YAAY,kBAAkB,IAAI,MAAM,MAAM,UAAU;AAC5E,aAAO,iBAAiB;AAAA,QACtB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY,MAAM;AAAA,QAClB,KAAK,IAAI,MAAM,OAAO;AAAA,QACtB,OAAO,IAAI,MAAM,SAAS;AAAA,QAC1B,UAAU,IAAI,MAAM,YAAY;AAAA,QAChC,QAAQ,IAAI,MAAM,UAAU;AAAA,QAC5B,SAAS,MAAM,QAAQ,IAAI,MAAM,OAAO,IAAI,IAAI,KAAK,UAAU,CAAC;AAAA,QAChE,KAAK,IAAI;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,iBAAiB;AAAA,IAC5C;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,SAAS,EAAE,KAAK,MAAM,IAAI,CAAC;AAC5F,aAAO,aAAa,gBAAgB,MAAM,YAAY,IAAI,IAAI,IAAI,MAAM,oBAAoB;AAAA,IAC9F;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,OAAO;AAAA,IAClC;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,UAAU;AAAA,QACzE,GAAG,MAAM;AAAA,QACT,GAAG,MAAM;AAAA,QACT,QAAQ,MAAM;AAAA,QACd,YAAY,MAAM;AAAA,MACpB,CAAC;AACD,aAAO,aAAa,iBAAiB,MAAM,YAAY,IAAI,IAAI,IAAI,MAAM,oBAAoB;AAAA,IAC/F;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,WAAW;AAAA,IACtC;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,SAAS,EAAE,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM,CAAC;AAClH,aAAO,aAAa,gBAAgB,MAAM,YAAY,IAAI,IAAI,IAAI,MAAM,oBAAoB;AAAA,IAC9F;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,QAAQ;AAAA,IACnC;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,WAAW;AAAA,QAC1E,SAAS,MAAM;AAAA,QACf,SAAS,MAAM;AAAA,QACf,GAAG,MAAM;AAAA,QACT,GAAG,MAAM;AAAA,MACX,CAAC;AACD,aAAO,aAAa,kBAAkB,MAAM,YAAY,IAAI,IAAI,IAAI,MAAM,oBAAoB;AAAA,IAChG;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,YAAY;AAAA,IACvC;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,UAAU,EAAE,MAAM,MAAM,KAAK,CAAC;AAC/F,aAAO,aAAa,iBAAiB,MAAM,YAAY,IAAI,IAAI,IAAI,MAAM,oBAAoB;AAAA,IAC/F;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,iBAAiB;AAAA,IAC5C;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,eAAe;AAChF,UAAI,CAAC,IAAI,GAAI,QAAO,YAAY,wBAAwB,IAAI,MAAM,MAAM,UAAU;AAClF,aAAO,iBAAiB;AAAA,QACtB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY,MAAM;AAAA,QAClB,WAAW,IAAI,MAAM,aAAa,IAAI,MAAM,YAAY;AAAA,QACxD,UAAU,IAAI,MAAM,YAAY,IAAI,MAAM,WAAW;AAAA,QACrD,cAAc,IAAI,MAAM,gBAAgB,IAAI,MAAM,eAAe;AAAA,QACjE,KAAK,IAAI;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,gBAAgB;AAAA,IAC3C;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,gBAAgB,EAAE,WAAW,MAAM,UAAU,CAAC;AAC/G,UAAI,CAAC,IAAI,GAAI,QAAO,YAAY,uBAAuB,IAAI,MAAM,MAAM,YAAY,MAAM,SAAS;AAClG,aAAO,iBAAiB;AAAA,QACtB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY,MAAM;AAAA,QAClB,WAAW,IAAI,MAAM,aAAa,IAAI,MAAM,YAAY,MAAM;AAAA,QAC9D,UAAU,IAAI,MAAM,YAAY,IAAI,MAAM,WAAW;AAAA,QACrD,cAAc,IAAI,MAAM,gBAAgB,IAAI,MAAM,eAAe;AAAA,QACjE,KAAK,IAAI;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,sBAAsB,IAAI;AAAA,IACrD;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,OAAO,mBAAmB,MAAM,UAAU,UAAU;AAC1E,UAAI,CAAC,IAAI,GAAI,QAAO,YAAY,wBAAwB,IAAI,MAAM,MAAM,UAAU;AAClF,YAAM,UAAU,MAAM,QAAQ,IAAI,MAAM,OAAO,IAAI,IAAI,KAAK,UAAU,CAAC;AACvE,aAAO,iBAAiB;AAAA,QACtB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY,MAAM;AAAA,QAClB;AAAA,QACA,OAAO,QAAQ;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,qBAAqB;AAAA,IAChD;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,eAAe,MAAM,YAAY,MAAM,WAAW,MAAM,QAAQ;AAClF,UAAI,CAAC,IAAI,GAAI,QAAO,YAAY,2BAA2B,IAAI,MAAM,MAAM,YAAY,MAAM,SAAS;AACtG,aAAO,iBAAiB;AAAA,QACtB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY,MAAM;AAAA,QAClB,WAAW,MAAM;AAAA,QACjB,WAAW,IAAI,MAAM,aAAa;AAAA,QAClC,OAAO,OAAO,IAAI,MAAM,UAAU,WAAW,IAAI,KAAK,QAAQ;AAAA,QAC9D,WAAW,IAAI,MAAM,aAAa;AAAA,QAClC,cAAc,IAAI,MAAM,gBAAgB;AAAA,MAC1C,CAAC;AAAA,IACH;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,0BAA0B,IAAI;AAAA,IACzD;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,WAAW,EAAE,SAAS,CAAC,MAAM,MAAM,EAAE,CAAC;AACvG,UAAI,CAAC,IAAI,GAAI,QAAO,YAAY,uBAAuB,IAAI,MAAM,MAAM,UAAU;AACjF,YAAM,SAAS,IAAI,MAAM,UAAU,CAAC;AACpC,YAAM,UAAU,QAAQ;AACxB,YAAM,UAAU,IAAI,MAAM,QAAQ;AAClC,UAAI,CAAC,QAAQ,SAAS,CAAC,SAAS;AAC9B,eAAO,YAAY,uBAAuB,EAAE,OAAO,QAAQ,SAAS,wCAAwC,OAAO,GAAG,MAAM,UAAU;AAAA,MACxI;AACA,UAAI,CAACG,cAAa,OAAO,GAAG;AAC1B,eAAO,YAAY,uBAAuB,EAAE,OAAO,qFAAqF,GAAG,MAAM,UAAU;AAAA,MAC7J;AACA,YAAM,SAAS,oBAAoB,SAAS,IAAI,MAAM,UAAU,MAAM,WAAW,CAAC;AAClF,YAAM,QAAQ,KAAK,IAAI,GAAG,WAAW,MAAM,wBAAwB,MAAM;AACzE,YAAM,WAAW,MAAM,oBAAoB;AAC3C,YAAM,aAAa;AAAA,QACjB,MAAM,MAAM,QAAQ;AAAA,QACpB,eAAe,OAAO,MAAM,QAAQ,CAAC,CAAC;AAAA,QACtC,aAAa,QAAQ,QAAQ,UAAU,QAAQ,CAAC,CAAC;AAAA,QACjD,MAAM,KAAK,MAAM,OAAO,IAAI;AAAA,QAC5B,KAAK,KAAK,MAAM,OAAO,GAAG;AAAA,QAC1B,OAAO,KAAK,MAAM,OAAO,KAAK;AAAA,QAC9B,QAAQ,KAAK,MAAM,OAAO,MAAM;AAAA,QAChC,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QAC5C,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QAC5C,GAAI,MAAM,YAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,MAC1D;AACA,aAAO,iBAAiB;AAAA,QACtB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY,MAAM;AAAA,QAClB,WAAW,IAAI,MAAM,QAAQ,aAAa,IAAI,MAAM,QAAQ,YAAY;AAAA,QACxE;AAAA,QACA,cAAc,OAAO;AAAA,QACrB,eAAe,OAAO;AAAA,QACtB,QAAQ,IAAI,KAAK;AAAA,QACjB;AAAA,QACA,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAAA,EACF;AAEA,EAAAH,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,qBAAqB;AAAA,IAChD;AAAA,IACA,OAAM,UAAS;AACb,YAAM,aAAa,MAAM,WAAW,GAAG,MAAM,QAAQ,YAAY;AACjE,YAAM,aAAa,MAAM,eAAe,MAAM,YAAY,MAAM,WAAW,UAAU;AACrF,UAAI,CAAC,WAAW,GAAI,QAAO,YAAY,2BAA2B,WAAW,MAAM,MAAM,YAAY,MAAM,SAAS;AACpH,UAAI;AACF,cAAM,aAAa,OAAO,WAAW,KAAK,SAAS;AACnD,cAAM,aAAa,wBAAwB,MAAM,YAAY,MAAM,WAAW,MAAM,QAAQ;AAC5F,2CAAU,wBAAKE,eAAc,GAAG,iBAAiB,GAAG,EAAE,WAAW,KAAK,CAAC;AACvE,cAAM,SAAS,MAAM,oBAAoB,YAAY,YAAY;AAAA,UAC/D,aAAa,MAAM;AAAA,UACnB,aAAa,MAAM;AAAA,UACnB,cAAc,MAAM;AAAA,UACpB,kBAAkB,MAAM;AAAA,UACxB,iBAAiB,MAAM;AAAA,QACzB,CAAC;AACD,eAAO,iBAAiB;AAAA,UACtB,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,YAAY,MAAM;AAAA,UAClB,WAAW,MAAM;AAAA,UACjB,kBAAkB;AAAA,UAClB,qBAAqB,OAAO;AAAA,UAC5B,OAAO,OAAO;AAAA,UACd,OAAO,OAAO;AAAA,UACd,QAAQ,OAAO;AAAA,UACf,kBAAkB,OAAO;AAAA,UACzB,WAAW;AAAA,QACb,CAAC;AAAA,MACH,SAAS,KAAK;AACZ,eAAO,YAAY,2BAA2B,EAAE,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,GAAG,MAAM,YAAY,MAAM,SAAS;AAAA,MAC9I;AAAA,IACF;AAAA,EACF;AAEA,EAAAF,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,EAAE,OAAO,yBAAyB,cAAc,OAAO,iBAAiB,MAAM,gBAAgB,MAAM,eAAe,MAAM;AAAA,IACxI;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,UAAU,mBAAmB,MAAM,UAAU,EAAE;AACrE,UAAI,CAAC,IAAI,GAAI,QAAO,YAAY,iBAAiB,IAAI,MAAM,MAAM,UAAU;AAC3E,aAAO,iBAAiB;AAAA,QACtB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY,MAAM;AAAA,QAClB,QAAQ;AAAA,QACR,KAAK,IAAI;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,yBAAyB,IAAI;AAAA,IACxD;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,OAAO,kBAAkB,MAAM,iBAAiB,WAAW,EAAE,EAAE;AACrF,UAAI,CAAC,IAAI,GAAI,QAAO,YAAY,yBAAyB,IAAI,IAAI;AACjE,YAAM,YAAY,IAAI,KAAK,YAAY,CAAC,GAAG,IAAI,CAAC,OAAY,EAAE,GAAG,GAAG,WAAW,GAAG,WAAW,YAAY,EAAE,UAAU,GAAG,EAAE;AAC1H,aAAO,iBAAiB;AAAA,QACtB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY;AAAA,QACZ;AAAA,QACA,OAAO,SAAS;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa,YAAY,2BAA2B;AAAA,IACtD;AAAA,IACA,OAAM,UAAS;AACb,YAAM,OAAO,CAAC,QAAiCI,aAAqB,iBAAiB;AAAA,QACnF,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,YAAY,MAAM;AAAA,QAClB,UAAU,OAAO;AAAA,QACjB,aAAa,OAAO;AAAA,QACpB,QAAQ,OAAO;AAAA,QACf,MAAM,OAAO;AAAA,QACb,SAAS,OAAO;AAAA,QAChB,cAAc,OAAO;AAAA,QACrB,YAAY,OAAO;AAAA,QACnB,cAAc,OAAO;AAAA,QACrB,UAAU,OAAO;AAAA,QACjB,QAAQ,OAAO;AAAA,QACf,YAAY,OAAO;AAAA,QACnB,oBAAoB,OAAO;AAAA,QAC3B,SAASA,YAAW;AAAA,QACpB,GAAI,OAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,IAAI,CAAC;AAAA,MAChD,CAAC;AACD,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,mBAAmB;AAAA,QAClF,QAAQ,MAAM;AAAA,QACd,SAAS,MAAM;AAAA,QACf,oBAAoB,MAAM;AAAA,QAC1B,OAAO,MAAM;AAAA,QACb,QAAQ,MAAM;AAAA,MAChB,GAAG,KAAK,IAAI,YAAY,MAAM,YAAY,MAAM,SAAS,MAAS,QAAU,GAAM,CAAC;AACnF,UAAI,CAAC,IAAI,GAAI,QAAO,YAAY,yBAAyB,IAAI,MAAM,MAAM,UAAU;AACnF,YAAM,SAAU,IAAI,MAAM,UAAU,IAAI;AACxC,UAAIA,WAAU,IAAI,MAAM,WAAW;AACnC,UAAI,MAAM,UAAU,CAACA,YAAW,iBAAiB,MAAM,GAAG;AACxD,YAAI;AACF,UAAAA,WAAU,aAAa,MAAM;AAAA,QAC/B,SAAS,KAAK;AACZ,iBAAO;AAAA,YACL;AAAA,YACA;AAAA,cACE,OAAO,6CAA6C,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,cACpG,QAAQ;AAAA,YACV;AAAA,YACA,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA,aAAO,KAAK,QAAQA,QAAO;AAAA,IAC7B;AAAA,EACF;AAEF;;;AOz2BA,IAAAC,cAA4C;AAC5C,IAAAC,kBAAoD;AACpD,IAAAC,oBAA+B;;;ACD/B,IAAAC,kBAAyC;AACzC,IAAAC,kBAAwB;AACxB,IAAAC,oBAAqB;;;ACSd,IAAM,mBAAqC;AAAA,EAChD;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,kBAAkB,CAAC,gBAAgB,sBAAsB,eAAe,oBAAoB,eAAe,aAAa;AAAA,IACxH,gBAAgB,CAAC,SAAS,mBAAmB;AAAA,IAC7C,gBAAgB,CAAC,UAAU,iBAAiB,aAAa,qBAAqB,cAAc,YAAY;AAAA,IACxG,UAAU,CAAC,gBAAgB,kBAAkB,sBAAsB,uCAAuC,aAAa;AAAA,IACvH,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,kBAAkB,CAAC,gBAAgB,eAAe,oBAAoB,aAAa;AAAA,IACnF,gBAAgB,CAAC,SAAS,UAAU;AAAA,IACpC,gBAAgB,CAAC,cAAc,kBAAkB,uBAAuB,eAAe,WAAW;AAAA,IAClG,UAAU,CAAC,+EAA+E,iBAAiB,eAAe,oBAAoB;AAAA,IAC9I,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,kBAAkB,CAAC,gBAAgB,eAAe,eAAe,eAAe,mBAAmB,oBAAoB;AAAA,IACvH,gBAAgB,CAAC,6BAA6B;AAAA,IAC9C,gBAAgB,CAAC,UAAU,YAAY,cAAc;AAAA,IACrD,UAAU,CAAC,iBAAiB,eAAe,kBAAkB,kBAAkB,iBAAiB;AAAA,IAChG,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,kBAAkB,CAAC,gBAAgB,eAAe,eAAe,oBAAoB,uBAAuB,6BAA6B,oBAAoB;AAAA,IAC7J,gBAAgB,CAAC,SAAS,mBAAmB;AAAA,IAC7C,gBAAgB,CAAC,cAAc,gBAAgB,eAAe,eAAe,gBAAgB;AAAA,IAC7F,UAAU,CAAC,sBAAsB,uBAAuB,4BAA4B,8BAA8B,oBAAoB;AAAA,IACtI,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,kBAAkB,CAAC,gBAAgB,eAAe,gBAAgB,+BAA+B,eAAe,eAAe,cAAc;AAAA,IAC7I,gBAAgB,CAAC,iBAAiB,4BAA4B;AAAA,IAC9D,gBAAgB,CAAC,kBAAkB,YAAY,YAAY;AAAA,IAC3D,UAAU,CAAC,uBAAuB,gBAAgB,2BAA2B,6BAA6B,sBAAsB;AAAA,IAChI,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,kBAAkB,CAAC,gBAAgB,eAAe,gBAAgB,+BAA+B,gBAAgB,sBAAsB,gBAAgB;AAAA,IACvJ,gBAAgB,CAAC,KAAK;AAAA,IACtB,gBAAgB,CAAC,WAAW,UAAU,YAAY,gBAAgB;AAAA,IAClE,UAAU,CAAC,mBAAmB,wBAAwB,uBAAuB,sBAAsB,qBAAqB;AAAA,IACxH,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,kBAAkB,CAAC,gBAAgB,sBAAsB,uBAAuB,mBAAmB,sBAAsB,eAAe,aAAa;AAAA,IACrJ,gBAAgB,CAAC,oBAAoB,eAAe;AAAA,IACpD,gBAAgB,CAAC,YAAY,cAAc,kBAAkB,YAAY;AAAA,IACzE,UAAU,CAAC,mBAAmB,mBAAmB,8BAA8B,0BAA0B,mBAAmB;AAAA,IAC5H,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,kBAAkB,CAAC,gBAAgB,uBAAuB,eAAe,aAAa;AAAA,IACtF,gBAAgB,CAAC,SAAS;AAAA,IAC1B,gBAAgB,CAAC,UAAU,OAAO,YAAY,gBAAgB,YAAY;AAAA,IAC1E,UAAU,CAAC,gBAAgB,uBAAuB,qBAAqB,eAAe,cAAc;AAAA,IACpG,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,kBAAkB,CAAC,gBAAgB,eAAe,eAAe,eAAe,uBAAuB;AAAA,IACvG,gBAAgB,CAAC,WAAW,eAAe;AAAA,IAC3C,gBAAgB,CAAC,YAAY,gBAAgB,YAAY;AAAA,IACzD,UAAU,CAAC,6BAA6B,kBAAkB,qBAAqB,kBAAkB,iBAAiB;AAAA,IAClH,SAAS;AAAA,EACX;AACF;AAEA,SAAS,UAAU,OAAuB;AACxC,SAAO,MAAM,YAAY,EAAE,QAAQ,eAAe,GAAG,EAAE,KAAK;AAC9D;AAEO,SAAS,uBAAuB,MAAc,QAAQ,GAAqB;AAChF,QAAM,aAAa,UAAU,IAAI;AACjC,QAAM,SAAS,iBAAiB,IAAI,YAAU;AAC5C,UAAM,WAAW,UAAU;AAAA,MACzB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO,eAAe,KAAK,GAAG;AAAA,MAC9B,OAAO,eAAe,KAAK,GAAG;AAAA,MAC9B,OAAO,SAAS,KAAK,GAAG;AAAA,IAC1B,EAAE,KAAK,GAAG,CAAC;AACX,QAAI,QAAQ;AACZ,eAAW,SAAS,WAAW,MAAM,KAAK,EAAE,OAAO,OAAO,GAAG;AAC3D,UAAI,SAAS,SAAS,KAAK,EAAG,UAAS;AAAA,IACzC;AACA,QAAI,SAAS,SAAS,UAAU,EAAG,UAAS;AAC5C,WAAO,EAAE,QAAQ,MAAM;AAAA,EACzB,CAAC;AACD,SAAO,OACJ,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,MAAM,cAAc,EAAE,OAAO,KAAK,CAAC,EAChF,MAAM,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC,EAC3B,IAAI,UAAQ,KAAK,MAAM;AAC5B;;;ACrHA,SAASC,WAAU,GAAmB;AACpC,SAAO,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,QAAQ,OAAO,EAAE;AAC1C;AAEO,SAAS,eACd,OACA,UAC8D;AAC9D,QAAM,cAAc,oBAAI,IAA2B;AACnD,aAAW,KAAK,MAAO,aAAY,IAAIA,WAAU,EAAE,GAAG,GAAG,EAAE,MAAM;AAEjE,QAAM,QAAoB,CAAC;AAC3B,aAAW,KAAK,OAAO;AACrB,eAAW,KAAK,EAAE,YAAY,CAAC,GAAG;AAChC,YAAM,YAAY,EAAE,OAAO,IAAI,MAAM,KAAK,EAAE,SAAS,UAAU;AAC/D,YAAM,KAAK;AAAA,QACT,MAAM,EAAE;AAAA,QACR,IAAI,EAAE;AAAA,QACN,QAAQ,EAAE;AAAA,QACV,KAAK,EAAE;AAAA,QACP,UAAU,EAAE;AAAA,QACZ;AAAA,QACA,cAAc,YAAY,IAAIA,WAAU,EAAE,IAAI,CAAC,KAAK;AAAA,MACtD,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,cAAc,oBAAI,IAAyB;AACjD,QAAM,iBAAiB,oBAAI,IAAsB;AACjD,QAAM,YAAY,oBAAI,IAAyB;AAC/C,aAAW,KAAK,OAAO;AACrB,QAAI,CAAC,EAAE,SAAU;AACjB,UAAM,KAAKA,WAAU,EAAE,EAAE;AACzB,UAAM,OAAOA,WAAU,EAAE,IAAI;AAC7B,QAAI,CAAC,YAAY,IAAI,EAAE,EAAG,aAAY,IAAI,IAAI,oBAAI,IAAI,CAAC;AACvD,gBAAY,IAAI,EAAE,EAAG,IAAI,IAAI;AAC7B,QAAI,EAAE,QAAQ;AACZ,UAAI,CAAC,eAAe,IAAI,EAAE,EAAG,gBAAe,IAAI,IAAI,CAAC,CAAC;AACtD,qBAAe,IAAI,EAAE,EAAG,KAAK,EAAE,MAAM;AAAA,IACvC;AACA,QAAI,CAAC,EAAE,aAAa,YAAY,IAAI,EAAE,MAAM,OAAO,CAAC,YAAY,IAAI,EAAE,IAAI;AACxE,UAAI,CAAC,UAAU,IAAI,IAAI,EAAG,WAAU,IAAI,MAAM,oBAAI,IAAI,CAAC;AACvD,gBAAU,IAAI,IAAI,EAAG,IAAI,EAAE;AAAA,IAC7B;AAAA,EACF;AAEA,QAAM,QAAQ,oBAAI,IAAoB;AACtC,QAAM,QAAQA,WAAU,QAAQ;AAChC,QAAM,QAAkB,CAAC,KAAK;AAC9B,QAAM,IAAI,OAAO,CAAC;AAClB,SAAO,MAAM,SAAS,GAAG;AACvB,UAAM,MAAM,MAAM,MAAM;AACxB,UAAM,IAAI,MAAM,IAAI,GAAG;AACvB,eAAW,QAAQ,UAAU,IAAI,GAAG,KAAK,CAAC,GAAG;AAC3C,UAAI,CAAC,MAAM,IAAI,IAAI,GAAG;AAAE,cAAM,IAAI,MAAM,IAAI,CAAC;AAAG,cAAM,KAAK,IAAI;AAAA,MAAE;AAAA,IACnE;AAAA,EACF;AAEA,QAAM,gBAAgB,CAAC,QAA0B;AAC/C,UAAM,SAAS,oBAAI,IAAoB;AACvC,eAAW,KAAK,eAAe,IAAI,GAAG,KAAK,CAAC,EAAG,QAAO,IAAI,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,CAAC;AACrF,WAAO,CAAC,GAAG,OAAO,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE,IAAI,OAAK,EAAE,CAAC,CAAC;AAAA,EACpF;AAEA,QAAM,UAAU,oBAAI,IAA6B;AACjD,aAAW,KAAK,OAAO;AACrB,UAAM,MAAMA,WAAU,EAAE,GAAG;AAC3B,UAAM,UAAU,YAAY,IAAI,GAAG,KAAK,oBAAI,IAAI;AAChD,YAAQ,IAAI,EAAE,KAAK;AAAA,MACjB,KAAK,EAAE;AAAA,MACP,SAAS,QAAQ;AAAA,MACjB,eAAe,QAAQ;AAAA,MACvB,mBAAmB,EAAE,YAAY,CAAC,GAAG,OAAO,OAAK,EAAE,QAAQ,EAAE;AAAA,MAC7D,mBAAmB,EAAE,YAAY,CAAC,GAAG,OAAO,OAAK,CAAC,EAAE,QAAQ,EAAE;AAAA,MAC9D,YAAY,MAAM,IAAI,GAAG,IAAI,MAAM,IAAI,GAAG,IAAK;AAAA,MAC/C,QAAQ,QAAQ,SAAS,KAAK,QAAQ;AAAA,MACtC,YAAY,cAAc,GAAG;AAAA,IAC/B,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,OAAO,QAAQ;AAC1B;;;AC7EA,SAAS,kBAAkB,MAAsB;AAC/C,QAAM,IAAI,KAAK,QAAQ,UAAU,EAAE,EAAE,YAAY;AACjD,QAAM,QAAQ,EAAE,MAAM,GAAG;AACzB,SAAO,MAAM,UAAU,IAAI,IAAI,MAAM,MAAM,EAAE,EAAE,KAAK,GAAG;AACzD;AAEO,SAAS,gBAAgB,OAAmB,SAA4B,SAA6B;AAC1G,MAAI,UAAU;AACd,MAAI;AAAE,cAAU,kBAAkB,IAAI,IAAI,OAAO,EAAE,QAAQ;AAAA,EAAE,QAAQ;AAAE,cAAU;AAAA,EAAG;AACpF,QAAM,gBAAgB,MAAM,OAAO,OAAK,EAAE,QAAQ;AAClD,QAAM,QAAQ,QAAQ;AACtB,QAAM,UAAU,QAAQ,OAAO,OAAK,EAAE,MAAM,EAAE;AAC9C,QAAM,iBAAiB,cAAc,OAAO,OAAK,EAAE,gBAAgB,QAAQ,EAAE,gBAAgB,GAAG,EAAE;AAClG,QAAM,aAAa,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,SAAS,CAAC;AAC5D,QAAM,cAAc,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,mBAAmB,EAAE,kBAAkB,CAAC;AAE3F,QAAM,eAAe,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,YAAY,EAAE;AAC1E,aAAW,KAAK,SAAS;AACvB,QAAI,EAAE,YAAY,EAAG,cAAa;AAAA,aACzB,EAAE,WAAW,EAAG,cAAa;AAAA,aAC7B,EAAE,WAAW,GAAI,cAAa;AAAA,QAClC,cAAa;AAAA,EACpB;AAEA,QAAM,eAAe,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,EAAE,EAChF,IAAI,QAAM,EAAE,KAAK,EAAE,KAAK,SAAS,EAAE,SAAS,kBAAkB,EAAE,kBAAkB,kBAAkB,EAAE,iBAAiB,EAAE;AAE5H,QAAM,SAAS,oBAAI,IAAqE;AACxF,MAAI,gBAAgB;AACpB,aAAW,KAAK,OAAO;AACrB,QAAI;AACJ,QAAI;AAAE,eAAS,kBAAkB,IAAI,IAAI,EAAE,EAAE,EAAE,QAAQ;AAAA,IAAE,QAAQ;AAAE;AAAA,IAAS;AAC5E,QAAI,CAAC,UAAU,WAAW,QAAS;AACnC;AACA,UAAM,IAAI,OAAO,IAAI,MAAM,KAAK,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,oBAAI,IAAY,EAAE;AAClF,MAAE;AACF,QAAI,EAAE,SAAU,GAAE;AAClB,MAAE,MAAM,IAAI,EAAE,IAAI;AAClB,WAAO,IAAI,QAAQ,CAAC;AAAA,EACtB;AACA,QAAM,kBAAkC,CAAC,GAAG,OAAO,QAAQ,CAAC,EACzD,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,OAAO,EAAE,OAAO,UAAU,EAAE,UAAU,OAAO,EAAE,MAAM,KAAK,EAAE,EAC5F,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAEnC,QAAM,QAAQ,CAAC,MAAc,KAAK,MAAM,IAAI,EAAE,IAAI;AAClD,SAAO;AAAA,IACL,SAAS;AAAA,MACP,UAAU;AAAA,QACR,YAAY,cAAc;AAAA,QAC1B;AAAA,QAAO;AAAA,QAAS;AAAA,QAChB,YAAY,QAAQ,MAAM,aAAa,KAAK,IAAI;AAAA,QAChD,aAAa,QAAQ,MAAM,cAAc,KAAK,IAAI;AAAA,QAClD;AAAA,QACA;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,YAAY;AAAA,QACZ,eAAe,gBAAgB;AAAA,QAC/B,YAAY,gBAAgB,MAAM,GAAG,EAAE;AAAA,MACzC;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,iBAAiB,GAAuB;AACtD,QAAM,IAAI,EAAE;AACZ,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,iBAAiB,EAAE,SAAS,UAAU,eAAY,EAAE,SAAS,KAAK,mBAAgB,EAAE,SAAS,UAAU,sBAAmB,EAAE,SAAS,OAAO,iBAAc,EAAE,SAAS,cAAc;AAAA,IACnL,iBAAiB,EAAE,SAAS,UAAU,aAAa,EAAE,SAAS,aAAa;AAAA,IAC3E;AAAA,IACA;AAAA,IACA,0BAA0B,EAAE,SAAS,aAAa,IAAI;AAAA,IACtD,eAAU,EAAE,SAAS,aAAa,QAAQ;AAAA,IAC1C,gBAAW,EAAE,SAAS,aAAa,UAAU;AAAA,IAC7C,UAAU,EAAE,SAAS,aAAa,UAAU;AAAA,IAC5C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,EAAE,SAAS,aAAa,IAAI,OAAK,KAAK,EAAE,OAAO,MAAM,EAAE,gBAAgB,IAAI,EAAE,gBAAgB,MAAM,EAAE,GAAG,IAAI;AAAA,IAC/G;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,EAAE,SAAS,WAAW,IAAI,OAAK,KAAK,EAAE,KAAK,MAAM,EAAE,QAAQ,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,IAAI;AAAA,EAC/F;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;;;AC9GA,IAAM,aAAa;AACnB,IAAM,YAAY;AAClB,IAAM,eAAe;AACrB,IAAM,YAAY;AAClB,IAAM,WAAW;AACjB,IAAM,WAAW;AACjB,IAAM,SAAS;AACf,IAAM,UAAU;AAEhB,SAAS,MAAS,OAAmB,KAAsD;AACzF,QAAM,SAAS,oBAAI,IAAsB;AACzC,aAAW,KAAK,OAAO;AACrB,UAAM,IAAI,IAAI,CAAC;AACf,QAAI,MAAM,QAAQ,MAAM,UAAa,MAAM,GAAI;AAC/C,UAAM,KAAK,OAAO,CAAC;AACnB,QAAI,CAAC,OAAO,IAAI,EAAE,EAAG,QAAO,IAAI,IAAI,CAAC,CAAC;AACtC,WAAO,IAAI,EAAE,EAAG,KAAK,EAAE,GAAG;AAAA,EAC5B;AACA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE,OAAO,OAAK,EAAE,SAAS,CAAC,EAAE,KAAK;AAC7D;AAEO,SAAS,cAAc,OAAmB,SAAoD;AACnG,QAAM,QAAQ,CAAC,UAAgC,EAAE,OAAO,KAAK,QAAQ,MAAM,KAAK,MAAM,GAAG,GAAG,EAAE;AAC9F,QAAM,QAAQ,CAAC,OAAiC,MAAM,OAAO,EAAE,EAAE,IAAI,OAAK,EAAE,GAAG;AAC/E,QAAM,KAAK,CAAC,MAAgB,EAAE,WAAW;AACzC,QAAM,WAAW,CAAC,MAAc;AAAE,QAAI;AAAE,aAAO,IAAI,IAAI,CAAC,EAAE;AAAA,IAAS,QAAQ;AAAE,aAAO;AAAA,IAAG;AAAA,EAAE;AAEzF,QAAM,SAAsB;AAAA,IAC1B,iBAAiB,MAAM,MAAM,OAAK,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;AAAA,IACpD,mBAAmB,MAAM,MAAM,MAAM,OAAO,EAAE,GAAG,OAAK,EAAE,KAAK,CAAC;AAAA,IAC9D,iBAAiB,MAAM,MAAM,QAAM,EAAE,eAAe,KAAK,cAAc,EAAE,eAAe,KAAK,YAAY,CAAC;AAAA,IAC1G,kBAAkB,MAAM,MAAM,OAAK,EAAE,SAAS,SAAS,EAAE,eAAe,KAAK,SAAS,CAAC;AAAA,IACvF,kBAAkB,MAAM,MAAM,OAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC;AAAA,IACzF,gBAAgB,MAAM,MAAM,OAAK,GAAG,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC;AAAA,IAC7D,kBAAkB,MAAM,MAAM,MAAM,OAAO,EAAE,GAAG,OAAK,EAAE,eAAe,CAAC;AAAA,IACvE,gBAAgB,MAAM,MAAM,QAAM,EAAE,kBAAkB,KAAK,QAAQ,CAAC;AAAA,IACpE,iBAAiB,MAAM,MAAM,OAAK,EAAE,mBAAmB,SAAS,EAAE,kBAAkB,KAAK,QAAQ,CAAC;AAAA,IAClG,cAAc,MAAM,MAAM,OAAK,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;AAAA,IAC9C,eAAe,MAAM,MAAM,OAAK,CAAC,CAAC,EAAE,IAAI,CAAC;AAAA,IACzC,gBAAgB,MAAM,MAAM,MAAM,OAAO,EAAE,GAAG,OAAK,EAAE,EAAE,CAAC;AAAA,IACxD,cAAc,MAAM,MAAM,QAAM,EAAE,IAAI,UAAU,KAAK,MAAM,CAAC;AAAA,IAC5D,cAAc,MAAM,MAAM,OAAK,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;AAAA,IACxD,6BAA6B,MAAM,MAAM,OAAK,CAAC,EAAE,SAAS,CAAC;AAAA,IAC3D,wBAAwB,MAAM,MAAM,OAAK,EAAE,uBAAuB,SAAS,CAAC;AAAA,IAC5E,qBAAqB,MAAM,MAAM,OAAK,GAAG,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;AAAA,IAC/D,2BAA2B,MAAM,MAAM,OAAK,EAAE,uBAAuB,eAAe,CAAC;AAAA,IACrF,sBAAsB,MAAM,MAAM,QAAM,EAAE,UAAU,MAAM,QAAQ,EAAE,UAAU,KAAK,GAAG,CAAC;AAAA,IACvF,qBAAqB,MAAM,MAAM,QAAM,EAAE,UAAU,MAAM,GAAG,CAAC;AAAA,IAC7D,wBAAwB,MAAM,MAAM,QAAM,EAAE,UAAU,MAAM,QAAQ,EAAE,UAAU,KAAK,GAAG,CAAC;AAAA,IACzF,uBAAuB,MAAM,MAAM,OAAK,EAAE,WAAW,IAAI,CAAC;AAAA,IAC1D,gBAAgB,MAAM,MAAM,OAAK,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,EAAE,YAAY,UAAU,CAAC;AAAA,IACtF,0BAA0B,MAAM,MAAM,MAAM,OAAO,OAAK,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,OAAK,EAAE,WAAW,CAAC;AAAA,IACpG,qBAAqB,MAAM,MAAM,OAAK,EAAE,mBAAmB,CAAC,CAAC;AAAA,IAC7D,kBAAkB,MAAM,MAAM,OAAK,GAAG,CAAC,KAAK,EAAE,YAAY,WAAW,CAAC,CAAC;AAAA,IACvE,eAAe,MAAM,MAAM,OAAK,EAAE,IAAI,SAAS,OAAO,CAAC;AAAA,IACvD,iBAAiB,MAAM,MAAM,OAAK,QAAQ,KAAK,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;AAAA,IAChE,mBAAmB,MAAM,MAAM,OAAK,SAAS,EAAE,GAAG,EAAE,SAAS,GAAG,CAAC,CAAC;AAAA,IAClE,gBAAgB,MAAM,CAAC,GAAG,QAAQ,OAAO,CAAC,EAAE,OAAO,OAAK,EAAE,MAAM,EAAE,IAAI,OAAK,EAAE,GAAG,CAAC;AAAA,EACnF;AAEA,QAAM,UAAU,CAAC,MAAc;AAAE,QAAI;AAAE,YAAM,IAAI,IAAI,IAAI,CAAC;AAAG,QAAE,OAAO;AAAI,cAAQ,EAAE,SAAS,EAAE,UAAU,QAAQ,QAAQ,EAAE,IAAI,EAAE;AAAA,IAAO,QAAQ;AAAE,aAAO,EAAE,QAAQ,QAAQ,EAAE,EAAE,QAAQ,QAAQ,EAAE;AAAA,IAAE;AAAA,EAAE;AACrM,QAAM,cAAc,IAAI,IAAI,MAAM,IAAI,OAAK,CAAC,QAAQ,EAAE,GAAG,GAAG,EAAE,MAAM,CAAC,CAAC;AACtE,QAAM,kBAAkB,oBAAI,IAAY;AACxC,aAAW,KAAK,OAAO;AACrB,eAAW,KAAK,EAAE,YAAY,CAAC,GAAG;AAChC,UAAI,CAAC,EAAE,SAAU;AACjB,YAAM,KAAK,YAAY,IAAI,QAAQ,EAAE,IAAI,CAAC;AAC1C,UAAI,MAAM,QAAQ,MAAM,IAAK,iBAAgB,IAAI,EAAE,GAAG;AAAA,IACxD;AAAA,EACF;AACA,SAAO,sBAAsB,IAAI,MAAM,CAAC,GAAG,eAAe,CAAC;AAE3D,SAAO;AACT;AAEO,SAAS,kBAAkB,SAAiB,OAAmB,QAAqB,SAA+C;AACxI,QAAM,QAAQ,MAAM;AACpB,QAAM,MAAM,CAAC,QACX,IAAI,WAAW,iBAAiB,KAAK,IAAI,WAAW,gBAAgB,KAAK,IAAI,WAAW,cAAc,IAAI,cACxG,IAAI,WAAW,eAAe,KAAK,IAAI,WAAW,YAAY,KAAK,IAAI,WAAW,cAAc,KAAK,IAAI,WAAW,mBAAmB,IAAI,cAC3I;AAEJ,QAAM,OAAO,OAAO,QAAQ,MAAM,EAC/B,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC7B,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,EACtC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,GAAG,CAAC,EAAE,KAAK,QAAK,CAAC,GAAG,EAAE,KAAK,SAAS,IAAI,YAAO,EAAE,IAAI;AAE9H,QAAM,SAAS,CAAC,GAAG,QAAQ,OAAO,CAAC,EAAE,IAAI,OAAK,EAAE,UAAU,EAAE,OAAO,CAAC,MAAmB,KAAK,IAAI;AAChG,QAAM,WAAW,OAAO,SAAS,KAAK,IAAI,GAAG,MAAM,IAAI;AACvD,QAAM,UAAU,CAAC,GAAG,QAAQ,OAAO,CAAC,EAAE,OAAO,OAAK,EAAE,MAAM,EAAE;AAC5D,QAAM,YAAY,CAAC,GAAG,QAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC;AAExF,SAAO;AAAA,IACL,uBAAuB,OAAO;AAAA,IAC9B,KAAK,KAAK,yCAAsC,QAAQ,SAAM,OAAO;AAAA,IACrE;AAAA;AAAA;AAAA;AAAA,EAAkF,KAAK,KAAK,IAAI,KAAK,gCAAsB;AAAA,IAC3H;AAAA;AAAA,EAA2B,UAAU,IAAI,OAAK,KAAK,EAAE,OAAO,uBAAoB,EAAE,cAAc,QAAG,SAAM,EAAE,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,IAC5H;AAAA,qBAAwB,SAAS,MAAM,YAAY,YAAY,QAAQ,UAAU,MAAM,aAAa,UAAU,eAAe,OAAO;AAAA,EACtI,EAAE,KAAK,IAAI;AACb;;;AC3EA,IAAM,aAAa,MAAM;AACzB,IAAM,SAAS,oBAAI,IAAI,CAAC,QAAQ,QAAQ,OAAO,SAAS,CAAC;AAElD,SAAS,YAAY,GAAiC;AAC3D,MAAI,KAAK,KAAM,QAAO;AACtB,MAAI,IAAI,KAAM,QAAO,GAAG,CAAC;AACzB,MAAI,IAAI,OAAO,KAAM,QAAO,IAAI,IAAI,MAAM,QAAQ,CAAC,CAAC;AACpD,SAAO,IAAI,KAAK,OAAO,OAAO,QAAQ,CAAC,CAAC;AAC1C;AAEA,IAAM,iBAAiB,CAAC,MACtB,EAAE,QAAQ,UAAU,GAAG,EAAE,QAAQ,YAAY,GAAG,EAAE,QAAQ,YAAY,GAAG,EAAE,KAAK;AAElF,IAAM,WAAW,CAAC,MAAsB,EAAE,QAAQ,iBAAiB,IAAI,EAAE,QAAQ,OAAO,EAAE;AAE1F,IAAM,WAAW,CAAC,IAAmB,QAAwB;AAC3D,MAAI,IAAI;AAAE,UAAM,IAAI,GAAG,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY;AAAG,QAAI,EAAE,WAAW,QAAQ,EAAG,QAAO,EAAE,QAAQ,UAAU,EAAE;AAAA,EAAE;AACtH,UAAQ,IAAI,MAAM,GAAG,EAAE,CAAC,EAAE,MAAM,iBAAiB,IAAI,CAAC,KAAK,WAAW,YAAY;AACpF;AAEA,SAAS,YAAY,OAA6B;AAChD,QAAM,QAAQ,oBAAI,IAAoB;AACtC,aAAW,KAAK,MAAO,YAAW,OAAQ,EAAE,cAAc,CAAC,GAAI;AAC7D,UAAM,IAAI,eAAe,GAAG;AAC5B,QAAI,CAAC,gBAAgB,KAAK,CAAC,EAAG;AAC9B,QAAI,eAAe,KAAK,CAAC,EAAG;AAC5B,UAAM,IAAI,SAAS,CAAC;AACpB,UAAM,OAAO,MAAM,IAAI,CAAC;AACxB,QAAI,CAAC,QAAS,WAAW,KAAK,CAAC,KAAK,UAAU,KAAK,IAAI,EAAI,OAAM,IAAI,GAAG,CAAC;AAAA,EAC3E;AACA,SAAO,CAAC,GAAG,MAAM,OAAO,CAAC;AAC3B;AAEA,eAAe,YAAY,KAAa,WAA8F;AACpI,QAAM,OAAO,IAAI,gBAAgB;AACjC,QAAM,IAAI,WAAW,MAAM,KAAK,MAAM,GAAG,SAAS;AAClD,QAAM,OAAO,CAAC,SAAmB;AAAA,IAC/B,KAAK,IAAI,QAAQ,IAAI,gBAAgB;AAAA,IACrC,IAAI,IAAI,QAAQ,IAAI,eAAe;AAAA,IACnC,IAAI,IAAI,QAAQ,IAAI,cAAc;AAAA,IAClC,QAAQ,IAAI;AAAA,EACd;AACA,MAAI;AACF,QAAI,QAAuB;AAC3B,QAAI,KAAoB;AACxB,QAAI,SAAwB;AAC5B,QAAI;AACF,YAAM,IAAI,KAAK,MAAM,MAAM,KAAK,EAAE,QAAQ,QAAQ,UAAU,UAAU,QAAQ,KAAK,OAAO,CAAC,CAAC;AAC5F,eAAS,EAAE;AAAQ,WAAK,EAAE;AAC1B,UAAI,EAAE,IAAK,SAAQ,OAAO,EAAE,GAAG;AAAA,IACjC,QAAQ;AAAA,IAAmC;AAC3C,QAAI,SAAS,MAAM;AACjB,YAAM,IAAI,MAAM,MAAM,KAAK,EAAE,QAAQ,OAAO,SAAS,EAAE,OAAO,YAAY,GAAG,UAAU,UAAU,QAAQ,KAAK,OAAO,CAAC;AACtH,YAAM,IAAI,KAAK,CAAC;AAChB,eAAS,UAAU,EAAE;AAAQ,WAAK,MAAM,EAAE;AAC1C,UAAI,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,GAAG;AAAE,cAAM,OAAO,EAAE,GAAG,MAAM,GAAG,EAAE,CAAC;AAAG,YAAI,QAAQ,SAAS,IAAK,SAAQ,OAAO,IAAI;AAAA,MAAE,WACzG,EAAE,IAAK,SAAQ,OAAO,EAAE,GAAG;AACpC,UAAI;AAAE,cAAM,EAAE,MAAM,OAAO;AAAA,MAAE,QAAQ;AAAA,MAAe;AAAA,IACtD;AACA,WAAO,EAAE,KAAK,QAAQ,OAAO,OAAO,SAAS,KAAe,IAAI,QAAQ,MAAM,aAAa,GAAG;AAAA,EAChG,SAAS,GAAG;AACV,WAAO,EAAE,KAAK,QAAQ,MAAM,OAAO,MAAM,aAAa,MAAM,OAAO,OAAQ,EAAY,WAAW,CAAC,EAAE;AAAA,EACvG,UAAE;AACA,iBAAa,CAAC;AAAA,EAChB;AACF;AAEA,eAAe,KAAW,OAAY,GAAW,IAA2C;AAC1F,QAAM,MAAM,IAAI,MAAS,MAAM,MAAM;AACrC,MAAI,IAAI;AACR,QAAM,QAAQ,IAAI,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,MAAM,MAAM,EAAE,GAAG,YAAY;AAC9E,WAAO,IAAI,MAAM,QAAQ;AAAE,YAAM,MAAM;AAAK,UAAI,GAAG,IAAI,MAAM,GAAG,MAAM,GAAG,CAAC;AAAA,IAAE;AAAA,EAC9E,CAAC,CAAC;AACF,SAAO;AACT;AAEA,eAAsB,YACpB,OACA,OAAmE,CAAC,GAC/C;AACrB,QAAM,cAAc,KAAK,eAAe;AACxC,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,OAAO,YAAY,KAAK,EAAE,MAAM,GAAG,KAAK,OAAO,GAAI;AAEzD,QAAM,QAAQ,MAAM,KAAK,MAAM,aAAa,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC;AAC5E,QAAM,OAAmB,MAAM,IAAI,OAAK;AACtC,UAAM,SAAS,SAAS,EAAE,aAAa,EAAE,GAAG;AAC5C,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM,YAAY,EAAE,KAAK;AAAA,MACzB;AAAA,MACA,WAAW,EAAE,SAAS,QAAQ,EAAE,QAAQ;AAAA,MACxC,cAAc,WAAW,aAAa,CAAC,OAAO,IAAI,MAAM;AAAA,IAC1D;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,KAAK,OAAO,OAAK,EAAE,SAAS,IAAI;AAC9C,QAAM,aAAa,MAAM,OAAO,CAAC,GAAG,MAAM,IAAK,EAAE,OAAkB,CAAC;AACpE,QAAM,eAAuC,CAAC;AAC9C,aAAW,KAAK,KAAM,cAAa,EAAE,MAAM,KAAK,aAAa,EAAE,MAAM,KAAK,KAAK;AAE/E,SAAO;AAAA,IACL,MAAM,KAAK,KAAK,CAAC,GAAG,OAAO,EAAE,SAAS,MAAM,EAAE,SAAS,EAAE;AAAA,IACzD,SAAS;AAAA,MACP,QAAQ,KAAK;AAAA,MACb,OAAO,MAAM;AAAA,MACb;AAAA,MACA,WAAW,YAAY,UAAU,KAAK;AAAA,MACtC,SAAS,YAAY,KAAK,MAAM,cAAc,MAAM,UAAU,EAAE,CAAC,KAAK;AAAA,MACtE,WAAW,KAAK,OAAO,OAAK,EAAE,SAAS,EAAE;AAAA,MACzC,cAAc,KAAK,OAAO,OAAK,EAAE,YAAY,EAAE;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,mBAAmB,OAA2B;AAC5D,QAAM,IAAI,MAAM;AAChB,QAAM,MAAM,OAAO,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI;AAC7G,QAAM,WAAW,MAAM,KAAK,OAAO,OAAK,EAAE,SAAS,EAAE,MAAM,GAAG,EAAE;AAChE,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,KAAK,EAAE,MAAM,yBAAsB,EAAE,SAAS,eAAY,EAAE,OAAO,aAAU,EAAE,SAAS,qBAAkB,EAAE,YAAY;AAAA,IACxH,YAAY,GAAG;AAAA,EACjB;AACA,MAAI,SAAS,QAAQ;AACnB,UAAM,KAAK,IAAI,2BAA2B,yBAAyB;AACnE,eAAW,KAAK,SAAU,OAAM,KAAK,KAAK,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,EAAE,GAAG,IAAI;AAAA,EAC/E;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;;;ALpJA,IAAI,sBAAsB;AAM1B,SAAS,mBAAmB,MAAsB;AAChD,SAAO;AAAA,IACL,KACG,QAAQ,uBAAuB,oBAAoB,EACnD,QAAQ,6BAA6B,2BAA2B,EAChE,QAAQ,2BAA2B,yBAAyB,EAC5D,QAAQ,yBAAyB,uBAAuB,EACxD,QAAQ,oBAAoB,kBAAkB,EAC9C,QAAQ,kBAAkB,SAAS,EACnC,QAAQ,mBAAmB,yBAAyB,EACpD,QAAQ,kBAAkB,mBAAmB;AAAA,EAClD;AACF;AAEA,SAAS,kBAAkB,OAAuB;AAChD,SAAO,MACJ,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE,EACtB,MAAM,GAAG,EAAE,KAAK;AACrB;AAEA,SAAS,YAAY,MAAsB;AACzC,QAAM,QAAQ,KAAK,MAAM,IAAI,EAAE,KAAK,UAAQ,KAAK,WAAW,IAAI,CAAC;AACjE,SAAO,OAAO,QAAQ,SAAS,EAAE,EAAE,KAAK,KAAK;AAC/C;AAEO,SAASC,iBAAwB;AACtC,SAAO,QAAQ,IAAI,wBAAwB,KAAK,SAAK,4BAAK,yBAAQ,GAAG,aAAa,aAAa;AACjG;AAEA,SAAS,eAAe,MAA6B;AACnD,MAAI,CAAC,uBAAuB,QAAQ,IAAI,6BAA6B,QAAS,QAAO;AACrF,QAAM,SAASA,eAAc;AAC7B,MAAI;AACF,mCAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AACrC,UAAM,SAAQ,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG;AAC3D,UAAM,WAAO,wBAAK,QAAQ,GAAG,KAAK,IAAI,kBAAkB,YAAY,IAAI,CAAC,CAAC,KAAK;AAC/E,uCAAc,MAAM,MAAM,MAAM;AAChC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB;AAE3B,SAAS,qBAA8B;AACrC,SAAO,uBAAuB,QAAQ,IAAI,6BAA6B;AACzE;AAcA,SAAS,aAAa,SAAiB,OAAmB,KAAiB,YAAmH;AAC5L,MAAI,CAAC,mBAAmB,EAAG,QAAO;AAClC,MAAI;AACF,UAAM,SAAQ,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG;AAC3D,UAAM,UAAM,wBAAKA,eAAc,GAAG,WAAW,kBAAkB,OAAO,CAAC,IAAI,KAAK,EAAE;AAClF,UAAM,eAAW,wBAAK,KAAK,OAAO;AAClC,mCAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AAEvC,UAAM,YAAY,MAAM,IAAI,CAAC,GAAG,MAAM;AACpC,YAAM,MAAM,OAAO,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG;AACzC,YAAM,OAAO,kBAAkB,EAAE,IAAI,QAAQ,gBAAgB,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,KAAK;AAClF,YAAM,QAAQ,GAAG,GAAG,IAAI,IAAI;AAC5B,YAAM,QAAQ,EAAE,gBAAgB,IAAI,KAAK;AACzC,YAAM,UAAU;AAAA,QACd,KAAK,EAAE,SAAS,UAAU;AAAA,QAC1B,cAAc,EAAE,GAAG;AAAA,QACnB,EAAE,kBAAkB,sBAAsB,EAAE,eAAe,KAAK;AAAA,QAChE,EAAE,aAAa,SAAS,iBAAiB,EAAE,YAAY,KAAK,IAAI,CAAC,KAAK;AAAA,QACtE;AAAA,QACA,QAAQ;AAAA,MACV,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAC3B,6CAAc,wBAAK,UAAU,KAAK,GAAG,SAAS,MAAM;AACpD,aAAO,KAAK,IAAI,CAAC,MAAM,KAAK,EAAE,SAAS,UAAU,CAAC,MAAM,EAAE,GAAG,YAAY,KAAK;AAAA,IAChF,CAAC;AAED,UAAM,mBAAmB,MAAM;AAAA,MAC7B;AAAA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,aAAa;AAAA,QACf;AAAA,QACA;AAAA,MACF,IAAI,CAAC;AAAA,MACL,GAAI,IAAI,WAAW,CAAC,qDAAgD,IAAI,CAAC;AAAA,IAC3E,EAAE,KAAK,IAAI,IAAI;AAEf,UAAM,QAAQ;AAAA,MACZ,mBAAmB,OAAO;AAAA,MAC1B,KAAK,MAAM,MAAM;AAAA,MACjB;AAAA,MACA,MAAM,mDAAmD;AAAA,MACzD;AAAA,MACA;AAAA;AAAA;AAAA;AAAA,EAAuE,UAAU,KAAK,IAAI,CAAC;AAAA,IAC7F,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAC3B,UAAM,gBAAY,wBAAK,KAAK,UAAU;AACtC,uCAAc,WAAW,OAAO,MAAM;AAEtC,QAAI;AACJ,QAAI,KAAK;AACP,YAAM,UAAU,CAAC,SAAyC,KAAK,IAAI,OAAK,KAAK,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI;AACpG,YAAM,iBAAa,wBAAK,KAAK,aAAa;AAC1C,YAAM,iBAAa,wBAAK,KAAK,aAAa;AAC1C,YAAM,mBAAe,wBAAK,KAAK,oBAAoB;AACnD,YAAM,iBAAa,wBAAK,KAAK,aAAa;AAC1C,YAAM,iBAAa,wBAAK,KAAK,WAAW;AACxC,yCAAc,YAAY,QAAQ,IAAI,QAAQ,GAAG,MAAM;AACvD,yCAAc,YAAY,QAAQ,IAAI,KAAK,GAAG,MAAM;AACpD,yCAAc,cAAc,QAAQ,IAAI,OAAO,GAAG,MAAM;AACxD,yCAAc,YAAY,KAAK,UAAU,IAAI,QAAQ,MAAM,CAAC,GAAG,MAAM;AACrE,yCAAc,YAAY,IAAI,YAAY,aAAa;AAAA;AAAA,EAAO,mBAAmB,UAAU,CAAC,KAAK,KAAK,MAAM;AAC5G,YAAM,qBAAiB,wBAAK,KAAK,gBAAgB;AACjD,YAAM,uBAAmB,wBAAK,KAAK,oBAAoB;AACvD,YAAM,0BAAsB,wBAAK,KAAK,uBAAuB;AAC7D,yCAAc,gBAAgB,iBAAiB,IAAI,UAAU,GAAG,MAAM;AACtE,yCAAc,kBAAkB,KAAK,UAAU,IAAI,WAAW,SAAS,MAAM,CAAC,GAAG,MAAM;AACvF,yCAAc,qBAAqB,KAAK,UAAU,IAAI,WAAW,iBAAiB,MAAM,CAAC,GAAG,MAAM;AAClG,iBAAW,CAAC,YAAY,YAAY,cAAc,YAAY,YAAY,gBAAgB,kBAAkB,mBAAmB;AAC/H,UAAI,YAAY;AACd,cAAM,kBAAc,wBAAK,KAAK,cAAc;AAC5C,cAAM,oBAAgB,wBAAK,KAAK,qBAAqB;AACrD,2CAAc,aAAa,WAAW,KAAK,IAAI,OAAK,KAAK,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI,GAAG,MAAM;AACzF,2CAAc,eAAe,KAAK,UAAU,WAAW,SAAS,MAAM,CAAC,GAAG,MAAM;AAChF,iBAAS,KAAK,aAAa,aAAa;AAAA,MAC1C;AACA,UAAI,IAAI,UAAU;AAChB,cAAM,mBAAe,wBAAK,KAAK,eAAe;AAC9C,2CAAc,cAAc,KAAK,UAAU,IAAI,UAAU,MAAM,CAAC,GAAG,MAAM;AACzE,iBAAS,KAAK,YAAY;AAAA,MAC5B;AAAA,IACF;AAEA,WAAO,EAAE,KAAK,WAAW,WAAW,MAAM,QAAQ,SAAS;AAAA,EAC7D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iBAAiB,SAAiB,MAAoE;AAC7G,MAAI,CAAC,mBAAmB,EAAG,QAAO;AAClC,MAAI;AACF,UAAM,SAASA,eAAc;AAC7B,mCAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AACrC,UAAM,SAAQ,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG;AAC3D,UAAM,WAAO,wBAAK,QAAQ,GAAG,KAAK,WAAW,kBAAkB,QAAQ,QAAQ,gBAAgB,EAAE,CAAC,CAAC,MAAM;AACzG,UAAM,MAAM,CAAC,MAAc,SAAS,KAAK,CAAC,IAAI,IAAI,EAAE,QAAQ,MAAM,IAAI,CAAC,MAAM;AAC7E,UAAM,OAAO,CAAC,cAAc,GAAG,KAAK,IAAI,OAAK,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC;AAC/E,uCAAc,MAAM,KAAK,KAAK,IAAI,GAAG,MAAM;AAC3C,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,yBAAyB,QAAgB,KAA4B;AAC5E,MAAI,CAAC,uBAAuB,QAAQ,IAAI,6BAA6B,QAAS,QAAO;AACrF,MAAI;AACF,UAAM,UAAM,wBAAKA,eAAc,GAAG,aAAa;AAC/C,mCAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,UAAM,SAAQ,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG;AAC3D,UAAM,OAAO,IAAI,QAAQ,gBAAgB,EAAE,EAAE,QAAQ,gBAAgB,GAAG,EAAE,QAAQ,YAAY,EAAE,EAAE,MAAM,GAAG,EAAE;AAC7G,UAAM,eAAW,wBAAK,KAAK,GAAG,KAAK,IAAI,IAAI,MAAM;AACjD,uCAAc,UAAU,OAAO,KAAK,QAAQ,QAAQ,CAAC;AACrD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,SAAS,SAAiB,aAAsC;AACvE,QAAM,WAAW,eAAe,eAAe,OAAO;AACtD,QAAM,OAAO,WAAW,GAAG,OAAO;AAAA;AAAA,qBAAmB,QAAQ,OAAO;AACpE,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,EAAE;AAC7C;AAMA,SAAS,oBAAoB,SAAmC;AAC9D,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,GAAG,QAAQ,IAAI,YAAU,KAAK,KAAK,OAAO,KAAK,CAAC,MAAM,OAAO,oBAAoB,KAAK,OAAO,iBAAiB,OAAO,YAAY,MAAM,KAAK,OAAO,SAAS,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,IAAI;AAAA,EACzL,EAAE,KAAK,IAAI;AACb;AAoBA,SAAS,sBAAsB,MAA+B,UAA0B;AACtF,MAAI,KAAK,UAAU,wBAAwB;AACzC,WAAO,kCAAkC,KAAK,eAAe,gCAAgC,KAAK,gBAAgB,uBAAuB,KAAK,SAAS;AAAA,EACzJ;AACA,MAAI,KAAK,UAAU,uBAAuB;AACxC,WAAO,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAAA,EAC3D;AACA,MAAI,OAAO,KAAK,eAAe,UAAU;AACvC,UAAM,UAAU,OAAO,KAAK,UAAU,WAClC,KAAK,QACL,OAAO,KAAK,YAAY,WACtB,KAAK,UACL;AACN,UAAM,YAAY,KAAK,cAAc,OAAO,qBAAqB;AACjE,WAAO,GAAG,KAAK,UAAU,KAAK,OAAO,GAAG,SAAS,GAAG,qBAAqB,IAAI,CAAC;AAAA,EAChF;AACA,MAAI,OAAO,KAAK,UAAU,SAAU,QAAO,KAAK;AAChD,SAAO,YAAY;AACrB;AAEA,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,IAAI,WAAW,OAAO,SAAS,OAAO,WAAY,QAAO,EAAE,OAAO,mBAAmB,sBAAsB,QAAQ,IAAI,CAAC,EAAE;AAC9H,UAAM,OAAQ,OAAO,UAAsC;AAC3D,WAAO,EAAE,KAAK;AAAA,EAChB,QAAQ;AACN,QAAI,IAAI,QAAS,QAAO,EAAE,OAAO,mBAAmB,QAAQ,YAAY,EAAE;AAC1E,WAAO,EAAE,OAAO,gCAAgC;AAAA,EAClD;AACF;AAKA,SAAS,iBAAiB,KAA6B;AACrD,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,QAAkB,CAAC;AACzB,MAAI,IAAI,UAAU,QAAQ;AACxB,eAAW,KAAK,IAAI,UAAU;AAC5B,YAAM,UAAU,CAAC,EAAE,QAAQ,OAAO,EAAE,IAAI,IAAI,EAAE,OAAO,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,QAAQ,EAAE,IAAI,EAAE,EAAE,OAAO,OAAO;AAC/G,UAAI,QAAQ,OAAQ,OAAM,KAAK,OAAO,EAAE,IAAI,aAAQ,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,IAC1E;AAAA,EACF;AACA,QAAM,cAAc,IAAI,KAAK,IAAI,YAAY,CAAC,GAAG,IAAI,OAAK,EAAE,IAAI,CAAC;AACjE,MAAI,CAAC,YAAY,MAAM;AACrB,QAAI,IAAI,OAAO,OAAS,OAAM,KAAK,8BAA8B,IAAI,MAAM,KAAK,IAAI,CAAC,EAAE;AACvF,QAAI,IAAI,MAAM,OAAU,OAAM,KAAK,cAAc,IAAI,KAAK,KAAK,IAAI,CAAC,EAAE;AACtE,QAAI,IAAI,OAAO,OAAS,OAAM,KAAK,eAAe,IAAI,MAAM,KAAK,IAAI,CAAC,EAAE;AAAA,EAC1E;AACA,SAAO,MAAM,SAAS;AAAA;AAAA,EAAoB,MAAM,KAAK,IAAI,CAAC,KAAK;AACjE;AAEA,SAAS,SAAS,GAA8B,KAAqB;AACnE,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,EAAE,SAAS,MAAM,EAAE,MAAM,GAAG,GAAG,IAAI,WAAM;AAClD;AAEO,SAAS,KAAK,GAAsC;AACzD,SAAO,OAAO,KAAK,EAAE,EAClB,QAAQ,WAAW,GAAG,EACtB,QAAQ,OAAO,KAAK,EACpB,QAAQ,QAAQ,GAAG,EACnB,KAAK;AACV;AAEA,SAAS,aAAa,OAAoB;AACxC,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,UAAU,MAAM,WAAW,CAAC;AAClC,QAAM,UAAU,MAAM,WAAW,CAAC;AAClC,QAAM,SAAS,QAAQ,kBAAkB,QAAQ,UAAU,CAAC;AAC5D,QAAM,UAAU,QAAQ,mBAAmB,CAAC;AAC5C,QAAM,MAAM,QAAQ,kBAAkB,CAAC;AACvC,QAAM,kBAAkB,OAAO,mBAAmB,CAAC;AACnD,QAAM,mBAAmB,MAAM;AAC/B,QAAM,aAAa,MAAM,QAAQ,kBAAkB,UAAU,IACzD,iBAAiB,WAAW,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,MAAW,GAAG,EAAE,IAAI,KAAK,EAAE,UAAU,KAAK,EAAE,KAAK,GAAG,EAAE,KAAK,IAAI,IAC5G;AACJ,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,iBAAiB,QAAQ,aAAa,OAAO,aAAa,SAAS,0BAAuB,OAAO,4BAA4B,OAAO,QAAQ,OAAO,0BAA0B,UAAU,MAAM,IAAI;AAAA,IACjM,uBAAuB,gBAAgB,UAAU,SAAS,GAAG,gBAAgB,SAAS,SAAM,gBAAgB,OAAO,SAAS,MAAM,IAAI,gBAAgB,OAAO,IAAI,KAAK,gBAAgB,OAAO,KAAK,KAAK,EAAE,GAAG,gBAAgB,QAAQ,SAAM,SAAS,gBAAgB,OAAO,GAAG,CAAC,KAAK,EAAE;AAAA,IACrR,sBAAsB,OAAO,aAAa,SAAS,0BAAuB,OAAO,4BAA4B,OAAO,QAAQ,OAAO,0BAA0B,UAAU,MAAM,OAAO,4BAA4B,QAAQ,OAAO,SAAS;AAAA,IACxO,qBAAqB,CAAC,QAAQ,IAAI,QAAQ,MAAM,QAAQ,QAAQ,QAAQ,OAAO,EAAE,OAAO,OAAO,EAAE,KAAK,QAAK,KAAK,QAAQ,SAAS,SAAS;AAAA,IAC1I,iBAAiB,SAAS,IAAI,cAAc,GAAG,KAAK,SAAS;AAAA,IAC7D,gBAAgB,SAAS,IAAI,UAAU,GAAG,KAAK,SAAS,kBAAe,IAAI,oBAAoB,OAAO,QAAQ,IAAI,oBAAoB,QAAQ,OAAO,SAAS,qBAAkB,IAAI,eAAe,OAAO,QAAQ,IAAI,eAAe,QAAQ,OAAO,SAAS;AAAA,EAC/P;AACA,MAAI,kBAAkB;AACpB,UAAM,KAAK,wBAAwB,iBAAiB,MAAM,GAAG,iBAAiB,WAAW,kBAAe,iBAAiB,SAAS,IAAI,GAAG,iBAAiB,SAAS,aAAa,KAAK,iBAAiB,SAAS,UAAU,KAAK,EAAE,KAAK,EAAE,GAAG,aAAa,oBAAiB,UAAU,KAAK,EAAE,EAAE;AAAA,EAC7R;AACA,SAAO,mBAAmB,MAAM,KAAK,IAAI,CAAC;AAC5C;AAEA,SAAS,qBAAqB,MAAuC;AACnE,QAAM,WAAW,MAAM,QAAQ,KAAK,QAAQ,IAAI,KAAK,WAAyC,CAAC;AAC/F,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,QAAM,QAAQ,SAAS,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,YAAY;AAClD,UAAM,QAAQ,QAAQ,SAAS,CAAC;AAChC,UAAM,UAAU,MAAM,WAAW,CAAC;AAClC,UAAM,SAAS,QAAQ,kBAAkB,QAAQ,UAAU,CAAC;AAC5D,UAAM,kBAAkB,OAAO,mBAAmB,CAAC;AACnD,UAAM,UAAU,QAAQ,mBAAmB;AAAA,MACzC,IAAI,QAAQ,cAAc,QAAQ;AAAA,MAClC,MAAM,QAAQ,gBAAgB,QAAQ;AAAA,MACtC,QAAQ,QAAQ,kBAAkB,QAAQ;AAAA,IAC5C;AACA,UAAM,MAAM,QAAQ,kBAAkB,CAAC;AACvC,UAAM,MAAM,CAAC,QAAQ,IAAI,QAAQ,MAAM,QAAQ,MAAM,EAAE,OAAO,OAAO,EAAE,KAAK,KAAK,KAAK;AACtF,UAAM,YAAY,QAAQ,sBAAsB,QAAQ,0BAA0B,QAAQ,qBAAqB,OAAO,aAAa;AACnI,UAAM,mBAAmB,QAAQ,6BAA6B,QAAQ;AACtE,UAAM,cAAc,gBAAgB,UAAU,QAAQ;AACtD,WAAO,aAAa,QAAQ,kBAAkB,QAAQ,iBAAiB,GAAG,KAAK,QAAQ,WAAW,QAAQ,UAAU,SAAS,iBAAc,SAAS,eAAY,MAAM,SAAS,aAAa,OAAO,aAAa,QAAQ,aAAa,SAAS,GAAG,cAAc,IAAI,WAAW,KAAK,EAAE,SAAM,GAAG,iBAAc,IAAI,oBAAoB,OAAO,QAAQ,IAAI,oBAAoB,QAAQ,OAAO,SAAS,iBAAc,qBAAqB,OAAO,QAAQ,qBAAqB,QAAQ,OAAO,SAAS;AAAA,EACpe,CAAC;AACD,SAAO;AAAA;AAAA;AAAA,EAAkB,MAAM,KAAK,IAAI,CAAC;AAC3C;AAOO,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,cAAc,EAAE;AACtB,QAAM,aAAc,EAAE,OAA+C;AAErE,QAAM,UAAU,KAAK;AAAA,IAAI,CAAC,GAAG,MAC3B,KAAK,IAAI,CAAC,MAAM,KAAK,EAAE,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,QAAQ,GAAG,CAAC,CAAC,MAAM,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,CAAC;AAAA,EACtH,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,KAAK,EAAE,KAAK,CAAC,OAAO,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,OAAO,KAAK,SAAS,EAAE,SAAS,GAAG,CAAC,CAAC;AAAA,EACxG,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,YAAyB,aAAa,qBAAqB,KAAK,SAAS,cAAc,SAAS,oBAAiB,KAAK,MAAM,oBAAiB,aAAa,KAAM,QAAQ,CAAC,CAAC,MAC1K;AAEJ,QAAM,OAAO;AAAA;AAAA;AAAA,mDAAwE,MAAM,gBAAgB,EAAE;AAAA;AAAA;AAE7G,QAAM,OAAO,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,aAAa,aAAa,KAAK,CAAC,GAAG,IAAI;AAErN,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,OAAO,MAAM;AAAA,MACb,UAAU,MAAM,YAAY;AAAA,MAC5B,eAAe,KAAK;AAAA,MACpB,kBAAkB,aAAa,oBAAoB;AAAA,MACnD,WAAW,KAAK,IAAI,QAAM;AAAA,QACxB,UAAU,OAAO,EAAE,YAAY,EAAE;AAAA,QACjC,QAAQ,EAAE,UAAU;AAAA,QACpB,aAAa,EAAE,gBAAgB;AAAA,QAC/B,YAAY,EAAE,eAAe;AAAA,MAC/B,EAAE;AAAA,MACF,gBAAgB,QAAQ,IAAI,QAAM;AAAA,QAChC,UAAU,OAAO,EAAE,QAAQ,KAAK;AAAA,QAChC,OAAO,OAAO,EAAE,SAAS,EAAE;AAAA,QAC3B,KAAK,OAAO,EAAE,OAAO,EAAE;AAAA,QACvB,QAAQ,OAAO,EAAE,UAAU,EAAE;AAAA,QAC7B,SAAS,EAAE,WAAW;AAAA,MACxB,EAAE;AAAA,MACF,YAAY,QAAQ,EAAE,UAAU,MAAM,aAAa,MAAM,MAAM,MAAM,QAAQ,KAAK,IAAI;AAAA,MACtF,WAAW,YACP,EAAE,UAAU,UAAU,YAAY,CAAC,GAAG,OAAO,UAAU,SAAS,CAAC,GAAG,MAAM,UAAU,QAAQ,CAAC,GAAG,OAAO,UAAU,SAAS,CAAC,EAAE,IAC7H;AAAA,MACJ,YAAY,cAAc;AAAA,IAC5B;AAAA,EACF;AACF;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;AACpB,QAAM,cAAc,EAAE;AAEtB,QAAM,WAAW,QAAQ;AAAA,IAAI,OAC3B,KAAK,EAAE,QAAQ,MAAM,KAAK,EAAE,KAAK,CAAC,OAAO,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,OAAO,KAAK,SAAS,EAAE,SAAS,GAAG,CAAC,CAAC;AAAA,EACxG,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,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,QAAG,KAAK,EAAE,eAAe,GAAG,OAAO,EAAE,aAAa,UAAU,EAAE,UAAU,MAAM,QAAG;AAAA,EACtI,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,mBAAmB,MAAM,KAAK,IAAI,MAAM,WAAW,SAAM,MAAM,QAAQ,KAAK,EAAE;AAAA;AAAA,EAAO,SAAS,GAAG,YAAY,GAAG,iBAAiB,SAAS,CAAC,GAAG,SAAS,GAAG,aAAa,aAAa,KAAK,CAAC,GAAG,IAAI;AAE9M,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,OAAO,MAAM;AAAA,MACb,UAAU,MAAM,YAAY;AAAA,MAC5B,gBAAgB,QAAQ,IAAI,QAAM;AAAA,QAChC,UAAU,OAAO,EAAE,QAAQ,KAAK;AAAA,QAChC,OAAO,OAAO,EAAE,SAAS,EAAE;AAAA,QAC3B,KAAK,OAAO,EAAE,OAAO,EAAE;AAAA,QACvB,QAAQ,OAAO,EAAE,UAAU,EAAE;AAAA,QAC7B,SAAS,EAAE,WAAW;AAAA,MACxB,EAAE;AAAA,MACF,WAAW,UAAU,IAAI,QAAM;AAAA,QAC7B,UAAU,OAAO,EAAE,QAAQ,KAAK;AAAA,QAChC,MAAM,OAAO,EAAE,QAAQ,EAAE;AAAA,QACzB,QAAQ,EAAE,UAAU;AAAA,QACpB,aAAa,EAAE,eAAe;AAAA,QAC9B,YAAY,EAAE,cAAc;AAAA,MAC9B,EAAE;AAAA,MACF,YAAY,QAAQ,EAAE,UAAU,MAAM,aAAa,MAAM,MAAM,MAAM,QAAQ,KAAK,IAAI;AAAA,MACtF,WAAW,YACP,EAAE,UAAU,UAAU,YAAY,CAAC,GAAG,OAAO,UAAU,SAAS,CAAC,GAAG,MAAM,UAAU,QAAQ,CAAC,GAAG,OAAO,UAAU,SAAS,CAAC,EAAE,IAC7H;AAAA,IACN;AAAA,EACF;AACF;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,MAAc,EAAE,OAAkB,MAAM;AAC9C,QAAM,QAAc,EAAE,SAA2B;AACjD,QAAM,WAAc,EAAE,YAA0B,CAAC;AACjD,QAAM,MAAa,EAAE;AACrB,QAAM,SAAc,EAAE,gBAAkC;AACxD,QAAM,SAAa,EAAE;AACrB,QAAM,iBAAiB,EAAE;AACzB,QAAM,iBAAiB,gBAAgB,SAAS,yBAAyB,eAAe,QAAQ,GAAG,IAAI;AACvG,QAAM,WAAa,EAAE;AACrB,QAAM,QAAa,EAAE;AAErB,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;AAAA;AAAA,0BAA+B,OAAO,OAAO,eAAe,CAAC,qDAAgD,EAAE,KACpL;AACJ,QAAM,kBAAkB,SAAS;AAAA;AAAA,EAAsB,MAAM,KAAK;AAElE,QAAM,MAAO,EAAE,UAAqK;AACpL,QAAM,aAAa,KAAK,YACpB;AAAA;AAAA,iCAA0D,IAAI,SAAS,QAAG,gBAAgB,IAAI,UAAU,QAAG,KAAK,IAAI,WAAW,SAAY,KAAK,IAAI,MAAM,qBAAqB,EAAE,sEACjL,KAAK,UACH;AAAA;AAAA,8BAAkE,IAAI,QAAQ,KAAK,IAAI,KAAK,MAAM,EAAE;AAAA,cAA4E,IAAI,OAAO;AAAA,iBAAoB,IAAI,iBAAiB,aAAa,oBACjP,MACE;AAAA;AAAA,EAAmC,IAAI,SAAS,eAAe,sEAC/D;AAER,QAAM,oBAAoB,iBACtB;AAAA;AAAA,cAAgC,kBAAkB,0EAAqE;AAAA,eAAkB,eAAe,YAAY,MAAM,QAAQ,CAAC,CAAC;AAAA,gBAAsB,eAAe,MAAM,KAC/N;AAEJ,QAAM,kBAAkB,WACpB;AAAA,IACE;AAAA;AAAA,IACA,SAAS,cAAc,uBAAuB,SAAS,WAAW,KAAK;AAAA,IACvE,gBAAgB,OAAO,QAAQ,SAAS,UAAU,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,GAAE,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,GAAG,KAAK,mBAAmB;AAAA,IACvI,eAAe,OAAO,QAAQ,SAAS,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,GAAE,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,GAAG,KAAK,mBAAmB;AAAA,IACrI,SAAS,QAAQ,OAAO,eAAe,SAAS,OAAO,IAAI,KAAK;AAAA,IAChE,SAAS,QAAQ,UAAU,kBAAkB,SAAS,OAAO,OAAO,KAAK;AAAA,EAC3E,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,IAC3B;AAEJ,QAAM,eAAe,QACjB;AAAA,IACE;AAAA;AAAA,IACA,gBAAgB,MAAM,UAAU,WAAW,MAAM,aAAa,0BAA0B,MAAM,OAAO,MAAM;AAAA,IAC3G,MAAM,YAAY,mBAAmB,MAAM,SAAS,KAAK;AAAA,EAC3D,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,IAC3B;AAEJ,QAAM,cAAc,MAAM,QAAQ,MAAM,IAAI,OAAO,SAAS;AAC5D,QAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,IAA2G,WAAW;AAEnI,QAAM,OAAO,kBAAkB,GAAG;AAAA,IAAO,KAAK;AAAA,EAAO,cAAc,GAAG,UAAU,GAAG,eAAe,GAAG,WAAW,GAAG,UAAU,GAAG,iBAAiB,GAAG,YAAY,GAAG,IAAI;AACvK,QAAM,aAAa,kBAAkB,GAAG;AAAA,IAAO,KAAK;AAAA,EAAO,cAAc,GAAG,UAAU,GAAG,eAAe,GAAG,eAAe,GAAG,UAAU,GAAG,iBAAiB,GAAG,YAAY,GAAG,IAAI;AAEjL,QAAM,aAAa,SAAS,MAAM,UAAU;AAC5C,QAAM,oBAAoB;AAAA,IACxB;AAAA,IACA,OAAQ,EAAE,SAA2B;AAAA,IACrC,UAAU,SAAS,IAAI,QAAM,EAAE,OAAO,OAAO,EAAE,KAAK,KAAK,GAAG,MAAM,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE;AAAA,IACzF,kBAAkB;AAAA,IAClB,YAAY,KAAK,cAAc;AAAA,IAC/B,aAAa,KAAK,QAAQ,CAAC;AAAA,IAC3B,UAAU,KAAK,YAAY;AAAA,IAC3B,qBAAqB,KAAK,iBAAiB,CAAC;AAAA,IAC5C,iBAAiB,kBAAkB;AAAA,IACnC,UAAU,YAAY;AAAA,IACtB,aAAa,OAAO,UAAU;AAAA,IAC9B,QAAQ,OAAO;AAAA,EACjB;AAEA,MAAI,gBAAgB,QAAQ;AAC1B,WAAO;AAAA,MACL,SAAS;AAAA,QACP,GAAI,WAAW;AAAA,QACf,EAAE,MAAM,SAAS,MAAM,eAAe,QAAQ,UAAU,YAAY;AAAA,MACtE;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,GAAG,YAAY,kBAAkB;AAC5C;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,SAAS,KAAK,SAAS;AAC7B,QAAM,gBAAgB,SAAS,iBAAiB,MAAM,KAAK,KAAK,IAAI,QAAM,EAAE,KAAK,EAAE,KAAK,QAAQ,EAAE,UAAU,KAAK,EAAE,CAAC,IAAI;AACxH,QAAM,cAAc,SAAS,qBAAqB;AAClD,QAAM,UAAU,KAAK,MAAM,GAAG,WAAW,EAAE,IAAI,CAAC,GAAG,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,UAAU,QAAG,IAAI,EAAE,KAAK,IAAI;AAElH,QAAM,gBAAgB,SAClB,gBACE;AAAA;AAAA,gBAA+C,aAAa,mCAA8B,KAAK,MAAM;AAAA,oBAA6B,WAAW,iDAC7I;AAAA;AAAA,+CAAkF,WAAW,OAAO,KAAK,MAAM,wFACjH;AAEJ,QAAM,OAAO;AAAA,IACX,cAAc,MAAM,GAAG;AAAA,IACvB,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,IACA;AAAA,kBAAqB,SAAS,WAAW,WAAW,OAAO,KAAK,MAAM,MAAM,EAAE;AAAA;AAAA;AAAA,EAAiD,OAAO;AAAA,IACtI,CAAC,UAAU,OAAO,SAAS;AAAA;AAAA,EAAqB,OAAO,IAAI,OAAK,KAAK,EAAE,GAAG,KAAK,EAAE,MAAM,GAAG,EAAE,KAAK,IAAI,CAAC,KAAK;AAAA,IAC3G;AAAA;AAAA;AAAA;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,UAAU,EAAE,YAAY,MAAM;AAAA,MAC9B,YAAY,EAAE,cAAc,KAAK;AAAA,MACjC,WAAW,EAAE,cAAc;AAAA,MAC3B,SAAS,GAAG;AAAA,MACZ,eAAe,UAAU;AAAA,MACzB,aAAa,OAAO;AAAA,MACpB,eAAe,iBAAiB;AAAA,MAChC,MAAM,KAAK,IAAI,QAAM,EAAE,KAAK,EAAE,KAAK,QAAQ,EAAE,UAAU,KAAK,EAAE;AAAA,MAC9D,YAAY,EAAE,cAAc;AAAA,IAC9B;AAAA,EACF;AACF;AAKA,SAAS,eAAe,SAAiB,OAAmB,UAA+B;AACzF,QAAM,EAAE,OAAO,QAAQ,IAAI,eAAe,OAAO,OAAO;AACxD,QAAM,WAAW,MAAM,IAAI,OAAK;AAC9B,UAAM,EAAE,cAAc,IAAI,QAAQ,IAAI,UAAU,IAAI,GAAG,KAAK,IAAI;AAChE,UAAM,IAAI,QAAQ,IAAI,EAAE,GAAG;AAC3B,WAAO,EAAE,GAAG,MAAM,SAAS,GAAG,WAAW,GAAG,YAAY,GAAG,cAAc,MAAM,QAAQ,GAAG,UAAU,MAAM;AAAA,EAC5G,CAAC;AACD,QAAM,SAAS,cAAc,OAAO,OAAO;AAC3C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS,CAAC,GAAG,QAAQ,OAAO,CAAC;AAAA,IAC7B;AAAA,IACA,UAAU,kBAAkB,SAAS,OAAO,QAAQ,OAAO;AAAA,IAC3D,YAAY,gBAAgB,OAAO,CAAC,GAAG,QAAQ,OAAO,CAAC,GAAG,OAAO;AAAA,IACjE,UAAU,YAAY;AAAA,EACxB;AACF;AAEO,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,gBAAgB,CAAC,MACrB,EAAE,KAAK,SAAS,MAAM,QAAQ,EAAE,MAAM,KAAK,EAAE,OAAO,SAAS,CAAC,GAAG,EAAE,OAAO,MAAM,WAAW,IAAI,CAAC;AAElG,QAAM,UAAU,CAAC,GAAmB,MAAc;AAChD,UAAM,aAAa,cAAc,CAAC,EAAE,KAAK,IAAI,KAAK;AAClD,WAAO,KAAK,IAAI,CAAC,MAAM,KAAK,EAAE,SAAS,UAAU,CAAC,MAAM,EAAE,GAAG,MAAM,UAAU;AAAA,EAC/E;AAEA,QAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AACb,QAAM,eAAe,KAAK,MAAM,MAAM,mBAAiB,EAAE,cAAc,KAAM,KAAM,QAAQ,CAAC,CAAC;AAE7F,QAAM,oBAAoB;AAAA,IACxB,KAAK,MAAM;AAAA,IACX,WAAW,MAAM;AAAA,IACjB,OAAO,MAAM,IAAI,QAAM;AAAA,MACrB,KAAK,OAAO,EAAE,OAAO,EAAE;AAAA,MACvB,OAAO,EAAE,SAAS;AAAA,MAClB,aAAa,cAAc,CAAC;AAAA,IAC9B,EAAE;AAAA,IACF,YAAY,EAAE,cAAc;AAAA,EAC9B;AAEA,MAAI,MAAM,SAAS,qBAAqB;AACtC,UAAM,OAAO,aAAa,MAAM,KAAK,MAAM,IAAI,QAAM;AAAA,MACnD,KAAK,OAAO,EAAE,OAAO,EAAE;AAAA,MACvB,OAAO,EAAE,SAAS;AAAA,MAClB,cAAc,EAAE,gBAAgB;AAAA,MAChC,iBAAiB,EAAE,mBAAmB;AAAA,MACtC,aAAa,cAAc,CAAC;AAAA,IAC9B,EAAE,CAAC;AACH,UAAM,UAAU,MAAM,MAAM,GAAG,mBAAmB,EAAE,IAAI,OAAO,EAAE,KAAK,IAAI;AAC1E,UAAM,WAAW,OACb;AAAA;AAAA,kBAA8C,KAAK,GAAG;AAAA,sBAA8D,KAAK,SAAS;AAAA,sBAA2D,KAAK,SAAS;AAAA;AAAA;AAAA;AAAA,0JAC3M;AAAA;AAAA,wDAAwF,MAAM,MAAM;AACxG,UAAMC,QAAO;AAAA,MACX,mBAAmB,MAAM,GAAG;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,kBAAqB,KAAK,IAAI,qBAAqB,MAAM,MAAM,CAAC,OAAO,MAAM,MAAM;AAAA;AAAA;AAAA,EAAkE,OAAO;AAAA,MAC5J;AAAA,IACF,EAAE,KAAK,IAAI;AACX,WAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAMA,MAAK,CAAC,GAAG,mBAAmB,EAAE,GAAG,mBAAmB,YAAY,MAAM,OAAO,KAAK,EAAE;AAAA,EAC/H;AAEA,QAAM,SAAS;AAAA,IACb,mBAAmB,MAAM,GAAG;AAAA,IAC5B;AAAA,IACA;AAAA;AAAA;AAAA;AAAA,EAA2E,MAAM,IAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,EAC1G,EAAE,KAAK,IAAI;AAEX,QAAM,OAAO,GAAG,MAAM,GAAG,IAAI;AAE7B,QAAM,cAAc,MAAM,IAAI,CAAC,GAAG,MAAM;AACtC,UAAM,QAAQ,EAAE,gBAAgB,IAAI,KAAK;AACzC,WAAO;AAAA,MACL;AAAA,KAAQ,IAAI,CAAC,KAAK,EAAE,SAAS,UAAU;AAAA,MACvC,cAAc,EAAE,GAAG;AAAA,MACnB,EAAE,kBAAkB,sBAAsB,EAAE,eAAe,KAAK;AAAA,MAChE,OAAO;AAAA,EAAK,IAAI,KAAK;AAAA,IACvB,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAAA,EAC7B,CAAC,EAAE,KAAK,IAAI;AAEZ,QAAM,aAAa,GAAG,MAAM;AAAA;AAAA;AAAA;AAAA,EAAiC,WAAW,GAAG,IAAI;AAE/E,SAAO,EAAE,GAAG,SAAS,MAAM,UAAU,GAAG,kBAAkB;AAC5D;AAEA,eAAsB,gBAAgB,KAAqB,OAAiD;AAC1G,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;AACjB,QAAM,QAAQ,EAAE,SAAS,CAAC;AAC1B,QAAM,gBAAgB,CAAC,MACrB,EAAE,KAAK,SAAS,MAAM,QAAQ,EAAE,MAAM,KAAK,EAAE,OAAO,SAAS,CAAC,GAAG,EAAE,OAAO,MAAM,WAAW,IAAI,CAAC;AAElG,QAAM,MAAM,eAAe,MAAM,KAAK,OAAgC,EAAE,QAAQ;AAChF,QAAM,aAAa,MAAM,YAAY,OAAgC,EAAE,aAAa,GAAG,CAAC;AACxF,QAAM,OAAO,aAAa,MAAM,KAAK,MAAM,IAAI,QAAM;AAAA,IACnD,KAAK,OAAO,EAAE,OAAO,EAAE;AAAA,IACvB,OAAO,EAAE,SAAS;AAAA,IAClB,cAAc,EAAE,gBAAgB;AAAA,IAChC,iBAAiB,EAAE,mBAAmB;AAAA,IACtC,aAAa,cAAc,CAAC;AAAA,EAC9B,EAAE,GAAG,KAAK,UAAU;AAEpB,QAAM,YAAY,OAAO,QAAQ,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,EAC5F,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,aAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,IAAI;AACvD,QAAM,MAAM,WAAW;AACvB,QAAM,UAAU,GAAG,IAAI,MAAM,gBAAa,IAAI,SAAS,eAAY,IAAI,SAAS,qBAAkB,IAAI,YAAY;AAClH,QAAM,KAAK,IAAI,WAAW;AAC1B,QAAM,SAAS,GAAG,SAAS,WAAW,MAAM,GAAG,CAAC,EAAE,IAAI,QAAM,GAAG,GAAG,MAAM,KAAK,GAAG,KAAK,GAAG,EAAE,KAAK,IAAI,KAAK;AACxG,QAAM,WAAW,GAAG,GAAG,SAAS,UAAU,eAAe,GAAG,SAAS,UAAU,wBAAqB,GAAG,SAAS,OAAO,iBAAc,GAAG,SAAS,cAAc,oBAAiB,GAAG,SAAS,UAAU,oCAAiC,MAAM;AAC7O,QAAM,eAAe,KAAK,MAAM,MAAM,mBAAiB,EAAE,cAAc,KAAM,KAAM,QAAQ,CAAC,CAAC;AAE7F,QAAM,oBAAoB;AAAA,IACxB,KAAK,MAAM;AAAA,IACX,WAAW,MAAM;AAAA,IACjB,YAAY,EAAE,cAAc;AAAA,IAC5B,YAAY,MAAM,OAAO;AAAA,IACzB,QAAQ,OAAO,YAAY,OAAO,QAAQ,IAAI,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAAA,IACnF,QAAQ,EAAE,QAAQ,IAAI,QAAQ,YAAY,IAAI,YAAY,WAAW,IAAI,WAAW,cAAc,IAAI,aAAa;AAAA,IACnH,OAAO,EAAE,UAAU,GAAG,SAAS,YAAY,UAAU,GAAG,SAAS,YAAY,SAAS,GAAG,SAAS,SAAS,gBAAgB,GAAG,SAAS,gBAAgB,iBAAiB,GAAG,SAAS,cAAc;AAAA,EACpM;AAEA,QAAM,WAAW,OACb;AAAA;AAAA,kBAAkD,KAAK,GAAG;AAAA,sBAA4D,KAAK,SAAS;AAAA;AAAA;AAAA,8LACpI;AAAA;AAAA;AAEJ,QAAM,OAAO;AAAA,IACX,0BAA0B,MAAM,GAAG;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA;AAAA,EAAoB,aAAa,cAAc;AAAA,IAC/C;AAAA;AAAA,EAAe,QAAQ;AAAA,IACvB;AAAA;AAAA,EAAgB,OAAO;AAAA,EACzB,EAAE,KAAK,IAAI;AACX,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,CAAC,GAAG,kBAAkB;AACtE;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,KAAK,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,QAAG,MAAM,EAAE,YAAY,QAAG,QAAQ,EAAE,OAAO;AAAA,EAClI,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,sBAAsB,KAAK;AAAA,IAC3B,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,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,MAAM,MAAM;AAAA,MACZ,YAAY,OAAO;AAAA,MACnB,SAAS,EAAE,cACP,EAAE,OAAO,EAAE,YAAY,SAAS,MAAM,iBAAiB,EAAE,YAAY,mBAAmB,KAAK,IAC7F;AAAA,MACJ,QAAQ,OAAO,IAAI,QAAM;AAAA,QACvB,SAAS,OAAO,EAAE,WAAW,EAAE;AAAA,QAC/B,OAAO,OAAO,EAAE,SAAS,EAAE;AAAA,QAC3B,aAAa,EAAE,eAAe;AAAA,QAC9B,OAAO,EAAE,SAAS;AAAA,QAClB,UAAU,EAAE,YAAY;AAAA,QACxB,KAAK,EAAE,OAAO;AAAA,MAChB,EAAE;AAAA,IACJ;AAAA,EACF;AACF;AAKA,SAAS,2BAA2B,QAAsF;AACxH,SAAO,OAAO,IAAI,QAAM;AAAA,IACtB,UAAU,OAAO,SAAS,EAAE,YAAY,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI;AAAA,IAC/D,QAAQ,OAAO,SAAS,EAAE,YAAY,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI;AAAA,IAC7D,MAAM,EAAE;AAAA,EACV,EAAE;AACJ;AAEA,SAAS,UAAU,MAAsB;AACvC,SAAO,KAAK,KAAK,IAAI,KAAK,KAAK,EAAE,MAAM,KAAK,EAAE,SAAS;AACzD;AAEO,SAAS,wBAAwB,KAAqB,OAA2D;AACtH,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,UAAU,EAAE,WAAW,MAAM,WAAW;AAC9C,QAAM,SAAS,EAAE,cAAc,EAAE,aAAa,KAAM,QAAQ,CAAC,IAAI;AACjE,QAAM,QAAQ,UAAU,IAAI;AAE5B,QAAM,YAAY,OAAO,MAAM,GAAG,EAAE,EAAE,IAAI,OAAK;AAC7C,UAAM,MAAM,OAAO,SAAS,EAAE,UAAU,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,UAAU,CAAC,CAAC,IAAI;AAC3E,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,KAAK,SAAS,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,EACvD,CAAC,EAAE,KAAK,IAAI;AAEZ,QAAM,OAAO;AAAA,IACX,2BAA2B,WAAW,MAAM,OAAO,OAAO;AAAA,IAC1D,iBAAiB,MAAM,YAAS,KAAK;AAAA,IACrC;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,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB;AAAA,MACA,KAAK,UAAU,mCAAmC,OAAO,KAAK,MAAM,OAAO;AAAA,MAC3E,WAAW;AAAA,MACX,YAAY,OAAO;AAAA,MACnB,YAAY,OAAO,EAAE,eAAe,WAAW,EAAE,aAAa;AAAA,MAC9D,gBAAgB;AAAA,MAChB,QAAQ,2BAA2B,MAAM;AAAA,MACzC,gBAAgB;AAAA,QACd;AAAA,QACA,KAAK,MAAM,OAAO;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AACF;AAiBO,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,GAAG,WAAW,QAAG;AAAA,IACvJ,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,aAAc,oBAAoB,GAAG,UAAU,KAAK;AAAA,IACtD,GAAG,YAAY,GAAG,WAAY,oBAAoB,GAAG,YAAY,GAAG,QAAQ,OAAO;AAAA,IACnF,GAAG,cAAc,GAAG,eAAgB,mBAAmB,GAAG,cAAc,GAAG,YAAY,KAAK;AAAA,EAC/F,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,aAAa;AAEhD,QAAM,OAAO;AAAA,IACX,wBAAwB,UAAU;AAAA,IAClC,KAAK,EAAE,QAAQ,eAAY,EAAE,WAAW,gBAAa,EAAE,UAAU,eAAY,EAAE,UAAU;AAAA,IACzF;AAAA,EAAK,QAAQ;AAAA,IACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,gBAAgB,EAAE,kBAAkB;AAAA,MACpC,UAAU,EAAE,YAAY;AAAA,MACxB,aAAa,EAAE,eAAe;AAAA,MAC9B,YAAY,EAAE,cAAc;AAAA,MAC5B,YAAY,EAAE,cAAc;AAAA,MAC5B,KAAK,IAAI,IAAI,SAAO;AAAA,QAClB,WAAW,GAAG,aAAa;AAAA,QAC3B,QAAQ,GAAG,UAAU;AAAA,QACrB,cAAc,GAAG,gBAAgB;AAAA,QACjC,aAAa,GAAG,eAAe;AAAA,QAC/B,UAAU,GAAG,YAAY;AAAA,QACzB,KAAK,GAAG,OAAO;AAAA,QACf,WAAW,GAAG,aAAa,GAAG,WAAW;AAAA,QACzC,YAAY,GAAG,cAAc;AAAA,QAC7B,QAAQ,GAAG,UAAU;AAAA,QACrB,UAAU,GAAG,YAAY,GAAG,YAAY;AAAA,QACxC,UAAU,GAAG,YAAY,GAAG,YAAY;AAAA,QACxC,aAAa,GAAG,eAAe;AAAA,QAC/B,YAAY,OAAO,GAAG,eAAe,WACjC,GAAG,aACH,OAAO,GAAG,iBAAiB,WACzB,GAAG,eACH;AAAA,MACR,EAAE;AAAA,IACJ;AAAA,EACF;AACF;AAKO,SAAS,mBAAmB,KAAqB,OAAwC;AAC9F,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;AAKjB,QAAM,WAAW,EAAE,YAAY,CAAC;AAChC,QAAM,YAAY,SAAS,IAAI,QAAM;AACnC,UAAM,SAAS,KAAK,OAAO,KAAK,IAAI,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;AAC7D,WAAO,GAAG,MAAM,SAAS,GAAG,UAAU,WAAW,OAAO,GAAG,SAAS,QAAG,OAAO,GAAG,QAAQ,IAAI,QAAQ,QAAQ,GAAG,EAAE,KAAK,CAAC;AAAA,EAC1H,CAAC,EAAE,KAAK,IAAI;AACZ,QAAM,OAAO;AAAA,IACX,KAAK,EAAE,SAAS,eAAe;AAAA,IAC/B,OAAO,EAAE,UAAU,WAAW,WAAQ,EAAE,SAAS,QAAG,SAAM,SAAS,MAAM;AAAA,IACzE,EAAE,WAAW;AAAA,EAAK,EAAE,QAAQ,KAAK;AAAA,IACjC;AAAA;AAAA,EAAkB,aAAa,yBAAyB;AAAA,EAC1D,EAAE,KAAK,IAAI;AACX,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,WAAW,EAAE,aAAa,MAAM,OAAO;AAAA,MACvC,cAAc,EAAE,gBAAgB;AAAA,MAChC,OAAO,EAAE,SAAS;AAAA,MAClB,QAAQ,EAAE,UAAU;AAAA,MACpB,OAAO,EAAE,SAAS;AAAA,MAClB,UAAU,EAAE,YAAY;AAAA,MACxB,aAAa,SAAS;AAAA,MACtB,UAAU,SAAS,IAAI,SAAO,EAAE,QAAQ,GAAG,UAAU,MAAM,OAAO,GAAG,SAAS,MAAM,OAAO,OAAO,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,QAAQ,GAAG,EAAE;AAAA,IAC1I;AAAA,EACF;AACF;AAEO,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,KAAK,EAAE,YAAY,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,QAAG,QAAQ,EAAE,mBAAmB,EAAE,aAAa,QAAG;AAAA,EACjH,EAAE,KAAK,IAAI;AAEX,QAAM,OAAO;AAAA,IACX,kCAAkC,MAAM,KAAK;AAAA,IAC7C,KAAK,YAAY,MAAM;AAAA,IACvB;AAAA;AAAA;AAAA;AAAA,EAAiG,IAAI;AAAA,IACrG;AAAA;AAAA;AAAA;AAAA;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,OAAO,MAAM;AAAA,MACb,iBAAiB,YAAY;AAAA,MAC7B,aAAa,YAAY,IAAI,QAAM;AAAA,QACjC,MAAM,EAAE,YAAY,EAAE,QAAQ;AAAA,QAC9B,QAAQ,EAAE,UAAU;AAAA,QACpB,SAAS,EAAE,WAAW;AAAA,QACtB,SAAS,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU;AAAA,QACrD,WAAW,EAAE,mBAAmB,EAAE,aAAa;AAAA,QAC/C,iBAAiB,EAAE,mBAAmB;AAAA,MACxC,EAAE;AAAA,IACJ;AAAA,EACF;AACF;AA8EA,SAAS,sBAAsB,OAmB5B;AACD,QAAM,WAAW,MAAM,QAAQ,KAAK,IAAI,QAA+B,CAAC;AACxE,SAAO,SAAS,IAAI,CAAC,SAAS,WAAW;AAAA,IACvC,eAAe,QAAQ,iBAAiB,QAAQ,kBAAkB,QAAQ;AAAA,IAC1E,aAAa,QAAQ,eAAe,QAAQ,gBAAgB,SAAS;AAAA,IACrE,QAAQ,QAAQ,WAAW,OAAO,OAAO;AAAA,IACzC,SAAS,QAAQ,WAAW,QAAQ,UAAU;AAAA,IAC9C,WAAW,QAAQ,aAAa,QAAQ,cAAc;AAAA,IACtD,YAAY,QAAQ,cAAc,QAAQ,eAAe;AAAA,IACzD,aAAa,QAAQ,eAAe,QAAQ,gBAAgB;AAAA,IAC5D,OAAO,QAAQ,QAAQ,mBAAmB,QAAQ,KAAK,IAAI;AAAA,IAC3D,WAAW,QAAQ,aAAa,QAAQ,cAAc;AAAA,IACtD,uBAAuB,QAAQ,yBAAyB,QAAQ,2BAA2B;AAAA,IAC3F,eAAe,QAAQ,iBAAiB,QAAQ,mBAAmB;AAAA,IACnE,kBAAkB,QAAQ,oBAAoB,QAAQ,sBAAsB;AAAA,IAC5E,qBAAqB,QAAQ,uBAAuB,QAAQ,yBAAyB;AAAA,IACrF,gBAAgB,QAAQ,kBAAkB,QAAQ,oBAAoB;AAAA,IACtE,wBAAwB,QAAQ,0BAA0B,QAAQ,sBAAsB;AAAA,IACxF,YAAY,QAAQ,cAAc,QAAQ,eAAe;AAAA,IACzD,cAAc,QAAQ,gBAAgB,QAAQ,iBAAiB;AAAA,IAC/D,gBAAgB,QAAQ,kBAAkB,QAAQ,mBAAmB;AAAA,EACvE,EAAE;AACJ;AAEA,SAAS,sBAAsB,KAA0E;AACvG,SAAO,MAAM,QAAQ,KAAK,SAAS,IAAI,IAAI,YAA8C,CAAC;AAC5F;AAEA,SAAS,qBAAqB,WAAmD;AAC/E,MAAI,CAAC,UAAU,OAAQ,QAAO;AAC9B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,GAAG,UAAU,IAAI,cAAY;AAC3B,YAAM,OAAO,SAAS,cAAc,SAAS,QAAQ;AACrD,YAAM,QAAQ,SAAS,SAAS;AAChC,YAAM,OAAO,CAAC,OAAO,GAAG,IAAI,UAAU,IAAI,QAAQ,GAAG,KAAK,WAAW,EAAE,EAAE,OAAO,OAAO,EAAE,KAAK,KAAK;AACnG,aAAO,KAAK,KAAK,OAAO,SAAS,SAAS,SAAS,QAAQ,UAAU,CAAC,CAAC,MAAM,KAAK,OAAO,SAAS,QAAQ,SAAS,gBAAgB,MAAM,CAAC,CAAC,QAAQ,OAAO,SAAS,MAAM,EAAE,CAAC,QAAQ,KAAK,QAAQ,QAAG,CAAC;AAAA,IACvM,CAAC;AAAA,EACH,EAAE,KAAK,IAAI;AACb;AAEO,SAAS,mBAAmB,KAAqB,OAAqD;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,YAAY,MAAM,QAAQ,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,YAA8C,CAAC;AACpH,QAAM,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA,GAAG,UAAU,IAAI,cAAY,OAAO,OAAO,SAAS,MAAM,EAAE,CAAC,QAAQ,KAAK,OAAO,SAAS,SAAS,EAAE,CAAC,CAAC,MAAM,KAAK,OAAO,SAAS,eAAe,EAAE,CAAC,CAAC,IAAI;AAAA,EAC3J,EAAE,KAAK,IAAI;AACX,QAAM,UAAU,MAAM,mBAAmB,QAAQ,CAAC,IAAI;AACtD,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA,UAAU,SAAS;AAAA;AAAA,EAA4B,YAAY,KAAK;AAAA,IAChE,QAAQ,SAAS;AAAA;AAAA,EAA4B,oBAAoB,OAAO,CAAC,KAAK;AAAA,IAC9E,QAAQ,SAAS,mMAAmM;AAAA,EACtN,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAC3B,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,WAAW,UAAU,IAAI,eAAa;AAAA,QACpC,IAAI,OAAO,SAAS,MAAM,EAAE;AAAA,QAC5B,OAAO,OAAO,SAAS,SAAS,EAAE;AAAA,QAClC,aAAa,OAAO,SAAS,eAAe,EAAE;AAAA,MAChD,EAAE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,sBAAsB,OAAkE;AACtG,QAAM,cAAc,uBAAuB,MAAM,MAAM,MAAM,kBAAkB,CAAC;AAChF,QAAM,OAAO;AAAA,IACX;AAAA,IACA,aAAa,MAAM,IAAI;AAAA,IACvB;AAAA,IACA,oBAAoB,WAAW;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACX,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,MAAM,MAAM;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,kBAAkB,MAAyC;AAClE,QAAM,OAAO,KAAK;AAClB,QAAM,WAAW,KAAK;AACtB,QAAM,OAAO,KAAK,SAAS;AAC3B,QAAM,QAAkB,CAAC;AACzB,MAAI,MAAM;AACR,UAAM,QAAQ,OAAO,KAAK,SAAS,CAAC;AACpC,UAAM,aAAa,KAAK,cAAc,OAAO,OAAO,KAAK,UAAU,IAAI;AACvE,UAAM,YAAY,aAAa,GAAG,QAAQ,CAAC,IAAI,UAAU,KAAK,GAAG,QAAQ,CAAC;AAC1E,UAAM,KAAK;AAAA,UAAa,SAAS,KAAK,KAAK,SAAS,KAAK,MAAM,EAAE,EAAE;AACnE,UAAM,SAAS,KAAK;AACpB,QAAI,UAAU,OAAO,KAAK,MAAM,EAAE,QAAQ;AACxC,YAAM,KAAK,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,KAAK,OAAO,MAAM,WAAW,KAAK,UAAU,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,IAClI;AACA,UAAM,WAAW,MAAM,QAAQ,KAAK,QAAQ,IAAI,KAAK,WAAuB,CAAC;AAC7E,QAAI,SAAS,OAAQ,OAAM,KAAK;AAAA;AAAA,EAAoB,SAAS,IAAI,OAAK,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EAC9F;AACA,MAAI,MAAM;AACR,UAAM,KAAK,iCAAiC;AAAA,EAC9C,WAAW,YAAY,OAAO,aAAa,UAAU;AACnD,UAAM,KAAK;AAAA,mBAAsB,SAAS,MAAM,SAAS,KAAK,gEAA2D;AAAA,EAC3H;AACA,SAAO;AACT;AAEO,SAAS,kBAAkB,KAAqB,OAAgF;AACrI,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,MAAM,OAAO,KAAK;AACxB,QAAM,UAAU,OAAO,KAAK;AAC5B,QAAM,YAAY,sBAAsB,GAAG;AAC3C,QAAM,QAAQ,OAAO,KAAK,MAAM,EAAE;AAClC,QAAM,SAAS,OAAO,KAAK,UAAU,SAAS,UAAU,SAAS;AACjE,QAAM,OAAO;AAAA,IACX,mBAAmB,MAAM,UAAU;AAAA,IACnC,iBAAiB,SAAS,SAAS;AAAA,IACnC,eAAe,MAAM;AAAA,IACrB,SAAS,QAAQ,cAAc,QAAQ,KAAK,KAAK;AAAA,IACjD,GAAG,kBAAkB,OAAO,IAAI;AAAA,IAChC,SAAS,UAAU;AAAA;AAAA,EAAiB,QAAQ,OAAO,KAAK;AAAA,IACxD,UAAU,SAAS;AAAA;AAAA,EAAmB,qBAAqB,SAAS,CAAC,KAAK;AAAA,IAC1E,UAAU,SAAS,gIAAgI;AAAA,EACrJ,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAC3B,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,YAAY,MAAM;AAAA,MAClB,OAAO,MAAM,SAAS,CAAC;AAAA,MACvB;AAAA,MACA;AAAA,MACA,MAAM,OAAO,KAAK;AAAA,MAClB,UAAU,OAAO,KAAK,YAAY;AAAA,MAClC,MAAM,OAAO,KAAK,SAAS;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,mBAAmB,KAAqB,OAA0C;AAChG,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,MAAM,OAAO,KAAK;AACxB,QAAM,UAAU,OAAO,KAAK;AAC5B,QAAM,YAAY,sBAAsB,GAAG;AAC3C,QAAM,OAAO,OAAO,KAAK,SAAS;AAClC,QAAM,OAAO;AAAA,IACX;AAAA,IACA,iBAAiB,MAAM,KAAK;AAAA,IAC5B,eAAe,KAAK,WAAW,OAAO,SAAS,UAAU;AAAA,IACzD,GAAG,kBAAkB,OAAO,IAAI;AAAA,IAChC,QAAQ,SAAS,UAAU;AAAA;AAAA,EAAiB,QAAQ,OAAO,KAAK;AAAA,IAChE,UAAU,SAAS;AAAA;AAAA,EAAmB,qBAAqB,SAAS,CAAC,KAAK;AAAA,IAC1E,QAAQ,UAAU,SAAS,gIAAgI;AAAA,EAC7J,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAC3B,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,OAAO,MAAM;AAAA,MACb;AAAA,MACA,SAAS,WAAW;AAAA,MACpB,MAAM,OAAO,KAAK;AAAA,MAClB,UAAU,OAAO,KAAK,YAAY;AAAA,MAClC;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,qBAAqB,KAAqB,OAA0C;AAClG,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,MAAM,OAAO,KAAK;AACxB,QAAM,YAAY,sBAAsB,GAAG;AAC3C,QAAM,OAAO;AAAA,IACX;AAAA,IACA,iBAAiB,MAAM,KAAK;AAAA,IAC5B,iBAAiB,KAAK,eAAe,SAAS;AAAA,IAC9C,eAAe,KAAK,UAAU,SAAS;AAAA,IACvC,KAAK,gBAAgB;AAAA;AAAA,EAAe,IAAI,aAAa,KAAK;AAAA,IAC1D,UAAU,SAAS;AAAA;AAAA,EAAmB,qBAAqB,SAAS,CAAC,KAAK;AAAA,EAC5E,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAC3B,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,2BAA2B,KAAqB,OAAiF;AAC/I,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,OAAO,OAAO,OAAO,KAAK,SAAS,WAAW,OAAO,KAAK,OAAO;AACvE,QAAM,cAAc,OAAO,OAAO,KAAK,eAAe,YAAY;AAClE,QAAM,QAAQ,OAAO,OAAO,KAAK,SAAS,CAAC;AAC3C,QAAM,YAAY,OAAO,KAAK,cAAc;AAC5C,QAAM,OAAO;AAAA,IACX;AAAA,IACA,iBAAiB,MAAM,KAAK;AAAA,IAC5B,sBAAsB,MAAM,UAAU;AAAA,IACtC,qBAAqB,WAAW;AAAA,IAChC,cAAc,KAAK,GAAG,YAAY,kBAAkB,MAAM,YAAY,GAAM,MAAM,EAAE;AAAA,IACpF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACX,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,OAAO,MAAM;AAAA,MACb,YAAY,MAAM;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEO,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;AACjE,QAAM,iBAAiB,EAAE;AACzB,QAAM,aAAa,gBAAgB;AAEnC,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,qBAAqB,iBACvB;AAAA,IACE;AAAA;AAAA,IACA,sBAAsB,eAAe,iBAAiB,SAAS,wBAAwB,eAAe,kBAAkB,IAAI,KAAK,GAAG;AAAA,IACpI,oBAAoB,eAAe,uBAAuB,SAAS;AAAA,IACnE,+BAA+B,YAAY,eAAe,UAAU;AAAA,IACpE,8BAA8B,YAAY,oBAAoB,2EAA2E;AAAA,IACzI,oBAAoB,YAAY,eAAe,gCAAgC;AAAA,EACjF,EAAE,KAAK,IAAI,IACX;AAEJ,QAAM,OAAO;AAAA,IACX;AAAA,IACA,gBAAgB,WAAW,SAAS;AAAA,IACpC;AAAA,IACA;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,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,gBAAgB,OAAO,YAAY,WAAW,UAAU;AAAA,MACxD,aAAa,UACT,EAAE,OAAO,QAAQ,OAAO,SAAS,QAAQ,SAAS,MAAM,QAAQ,MAAM,OAAO,QAAQ,SAAS,KAAK,IACnG;AAAA,MACJ,OAAO,MAAM,IAAI,QAAM;AAAA,QACrB,KAAK,EAAE;AAAA,QACP,OAAO,EAAE;AAAA,QACT,SAAS,EAAE;AAAA,QACX,MAAM,EAAE;AAAA,QACR,OAAO,EAAE,SAAS;AAAA,MACpB,EAAE;AAAA,MACF,QAAQ,OAAO,IAAI,UAAQ;AAAA,QACzB,WAAW,OAAO,IAAI,cAAc,EAAE;AAAA,QACtC,WAAW,OAAO,IAAI,aAAa,EAAE;AAAA,QACrC,SAAS,IAAI,YAAY;AAAA,QACzB,aAAa,IAAI,eAAe;AAAA,MAClC,EAAE;AAAA,MACF,aAAa,kBAAkB,aAC3B;AAAA,QACE,mBAAmB,OAAO,eAAe,uBAAuB,CAAC;AAAA,QACjE,cAAc,OAAO,eAAe,iBAAiB,CAAC;AAAA,QACtD,iBAAiB,eAAe,qBAAqB;AAAA,QACrD,SAAS;AAAA,UACP,SAAS,OAAO,WAAW,WAAW,wBAAwB;AAAA,UAC9D,YAAY,OAAO,WAAW,eAAe,UAAU;AAAA,UACvD,eAAe,OAAO,WAAW,mBAAmB,CAAC;AAAA,UACrD,UAAU,OAAO,WAAW,YAAY,KAAK;AAAA,UAC7C,UAAU,OAAO,WAAW,YAAY,OAAO;AAAA,UAC/C,YAAY,OAAO,WAAW,eAAe,gCAAgC;AAAA,UAC7E,iBAAiB,OAAO,WAAW,oBAAoB,2EAA2E;AAAA,UAClI,8BAA8B,OAAO,WAAW,qCAAqC,gHAAgH;AAAA,QACvM;AAAA,MACF,IACA;AAAA,IACN;AAAA,EACF;AACF;AAEO,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;AACjB,QAAM,UAAW,EAAE,WAAoC,CAAC;AACxD,QAAM,oBAAoB,QAAQ,IAAI,aAAW;AAAA,IAC/C,GAAG;AAAA,IACH,OAAO,OAAO,SAAS;AAAA,IACvB,aAAa,OAAO,eAAe;AAAA,EACrC,EAAE;AACF,QAAM,cAAe,EAAE,eAAsC,CAAC,MAAM,OAAO,MAAM,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AACnH,QAAM,eAAgB,EAAE,uBAA8C,MAAM,cAAc;AAC1F,QAAM,aAAa,EAAE;AACrB,QAAM,WAAW,sBAAsB,EAAE,QAAQ;AACjD,QAAM,cAAc,SAAS,GAAG,EAAE;AAElC,QAAM,OAAO,QAAQ,IAAI,CAAC,MAAM;AAC9B,UAAM,SAAS,CAAC,EAAE,QAAQ,EAAE,cAAc,IAAI,EAAE,WAAW,MAAM,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAC/F,WAAO,KAAK,EAAE,QAAQ,MAAM,KAAK,EAAE,IAAI,CAAC,MAAM,KAAK,EAAE,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,aAAa,KAAK,EAAE,UAAU,OAAO,QAAG,MAAM,EAAE,aAAa,UAAU,EAAE,UAAU,MAAM,QAAG,aAAa,EAAE,QAAQ;AAAA,EAClO,CAAC,EAAE,KAAK,IAAI;AAEZ,QAAM,kBAAkB,QAAQ,SAC5B;AAAA;AAAA,EAA4B,QAAQ,IAAI,OAAK;AAC7C,UAAM,OAAO,EAAE,UAAU,SAAS,EAAE,SAAS,MAAM,GAAG,CAAC,EAAE,IAAI,OAAK,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI,IAAI;AAC3F,WAAO,OAAO,EAAE,QAAQ,KAAK,EAAE,IAAI;AAAA,EAAK,IAAI;AAAA,EAC9C,CAAC,EAAE,KAAK,MAAM,CAAC,KACb;AAEJ,QAAM,OAAO;AAAA,IACX,0BAA0B,WAAW;AAAA,IACrC,iBAAiB,QAAQ,MAAM,qBAAqB,QAAQ,WAAW,IAAI,KAAK,GAAG,4BAAyB,YAAY;AAAA,IACxH,SAAS,SAAS,iBAAiB,SAAS,MAAM,IAAI,aAAa,eAAe,SAAS,MAAM,oBAAiB,aAAa,aAAa,SAAS,GAAG,aAAa,wBAAwB,IAAI,YAAY,qBAAqB,KAAK,EAAE,uBAAoB,CAAC,aAAa,cAAc,aAAa,cAAc,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,KAAK,SAAS,KAAK;AAAA,IAClW;AAAA;AAAA;AAAA;AAAA,EAAuJ,IAAI;AAAA,IAC3J;AAAA,IACA;AAAA;AAAA;AAAA,IACA,cAAc,OAAO;AAAA,iBAAoB,aAAa,KAAM,QAAQ,CAAC,CAAC,OAAO;AAAA,EAC/E,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,OAAO,EAAE;AAAA,MACT,UAAU,EAAE,YAAY;AAAA,MACxB,aAAa,EAAE;AAAA,MACf,WAAW,EAAE;AAAA,MACb,aAAa,EAAE;AAAA,MACf,qBAAqB;AAAA,MACrB,aAAa,QAAQ;AAAA,MACrB,SAAS;AAAA,MACT;AAAA,MACA,YAAY,cAAc;AAAA,IAC5B;AAAA,EACF;AACF;AAEO,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;AACjB,QAAM,UAAW,EAAE,UAAsC,CAAC,GAAG,IAAI,WAAS;AAAA,IACxE,GAAG;AAAA,IACH,UAAU,sBAAsB,KAAK,QAAQ;AAAA,IAC7C,SAAS,KAAK,QAAQ,IAAI,aAAW;AAAA,MACnC,GAAG;AAAA,MACH,OAAO,OAAO,SAAS;AAAA,MACvB,aAAa,OAAO,eAAe;AAAA,IACrC,EAAE;AAAA,EACJ,EAAE;AACF,QAAM,WAAY,EAAE,YAAqC,CAAC;AAC1D,QAAM,UAAW,EAAE,WAAyC;AAC5D,QAAM,mBAAoB,EAAE,oBAA2C,OAAO,OAAO,CAAC,KAAK,SAAS,MAAM,KAAK,aAAa,CAAC;AAC7H,QAAM,aAAa,EAAE;AAErB,QAAM,aAAa,OAAO,IAAI,CAAC,SAAS;AACtC,UAAM,OAAO,KAAK,MAAM,SAAS,KAAK,KAAK,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,SAAS,CAAC,KAAK,MAAM;AAC/H,WAAO,KAAK,KAAK,KAAK,IAAI,CAAC,MAAM,KAAK,WAAW,eAAe,CAAC,MAAM,KAAK,MAAM,UAAU,CAAC,MAAM,KAAK,WAAW,MAAM,KAAK,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,EACtJ,CAAC,EAAE,KAAK,IAAI;AAEZ,QAAM,eAAe,OAClB,QAAQ,UAAQ,KAAK,QAAQ,MAAM,GAAG,CAAC,EAAE,IAAI,aAAW,EAAE,MAAM,OAAO,EAAE,CAAC,EAC1E,IAAI,CAAC,EAAE,MAAM,OAAO,MAAM;AACzB,UAAM,SAAS,CAAC,OAAO,QAAQ,OAAO,cAAc,IAAI,OAAO,WAAW,MAAM,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAC9G,WAAO,KAAK,KAAK,KAAK,IAAI,CAAC,MAAM,OAAO,QAAQ,MAAM,KAAK,OAAO,IAAI,CAAC,MAAM,KAAK,OAAO,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,OAAO,aAAa,UAAU,OAAO,UAAU,MAAM,QAAG,aAAa,OAAO,QAAQ;AAAA,EAChN,CAAC,EAAE,KAAK,IAAI;AAEd,QAAM,cAAc,SAAS,SAAS;AAAA;AAAA,EAAkB,SAAS,IAAI,OAAK,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,KAAK;AACnG,QAAM,UAAU,UAAU;AAAA,aAAgB,OAAO,OAAO;AACxD,QAAM,OAAO;AAAA,IACX,yBAAyB,MAAM,KAAK;AAAA,IACpC,gBAAgB,OAAO,MAAM,2BAAwB,gBAAgB,oBAAiB,EAAE,SAAS,MAAM,SAAS,IAAI,mCAAgC,EAAE,iBAAiB,MAAM,iBAAiB,GAAM;AAAA,IACpM;AAAA,IACA;AAAA;AAAA;AAAA;AAAA,EAAkH,UAAU;AAAA,IAC5H,eAAe;AAAA;AAAA;AAAA;AAAA,EAA0H,YAAY,KAAK;AAAA,IAC1J;AAAA,IACA;AAAA;AAAA,gBAA+B,EAAE,mBAAmB,qCAAqC;AAAA,gBAAmB,EAAE,oBAAoB,gBAAgB;AAAA,IAClJ,cAAc,OAAO;AAAA,iBAAoB,aAAa,KAAM,QAAQ,CAAC,CAAC,OAAO;AAAA,EAC/E,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,OAAO,EAAE;AAAA,MACT,OAAO,EAAE;AAAA,MACT,eAAe,EAAE;AAAA,MACjB,gBAAgB,EAAE;AAAA,MAClB,mBAAmB,EAAE;AAAA,MACrB,aAAa,EAAE;AAAA,MACf,iBAAiB,EAAE;AAAA,MACnB,kBAAkB,EAAE,oBAAoB;AAAA,MACxC;AAAA,MACA,aAAa,EAAE;AAAA,MACf,mBAAmB,EAAE;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,cAAc;AAAA,IAC5B;AAAA,EACF;AACF;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,YAAiB,EAAE,mBAA4C,CAAC;AACtE,QAAM,SAAiB,EAAE,gBAAuC,CAAC;AACjE,QAAM,QAAiB,EAAE,mBAAwC,CAAC;AAClE,QAAM,UAAiB,EAAE,WAAuC,CAAC;AACjE,QAAM,gBAAiB,EAAE,iBAAgD;AAEzE,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,kBAAkB,MAAM;AAC5B,QAAI,kBAAkB,gBAAiB,QAAO;AAC9C,QAAI,kBAAkB,cAAe,QAAO;AAC5C,QAAI,kBAAkB,aAAc,QAAO;AAC3C,QAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,WAAO;AAAA,cAAiB,QAAQ,MAAM;AAAA,EAAM,QAAQ,IAAI,CAAC,GAAG,MAAM;AAChE,YAAM,SAAS,SAAS,EAAE,SAAS,GAAG;AACtC,YAAM,QAAS,SAAI,OAAO,MAAM,IAAI,SAAI,OAAO,IAAI,MAAM;AACzD,aAAO,OAAO,IAAI,CAAC,KAAK,EAAE,UAAU,WAAW,WAAM,KAAK;AAAA,GAAM,EAAE,QAAQ,EAAE;AAAA;AAAA,EAAQ,EAAE,QAAQ,EAAE;AAAA,IAClG,CAAC,EAAE,KAAK,MAAM,CAAC;AAAA,EACjB,GAAG;AAEH,QAAM,OAAO;AAAA,IACX,KAAK,IAAI;AAAA,IACT,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,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB;AAAA,MACA,QAAQ,UAAU;AAAA,MAClB,aAAa,eAAe;AAAA,MAC5B,UAAU,YAAY;AAAA,MACtB,SAAS,WAAW;AAAA,MACpB,OAAO,SAAS;AAAA,MAChB,SAAS,WAAW;AAAA,MACpB,cAAc,gBAAgB;AAAA,MAC9B,YAAY,cAAc;AAAA,MAC1B,OAAO,SAAS;AAAA,MAChB,YAAY,cAAc;AAAA,MAC1B,QAAQ,UAAU;AAAA,MAClB,KAAK,OAAO;AAAA,MACZ,KAAK,OAAO;AAAA,MACZ;AAAA,MACA,kBAAkB,QAAQ;AAAA,MAC1B,cAAc,OAAO,IAAI,QAAM,EAAE,OAAO,OAAO,EAAE,SAAS,EAAE,GAAG,OAAO,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE;AAAA,IAChG;AAAA,EACF;AACF;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;AACjE,QAAM,QAAQ,UAAU,IAAI;AAE5B,QAAM,YAAY,OAAO,MAAM,GAAG,EAAE,EAAE,IAAI,OAAK;AAC7C,UAAM,MAAM,OAAO,SAAS,EAAE,UAAU,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,UAAU,CAAC,CAAC,IAAI;AAC3E,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,KAAK,SAAS,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,EACvD,CAAC,EAAE,KAAK,IAAI;AAEZ,QAAM,OAAO;AAAA,IACX;AAAA,IACA,iBAAiB,MAAM,YAAS,KAAK;AAAA,IACrC;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,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,UAAU,MAAM;AAAA,MAChB,WAAW;AAAA,MACX,YAAY,OAAO;AAAA,MACnB,YAAY,OAAO,EAAE,eAAe,WAAW,EAAE,aAAa;AAAA,MAC9D,gBAAgB;AAAA,MAChB,QAAQ,2BAA2B,MAAM;AAAA,MACzC,gBAAgB;AAAA,QACd,UAAU,MAAM;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AACF;AAaO,SAAS,8BAA8B,KAAqB,OAA0D;AAC3H,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,OAAO,EAAE,QAAQ;AACvB,QAAM,SAAS,EAAE,UAAU,CAAC;AAC5B,QAAMC,aAAY,KAAK,KAAK,IAAI,KAAK,KAAK,EAAE,MAAM,KAAK,EAAE,SAAS;AAClE,QAAM,SAAS,EAAE,cAAc,EAAE,aAAa,KAAM,QAAQ,CAAC,IAAI;AACjE,QAAM,gBAAgB,OAAO,EAAE,qBAAqB,WAAW,GAAG,KAAK,MAAM,EAAE,gBAAgB,CAAC,MAAM;AACtG,QAAM,QAAQ,EAAE,UAAU,4BAA4B,EAAE,OAAO,OAAO;AAEtE,QAAM,YAAY,OAAO,MAAM,GAAG,EAAE,EAAE,IAAI,OAAK;AAC7C,UAAM,MAAM,OAAO,SAAS,EAAE,UAAU,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,UAAU,CAAC,CAAC,IAAI;AAC3E,UAAM,KAAK,OAAO,KAAK,MAAM,MAAM,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;AACvD,UAAM,KAAK,OAAO,MAAM,EAAE,EAAE,SAAS,GAAG,GAAG;AAC3C,WAAO,KAAK,EAAE,IAAI,EAAE,MAAM,KAAK,SAAS,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,EACvD,CAAC,EAAE,KAAK,IAAI;AAEZ,QAAM,OAAO;AAAA,IACX,KAAK,KAAK;AAAA,IACV,EAAE,YAAY,cAAc,EAAE,SAAS,KAAK;AAAA,IAC5C,uBAAuB,aAAa,6BAA0B,MAAM,YAASA,UAAS;AAAA,IACtF,EAAE,UAAU,iBAAiB,EAAE,OAAO,KAAK,iBAAiB,MAAM,GAAG;AAAA,IACrE,EAAE,WAAW,wBAAwB,EAAE,QAAQ,OAAO;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,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,WAAW,EAAE,aAAa,MAAM;AAAA,MAChC,SAAS,EAAE,WAAW,MAAM;AAAA,MAC5B,SAAS,EAAE,WAAW;AAAA,MACtB,WAAW,EAAE,aAAa;AAAA,MAC1B,iBAAiB,EAAE,mBAAmB,MAAM,WAAW;AAAA,MACvD,SAAS,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU;AAAA,MACrD,kBAAkB,OAAO,EAAE,qBAAqB,WAAW,EAAE,mBAAmB;AAAA,MAChF,UAAU,EAAE,YAAY;AAAA,MACxB,WAAAA;AAAA,MACA,YAAY,OAAO;AAAA,MACnB,gBAAgB;AAAA,MAChB,QAAQ,OAAO,IAAI,QAAM;AAAA,QACvB,UAAU,OAAO,SAAS,EAAE,UAAU,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI;AAAA,QAC7D,QAAQ,OAAO,SAAS,EAAE,UAAU,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI;AAAA,QAC3D,MAAM,EAAE;AAAA,MACV,EAAE;AAAA,IACJ;AAAA,EACF;AACF;AA0DA,SAAS,2BAA2B,KAA0C;AAC5E,QAAM,UAAU,OAAO,OAAO,QAAQ,WAAW,MAAiC,CAAC;AACnF,SAAO;AAAA,IACL,MAAM;AAAA,IACN,eAAe;AAAA,IACf,aAAa,OAAO,QAAQ,gBAAgB,WAAW,QAAQ,cAAc;AAAA,IAC7E,eAAe;AAAA,IACf,sBAAsB;AAAA,IACtB,0BAA0B;AAAA,EAC5B;AACF;AAEA,SAAS,8BAA8B,KAAc,OAAsI;AACzL,QAAM,aAAa,OAAO,OAAO,QAAQ,WAAW,MAAiC,CAAC;AACtF,QAAM,SAAS,MAAM,QAAQ,WAAW,MAAM,IAAI,WAAW,SAAS,CAAC;AACvE,QAAM,gBAAiB,OAAO,WAAW,kBAAkB,YACtD,CAAC,aAAa,uBAAuB,kBAAkB,eAAe,YAAY,EAAE,SAAS,WAAW,aAAa,IACtH,WAAW,gBACX;AACJ,SAAO;AAAA,IACL,UAAU,OAAO,WAAW,aAAa,WAAW,WAAW,WAAW,OAAO,MAAM,YAAY,EAAE;AAAA,IACrG,YAAY,OAAO,WAAW,eAAe,WAAW,WAAW,aAAa,OAAO,MAAM,cAAc,EAAE;AAAA,IAC7G,kBAAkB,OAAO,WAAW,qBAAqB,WAAW,WAAW,mBAAmB;AAAA,IAClG,eAAe,OAAO,WAAW,kBAAkB,WAAW,WAAW,gBAAgB;AAAA,IACzF,mBAAmB,OAAO,WAAW,sBAAsB,WAAW,WAAW,oBAAoB,OAAO,MAAM,qBAAqB,CAAC;AAAA,IACxI,eAAe,OAAO,WAAW,kBAAkB,WAAW,WAAW,gBAAgB,OAAO,MAAM,iBAAiB,IAAI;AAAA,IAC3H,iBAAiB,WAAW,oBAAoB;AAAA,IAChD,0BAA0B,WAAW,6BAA6B;AAAA,IAClE,mBAAmB,OAAO,WAAW,sBAAsB,WAAW,WAAW,oBAAoB;AAAA,IACrG;AAAA,IACA,QAAQ,OAAO,IAAI,CAAC,UAAU;AAC5B,YAAM,MAAM,SAAS,OAAO,UAAU,WAAW,QAAmC,CAAC;AACrF,aAAO;AAAA,QACL,OAAO,OAAO,IAAI,SAAS,EAAE;AAAA,QAC7B,WAAW,OAAO,IAAI,cAAc,WAAW,IAAI,YAAY;AAAA,QAC/D,YAAY,OAAO,IAAI,eAAe,WAAW,IAAI,aAAa;AAAA,QAClE,SAAS,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU;AAAA,QACzD,cAAc,OAAO,IAAI,iBAAiB,WAAW,IAAI,eAAe;AAAA,MAC1E;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEO,SAAS,8BACd,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;AACjB,QAAM,QAAS,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,QAAQ,CAAC;AACnD,QAAM,aAAa,EAAE;AACrB,QAAM,cAAc,MAAM,QAAQ,EAAE,WAAW,IAAI,EAAE,YAAY,IAAI,MAAM,IAAI,CAAC;AAChF,QAAM,UAAU,2BAA2B,EAAE,OAAO;AACpD,QAAM,aAAa,8BAA8B,EAAE,YAAY,KAAK;AACpE,QAAM,WAAW,MAAM,MAAM,GAAG,GAAG,EAAE;AAAA,IAAI,CAAC,MAAM,MAC9C,KAAK,IAAI,CAAC,MAAM,KAAK,IAAI,QAAQ,KAAK,SAAS,QAAQ,KAAK,GAAG,MAAM,KAAK,KAAK,kBAAkB,EAAE,CAAC;AAAA,EACtG,EAAE,KAAK,IAAI;AACX,QAAM,eAAe,QAAQ,cAAc,0BAA0B,QAAQ,WAAW,KAAK;AAE7F,QAAM,OAAO;AAAA,IACX,gCAAgC,EAAE,UAAU,MAAM,UAAU,MAAM,OAAO,SAAS;AAAA,IAClF,kBAAkB,MAAM,MAAM,qBAAkB,YAAY,QAAQ,CAAC,eAAY,YAAY,QAAQ,CAAC,YAAS,YAAY,MAAM,CAAC;AAAA,IAClI,gBAAgB,YAAY;AAAA,IAC5B,mBAAmB,WAAW,gBAAgB,0BAAuB,WAAW,aAAa;AAAA,IAC7F,EAAE,wBAAwB,sBAAsB,EAAE,qBAAqB,KAAK;AAAA,IAC5E,EAAE,oBAAoB,kBAAkB,EAAE,iBAAiB,KAAK;AAAA,IAChE;AAAA;AAAA;AAAA;AAAA,EAAiH,YAAY,gDAAuB;AAAA,IACpJ,YAAY,SAAS;AAAA;AAAA,EAAgB,YAAY,IAAI,OAAK,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,KAAK;AAAA,IACnF;AAAA;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,QAAQ,OAAO,EAAE,UAAU,MAAM,UAAU,EAAE;AAAA,MAC7C,YAAY,OAAO,EAAE,cAAc,MAAM,OAAO,EAAE;AAAA,MAClD,SAAS,OAAO,EAAE,WAAW,EAAE,cAAc,MAAM,OAAO,EAAE;AAAA,MAC5D;AAAA,MACA,aAAa,OAAO,EAAE,gBAAgB,WAAW,EAAE,cAAc;AAAA,MACjE,mBAAmB,OAAO,EAAE,sBAAsB,WAAW,EAAE,oBAAoB;AAAA,MACnF,uBAAuB,OAAO,EAAE,0BAA0B,WAAW,EAAE,wBAAwB;AAAA,MAC/F,mBAAmB,OAAO,EAAE,sBAAsB,WAAW,EAAE,oBAAoB;AAAA,MACnF,oBAAoB,OAAO,EAAE,uBAAuB,WAAW,EAAE,qBAAqB;AAAA,MACtF,uBAAuB,MAAM;AAAA,MAC7B,YAAY;AAAA,QACV,MAAM,OAAO,YAAY,QAAQ,CAAC;AAAA,QAClC,MAAM,OAAO,YAAY,QAAQ,CAAC;AAAA,QAClC,IAAI,OAAO,YAAY,MAAM,CAAC;AAAA,MAChC;AAAA,MACA;AAAA,MACA,SAAS,EAAE,YAAY;AAAA,MACvB;AAAA,MACA,OAAO,MAAM,IAAI,WAAS;AAAA,QACxB,KAAK,OAAO,KAAK,OAAO,EAAE;AAAA,QAC1B,MAAM,KAAK;AAAA,QACX,WAAW,OAAO,KAAK,aAAa,EAAE;AAAA,QACtC,YAAY,KAAK,cAAc;AAAA,QAC/B,gBAAgB,OAAO,KAAK,kBAAkB,EAAE;AAAA,MAClD,EAAE;AAAA,IACJ;AAAA,EACF;AACF;AAEA,SAAS,yBAAyB,OAA+E;AAC/G,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO;AAAA,IACL,KAAK,OAAO,MAAM,OAAO,EAAE;AAAA,IAC3B,YAAY,MAAM,cAAc;AAAA,IAChC,SAAS,OAAO,MAAM,YAAY,WAAW,MAAM,UAAU;AAAA,IAC7D,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc;AAAA,IACzE,YAAY,MAAM,cAAc;AAAA,IAChC,OAAO,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAAA,IACvD,QAAQ,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS;AAAA,EAC5D;AACF;AAEO,SAAS,6BACd,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;AACjB,QAAM,SAAU,MAAM,QAAQ,EAAE,MAAM,IAAI,EAAE,SAAS,CAAC;AACtD,QAAM,YAAa,MAAM,QAAQ,EAAE,SAAS,IAAI,EAAE,YAAY,CAAC;AAC/D,QAAM,WAAW,MAAM,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,IAAI,MAAM,IAAI,CAAC;AACvE,QAAM,cAAc,MAAM,QAAQ,EAAE,WAAW,IAAI,EAAE,YAAY,IAAI,MAAM,IAAI,CAAC;AAChF,QAAM,aAAa,EAAE;AACrB,QAAM,iBAAiB,YAAY,QAAQ;AAC3C,QAAM,SAAS,YAAY,UAAU,CAAC;AACtC,QAAM,UAAU,2BAA2B,EAAE,OAAO;AACpD,QAAM,eAAe,QAAQ,cAAc,0BAA0B,QAAQ,WAAW,KAAK;AAE7F,QAAM,eAAe,UAAU,IAAI,CAAC,UAAU,MAAM;AAClD,UAAM,SAAS,SAAS,QAAQ,UAAU,KAAK,SAAS,KAAK,CAAC,KAAK,GAAG,SAAS,aAAa,CAAC;AAC7F,WAAO,KAAK,IAAI,CAAC,MAAM,SAAS,IAAI,MAAM,SAAS,YAAY,KAAK,SAAS,SAAS,OAAO,QAAG,MAAM,MAAM;AAAA,EAC9G,CAAC,EAAE,KAAK,IAAI;AACZ,QAAM,YAAY,OAAO,MAAM,GAAG,EAAE,EAAE;AAAA,IAAI,CAAC,OAAO,MAChD,KAAK,IAAI,CAAC,MAAM,MAAM,UAAU,MAAM,MAAM,WAAW,QAAG,MAAM,MAAM,eAAe,QAAG,MAAM,KAAK,MAAM,cAAc,EAAE,CAAC;AAAA,EAC5H,EAAE,KAAK,IAAI;AAEX,QAAM,OAAO;AAAA,IACX;AAAA,IACA,YAAY,EAAE,WAAW,MAAM,GAAG;AAAA,IAClC,gBAAgB,YAAY;AAAA,IAC5B,EAAE,YAAY,cAAc,EAAE,SAAS,KAAK;AAAA,IAC5C,EAAE,YAAY,oBAAoB,EAAE,SAAS,OAAO;AAAA,IACpD,EAAE,UAAU;AAAA;AAAA,EAAiB,SAAS,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC,KAAK;AAAA,IACnE,EAAE,WAAW;AAAA;AAAA,EAAe,EAAE,QAAQ,KAAK;AAAA,IAC3C,OAAO,SAAS;AAAA;AAAA;AAAA;AAAA,EAAwG,SAAS,KAAK;AAAA,IACtI,UAAU,SAAS;AAAA;AAAA;AAAA;AAAA,EAA+E,YAAY,KAAK;AAAA,IACnH,EAAE,YAAY;AAAA,0BAA6B,EAAE,SAAS,OAAO;AAAA,IAC7D,aAAa;AAAA;AAAA,IAAsB,UAAU,cAAc,CAAC,iBAAc,OAAO,MAAM;AAAA;AAAA,EAAc,cAAc,KAAK;AAAA,IACxH,SAAS,SAAS;AAAA;AAAA,EAAkB,SAAS,IAAI,OAAK,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,KAAK;AAAA,IAC/E,YAAY,SAAS;AAAA;AAAA,EAAgB,YAAY,IAAI,OAAK,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,KAAK;AAAA,IACnF;AAAA;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO;AAAA,IACL,GAAG,SAAS,IAAI;AAAA,IAChB,mBAAmB;AAAA,MACjB,WAAW,OAAO,EAAE,aAAa,MAAM,GAAG;AAAA,MAC1C,SAAS,OAAO,EAAE,WAAW,MAAM,GAAG;AAAA,MACtC;AAAA,MACA,MAAM,EAAE,SAAS,UAAU,EAAE,SAAS,UAAU,EAAE,SAAS,OAAO,EAAE,OAAO;AAAA,MAC3E,WAAW,OAAO,EAAE,cAAc,WAAW,EAAE,YAAY;AAAA,MAC3D,WAAW,OAAO,EAAE,cAAc,WAAW,EAAE,YAAY;AAAA,MAC3D,SAAS,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU;AAAA,MACrD,UAAU,OAAO,EAAE,aAAa,WAAW,EAAE,WAAW;AAAA,MACxD,YAAY,OAAO;AAAA,MACnB,oBAAoB,yBAAyB,EAAE,kBAA4D;AAAA,MAC3G,oBAAoB,yBAAyB,EAAE,kBAA4D;AAAA,MAC3G,WAAW,UAAU,IAAI,eAAa;AAAA,QACpC,MAAM,SAAS;AAAA,QACf,KAAK,SAAS,OAAO;AAAA,QACrB,WAAW,SAAS,aAAa;AAAA,QACjC,WAAW,OAAO,SAAS,cAAc,WAAW,SAAS,YAAY;AAAA,QACzE,UAAU,SAAS,YAAY;AAAA,QAC/B,OAAO,SAAS,SAAS;AAAA,MAC3B,EAAE;AAAA,MACF,WAAW,OAAO,EAAE,cAAc,WAAW,EAAE,YAAY;AAAA,MAC3D;AAAA,MACA;AAAA,MACA,YAAY,aAAa;AAAA,QACvB,WAAW,UAAU,cAAc;AAAA,QACnC,YAAY,OAAO;AAAA,QACnB,YAAY,OAAO,WAAW,eAAe,WAAW,WAAW,aAAa;AAAA,QAChF;AAAA,QACA,QAAQ,2BAA2B,MAAM;AAAA,MAC3C,IAAI;AAAA,IACN;AAAA,EACF;AACF;;;AM9iEO,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoEjC,KAAK;;;ACpEP,IAAAC,cAAkB;;;ACAlB,IAAAC,cAAkB;AAEX,IAAM,qBAAqB;AAC3B,IAAM,0BAA0B;AAEhC,IAAM,uBAAuB,cAAE,OAAO;AAAA,EAC3C,OAAc,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC9B,UAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EAClC,IAAc,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EAC/C,IAAc,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EAC/C,QAAc,cAAE,KAAK,CAAC,WAAW,QAAQ,CAAC,EAAE,QAAQ,SAAS;AAAA,EAC7D,WAAc,cAAE,KAAK,CAAC,YAAY,cAAc,MAAM,CAAC,EAAE,QAAQ,kBAAkB;AAAA,EACnF,UAAc,cAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS;AAAA,EACnD,OAAc,cAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EACvC,OAAc,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC;AAAA,EACvD,cAAc,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAI,EAAE,QAAQ,GAAG;AAAA,EAC3D,UAAc,cAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EACvC,YAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EAClC,OAAc,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACxC,cAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EAClC,eAAe,cAAE,OAAO,EAAE,SAAS;AAAA,EACnC,uBAAuB,cAAE,QAAQ,EAAE,SAAS;AAAA,EAC5C,WAAc,cAAE,OAAO,EAAE,QAAQ,cAAc;AAAA,EAC/C,QAAc,cAAE,KAAK,CAAC,QAAQ,OAAO,MAAM,CAAC,EAAE,QAAQ,MAAM;AAAA,EAC5D,UAAc,cAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EACvC,OAAc,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;AAAA,EACtD,gBAAgB,cAAE,OAAO,EAAE,SAAS;AACtC,CAAC;AAEM,IAAM,yBAAyB,cAAE,OAAO;AAAA,EAC7C,cAAe,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC/B,UAAe,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC/B,IAAe,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EAChD,IAAe,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EAChD,gBAAgB,cAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EACzC,YAAe,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAAA,EAC1D,cAAe,cAAE,OAAO,EAAE,SAAS;AAAA,EACnC,eAAe,cAAE,OAAO,EAAE,SAAS;AAAA,EACnC,UAAe,cAAE,QAAQ,EAAE,QAAQ,IAAI;AACzC,CAAC;AAEM,IAAM,0BAA0B,cAAE,OAAO;AAAA,EAC9C,OAAe,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC/B,UAAe,cAAE,OAAO,EAAE,SAAS;AAAA,EACnC,IAAe,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EAChD,IAAe,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EAChD,YAAe,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE;AAAA,EACzD,WAAe,cAAE,KAAK,CAAC,YAAY,cAAc,MAAM,CAAC,EAAE,QAAQ,uBAAuB;AAAA,EACzF,UAAe,cAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS;AAAA,EACpD,OAAe,cAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EACxC,cAAe,cAAE,OAAO,EAAE,SAAS;AAAA,EACnC,eAAe,cAAE,OAAO,EAAE,SAAS;AAAA,EACnC,uBAAuB,cAAE,QAAQ,EAAE,SAAS;AAAA,EAC5C,UAAe,cAAE,QAAQ,EAAE,QAAQ,IAAI;AACzC,CAAC;AAEM,IAAM,mBAAmB,cAAE,OAAO;AAAA,EACvC,UAAa,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC7B,QAAa,cAAE,OAAO,EAAE,SAAS;AAAA,EACjC,aAAa,cAAE,OAAO,EAAE,SAAS;AAAA,EACjC,YAAa,cAAE,OAAO,EAAE,SAAS;AAAA,EACjC,YAAa,cAAE,OAAO,EAAE,SAAS;AACnC,CAAC;AAEM,IAAM,wBAAwB,cAAE,OAAO;AAAA,EAC5C,MAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EAClC,QAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EAClC,aAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EAClC,UAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EAClC,SAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EAClC,cAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EAClC,OAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EAClC,cAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EAClC,SAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EAClC,UAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EAClC,YAAc,cAAE,OAAO,EAAE,SAAS;AACpC,CAAC;AAEM,IAAM,wBAAwB,cAAE,OAAO;AAAA,EAC5C,KAAO,cAAE,OAAO;AAAA,EAChB,OAAO,cAAE,OAAO;AAClB,CAAC;AAEM,IAAM,2BAA2B,cAAE,OAAO;AAAA,EAC/C,iBAAiB,cAAE,MAAM,cAAE,OAAO;AAAA,IAChC,OAAO,cAAE,OAAO;AAAA,IAChB,OAAO,cAAE,OAAO;AAAA,EAClB,CAAC,CAAC;AAAA,EACF,cAAc,cAAE,MAAM,cAAE,OAAO;AAAA,IAC7B,OAAO,cAAE,OAAO;AAAA,IAChB,OAAO,cAAE,OAAO;AAAA,EAClB,CAAC,CAAC;AACJ,CAAC;AAEM,IAAM,0BAA0B,cAAE,OAAO;AAAA,EAC9C,UAAe,cAAE,OAAO;AAAA,EACxB,QAAe,cAAE,OAAO,EAAE,SAAS;AAAA,EACnC,OAAe,cAAE,OAAO,EAAE,SAAS;AAAA,EACnC,MAAe,cAAE,OAAO,EAAE,SAAS;AAAA,EACnC,MAAe,cAAE,OAAO,EAAE,SAAS;AAAA,EACnC,eAAe,cAAE,OAAO,EAAE,SAAS;AACrC,CAAC;AAEM,IAAM,8BAA8B,cAAE,OAAO;AAAA,EAClD,SAAW,cAAE,OAAO;AAAA,EACpB,WAAW,cAAE,OAAO;AACtB,CAAC;;;ADvGM,IAAM,wBAAwB;AAAA,EACnC,OAAc,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,oMAAoM;AAAA,EAC7O,UAAc,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kJAAkJ;AAAA,EAC/L,cAAc,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,gVAA2U;AAAA,EAC/Y,IAAc,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS,gJAAgJ;AAAA,EAC1M,IAAc,cAAE,OAAO,EAAE,QAAQ,IAAI,EAAE,SAAS,+HAA+H;AAAA,EAC/K,QAAc,cAAE,KAAK,CAAC,WAAW,QAAQ,CAAC,EAAE,QAAQ,SAAS,EAAE,SAAS,sGAAsG;AAAA,EAC9K,WAAc,cAAE,KAAK,CAAC,YAAY,cAAc,MAAM,CAAC,EAAE,QAAQ,kBAAkB,EAAE,SAAS,iLAA4K;AAAA,EAC1Q,UAAc,cAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,EAAE,SAAS,qLAAqL;AAAA,EACnP,OAAc,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,2IAA2I;AAC/L;AAGO,IAAM,wBAAwB;AAAA,EACnC,KAAkB,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS,0FAA0F;AAAA,EACtI,YAAkB,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,gLAAgL;AAAA,EACtO,kBAAkB,cAAE,KAAK,CAAC,WAAW,QAAQ,CAAC,EAAE,QAAQ,SAAS,EAAE,SAAS,uFAAiF;AAAA,EAC7J,iBAAkB,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,2TAA2T;AAAA,EACjX,eAAkB,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,0OAA0O;AAAA,EAChS,YAAkB,cAAE,MAAM,cAAE,KAAK,CAAC,SAAS,SAAS,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,SAAS,SAAS,OAAO,CAAC,EAAE,SAAS,mDAAmD;AAAA,EAChK,YAAkB,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,uEAAuE;AAAA,EAC7H,gBAAkB,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,qVAAiV;AAAA,EACvY,WAAkB,cAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,wEAAyE;AACnJ;AAGO,IAAM,yBAAyB;AAAA,EACpC,KAAS,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS,gIAAgI;AAAA,EACnK,SAAS,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAK,EAAE,SAAS,EAAE,SAAS,4OAA4O;AAC9S;AAGO,IAAM,yBAAyB;AAAA,EACpC,KAAU,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS,wUAAoU;AAAA,EACxW,UAAU,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAK,EAAE,SAAS,EAAE,SAAS,oUAAoU;AAAA,EACrY,eAAe,cAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,yZAA0Z;AAAA,EACzc,kBAAkB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,qMAAqM;AAAA,EAC5Q,SAAS,cAAE,MAAM,cAAE,KAAK,CAAC,YAAY,SAAS,QAAQ,UAAU,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,odAAod;AACxjB;AAGO,IAAM,uBAAuB;AAAA,EAClC,KAAU,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS,gXAA2W;AAAA,EAC/Y,UAAU,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAK,EAAE,SAAS,EAAE,SAAS,qTAAqT;AAAA,EACtX,eAAe,cAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,2MAA2M;AAAA,EAC1P,kBAAkB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,+HAA+H;AACxM;AAGO,IAAM,4BAA4B;AAAA,EACvC,MAAe,cAAE,KAAK,CAAC,UAAU,SAAS,CAAC,EAAE,SAAS,gHAAgH;AAAA,EACtK,OAAe,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kFAA6E;AAAA,EAC3H,eAAe,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kGAAkG;AAAA,EAChJ,WAAe,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,mPAAmP;AAC1T;AAGO,IAAM,+BAA+B;AAAA,EAC1C,SAAS,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,gIAAgI;AAAA,EAC/K,KAAK,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,mLAAmL;AAC/N;AAGO,IAAM,+BAA+B;AAAA,EAC1C,QAAW,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sKAAsK;AAAA,EAChN,WAAW,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uKAAuK;AAAA,EACjN,OAAW,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,8GAA8G;AAAA,EACxJ,QAAW,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,+JAA+J;AAAA,EAChO,SAAW,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS,iIAAiI;AAC1L;AAGO,IAAM,8BAA8B;AAAA,EACzC,OAAY,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,oFAAoF;AAAA,EAC3H,SAAY,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS,2EAA2E;AAAA,EACnI,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,SAAS,0GAA0G;AAC7K;AAGO,IAAM,0BAA0B;AAAA,EACrC,KAAK,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0LAA0L;AAAA,EAC1N,aAAa,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAI,EAAE,SAAS,EAAE,SAAS,0EAA0E;AAC/I;AAGO,IAAM,kCAAkC;AAAA,EAC7C,UAAU,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS,sLAAsL;AAC5N;AAGO,IAAM,qCAAqC;AAAA,EAChD,KAAK,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS,iUAAiU;AAAA,EAChW,SAAS,cAAE,KAAK,CAAC,QAAQ,MAAM,IAAI,CAAC,EAAE,QAAQ,MAAM,EAAE,SAAS,0HAA0H;AAC3L;AAGO,IAAM,qCAAqC;AAAA,EAChD,QAAQ,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,6DAA6D;AAAA,EAC3G,KAAK,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,4FAA4F;AAAA,EACtI,SAAS,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,6JAA6J;AAAA,EAC5M,oBAAoB,cAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,gIAAgI;AAAA,EACpL,UAAU,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAI,EAAE,QAAQ,EAAE,EAAE,SAAS,8IAA8I;AAAA,EAC/M,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,2IAA2I;AAAA,EAC7M,eAAe,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,IAAI,GAAI,EAAE,QAAQ,IAAI,EAAE,SAAS,+IAA+I;AAAA,EACzN,mBAAmB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,2FAA2F;AACpK;AAGO,IAAM,oCAAoC;AAAA,EAC/C,KAAK,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS,4KAA4K;AAAA,EAC3M,SAAS,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,6JAA6J;AAAA,EAC5M,oBAAoB,cAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,gIAAgI;AAAA,EACpL,YAAY,cAAE,MAAM,cAAE,KAAK,CAAC,SAAS,SAAS,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,SAAS,SAAS,OAAO,CAAC,EAAE,SAAS,gIAAgI;AAAA,EACvO,eAAe,cAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,mKAAmK;AAAA,EACrN,mBAAmB,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,yJAAyJ;AAAA,EAChN,mBAAmB,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,uGAAuG;AAAA,EAC9J,KAAK,cAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,sKAAsK;AAChN;AAGO,IAAM,4BAA4B;AAAA,EACvC,cAAgB,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,yHAAyH;AAAA,EACpK,UAAgB,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0HAA0H;AAAA,EACrK,IAAgB,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS,6CAA6C;AAAA,EACzG,IAAgB,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS,sCAAsC;AAAA,EAClG,gBAAgB,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,mJAAmJ;AAAA,EACvM,YAAgB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,mKAAmK;AAC3O;AAGO,IAAM,wBAAwB;AAAA,EACnC,OAAY,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,mMAAmM;AAAA,EAC1O,UAAY,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0HAA0H;AAAA,EACrK,IAAY,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS,6CAA6C;AAAA,EACrG,IAAY,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS,sCAAsC;AAAA,EAC9F,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,SAAS,4HAA4H;AAAA,EAC7L,WAAY,cAAE,KAAK,CAAC,YAAY,cAAc,MAAM,CAAC,EAAE,QAAQ,uBAAuB,EAAE,SAAS,2PAA2P;AAAA,EAC5V,UAAY,cAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,EAAE,SAAS,+HAA+H;AAAA,EAC3L,OAAY,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,2GAA2G;AAC7J;AAGO,IAAM,+BAA+B;AAAA,EAC1C,OAAmB,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0JAA0J;AAAA,EACxM,OAAmB,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS,yFAAyF;AAAA,EACrJ,eAAmB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAM,EAAE,SAAS,sGAAsG;AAAA,EAC1K,gBAAmB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI,EAAE,QAAQ,IAAI,EAAE,SAAS,qGAAqG;AAAA,EACpL,WAAmB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,8EAA8E;AAAA,EACvJ,mBAAmB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,SAAS,+EAA+E;AAAA,EACvJ,aAAmB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,qGAAqG;AAAA,EAC3K,kBAAmB,cAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,6JAA6J;AAAA,EACnN,eAAmB,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,4MAA4M;AAAA,EAC9P,SAAmB,cAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,2SAA2S;AAAA,EACjW,WAAmB,cAAE,KAAK,CAAC,YAAY,cAAc,MAAM,CAAC,EAAE,QAAQ,uBAAuB,EAAE,SAAS,uRAAuR;AAAA,EAC/X,UAAmB,cAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,EAAE,SAAS,wHAAwH;AAAA,EAC3L,OAAmB,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,0FAA0F;AACnJ;AAGO,IAAM,wBAAwB,cAAE,KAAK,CAAC,QAAQ,WAAW,eAAe,KAAK,CAAC;AAG9E,IAAM,kCAAkC;AAAA,EAC7C,aAAoB,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,kEAAkE;AAAA,EAC5H,cAAoB,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,uGAAuG;AAAA,EACjK,oBAAoB,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,4HAA4H;AAAA,EACtL,eAAoB,cAAE,MAAM,qBAAqB,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,QAAQ,WAAW,eAAe,KAAK,CAAC,EAAE,SAAS,qLAAqL;AAAA,EAClT,UAAoB,cAAE,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,SAAS,gIAAgI;AAAA,EAC7M,WAAoB,cAAE,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,SAAS,8HAA8H;AAAA,EAC3M,aAAoB,cAAE,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,SAAS,iFAAiF;AAAA,EAC9J,UAAoB,cAAE,KAAK,CAAC,YAAY,QAAQ,YAAY,UAAU,OAAO,CAAC,EAAE,QAAQ,UAAU,EAAE,SAAS,6EAA6E;AAAA,EAC1L,iBAAoB,cAAE,KAAK,CAAC,SAAS,UAAU,WAAW,QAAQ,CAAC,EAAE,QAAQ,QAAQ,EAAE,SAAS,6EAA6E;AAAA,EAC7K,YAAoB,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,wDAAwD;AAAA,EAClH,UAAoB,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,KAAK,EAAE,SAAS,+DAA+D;AAAA,EAC7H,aAAoB,cAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,kFAAkF;AAAA,EACzI,kBAAoB,cAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,mEAAmE;AAAA,EAC1H,eAAoB,cAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,sEAAsE;AAAA,EAC7H,OAAoB,cAAE,OAAO,EAAE,IAAI,GAAI,EAAE,SAAS,EAAE,SAAS,gGAAgG;AAC/J;AAGA,IAAMC,kBAAiB,cAAE,OAAO,EAAE,SAAS;AAE3C,IAAM,0BAA0B,cAAE,OAAO;AAAA,EACvC,eAAe,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACrC,aAAa,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACnC,QAAQ,cAAE,KAAK,CAAC,MAAM,QAAQ,CAAC;AAAA,EAC/B,SAAS,cAAE,OAAO;AAAA,EAClB,WAAW,cAAE,QAAQ;AAAA,EACrB,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAClC,aAAa,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACnC,OAAOA;AAAA,EACP,WAAW,cAAE,KAAK,CAAC,YAAY,cAAc,MAAM,CAAC;AAAA,EACpD,uBAAuB,cAAE,KAAK,CAAC,YAAY,mBAAmB,oBAAoB,uBAAuB,aAAa,CAAC,EAAE,SAAS;AAAA,EAClI,eAAeA;AAAA,EACf,kBAAkB,cAAE,KAAK,CAAC,OAAO,QAAQ,OAAO,CAAC,EAAE,SAAS;AAAA,EAC5D,qBAAqBA;AAAA,EACrB,gBAAgBA;AAAA,EAChB,wBAAwBA;AAAA,EACxB,YAAYA;AAAA,EACZ,cAAcA;AAAA,EACd,gBAAgBA;AAClB,CAAC;AAEM,IAAM,yBAAyB;AAAA,EACpC,OAAO,cAAE,OAAO;AAAA,EAChB,UAAU,cAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,aAAa,cAAE,OAAO;AAAA,EACtB,WAAW,cAAE,OAAO,EAAE,IAAI;AAAA,EAC1B,aAAa,cAAE,OAAO;AAAA,EACtB,qBAAqB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA,EACnD,aAAa,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA,EAC3C,SAAS,cAAE,MAAM,cAAE,OAAO;AAAA,IACxB,UAAU,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAChC,MAAM,cAAE,OAAO;AAAA,IACf,UAAU,cAAE,OAAO,EAAE,IAAI;AAAA,IACzB,KAAKA;AAAA,IACL,YAAYA;AAAA,IACZ,QAAQA;AAAA,IACR,aAAaA;AAAA,IACb,UAAUA;AAAA,IACV,SAASA;AAAA,IACT,OAAOA;AAAA,IACP,aAAaA;AAAA,IACb,YAAYA;AAAA,IACZ,eAAeA;AAAA,IACf,UAAU,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EAC9B,CAAC,CAAC;AAAA,EACF,UAAU,cAAE,MAAM,uBAAuB;AAAA,EACzC,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AACpC;AAEA,IAAM,8BAA8B,cAAE,OAAO;AAAA,EAC3C,UAAU,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAChC,MAAM,cAAE,OAAO;AAAA,EACf,UAAU,cAAE,OAAO,EAAE,IAAI;AAAA,EACzB,KAAKA;AAAA,EACL,YAAYA;AAAA,EACZ,QAAQA;AAAA,EACR,aAAaA;AAAA,EACb,UAAUA;AAAA,EACV,SAASA;AAAA,EACT,OAAOA;AAAA,EACP,aAAaA;AAAA,EACb,YAAYA;AAAA,EACZ,eAAeA;AAAA,EACf,UAAU,cAAE,MAAM,cAAE,OAAO,CAAC;AAC9B,CAAC;AAEM,IAAM,gCAAgC;AAAA,EAC3C,OAAO,cAAE,OAAO;AAAA,EAChB,OAAO,cAAE,OAAO;AAAA,EAChB,eAAe,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACrC,gBAAgB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI;AAAA,EACnD,mBAAmB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA,EACjD,aAAa,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EAC1C,iBAAiB,cAAE,OAAO,EAAE,IAAI;AAAA,EAChC,kBAAkBA;AAAA,EAClB,UAAU,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EAC5B,aAAa,cAAE,OAAO;AAAA,EACtB,mBAAmB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACzC,kBAAkB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACxC,SAASA;AAAA,EACT,QAAQ,cAAE,MAAM,cAAE,OAAO;AAAA,IACvB,MAAM,cAAE,OAAO;AAAA,IACf,OAAO,cAAE,OAAO;AAAA,IAChB,UAAU,cAAE,OAAO;AAAA,IACnB,SAAS,cAAE,OAAO;AAAA,IAClB,YAAY,cAAE,OAAO;AAAA,IACrB,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAClC,gBAAgB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI;AAAA,IACnD,MAAM,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,IACxB,UAAU,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,IAC5B,QAAQ,cAAE,KAAK,CAAC,MAAM,SAAS,QAAQ,CAAC;AAAA,IACxC,OAAOA;AAAA,IACP,aAAa,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IACnC,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAClC,UAAU,cAAE,MAAM,uBAAuB;AAAA,IACzC,SAAS,cAAE,MAAM,2BAA2B;AAAA,EAC9C,CAAC,CAAC;AAAA,EACF,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AACpC;AAEA,IAAM,4BAA4B,cAAE,OAAO;AAAA,EACzC,MAAM,cAAE,OAAO;AAAA,EACf,SAAS,cAAE,OAAO;AACpB,CAAC;AAED,IAAM,yBAAyB,cAAE,OAAO;AAAA,EACtC,MAAM,cAAE,OAAO;AAAA,EACf,SAAS,cAAE,OAAO;AAAA,EAClB,YAAY,cAAE,MAAM,cAAE,OAAO,CAAC;AAChC,CAAC;AAED,IAAM,2BAA2B,cAAE,OAAO;AAAA,EACxC,MAAM,cAAE,OAAO;AAAA,EACf,SAAS,cAAE,OAAO;AAAA,EAClB,OAAO,cAAE,MAAM,qBAAqB;AAAA,EACpC,kBAAkB,cAAE,MAAM,cAAE,OAAO,CAAC;AACtC,CAAC;AAEM,IAAM,mCAAmC;AAAA,EAC9C,aAAa,cAAE,OAAO;AAAA,EACtB,cAAcA;AAAA,EACd,oBAAoBA;AAAA,EACpB,eAAe,cAAE,MAAM,qBAAqB;AAAA,EAC5C,UAAU,cAAE,OAAO;AAAA,EACnB,kBAAkB,cAAE,MAAM,yBAAyB;AAAA,EACnD,QAAQ,cAAE,MAAM,sBAAsB;AAAA,EACtC,MAAM,cAAE,OAAO;AAAA,IACb,SAAS,cAAE,QAAQ;AAAA,IACnB,SAAS,cAAE,OAAO;AAAA,IAClB,YAAY,cAAE,OAAO;AAAA,IACrB,UAAU,cAAE,OAAO;AAAA,IACnB,MAAM,cAAE,MAAM,wBAAwB;AAAA,EACxC,CAAC;AAAA,EACD,SAAS,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EAC3B,sBAAsB,cAAE,OAAO;AACjC;AAEA,IAAM,sBAAsB,cAAE,OAAO;AAAA,EACnC,UAAU,cAAE,OAAO,EAAE,IAAI;AAAA,EACzB,OAAO,cAAE,OAAO;AAAA,EAChB,KAAK,cAAE,OAAO;AAAA,EACd,QAAQ,cAAE,OAAO;AAAA,EACjB,SAASA;AACX,CAAC;AAED,IAAM,mBAAmB,cAAE,OAAO;AAAA,EAChC,UAAU,cAAE,QAAQ;AAAA,EACpB,MAAMA;AACR,CAAC,EAAE,SAAS;AAEZ,IAAM,kBAAkB,cAAE,OAAO;AAAA,EAC/B,UAAU,cAAE,MAAM,cAAE,OAAO;AAAA,IACzB,MAAM,cAAE,OAAO;AAAA,IACf,MAAM,cAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,KAAK,cAAE,OAAO,EAAE,SAAS;AAAA,IACzB,MAAM,cAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,CAAC,CAAC,EAAE,SAAS,4OAAuO;AAAA,EACpP,OAAO,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EACzB,MAAM,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EACxB,OAAO,cAAE,MAAM,cAAE,OAAO,CAAC;AAC3B,CAAC,EAAE,SAAS;AAEL,IAAM,yBAAyB;AAAA,EACpC,OAAO,cAAE,OAAO;AAAA,EAChB,UAAUA;AAAA,EACV,eAAe,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACrC,kBAAkBA;AAAA,EAClB,WAAW,cAAE,MAAM,cAAE,OAAO;AAAA,IAC1B,UAAU,cAAE,OAAO;AAAA,IACnB,QAAQA;AAAA,IACR,aAAaA;AAAA,IACb,YAAYA;AAAA,EACd,CAAC,CAAC;AAAA,EACF,gBAAgB,cAAE,MAAM,mBAAmB;AAAA,EAC3C,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,YAAY,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AACzC;AAEO,IAAM,yBAAyB;AAAA,EACpC,OAAO,cAAE,OAAO;AAAA,EAChB,UAAUA;AAAA,EACV,gBAAgB,cAAE,MAAM,mBAAmB;AAAA,EAC3C,WAAW,cAAE,MAAM,cAAE,OAAO;AAAA,IAC1B,UAAU,cAAE,OAAO,EAAE,IAAI;AAAA,IACzB,MAAM,cAAE,OAAO;AAAA,IACf,QAAQA;AAAA,IACR,aAAaA;AAAA,IACb,YAAYA;AAAA,EACd,CAAC,CAAC;AAAA,EACF,YAAY;AAAA,EACZ,WAAW;AACb;AAEO,IAAM,yBAAyB;AAAA,EACpC,KAAK,cAAE,OAAO;AAAA,EACd,OAAOA;AAAA,EACP,UAAU,cAAE,MAAM,cAAE,OAAO;AAAA,IACzB,OAAO,cAAE,OAAO,EAAE,IAAI;AAAA,IACtB,MAAM,cAAE,OAAO;AAAA,EACjB,CAAC,CAAC;AAAA,EACF,kBAAkB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACxC,YAAYA;AAAA,EACZ,aAAa,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EAC/B,UAAU,cAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,qBAAqB,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EACvC,iBAAiBA;AAAA,EACjB,QAAQ,cAAE,OAAO;AAAA,IACf,WAAe,cAAE,QAAQ;AAAA,IACzB,OAAe,cAAE,OAAO,EAAE,SAAS;AAAA,IACnC,QAAe,cAAE,OAAO,EAAE,SAAS;AAAA,IACnC,MAAe,cAAE,OAAO,EAAE,SAAS;AAAA,IACnC,QAAe,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,IACzC,SAAe,cAAE,OAAO,EAAE,SAAS;AAAA,IACnC,eAAe,cAAE,OAAO,EAAE,SAAS;AAAA,IACnC,OAAe,cAAE,OAAO,EAAE,SAAS;AAAA,EACrC,CAAC,EAAE,SAAS;AACd;AAEO,IAAM,0BAA0B;AAAA,EACrC,KAAK,cAAE,OAAO;AAAA,EACd,WAAW,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACjC,OAAO,cAAE,MAAM,cAAE,OAAO;AAAA,IACtB,KAAK,cAAE,OAAO;AAAA,IACd,OAAOA;AAAA,IACP,aAAa,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EACjC,CAAC,CAAC;AAAA,EACF,YAAY,cAAE,OAAO,EAAE,IAAI,CAAC;AAC9B;AAEO,IAAM,wBAAwB;AAAA,EACnC,KAAK,cAAE,OAAO;AAAA,EACd,WAAW,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACjC,YAAY,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC5B,YAAY,cAAE,OAAO,EAAE,SAAS;AAAA,EAChC,QAAQ,cAAE,OAAO,cAAE,OAAO,GAAG,cAAE,OAAO,CAAC;AAAA,EACvC,QAAQ,cAAE,OAAO;AAAA,IACf,QAAQ,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAC9B,YAAY,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IAC5B,WAAW,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IACjC,cAAc,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACtC,CAAC;AAAA,EACD,OAAO,cAAE,OAAO;AAAA,IACd,UAAU,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAChC,UAAU,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAChC,SAAS,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAC/B,gBAAgB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IACtC,iBAAiB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACzC,CAAC;AACH;AAEO,IAAM,6BAA6B;AAAA,EACxC,MAAM,cAAE,OAAO;AAAA,EACf,QAAQA;AAAA,EACR,aAAaA;AAAA,EACb,UAAUA;AAAA,EACV,SAASA;AAAA,EACT,OAAOA;AAAA,EACP,SAASA;AAAA,EACT,cAAcA;AAAA,EACd,YAAYA;AAAA,EACZ,OAAOA;AAAA,EACP,YAAYA;AAAA,EACZ,QAAQA;AAAA,EACR,KAAK,cAAE,OAAO,EAAE,SAAS;AAAA,EACzB,KAAK,cAAE,OAAO,EAAE,SAAS;AAAA,EACzB,eAAe,cAAE,OAAO;AAAA,EACxB,kBAAkB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACxC,cAAc,cAAE,MAAM,cAAE,OAAO;AAAA,IAC7B,OAAO,cAAE,OAAO;AAAA,IAChB,OAAO,cAAE,OAAO;AAAA,EAClB,CAAC,CAAC;AACJ;AAEO,IAAM,0BAA0B;AAAA,EACrC,gBAAgB,cAAE,OAAO,EAAE,SAAS;AAAA,EACpC,aAAa,cAAE,OAAO;AAAA,IACpB,OAAO,cAAE,OAAO;AAAA,IAChB,SAAS,cAAE,OAAO;AAAA,IAClB,MAAM,cAAE,OAAO;AAAA,IACf,OAAOA;AAAA,EACT,CAAC,EAAE,SAAS;AAAA,EACZ,OAAO,cAAE,MAAM,cAAE,OAAO;AAAA,IACtB,KAAK,cAAE,OAAO;AAAA,IACd,OAAO,cAAE,OAAO;AAAA,IAChB,SAAS,cAAE,OAAO;AAAA,IAClB,MAAM,cAAE,OAAO;AAAA,IACf,OAAOA;AAAA,EACT,CAAC,CAAC;AAAA,EACF,QAAQ,cAAE,MAAM,cAAE,OAAO;AAAA,IACvB,WAAW,cAAE,OAAO;AAAA,IACpB,WAAW,cAAE,OAAO;AAAA,IACpB,SAAS,cAAE,OAAO;AAAA,IAClB,aAAaA;AAAA,EACf,CAAC,CAAC;AAAA,EACF,aAAa,cAAE,OAAO;AAAA,IACpB,mBAAmB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IACzC,cAAc,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IACpC,iBAAiB,cAAE,QAAQ;AAAA,IAC3B,SAAS,cAAE,OAAO;AAAA,MAChB,SAAS,cAAE,OAAO;AAAA,MAClB,YAAY,cAAE,OAAO;AAAA,MACrB,eAAe,cAAE,OAAO;AAAA,MACxB,UAAU,cAAE,OAAO;AAAA,MACnB,UAAU,cAAE,OAAO;AAAA,MACnB,YAAY,cAAE,OAAO,EAAE,IAAI;AAAA,MAC3B,iBAAiB,cAAE,OAAO;AAAA,MAC1B,8BAA8B,cAAE,OAAO;AAAA,IACzC,CAAC;AAAA,EACH,CAAC,EAAE,SAAS;AACd;AAEO,IAAM,0BAA0B;AAAA,EACrC,UAAU,cAAE,OAAO;AAAA,EACnB,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAClC,WAAW,cAAE,QAAQ;AAAA,EACrB,SAAS,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAC/B,eAAe,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACrC,aAAa,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACnC,MAAM,cAAE,MAAM,cAAE,OAAO;AAAA,IACrB,KAAK,cAAE,OAAO;AAAA,IACd,QAAQ,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACpC,CAAC,CAAC;AAAA,EACF,YAAY,cAAE,OAAO,EAAE,IAAI,CAAC;AAC9B;AAEO,IAAM,6BAA6B;AAAA,EACxC,MAAM,cAAE,OAAO;AAAA,EACf,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAClC,SAAS,cAAE,OAAO;AAAA,IAChB,OAAOA;AAAA,IACP,iBAAiBA;AAAA,EACnB,CAAC,EAAE,SAAS;AAAA,EACZ,QAAQ,cAAE,MAAM,cAAE,OAAO;AAAA,IACvB,SAAS,cAAE,OAAO;AAAA,IAClB,OAAO,cAAE,OAAO;AAAA,IAChB,aAAaA;AAAA,IACb,OAAOA;AAAA,IACP,UAAUA;AAAA,IACV,KAAKA;AAAA,EACP,CAAC,CAAC;AACJ;AAEO,IAAM,+BAA+B;AAAA,EAC1C,OAAO,cAAE,OAAO;AAAA,EAChB,iBAAiB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACvC,aAAa,cAAE,MAAM,cAAE,OAAO;AAAA,IAC5B,MAAMA;AAAA,IACN,QAAQA;AAAA,IACR,SAASA;AAAA,IACT,SAAS,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,IACnC,WAAWA;AAAA,IACX,iBAAiBA;AAAA,EACnB,CAAC,CAAC;AACJ;AAEO,IAAM,2BAA2B;AAAA,EACtC,WAAWA;AAAA,EACX,cAAcA;AAAA,EACd,OAAOA;AAAA,EACP,QAAQA;AAAA,EACR,OAAOA;AAAA,EACP,UAAUA;AAAA,EACV,aAAa,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACnC,UAAU,cAAE,MAAM,cAAE,OAAO;AAAA,IACzB,QAAQA;AAAA,IACR,OAAOA;AAAA,IACP,OAAO,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAC7B,MAAM,cAAE,OAAO;AAAA,EACjB,CAAC,CAAC;AACJ;AAEO,IAAM,gCAAgC;AAAA,EAC3C,gBAAgBA;AAAA,EAChB,UAAU,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAChC,aAAa,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACnC,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAClC,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAClC,KAAK,cAAE,MAAM,cAAE,OAAO;AAAA,IACpB,WAAWA;AAAA,IACX,QAAQA;AAAA,IACR,cAAcA;AAAA,IACd,aAAaA;AAAA,IACb,UAAUA;AAAA,IACV,KAAKA;AAAA,IACL,WAAWA;AAAA,IACX,YAAYA;AAAA,IACZ,QAAQA;AAAA,IACR,UAAUA;AAAA,IACV,UAAUA;AAAA,IACV,aAAaA;AAAA,IACb,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACxC,CAAC,CAAC;AACJ;AAEO,IAAM,sCAAsC;AAAA,EACjD,WAAW,cAAE,OAAO,EAAE,IAAI;AAAA,EAC1B,SAAS,cAAE,OAAO,EAAE,IAAI;AAAA,EACxB,SAASA;AAAA,EACT,WAAWA;AAAA,EACX,iBAAiB,cAAE,OAAO;AAAA,EAC1B,SAAS,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACnC,kBAAkB,cAAE,OAAO,EAAE,SAAS;AAAA,EACtC,UAAU,cAAE,OAAO,EAAE,IAAI;AAAA,EACzB,WAAW,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACjC,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAClC,gBAAgB,cAAE,OAAO;AAAA,EACzB,QAAQ,cAAE,MAAM,cAAE,OAAO;AAAA,IACvB,UAAU,cAAE,OAAO;AAAA,IACnB,QAAQ,cAAE,OAAO;AAAA,IACjB,MAAM,cAAE,OAAO;AAAA,EACjB,CAAC,CAAC;AACJ;AAEA,IAAM,wBAAwB,cAAE,OAAO;AAAA,EACrC,UAAU,cAAE,OAAO;AAAA,EACnB,QAAQ,cAAE,OAAO;AAAA,EACjB,MAAM,cAAE,OAAO;AACjB,CAAC;AAED,IAAM,yBAAyB,cAAE,OAAO;AAAA,EACtC,MAAM,cAAE,QAAQ,QAAQ;AAAA,EACxB,eAAe,cAAE,QAAQ,QAAQ;AAAA,EACjC,aAAaA;AAAA,EACb,eAAe,cAAE,QAAQ,QAAQ;AAAA,EACjC,sBAAsB,cAAE,QAAQ;AAAA,EAChC,0BAA0B,cAAE,QAAQ;AACtC,CAAC;AAED,IAAM,4BAA4B,cAAE,OAAO;AAAA,EACzC,UAAU,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAI;AAAA,EAC1C,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EAC3C,kBAAkB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACxC,eAAe,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACrC,mBAAmB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA,EACjD,eAAe,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,IAAI,GAAI;AAAA,EACjD,iBAAiB,cAAE,QAAQ;AAAA,EAC3B,0BAA0B,cAAE,QAAQ;AAAA,EACpC,mBAAmB,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EAC7C,eAAe,cAAE,KAAK,CAAC,aAAa,uBAAuB,kBAAkB,eAAe,YAAY,CAAC;AAAA,EACzG,QAAQ,cAAE,MAAM,cAAE,OAAO;AAAA,IACvB,OAAO,cAAE,OAAO;AAAA,IAChB,WAAW,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IACjC,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAClC,SAAS,cAAE,OAAO,EAAE,SAAS;AAAA,IAC7B,cAAc,cAAE,OAAO,EAAE,SAAS;AAAA,EACpC,CAAC,CAAC;AACJ,CAAC;AAEM,IAAM,sCAAsC;AAAA,EACjD,QAAQ,cAAE,OAAO;AAAA,EACjB,YAAY,cAAE,OAAO,EAAE,IAAI;AAAA,EAC3B,SAAS,cAAE,OAAO,EAAE,IAAI;AAAA,EACxB,SAAS;AAAA,EACT,aAAaA;AAAA,EACb,mBAAmB,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EAC7C,uBAAuBA;AAAA,EACvB,mBAAmBA;AAAA,EACnB,oBAAoBA;AAAA,EACpB,uBAAuB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAC7C,YAAY,cAAE,OAAO;AAAA,IACnB,MAAM,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAC5B,MAAM,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAC5B,IAAI,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAC5B,CAAC;AAAA,EACD,YAAY;AAAA,EACZ,SAAS,cAAE,QAAQ;AAAA,EACnB,aAAa,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EAC/B,OAAO,cAAE,MAAM,cAAE,OAAO;AAAA,IACtB,KAAK,cAAE,OAAO,EAAE,IAAI;AAAA,IACpB,MAAM,cAAE,KAAK,CAAC,QAAQ,QAAQ,IAAI,CAAC;AAAA,IACnC,WAAW,cAAE,OAAO;AAAA,IACpB,YAAYA;AAAA,IACZ,gBAAgB,cAAE,OAAO;AAAA,EAC3B,CAAC,CAAC;AACJ;AAEA,IAAM,4BAA4B,cAAE,OAAO;AAAA,EACzC,KAAK,cAAE,OAAO,EAAE,IAAI;AAAA,EACpB,YAAY,cAAE,KAAK,CAAC,SAAS,SAAS,SAAS,CAAC;AAAA,EAChD,SAAS,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACnC,aAAa,cAAE,OAAO,EAAE,SAAS;AAAA,EACjC,YAAYA;AAAA,EACZ,OAAO,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACjC,QAAQ,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AACpC,CAAC;AAED,IAAM,0BAA0B,cAAE,OAAO;AAAA,EACvC,MAAM,cAAE,KAAK,CAAC,QAAQ,SAAS,SAAS,SAAS,aAAa,CAAC;AAAA,EAC/D,KAAK,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EAC/B,WAAWA;AAAA,EACX,WAAW,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACrC,UAAUA;AAAA,EACV,OAAOA;AACT,CAAC;AAEM,IAAM,qCAAqC;AAAA,EAChD,WAAW,cAAE,OAAO,EAAE,IAAI;AAAA,EAC1B,SAAS,cAAE,OAAO,EAAE,IAAI;AAAA,EACxB,SAAS;AAAA,EACT,MAAM,cAAE,KAAK,CAAC,QAAQ,QAAQ,IAAI,CAAC,EAAE,SAAS;AAAA,EAC9C,WAAWA;AAAA,EACX,WAAWA;AAAA,EACX,SAASA;AAAA,EACT,UAAU,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACpC,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAClC,oBAAoB,0BAA0B,SAAS;AAAA,EACvD,oBAAoB,0BAA0B,SAAS;AAAA,EACvD,WAAW,cAAE,MAAM,uBAAuB;AAAA,EAC1C,WAAWA;AAAA,EACX,UAAU,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EAC5B,aAAa,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EAC/B,YAAY,cAAE,OAAO;AAAA,IACnB,WAAW,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IACjC,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAClC,YAAY,cAAE,OAAO,EAAE,SAAS;AAAA,IAChC,gBAAgB,cAAE,OAAO;AAAA,IACzB,QAAQ,cAAE,MAAM,qBAAqB;AAAA,EACvC,CAAC,EAAE,SAAS;AACd;AAEO,IAAM,gCAAgC;AAAA,EAC3C,SAASA;AAAA,EACT,KAAKA;AAAA,EACL,WAAW,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACjC,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAClC,YAAY,cAAE,OAAO,EAAE,SAAS;AAAA,EAChC,gBAAgB,cAAE,OAAO;AAAA,EACzB,QAAQ,cAAE,MAAM,qBAAqB;AAAA,EACrC,gBAAgB,cAAE,OAAO;AAAA,IACvB,SAASA;AAAA,IACT,KAAKA;AAAA,EACP,CAAC;AACH;AAEO,IAAM,mCAAmC;AAAA,EAC9C,UAAU,cAAE,OAAO,EAAE,IAAI;AAAA,EACzB,WAAW,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACjC,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAClC,YAAY,cAAE,OAAO,EAAE,SAAS;AAAA,EAChC,gBAAgB,cAAE,OAAO;AAAA,EACzB,QAAQ,cAAE,MAAM,qBAAqB;AAAA,EACrC,gBAAgB,cAAE,OAAO;AAAA,IACvB,UAAU,cAAE,OAAO,EAAE,IAAI;AAAA,EAC3B,CAAC;AACH;AAEO,IAAM,kCAAkC;AAAA,EAC7C,eAAe,cAAE,QAAQ,8BAA8B;AAAA,EACvD,QAAQ,cAAE,OAAO;AAAA,EACjB,OAAOA;AAAA,EACP,UAAUA;AAAA,EACV,YAAYA;AAAA,EACZ,aAAa,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC9C,YAAYA;AAAA,EACZ,gBAAgB,cAAE,OAAO,cAAE,QAAQ,CAAC;AAAA,EACpC,WAAW,cAAE,MAAM,cAAE,OAAO,cAAE,QAAQ,CAAC,CAAC;AAAA,EACxC,aAAa,cAAE,OAAO,cAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EAC5C,iBAAiB,cAAE,OAAO,cAAE,QAAQ,CAAC;AACvC;AAEO,IAAM,uCAAuC;AAAA,EAClD,eAAe,cAAE,QAAQ,qCAAqC;AAAA,EAC9D,QAAQ,cAAE,OAAO;AAAA,EACjB,OAAO,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAC7B,aAAa,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACnC,UAAU,cAAE,MAAM,cAAE,OAAO,cAAE,QAAQ,CAAC,CAAC;AAAA,EACvC,gBAAgB,cAAE,OAAO,cAAE,QAAQ,CAAC;AAAA,EACpC,aAAa,cAAE,OAAO,cAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EAC5C,iBAAiB,cAAE,OAAO,cAAE,QAAQ,CAAC;AACvC;AAEO,IAAM,yBAAyB;AAAA,EACpC,MAAe,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,6HAA6H;AAAA,EAC3K,eAAe,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,iDAAiD;AACtG;AAGO,IAAM,mBAAmB,cAAE,KAAK;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,IAAM,0BAA0B;AAAA,EACrC,gBAAgB,cAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,2MAA2M;AAChQ;AAGO,IAAM,6BAA6B;AAAA,EACxC,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,oKAAoK;AAAA,EACrM,OAAO,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qDAAqD;AAAA,EAC3F,SAAS,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,gEAAgE;AAAA,EACxG,QAAQ,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,2CAA2C;AAAA,EAClF,KAAK,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,8DAA8D;AAAA,EACxG,UAAU,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,8DAA8D;AAAA,EACvG,OAAO,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,+DAA+D;AAAA,EACrG,gBAAgB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,gDAAgD;AACrH;AAGO,IAAM,yBAAyB;AAAA,EACpC,YAAY,iBAAiB,SAAS,4OAA4O;AAAA,EAClR,OAAO,cAAE,OAAO,cAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,SAAS,+XAA+X;AAAA,EACjb,YAAY,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,4EAA4E;AAC/H;AAGO,IAAM,0BAA0B;AAAA,EACrC,OAAO,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,uNAAuN;AAC3P;AAGO,IAAM,4BAA4B;AAAA,EACvC,OAAO,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,wIAAwI;AAC5K;AAGO,IAAM,kCAAkC;AAAA,EAC7C,OAAO,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,wIAAwI;AAAA,EAC1K,YAAY,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,oKAAoK;AAAA,EAC3M,UAAU,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAK,EAAE,IAAI,GAAS,EAAE,QAAQ,GAAO,EAAE,SAAS,wJAAwJ;AACzO;AAGA,IAAM,uBAAuB,cAAE,OAAO;AAAA,EACpC,IAAI,cAAE,OAAO;AAAA,EACb,OAAO,cAAE,OAAO;AAAA,EAChB,aAAa,cAAE,OAAO;AAAA,EACtB,mBAAmB,cAAE,OAAO,EAAE,SAAS;AAAA,EACvC,kBAAkB,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EACpC,gBAAgB,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EAClC,gBAAgB,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EAClC,UAAU,cAAE,MAAM,cAAE,OAAO,CAAC;AAAA,EAC5B,SAAS,cAAE,OAAO;AACpB,CAAC;AAED,IAAM,2BAA2B,cAAE,OAAO;AAAA,EACxC,IAAI,cAAE,OAAO;AAAA,EACb,OAAO,cAAE,OAAO;AAAA,EAChB,aAAa,cAAE,OAAO;AACxB,CAAC;AAED,IAAM,yBAAyB,cAAE,OAAO,cAAE,QAAQ,CAAC;AAE5C,IAAM,2BAA2B;AAAA,EACtC,WAAW,cAAE,MAAM,wBAAwB;AAAA,EAC3C,SAAS,cAAE,MAAM,oBAAoB;AACvC;AAEO,IAAM,8BAA8B;AAAA,EACzC,MAAM,cAAE,OAAO;AAAA,EACf,aAAa,cAAE,MAAM,oBAAoB;AAC3C;AAEO,IAAM,0BAA0B;AAAA,EACrC,YAAY,cAAE,OAAO;AAAA,EACrB,OAAO,cAAE,OAAO,cAAE,QAAQ,CAAC;AAAA,EAC3B,KAAK,cAAE,OAAO,cAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EACpC,SAAS,cAAE,OAAO,cAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EACxC,MAAM,cAAE,OAAO,cAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EACrC,UAAU,cAAE,OAAO,cAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EACpD,MAAM,cAAE,QAAQ,EAAE,SAAS;AAAA,EAC3B,WAAW,cAAE,MAAM,sBAAsB;AAC3C;AAEO,IAAM,2BAA2B;AAAA,EACtC,OAAO,cAAE,OAAO;AAAA,EAChB,KAAK,cAAE,OAAO,cAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EACpC,SAAS,cAAE,OAAO,cAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EACnD,MAAM,cAAE,OAAO,cAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EACrC,UAAU,cAAE,OAAO,cAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EACpD,MAAM,cAAE,QAAQ;AAAA,EAChB,WAAW,cAAE,MAAM,sBAAsB;AAC3C;AAEO,IAAM,6BAA6B;AAAA,EACxC,KAAK,cAAE,OAAO,cAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EACpC,WAAW,cAAE,MAAM,sBAAsB;AAC3C;AAEO,IAAM,mCAAmC;AAAA,EAC9C,OAAO,cAAE,OAAO;AAAA,EAChB,YAAY,cAAE,OAAO;AAAA,EACrB,aAAa,cAAE,OAAO;AAAA,EACtB,OAAO,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAC7B,WAAW,cAAE,QAAQ;AAAA,EACrB,MAAM,cAAE,OAAO;AACjB;AAEO,IAAM,wBAAwB;AAAA,EACnC,OAAU,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,iKAAiK;AAAA,EACtM,UAAU,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,6FAA6F;AAAA,EACtI,IAAU,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS,8DAA8D;AAAA,EACpH,IAAU,cAAE,OAAO,EAAE,QAAQ,IAAI,EAAE,SAAS,+DAA+D;AAAA,EAC3G,QAAU,cAAE,KAAK,CAAC,WAAW,QAAQ,CAAC,EAAE,QAAQ,SAAS,EAAE,SAAS,sGAAsG;AAAA,EAC1K,WAAW,cAAE,KAAK,CAAC,YAAY,cAAc,MAAM,CAAC,EAAE,QAAQ,kBAAkB,EAAE,SAAS,6FAAwF;AAAA,EACnL,UAAW,cAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,EAAE,SAAS,qLAAqL;AAAA,EAChP,OAAU,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,2IAA2I;AAAA,EACzL,OAAU,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,4CAAuC;AACtG;AAGO,IAAM,iCAAiC;AAAA,EAC5C,OAAsB,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,gKAAgK;AAAA,EACjN,UAAsB,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,2JAA2J;AAAA,EAChN,IAAsB,cAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS,8EAA8E;AAAA,EAChJ,IAAsB,cAAE,OAAO,EAAE,QAAQ,IAAI,EAAE,SAAS,mEAAmE;AAAA,EAC3H,QAAsB,cAAE,KAAK,CAAC,WAAW,QAAQ,CAAC,EAAE,QAAQ,SAAS,EAAE,SAAS,sGAAsG;AAAA,EACtL,WAAsB,cAAE,KAAK,CAAC,YAAY,cAAc,MAAM,CAAC,EAAE,QAAQ,kBAAkB,EAAE,SAAS,2FAAsF;AAAA,EAC5L,UAAsB,cAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,EAAE,SAAS,wJAAwJ;AAAA,EAC9N,OAAsB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,kHAAkH;AAAA,EAC3L,OAAsB,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,qJAAqJ;AAAA,EAC/M,sBAAsB,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,mGAAmG;AAAA,EAC7J,mBAAsB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,uHAAuH;AACnM;AAGO,IAAM,wBAAwB;AAAA,EACnC,KAAY,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS,qJAAqJ;AAAA,EAC3L,QAAY,cAAE,KAAK,CAAC,WAAW,QAAQ,CAAC,EAAE,QAAQ,SAAS,EAAE,SAAS,wIAAkI;AAAA,EACxM,YAAY,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,oIAA+H;AACjL;AAGO,IAAM,sCAAsC;AAAA,EACjD,MAAgB,cAAE,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,+IAA+I;AAAA,EACjN,SAAgB,cAAE,MAAM,cAAE,OAAO;AAAA,IAC/B,KAAgB,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS,mCAAmC;AAAA,IAC7E,YAAgB,cAAE,KAAK,CAAC,WAAW,eAAe,sBAAsB,qBAAqB,cAAc,CAAC,EAAE,QAAQ,mBAAmB,EAAE,SAAS,iEAAiE;AAAA,IACrN,gBAAgB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,qEAAqE;AAAA,EACnI,CAAC,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,8GAA8G;AAAA,EAC9J,gBAAgB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,4FAA4F;AAAA,EAC/J,WAAgB,cAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAK,EAAE,IAAI,GAAM,EAAE,QAAQ,IAAM,EAAE,SAAS,mIAAmI;AAAA,EACpN,OAAgB,cAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,mIAAmI;AACzL;;;AEv3BA,IAAM,gBAAmC,CAAC,QAAQ,WAAW,eAAe,KAAK;AAEjF,SAAS,gBAAgB,OAA+B;AACtD,QAAM,UAAU,OAAO,KAAK;AAC5B,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,QAAQ,SAAS,KAAK,IAAI,UAAU,WAAW,OAAO,EAAE;AAC5E,WAAO,IAAI,SAAS,QAAQ,UAAU,EAAE,EAAE,YAAY;AAAA,EACxD,QAAQ;AACN,WAAO,QAAQ,QAAQ,gBAAgB,EAAE,EAAE,QAAQ,UAAU,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,YAAY,KAAK;AAAA,EACnG;AACF;AAEA,SAAS,YAAY,OAA8C;AACjE,QAAM,QAAQ,OAAO,SAAS,QAAQ;AACtC,SAAO,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;AAC3B;AAEA,SAAS,eAAe,SAAuD,YAA6B;AAC1G,MAAI,YAAY,QAAS,QAAO;AAChC,MAAI,YAAY,UAAW,QAAO;AAClC,MAAI,YAAY,SAAU,QAAO,YAAY,KAAK,KAAK;AACvD,SAAO;AACT;AAEA,SAAS,SAAS,OAA0B,MAAgC;AAC1E,SAAO,MAAM,SAAS,IAAI;AAC5B;AAEA,SAAS,cAAc,OAAsC;AAC3D,QAAM,QAAoB,CAAC;AAC3B,QAAM,OAAO,CAAC,MAAc,YAAoB;AAC9C,QAAI,CAAC,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,EAAG,OAAM,KAAK,EAAE,MAAM,QAAQ,CAAC;AAAA,EAC7E;AAEA,OAAK,gBAAgB,0EAA0E;AAE/F,MAAI,SAAS,OAAO,MAAM,GAAG;AAC3B,SAAK,sBAAsB,iFAAiF;AAC5G,SAAK,eAAe,0EAA0E;AAC9F,SAAK,oBAAoB,0FAA0F;AAAA,EACrH;AACA,MAAI,SAAS,OAAO,SAAS,GAAG;AAC9B,SAAK,eAAe,oGAAoG;AAAA,EAC1H;AACA,MAAI,SAAS,OAAO,aAAa,GAAG;AAClC,SAAK,eAAe,iFAAiF;AACrG,SAAK,eAAe,wFAAwF;AAAA,EAC9G;AACA,MAAI,SAAS,OAAO,KAAK,GAAG;AAC1B,SAAK,eAAe,yFAAyF;AAAA,EAC/G;AAEA,SAAO;AACT;AAEA,SAAS,YAAY,OAA0B,kBAA2B,eAAwB,gBAAsC;AACtI,QAAM,SAAsB;AAAA,IAC1B;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,CAAC,MAAM,QAAQ,iBAAiB,wBAAwB,iBAAiB,YAAY,YAAY;AAAA,IAC/G;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,CAAC,MAAM,cAAc,QAAQ,SAAS,gBAAgB,oBAAoB,QAAQ;AAAA,IAChG;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,CAAC,MAAM,cAAc,WAAW,UAAU,aAAa,QAAQ;AAAA,IAC7E;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,CAAC,MAAM,cAAc,SAAS,MAAM,MAAM,aAAa,UAAU,QAAQ;AAAA,IACvF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,CAAC,MAAM,cAAc,iBAAiB,cAAc,gBAAgB,UAAU,mBAAmB,eAAe;AAAA,IAC9H;AAAA,EACF;AAEA,MAAI,SAAS,OAAO,SAAS,GAAG;AAC9B,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,CAAC,MAAM,UAAU,cAAc,eAAe,UAAU,YAAY,SAAS,OAAO,UAAU,WAAW;AAAA,IACvH,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,OAAO,MAAM,GAAG;AAC3B,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,CAAC,MAAM,UAAU,cAAc,eAAe,YAAY,iBAAiB,aAAa,OAAO,eAAe,UAAU,gBAAgB,WAAW;AAAA,IACjK,CAAC;AACD,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,CAAC,MAAM,cAAc,SAAS,QAAQ,SAAS,cAAc,kBAAkB,oBAAoB;AAAA,IACjH,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,OAAO,aAAa,GAAG;AAClC,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,CAAC,MAAM,UAAU,cAAc,eAAe,YAAY,gBAAgB,sBAAsB,eAAe;AAAA,IAC7H,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,OAAO,KAAK,GAAG;AAC1B,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,CAAC,MAAM,UAAU,cAAc,eAAe,YAAY,UAAU,gBAAgB,eAAe,gBAAgB;AAAA,IACjI,CAAC;AAAA,EACH;AAEA,MAAI,gBAAgB;AAClB,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,CAAC,MAAM,UAAU,aAAa,WAAW,iBAAiB,kBAAkB,kBAAkB;AAAA,IAC5G,CAAC;AAAA,EACH;AAEA,MAAI,kBAAkB;AACpB,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,CAAC,MAAM,cAAc,eAAe,cAAc,eAAe,WAAW,eAAe,cAAc;AAAA,IACvH,CAAC;AAAA,EACH;AAEA,MAAI,eAAe;AACjB,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,CAAC,MAAM,cAAc,UAAU,WAAW,YAAY,aAAa,WAAW,cAAc,iBAAiB;AAAA,IAC3H,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,cAAc,OAA0B,kBAA2B,eAAuC;AACjH,QAAM,OAAsB;AAAA,IAC1B;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,MACT;AAAA,MACA,kBAAkB,CAAC,cAAc;AAAA,IACnC;AAAA,EACF;AAEA,MAAI,SAAS,OAAO,MAAM,GAAG;AAC3B,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,OAAO,CAAC,MAAM;AAAA,MACd,kBAAkB,CAAC,eAAe,sBAAsB,kBAAkB;AAAA,IAC5E,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,OAAO,SAAS,KAAK,SAAS,OAAO,aAAa,GAAG;AAChE,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,OAAO,MAAM,OAAO,CAAC,SAAS,SAAS,aAAa,SAAS,aAAa;AAAA,MAC1E,kBAAkB,CAAC,aAAa;AAAA,IAClC,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,OAAO,KAAK,KAAK,SAAS,OAAO,aAAa,GAAG;AAC5D,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,OAAO,MAAM,OAAO,CAAC,SAAS,SAAS,SAAS,SAAS,aAAa;AAAA,MACtE,kBAAkB,CAAC,aAAa;AAAA,IAClC,CAAC;AAAA,EACH;AAEA,MAAI,kBAAkB;AACpB,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT;AAAA,MACA,kBAAkB,CAAC;AAAA,IACrB,CAAC;AAAA,EACH;AAEA,MAAI,eAAe;AACjB,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT;AAAA,MACA,kBAAkB,CAAC;AAAA,IACrB,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,aAAa,OAA0B,kBAA2B,eAAkC;AAC3G,QAAM,UAAoB,CAAC,oBAAoB,0BAA0B,8BAA8B;AAEvG,MAAI,SAAS,OAAO,MAAM,GAAG;AAC3B,YAAQ,KAAK,sBAAsB,uBAAuB,qBAAqB,oCAAoC;AAAA,EACrH;AACA,MAAI,SAAS,OAAO,SAAS,GAAG;AAC9B,YAAQ,KAAK,yBAAyB,0BAA0B,2BAA2B,kBAAkB;AAAA,EAC/G;AACA,MAAI,SAAS,OAAO,aAAa,GAAG;AAClC,YAAQ,KAAK,wBAAwB,4BAA4B,mCAAmC;AAAA,EACtG;AACA,MAAI,SAAS,OAAO,KAAK,GAAG;AAC1B,YAAQ,KAAK,sBAAsB,2BAA2B,qBAAqB,oBAAoB;AAAA,EACzG;AACA,MAAI,iBAAkB,SAAQ,KAAK,uBAAuB,qBAAqB,oBAAoB;AACnG,MAAI,cAAe,SAAQ,KAAK,0BAA0B,wBAAwB;AAElF,SAAO;AACT;AAEA,SAAS,kBAAkB,QAA8B,UAA0B;AACjF,QAAM,QAAQ,QAAQ,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAAE,OAAO,OAAO,KAAK,CAAC;AACvE,MAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,SAAO,MAAM,IAAI,CAAC,UAAU,KAAK,KAAK,EAAE,EAAE,KAAK,IAAI;AACrD;AAEA,SAAS,YACP,OACA,OACA,OACA,QACA,MACA,SACA,YACA,cACA,oBACQ;AACR,QAAM,WAAW,kBAAkB,MAAM,UAAU,8BAA8B;AACjF,QAAM,YAAY,kBAAkB,MAAM,WAAW,uCAAuC;AAC5F,QAAM,cAAc,kBAAkB,MAAM,aAAa,iDAAiD;AAC1G,QAAM,QAAQ,MAAM,OAAO,KAAK,KAAK;AAErC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,YAAY,MAAM,eAAe,0BAA0B;AAAA,IAC3D,kBAAkB,gBAAgB,oBAAoB;AAAA,IACtD,6BAA6B,sBAAsB,2BAA2B;AAAA,IAC9E,oBAAoB,MAAM,YAAY,UAAU;AAAA,IAChD,mBAAmB,MAAM,KAAK,IAAI,CAAC;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,IAAI,CAAC,SAAS,KAAK,KAAK,IAAI,KAAK,KAAK,OAAO,EAAE,EAAE,KAAK,IAAI;AAAA,IAChE;AAAA,IACA;AAAA,IACA,OAAO,IAAI,CAAC,UAAU,KAAK,MAAM,IAAI,KAAK,MAAM,WAAW,KAAK,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI;AAAA,IAClF;AAAA,IACA;AAAA,IACA,0BAA0B,UAAU,kBAAkB,MAAM,YAAY,KAAK;AAAA,IAC7E;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,IAAI,CAAC,WAAW,KAAK,MAAM,EAAE,EAAE,KAAK,IAAI;AAAA,IAChD;AAAA,IACA;AAAA,IACA,MAAM,gBACF,uIACA;AAAA,IACJ;AAAA,IACA;AAAA,IACA,MAAM,mBACF,sJACA;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEO,SAAS,0BAA0B,OAAkD;AAC1F,QAAM,gBAAgB,YAAY,MAAM,aAAa;AACrD,QAAM,eAAe,gBAAgB,MAAM,YAAY;AACvD,QAAM,qBAAqB,MAAM,oBAAoB,KAAK,KAAK;AAC/D,QAAM,cAAc,MAAM,aAAa,KAAK,KAAK;AACjD,QAAM,WAAW,MAAM,YAAY;AACnC,QAAM,aAAa,eAAe,MAAM,mBAAmB,UAAU,MAAM,UAAU;AACrF,QAAM,QAAQ,cAAc,aAAa;AACzC,QAAM,SAAS,YAAY,eAAe,MAAM,qBAAqB,OAAO,MAAM,kBAAkB,OAAO,QAAQ,MAAM,aAAa,MAAM,CAAC;AAC7I,QAAM,OAAO,MAAM,gBAAgB,QAAQ,CAAC,IAAI,cAAc,eAAe,MAAM,qBAAqB,OAAO,MAAM,kBAAkB,KAAK;AAC5I,QAAM,UAAU,aAAa,eAAe,MAAM,qBAAqB,OAAO,MAAM,kBAAkB,KAAK;AAC3G,QAAM,uBAAuB,YAAY,OAAO,eAAe,OAAO,QAAQ,MAAM,SAAS,YAAY,cAAc,kBAAkB;AAEzI,QAAM,YAAkC;AAAA,IACtC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB;AAAA,IAClB;AAAA,IACA,MAAM;AAAA,MACJ,SAAS,MAAM,gBAAgB;AAAA,MAC/B,SAAS,MAAM,mBAAmB;AAAA,MAClC,YAAY,MAAM,gBAAgB,QAAQ,aAAa;AAAA,MACvD,UAAU,MAAM,YAAY;AAAA,MAC5B;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,OAAO;AAAA,IACX,KAAK,WAAW;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,EAAE,KAAK,IAAI;AAAA,IAClD;AAAA,IACA;AAAA,IACA,MAAM,IAAI,CAAC,SAAS,OAAO,KAAK,IAAI,QAAQ,KAAK,OAAO,EAAE,EAAE,KAAK,IAAI;AAAA,IACrE;AAAA,IACA;AAAA,IACA,OAAO,IAAI,CAAC,UAAU,OAAO,MAAM,IAAI,QAAQ,MAAM,OAAO,EAAE,EAAE,KAAK,IAAI;AAAA,IACzE;AAAA,IACA;AAAA,IACA,UAAU,KAAK,UACX,cAAc,UAAU,KAAK,OAAO;AAAA,YAAe,UAAU,KAAK,UAAU;AAAA,cAAmB,UAAU,KAAK,QAAQ;AAAA,UAAa,KAAK,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,KAAK,IAAI,CAAC,KACzK;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,SAAO;AAAA,IACL,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,IAChC,mBAAmB;AAAA,EACrB;AACF;;;AVzTO,SAAS,uBAAuB,OAAe;AACpD,SAAO;AAAA,IACL;AAAA,IACA,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,eAAe;AAAA,EACjB;AACF;AAEA,SAAS,6BAA6B,OAAe;AACnD,SAAO;AAAA,IACL;AAAA,IACA,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,eAAe;AAAA,EACjB;AACF;AAEA,SAAS,mBAAiE;AACxE,MAAI;AACF,UAAM,MAAMC,eAAc;AAC1B,eAAO,6BAAY,GAAG,EACnB,OAAO,OAAK,EAAE,SAAS,KAAK,CAAC,EAC7B,IAAI,QAAM,EAAE,UAAU,GAAG,aAAS,8BAAS,wBAAK,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,EACnE,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO,EACpC,MAAM,GAAG,GAAG;AAAA,EACjB,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,SAAS,6BAA6BC,SAAyB;AAC7D,EAAAA,QAAO;AAAA,IACL;AAAA,IACA,IAAI,6BAAiB,uBAAuB;AAAA,MAC1C,MAAM,OAAO;AAAA,QACX,WAAW,iBAAiB,EAAE,IAAI,QAAM;AAAA,UACtC,KAAK,YAAY,mBAAmB,EAAE,QAAQ,CAAC;AAAA,UAC/C,MAAM,EAAE;AAAA,UACR,UAAU;AAAA,QACZ,EAAE;AAAA,MACJ;AAAA,IACF,CAAC;AAAA,IACD;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,OAAO,KAAK,cAAc;AACxB,YAAM,YAAY,MAAM,QAAQ,UAAU,QAAQ,IAAI,UAAU,SAAS,CAAC,IAAI,UAAU;AACxF,YAAM,eAAW,4BAAS,mBAAmB,OAAO,aAAa,EAAE,CAAC,CAAC;AACrE,UAAI,CAAC,SAAS,SAAS,KAAK,EAAG,OAAM,IAAI,MAAM,oCAAoC;AACnF,YAAM,WAAO,kCAAa,wBAAKD,eAAc,GAAG,QAAQ,GAAG,MAAM;AACjE,aAAO,EAAE,UAAU,CAAC,EAAE,KAAK,IAAI,MAAM,UAAU,iBAAiB,KAAK,CAAC,EAAE;AAAA,IAC1E;AAAA,EACF;AACF;AAWO,SAAS,6BACdE,SACA,UACA,UAAiC,CAAC,GAC5B;AACN,QAAM,eAAe,QAAQ,wBAAwB;AACrD,QAAM,aAAa,eACf,2CACA;AACJ,QAAM,iBAAiB,CAAC,gBAAwB,GAAG,WAAW,GAAG,UAAU;AAE3E,MAAI,aAAc,8BAA6BA,OAAM;AAErD,EAAAA,QAAO,aAAa,eAAe;AAAA,IACjC,OAAO;AAAA,IACP,aAAa,eAAe,64BAAm4B;AAAA,IAC/5B,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,2BAA2B;AAAA,EACjE,GAAG,OAAO,UAAU,iBAAiB,MAAM,SAAS,WAAW,KAAK,GAAG,KAAK,CAAC;AAE7E,EAAAA,QAAO,aAAa,eAAe;AAAA,IACjC,OAAO;AAAA,IACP,aAAa,eAAe,iTAA4S;AAAA,IACxU,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,oBAAoB;AAAA,EAC1D,GAAG,OAAO,UAAU,iBAAiB,MAAM,SAAS,WAAW,KAAK,GAAG,KAAK,CAAC;AAE7E,EAAAA,QAAO,aAAa,eAAe;AAAA,IACjC,OAAO;AAAA,IACP,aAAa,eAAe,0hBAA2hB;AAAA,IACvjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,oBAAoB;AAAA,EAC1D,GAAG,OAAO,UAAU,iBAAiB,MAAM,SAAS,WAAW,KAAK,GAAG,KAAK,CAAC;AAE7E,EAAAA,QAAO,aAAa,iBAAiB;AAAA,IACnC,OAAO;AAAA,IACP,aAAa,eAAe,+cAA+c;AAAA,IAC3e,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,cAAc;AAAA,EACpD,GAAG,OAAO,UAAU,kBAAkB,MAAM,SAAS,YAAY,KAAK,GAAG,KAAK,CAAC;AAE/E,EAAAA,QAAO,aAAa,gBAAgB;AAAA,IAClC,OAAO;AAAA,IACP,aAAa,eAAe,qmBAAgmB;AAAA,IAC5nB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,+BAA+B;AAAA,EACrE,GAAG,OAAO,UAAU,kBAAkB,MAAM,SAAS,YAAY,KAAK,GAAG,KAAK,CAAC;AAE/E,EAAAA,QAAO,aAAa,cAAc;AAAA,IAChC,OAAO;AAAA,IACP,aAAa,eAAe,o1BAAo1B;AAAA,IACh3B,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,qBAAqB;AAAA,EAC3D,GAAG,OAAO,UAAU,gBAAgB,MAAM,SAAS,UAAU,KAAK,GAAG,KAAK,CAAC;AAE3E,EAAAA,QAAO,aAAa,mBAAmB;AAAA,IACrC,OAAO;AAAA,IACP,aAAa,eAAe,uZAAuZ;AAAA,IACnb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,uBAAuB;AAAA,EAC7D,GAAG,OAAO,UAAU,qBAAqB,MAAM,SAAS,eAAe,KAAK,GAAG,KAAK,CAAC;AAErF,EAAAA,QAAO,aAAa,sBAAsB;AAAA,IACxC,OAAO;AAAA,IACP,aAAa,eAAe,2cAA2c;AAAA,IACve,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,uBAAuB;AAAA,EAC7D,GAAG,OAAO,UAAU,wBAAwB,MAAM,SAAS,kBAAkB,KAAK,GAAG,KAAK,CAAC;AAE3F,EAAAA,QAAO,aAAa,uBAAuB;AAAA,IACzC,OAAO;AAAA,IACP,aAAa,eAAe,ygBAAygB;AAAA,IACriB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,8BAA8B;AAAA,EACpE,GAAG,OAAO,UAAU,wBAAwB,MAAM,SAAS,kBAAkB,KAAK,GAAG,KAAK,CAAC;AAE3F,EAAAA,QAAO,aAAa,sBAAsB;AAAA,IACxC,OAAO;AAAA,IACP,aAAa,eAAe,oRAAoR;AAAA,IAChT,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,4BAA4B;AAAA,EAClE,GAAG,OAAO,UAAU,uBAAuB,MAAM,SAAS,iBAAiB,KAAK,GAAG,KAAK,CAAC;AAEzF,EAAAA,QAAO,aAAa,iBAAiB;AAAA,IACnC,OAAO;AAAA,IACP,aAAa,eAAe,8gBAA+gB;AAAA,IAC3iB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,0BAA0B;AAAA,EAChE,GAAG,OAAO,UAAU,mBAAmB,MAAM,SAAS,aAAa,KAAK,GAAG,KAAK,CAAC;AAEjF,EAAAA,QAAO,aAAa,0BAA0B;AAAA,IAC5C,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,2BAA2B;AAAA,EACjE,GAAG,OAAO,UAAU,2BAA2B,MAAM,SAAS,qBAAqB,KAAK,GAAG,KAAK,CAAC;AAEjG,EAAAA,QAAO,aAAa,6BAA6B;AAAA,IAC/C,OAAO;AAAA,IACP,aAAa,eAAe,+eAA+e;AAAA,IAC3gB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,sCAAsC;AAAA,EAC5E,GAAG,OAAO,UAAU,8BAA8B,MAAM,SAAS,wBAAwB,KAAK,GAAG,KAAK,CAAC;AAEvG,EAAAA,QAAO,aAAa,6BAA6B;AAAA,IAC/C,OAAO;AAAA,IACP,aAAa,eAAe,gVAAgV;AAAA,IAC5W,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,qCAAqC;AAAA,EAC3E,GAAG,OAAO,UAAU,8BAA8B,MAAM,SAAS,wBAAwB,KAAK,GAAG,KAAK,CAAC;AAEvG,EAAAA,QAAO,aAAa,4BAA4B;AAAA,IAC9C,OAAO;AAAA,IACP,aAAa,eAAe,uaAAua;AAAA,IACnc,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,oCAAoC;AAAA,EAC1E,GAAG,OAAO,UAAU,6BAA6B,MAAM,SAAS,uBAAuB,KAAK,GAAG,KAAK,CAAC;AAErG,EAAAA,QAAO,aAAa,oBAAoB;AAAA,IACtC,OAAO;AAAA,IACP,aAAa,eAAe,kkBAAkkB;AAAA,IAC9lB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,sCAAsC;AAAA,EAC5E,GAAG,OAAO,UAAU,qBAAqB,MAAM,SAAS,eAAe,KAAK,GAAG,KAAK,CAAC;AAErF,EAAAA,QAAO,aAAa,eAAe;AAAA,IACjC,OAAO;AAAA,IACP,aAAa,eAAe,unBAAknB;AAAA,IAC9oB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,6BAA6B;AAAA,EACnE,GAAG,OAAO,UAAU,iBAAiB,MAAM,SAAS,WAAW,KAAK,GAAG,KAAK,CAAC;AAE7E,EAAAA,QAAO,aAAa,sBAAsB;AAAA,IACxC,OAAO;AAAA,IACP,aAAa,eAAe,glCAAglC;AAAA,IAC5mC,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,oCAAoC;AAAA,EAC1E,GAAG,OAAO,UAAU,wBAAwB,MAAM,SAAS,kBAAkB,KAAK,GAAG,KAAK,CAAC;AAE3F,EAAAA,QAAO,aAAa,iBAAiB;AAAA,IACnC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,6BAA6B,kBAAkB;AAAA,EAC9D,GAAG,OAAO,UAAU,mBAAmB,MAAM,SAAS,aAAa,KAAK,GAAG,KAAK,CAAC;AAEjF,EAAAA,QAAO,aAAa,oBAAoB;AAAA,IACtC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,6BAA6B,wBAAwB;AAAA,EACpE,GAAG,OAAO,UAAU,sBAAsB,KAAK,CAAC;AAEhD,EAAAA,QAAO,aAAa,gBAAgB;AAAA,IAClC,OAAO;AAAA,IACP,aAAa,eAAe,0vBAAqvB;AAAA,IACjxB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,cAAc;AAAA,EACpD,GAAG,OAAO,UAAU,kBAAkB,MAAM,SAAS,YAAY,KAAK,GAAG,KAAK,CAAC;AAE/E,EAAAA,QAAO,aAAa,iBAAiB;AAAA,IACnC,OAAO;AAAA,IACP,aAAa,eAAe,4dAAwd;AAAA,IACpf,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,uBAAuB;AAAA,EAC7D,GAAG,OAAO,UAAU,mBAAmB,MAAM,SAAS,aAAa,KAAK,GAAG,KAAK,CAAC;AAEjF,EAAAA,QAAO,aAAa,mBAAmB;AAAA,IACrC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,iBAAiB;AAAA,EACvD,GAAG,OAAO,UAAU,qBAAqB,MAAM,SAAS,eAAe,KAAK,GAAG,KAAK,CAAC;AAErF,EAAAA,QAAO,aAAa,0BAA0B;AAAA,IAC5C,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,uBAAuB,wBAAwB;AAAA,EAC9D,GAAG,OAAO,UAAU,2BAA2B,MAAM,SAAS,qBAAqB,KAAK,GAAG,KAAK,CAAC;AAEjG,EAAAA,QAAO,aAAa,yBAAyB;AAAA,IAC3C,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa,6BAA6B,gCAAgC;AAAA,EAC5E,GAAG,OAAO,UAAU,0BAA0B,KAAK,CAAC;AAEpD,EAAAA,QAAO,aAAa,gBAAgB;AAAA,IAClC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,EACF,GAAG,OAAO,UAAU,kBAAkB,MAAM,SAAS,YAAY,KAAK,GAAG,KAAK,CAAC;AAEjF;;;AW9XA,IAAM,QAAwC;AAAA,EAC5C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM;AACR;AAEA,SAAS,SAAS,OAAe,MAAY,SAA0B;AACrE,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,GAAG,MAAM,IAAI,CAAC,GAAG,KAAK,GAAG,MAAM,KAAK;AAC7C;AAEA,SAAS,QAAQ,OAAe,OAAiB,SAA0B;AACzE,QAAM,SAAS,MAAM,OAAO,GAAG,GAAG;AAClC,SAAO,KAAK,SAAS,QAAQ,SAAS,OAAO,CAAC,IAAI,MAAM,KAAK,SAAS,SAAS,SAAS,OAAO,CAAC,CAAC;AACnG;AAEO,SAAS,sBAAsB,SAAyC;AAC7E,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,cAAc,QAAQ,mBAAmB,yBAAyB;AACxE,QAAM,QAAQ,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcrB,QAAM,gBAAgB;AAAA,IACpB,uBAAuB,WAAW;AAAA,IAClC;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA,kCAAkC,WAAW;AAAA,EAC/C,EAAE,KAAK,IAAI;AAEX,SAAO;AAAA,IACL,SAAS,gBAAgB,QAAQ,OAAO,IAAI,QAAQ,KAAK;AAAA,IACzD,SAAS,yBAAyB,SAAS,KAAK;AAAA,IAChD,SAAS,OAAO,SAAS,KAAK;AAAA,IAC9B,GAAG,SAAS,qBAAqB,QAAQ,KAAK,CAAC,SAAS,QAAQ,OAAO;AAAA,IACvE;AAAA,IACA,SAAS,0LAA0L,QAAQ,KAAK;AAAA,IAChN;AAAA,IACA,GAAG,SAAS,SAAS,QAAQ,KAAK,CAAC,KAAK,SAAS,kBAAkB,SAAS,KAAK,CAAC;AAAA,IAClF,QAAQ,UAAU,CAAC,eAAe,eAAe,eAAe,kBAAkB,GAAG,KAAK;AAAA,IAC1F,QAAQ,WAAW,CAAC,eAAe,iBAAiB,gBAAgB,cAAc,oBAAoB,GAAG,KAAK;AAAA,IAC9G,QAAQ,SAAS,CAAC,yBAAyB,aAAa,iBAAiB,GAAG,KAAK;AAAA,IACjF,QAAQ,SAAS,CAAC,mBAAmB,sBAAsB,sBAAsB,uBAAuB,0BAA0B,6BAA6B,6BAA6B,4BAA4B,eAAe,GAAG,KAAK;AAAA,IAC/O,QAAQ,WAAW,CAAC,gBAAgB,2BAA2B,wBAAwB,iBAAiB,sBAAsB,gBAAgB,kBAAkB,uBAAuB,yBAAyB,GAAG,KAAK;AAAA,IACxN,QAAQ,WAAW,CAAC,gBAAgB,WAAW,eAAe,GAAG,KAAK;AAAA,IACtE,GAAG,SAAS,aAAa,QAAQ,KAAK,CAAC,KAAK,SAAS,qBAAqB,SAAS,KAAK,CAAC;AAAA,IACzF,QAAQ,SAAS,CAAC,iBAAiB,oBAAoB,gBAAgB,iBAAiB,mBAAmB,wBAAwB,GAAG,KAAK;AAAA,IAC3I,QAAQ,OAAO,CAAC,aAAa,gBAAgB,qBAAqB,uBAAuB,kBAAkB,gBAAgB,GAAG,KAAK;AAAA,IACnI;AAAA,IACA,SAAS,eAAe,SAAS,KAAK;AAAA,IACtC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,SAAS,UAAU,QAAQ,KAAK,CAAC;AAAA,IACpC;AAAA,IACA,SAAS,gBAAgB,SAAS,KAAK;AAAA,IACvC;AAAA,IACA;AAAA,IACA,SAAS,wBAAwB,SAAS,KAAK;AAAA,IAC/C;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,iCAAiC,SAAS,KAAK;AAAA,IACxD;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,gBAAgB,SAAS,KAAK;AAAA,IACvC;AAAA,IACA;AAAA,IACA,SAAS,4BAA4B,SAAS,KAAK;AAAA,IACnD;AAAA,IACA;AAAA,IACA,SAAS,gBAAgB,SAAS,KAAK;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;;;AtBjGA,IAAM,aACJ,QAAQ,KAAK,SAAS,SAAS,KAC/B,QAAQ,IAAI,4BAA4B;AAC1C,IAAM,sBAAsB,QAAQ,QAAQ,MAAM,SAAS,QAAQ,OAAO,KAAK;AAC/E,IAAM,YAAY,QAAQ,KAAK,SAAS,QAAQ,KAAK,QAAQ,KAAK,SAAS,IAAI;AAE/E,IAAI,CAAC,eAAe,uBAAuB,YAAY;AACrD,QAAM,UACJ,QAAQ,KAAK,SAAS,YAAY,KAClC,QAAQ,IAAI,aAAa,UACzB,QAAQ,IAAI,gBAAgB,OAC5B,CAAC,QAAQ,OAAO;AAElB,UAAQ,OAAO,MAAM,sBAAsB;AAAA,IACzC,SAAS;AAAA,IACT,OAAO,CAAC;AAAA,IACR,kBAAkB,QAAQ,QAAQ,IAAI,qBAAqB,KAAK,CAAC;AAAA,EACnE,CAAC,CAAC;AACF,UAAQ,KAAK,CAAC;AAChB;AAEA,SAAS,iBAAqC;AAC5C,QAAM,eAAe,QAAQ,IAAI,sBAAsB,KAAK;AAC5D,QAAM,QAAQ,CAAC,kBAAc,4BAAK,yBAAQ,GAAG,kBAAkB,CAAC,EAAE,OAAO,OAAO;AAChF,aAAW,QAAQ,OAAO;AACxB,QAAI;AACF,YAAM,YAAQ,8BAAa,MAAM,MAAM,EAAE,KAAK;AAC9C,UAAI,MAAO,QAAO;AAAA,IACpB,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAM,UACJ,QAAQ,IAAI,uBACZ,QAAQ,IAAI,mBACZ,QAAQ,IAAI,eACZ,eAAe,IACd,KAAK;AACR,IAAI,CAAC,QAAQ;AACX,UAAQ,OAAO,MAAM,iEAAiE;AACtF,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,UAAU,QAAQ,IAAI,sBAAsB,KAAK,KAAK,QAAQ,IAAI,cAAc,KAAK,KAAK;AAChG,IAAM,iBAAiB,QAAQ,IAAI,2BAA2B,KAAK,KAAK;AACxE,IAAM,SAAS,IAAI,sBAAU,EAAE,MAAM,eAAe,SAAS,gBAAgB,GAAG,EAAE,cAAc,oBAAoB,CAAC;AAErH,6BAA6B,QAAQ,IAAI,oBAAoB,SAAS,MAAM,CAAC;AAC7E,6BAA6B,QAAQ,EAAE,SAAS,QAAQ,eAAe,CAAC;AAExE,IAAM,YAAY,IAAI,kCAAqB;AAE3C,eAAe,OAAO;AACpB,QAAM,OAAO,QAAQ,SAAS;AAChC;AAEA,KAAK,EAAE,MAAM,SAAO;AAClB,UAAQ,OAAO,MAAM,GAAG,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,CAAI;AAC5E,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["import_node_fs","import_node_os","import_node_path","import_mcp","baseUrl","apiKey","import_node_fs","import_node_os","import_node_path","Papa","import_node_os","import_node_path","safe","rect","safe","outputBaseDir","finiteNumber","server","baseUrl","outputBaseDir","finiteNumber","exports","import_mcp","import_node_fs","import_node_path","import_node_fs","import_node_os","import_node_path","normalize","outputBaseDir","full","wordCount","import_zod","import_zod","NullableString","outputBaseDir","server","server"]}
1
+ {"version":3,"sources":["../../bin/mcp-stdio-server.ts","../../src/harvest-timeout.ts","../../src/lib/browser-service-env.ts","../../src/mcp/http-mcp-tool-executor.ts","../../src/mcp/browser-agent-mcp-server.ts","../../src/services/fanout/export.ts","../../src/version.ts","../../src/mcp/browser-agent-tool-schemas.ts","../../src/mcp/replay-annotator.ts","../../src/errors.ts","../../src/api/outbound-sanitize.ts","../../src/mcp/paa-mcp-server.ts","../../src/mcp/mcp-response-formatter.ts","../../src/mcp/workflow-catalog.ts","../../src/api/seo-link-graph.ts","../../src/api/seo-link-report.ts","../../src/api/seo-issues.ts","../../src/api/image-audit.ts","../../src/mcp/server-instructions.ts","../../src/mcp/mcp-tool-schemas.ts","../../src/schemas.ts","../../src/mcp/rank-tracker-blueprint.ts","../../src/install-terminal.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { HttpMcpToolExecutor } from '../src/mcp/http-mcp-tool-executor.js'\nimport { registerBrowserAgentMcpTools } from '../src/mcp/browser-agent-mcp-server.js'\nimport { registerPaaExtractorMcpTools, registerSerpIntelligenceCaptureTools } from '../src/mcp/paa-mcp-server.js'\nimport { SERVER_INSTRUCTIONS } from '../src/mcp/server-instructions.js'\nimport { renderInstallTerminal } from '../src/install-terminal.js'\nimport { PACKAGE_VERSION } from '../src/version.js'\n\nconst forceStdio =\n process.argv.includes('--stdio') ||\n process.env.MCP_SCRAPER_FORCE_STDIO === '1'\nconst interactiveTerminal = Boolean(process.stdin.isTTY && process.stdout.isTTY)\nconst wantsHelp = process.argv.includes('--help') || process.argv.includes('-h')\n\nif (!forceStdio && (interactiveTerminal || wantsHelp)) {\n const noColor =\n process.argv.includes('--no-color') ||\n process.env.NO_COLOR !== undefined ||\n process.env.FORCE_COLOR === '0' ||\n !process.stdout.isTTY\n\n process.stdout.write(renderInstallTerminal({\n version: PACKAGE_VERSION,\n color: !noColor,\n apiKeyConfigured: Boolean(process.env.MCP_SCRAPER_API_KEY?.trim()),\n }))\n process.exit(0)\n}\n\nfunction readApiKeyFile(): string | undefined {\n const explicitPath = process.env.MCP_SCRAPER_KEY_PATH?.trim()\n const paths = [explicitPath, join(homedir(), '.mcp-scraper-key')].filter(Boolean) as string[]\n for (const path of paths) {\n try {\n const value = readFileSync(path, 'utf8').trim()\n if (value) return value\n } catch {\n void 0\n }\n }\n return undefined\n}\n\nconst apiKey = (\n process.env.MCP_SCRAPER_API_KEY ??\n process.env.MCP_SCRAPER_KEY ??\n process.env.MCP_API_KEY ??\n readApiKeyFile()\n)?.trim()\nif (!apiKey) {\n process.stderr.write('MCP_SCRAPER_API_KEY env var or ~/.mcp-scraper-key is required\\n')\n process.exit(1)\n}\n\nconst baseUrl = process.env.MCP_SCRAPER_BASE_URL?.trim() || process.env.MCP_BASE_URL?.trim() || 'https://mcpscraper.dev'\nconst consoleBaseUrl = process.env.BROWSER_AGENT_CONSOLE_URL?.trim() || baseUrl\nconst server = new McpServer({ name: 'mcp-scraper', version: PACKAGE_VERSION }, { instructions: SERVER_INSTRUCTIONS })\n\nconst httpExecutor = new HttpMcpToolExecutor(baseUrl, apiKey)\nregisterPaaExtractorMcpTools(server, httpExecutor)\nregisterSerpIntelligenceCaptureTools(server, httpExecutor)\nregisterBrowserAgentMcpTools(server, { baseUrl, apiKey, consoleBaseUrl })\n\nconst transport = new StdioServerTransport()\n\nasync function main() {\n await server.connect(transport)\n}\n\nmain().catch(err => {\n process.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`)\n process.exit(1)\n})\n","export const VERCEL_FUNCTION_MAX_MS = 300_000\n\nexport const CLIENT_OVER_SERVER_MARGIN_MS = 15_000\n\nexport interface HarvestTimeoutBudget {\n serverMs: number\n clientMs: number\n}\n\nexport function harvestTimeoutBudget(maxQuestions: number, serpOnly = false): HarvestTimeoutBudget {\n const requested = Number.isFinite(maxQuestions) && maxQuestions > 0 ? Math.trunc(maxQuestions) : 30\n let serverMs: number\n if (serpOnly) serverMs = 110_000\n else if (requested <= 50) serverMs = 170_000\n else if (requested <= 100) serverMs = 230_000\n else serverMs = 285_000\n const clientMs = Math.min(serverMs + CLIENT_OVER_SERVER_MARGIN_MS, VERCEL_FUNCTION_MAX_MS - 5_000)\n return { serverMs, clientMs }\n}\n","export function browserServiceApiKey(): string | undefined {\n const value = (process.env.BROWSER_SERVICE_API_KEY ?? process.env.KERNEL_API_KEY)?.trim()\n return value || undefined\n}\n\nexport function browserServiceProxyId(): string | undefined {\n return undefined\n}\n\nexport function browserServiceProfileName(): string | undefined {\n const value = (\n process.env.BROWSER_AGENT_PROFILE_NAME ??\n process.env.BROWSER_SERVICE_PROFILE_NAME ??\n process.env.KERNEL_BROWSER_PROFILE_NAME ??\n process.env.KERNEL_PROFILE_NAME\n )?.trim()\n return value || undefined\n}\n\nexport function browserServiceProfileSaveChanges(): boolean | undefined {\n const value = (\n process.env.BROWSER_AGENT_PROFILE_SAVE_CHANGES ??\n process.env.BROWSER_SERVICE_PROFILE_SAVE_CHANGES ??\n process.env.KERNEL_BROWSER_PROFILE_SAVE_CHANGES ??\n process.env.KERNEL_PROFILE_SAVE_CHANGES\n )?.trim().toLowerCase()\n if (!value) return undefined\n if (['1', 'true', 'yes', 'on'].includes(value)) return true\n if (['0', 'false', 'no', 'off'].includes(value)) return false\n return undefined\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { IMcpToolExecutor, ISerpIntelligenceToolExecutor } from './IMcpToolExecutor.js'\nimport { harvestTimeoutBudget } from '../harvest-timeout.js'\nimport {\n browserServiceProfileName,\n browserServiceProfileSaveChanges,\n} from '../lib/browser-service-env.js'\nimport type {\n HarvestPaaInput,\n SearchSerpInput,\n ExtractUrlInput,\n MapSiteUrlsInput,\n ExtractSiteInput,\n AuditSiteInput,\n YoutubeHarvestInput,\n YoutubeTranscribeInput,\n FacebookPageIntelInput,\n FacebookAdSearchInput,\n RedditThreadInput,\n FacebookAdTranscribeInput,\n FacebookVideoTranscribeInput,\n GoogleAdsSearchInput,\n GoogleAdsPageIntelInput,\n GoogleAdsTranscribeInput,\n InstagramProfileContentInput,\n InstagramMediaDownloadInput,\n MapsPlaceIntelInput,\n MapsSearchInput,\n DirectoryWorkflowInput,\n CreditsInfoInput,\n WorkflowListInput,\n WorkflowRunInput,\n WorkflowStepInput,\n WorkflowStatusInput,\n WorkflowArtifactReadInput,\n CaptureSerpSnapshotInput,\n CaptureSerpPageSnapshotsInput,\n} from './mcp-tool-schemas.js'\n\nfunction youtubeVideoIdFromUrl(url: string | undefined): string | null {\n if (!url) return null\n try {\n const parsed = new URL(url)\n const host = parsed.hostname.replace(/^www\\./, '').replace(/^m\\./, '')\n if (host === 'youtu.be') {\n const id = parsed.pathname.split('/').filter(Boolean)[0]\n return id || null\n }\n if (host === 'youtube.com' || host === 'music.youtube.com') {\n const watchId = parsed.searchParams.get('v')\n if (watchId) return watchId\n const parts = parsed.pathname.split('/').filter(Boolean)\n const markerIndex = parts.findIndex(part => ['shorts', 'embed', 'live'].includes(part))\n if (markerIndex >= 0 && parts[markerIndex + 1]) return parts[markerIndex + 1]\n }\n } catch {\n return null\n }\n return null\n}\n\nasync function readResponseData(res: Response): Promise<unknown> {\n const text = await res.text()\n if (!text.trim()) return null\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n}\n\nfunction httpErrorPayload(path: string, res: Response, data: unknown): Record<string, unknown> {\n const objectData = data && typeof data === 'object' && !Array.isArray(data)\n ? data as Record<string, unknown>\n : null\n const bodyMessage = objectData\n ? objectData.message ?? objectData.error ?? objectData.error_code\n : data\n return {\n ...(objectData ?? { body: data }),\n error: objectData?.error ?? objectData?.error_code ?? 'mcp_http_error',\n error_type: 'http',\n retryable: res.status === 429 || res.status >= 500,\n status: res.status,\n statusText: res.statusText,\n path,\n message: typeof bodyMessage === 'string' && bodyMessage.trim()\n ? bodyMessage\n : `MCP Scraper HTTP ${res.status}${res.statusText ? ` ${res.statusText}` : ''} for ${path}`,\n }\n}\n\nfunction withDefaultHostedProfile<T extends { profile?: string; saveProfileChanges?: boolean }>(input: T): T {\n const profile = input.profile?.trim() || browserServiceProfileName()\n const saveProfileChanges = input.saveProfileChanges ?? browserServiceProfileSaveChanges()\n return {\n ...input,\n ...(profile ? { profile } : {}),\n ...(typeof saveProfileChanges === 'boolean' ? { saveProfileChanges } : {}),\n }\n}\n\nexport class HttpMcpToolExecutor implements IMcpToolExecutor, ISerpIntelligenceToolExecutor {\n private readonly baseUrl: string\n private readonly apiKey: string\n private readonly timeoutMs: number\n private readonly httpTimeoutOverrideMs: number | null\n private readonly serpIntelligenceTimeoutMs: number\n\n constructor(baseUrl: string, apiKey: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n this.apiKey = apiKey\n const rawOverride = process.env.MCP_SCRAPER_HTTP_TIMEOUT_MS\n const parsedOverride = rawOverride === undefined ? NaN : Number(rawOverride)\n this.httpTimeoutOverrideMs = Number.isFinite(parsedOverride) && parsedOverride > 0 ? parsedOverride : null\n this.timeoutMs = this.httpTimeoutOverrideMs ?? 110_000\n const configuredSerpIntelligenceTimeoutMs = Number(process.env.MCP_SCRAPER_SERP_INTELLIGENCE_HTTP_TIMEOUT_MS ?? this.timeoutMs)\n this.serpIntelligenceTimeoutMs = Number.isFinite(configuredSerpIntelligenceTimeoutMs) && configuredSerpIntelligenceTimeoutMs > 0\n ? configuredSerpIntelligenceTimeoutMs\n : this.timeoutMs\n }\n\n private async call(path: string, body: Record<string, unknown>, timeoutMs = this.timeoutMs): 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(timeoutMs),\n })\n const data = await readResponseData(res)\n if (!res.ok) {\n return { content: [{ type: 'text', text: JSON.stringify(httpErrorPayload(path, res, 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 if (err instanceof DOMException && err.name === 'TimeoutError') {\n return {\n content: [{\n type: 'text',\n text: JSON.stringify({\n error: 'mcp_request_timeout',\n error_type: 'timeout',\n retryable: true,\n path,\n timeoutMs,\n message: `MCP Scraper request exceeded ${Math.round(timeoutMs / 1000)}s and was cancelled. Retry with fewer results or use the async API for deep harvests.`,\n }),\n }],\n isError: true,\n }\n }\n return { content: [{ type: 'text', text: msg }], isError: true }\n }\n }\n\n private async getJson(path: string, timeoutMs = this.timeoutMs): Promise<CallToolResult> {\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: 'GET',\n headers: {\n 'x-api-key': this.apiKey,\n },\n signal: AbortSignal.timeout(timeoutMs),\n })\n const data = await readResponseData(res)\n if (!res.ok) {\n return { content: [{ type: 'text', text: JSON.stringify(httpErrorPayload(path, res, 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 private async getTextArtifact(path: string, maxBytes: number, timeoutMs = this.timeoutMs): Promise<CallToolResult> {\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: 'GET',\n headers: {\n 'x-api-key': this.apiKey,\n },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (!res.ok) {\n const data = await res.json().catch(async () => ({ error: await res.text().catch(() => `HTTP ${res.status}`) }))\n return { content: [{ type: 'text', text: JSON.stringify(data) }], isError: true }\n }\n const bytes = Buffer.from(await res.arrayBuffer())\n const sliced = bytes.subarray(0, Math.min(maxBytes, bytes.length))\n return {\n content: [{\n type: 'text',\n text: JSON.stringify({\n contentType: res.headers.get('content-type') ?? 'application/octet-stream',\n bytes: bytes.length,\n truncated: sliced.length < bytes.length,\n maxBytes,\n text: sliced.toString('utf8'),\n }),\n }],\n }\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 const timeoutMs = this.httpTimeoutOverrideMs ?? harvestTimeoutBudget(input.maxQuestions ?? 30).clientMs\n return this.call('/harvest/sync', input as Record<string, unknown>, timeoutMs)\n }\n\n searchSerp(input: SearchSerpInput): Promise<CallToolResult> {\n const timeoutMs = this.httpTimeoutOverrideMs ?? harvestTimeoutBudget(0, true).clientMs\n return this.call('/harvest/sync', { ...input, serpOnly: true } as Record<string, unknown>, timeoutMs)\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 auditSite(input: AuditSiteInput): 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 const videoId = input.videoId?.trim() || youtubeVideoIdFromUrl(input.url)\n if (!videoId) {\n return Promise.resolve({\n content: [{\n type: 'text',\n text: JSON.stringify({\n error_code: 'youtube_video_id_required',\n error: 'Pass videoId from youtube_harvest or a YouTube url that contains a video id.',\n retryable: false,\n }),\n }],\n isError: true,\n })\n }\n return this.call('/youtube/transcribe', { videoId })\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 redditThread(input: RedditThreadInput): Promise<CallToolResult> {\n return this.call('/reddit/thread', input as Record<string, unknown>, this.httpTimeoutOverrideMs ?? 240_000)\n }\n\n facebookAdTranscribe(input: FacebookAdTranscribeInput): Promise<CallToolResult> {\n return this.call('/facebook/transcribe', input as Record<string, unknown>)\n }\n\n facebookVideoTranscribe(input: FacebookVideoTranscribeInput): Promise<CallToolResult> {\n return this.call('/facebook/video-transcribe', input as Record<string, unknown>, this.httpTimeoutOverrideMs ?? 240_000)\n }\n\n googleAdsSearch(input: GoogleAdsSearchInput): Promise<CallToolResult> {\n return this.call('/google-ads/search', input as Record<string, unknown>, this.httpTimeoutOverrideMs ?? 240_000)\n }\n\n googleAdsPageIntel(input: GoogleAdsPageIntelInput): Promise<CallToolResult> {\n return this.call('/google-ads/page-intel', input as Record<string, unknown>, this.httpTimeoutOverrideMs ?? 300_000)\n }\n\n googleAdsTranscribe(input: GoogleAdsTranscribeInput): Promise<CallToolResult> {\n return this.call('/google-ads/transcribe', input as Record<string, unknown>, this.httpTimeoutOverrideMs ?? 240_000)\n }\n\n instagramProfileContent(input: InstagramProfileContentInput): Promise<CallToolResult> {\n return this.call('/instagram/profile-content', withDefaultHostedProfile(input) as Record<string, unknown>, this.httpTimeoutOverrideMs ?? 240_000)\n }\n\n instagramMediaDownload(input: InstagramMediaDownloadInput): Promise<CallToolResult> {\n return this.call('/instagram/media-download', withDefaultHostedProfile(input) as Record<string, unknown>, this.httpTimeoutOverrideMs ?? 300_000)\n }\n\n mapsPlaceIntel(input: MapsPlaceIntelInput): Promise<CallToolResult> {\n return this.call('/maps/place', input as Record<string, unknown>)\n }\n\n mapsSearch(input: MapsSearchInput): Promise<CallToolResult> {\n return this.call('/maps/search', input as Record<string, unknown>)\n }\n\n directoryWorkflow(input: DirectoryWorkflowInput): Promise<CallToolResult> {\n const cityCount = typeof input.maxCities === 'number' ? input.maxCities : 25\n const concurrency = typeof input.concurrency === 'number' && input.concurrency > 0 ? input.concurrency : 5\n const timeoutMs = this.httpTimeoutOverrideMs ?? Math.min(900_000, Math.max(180_000, Math.ceil(cityCount / concurrency) * 120_000))\n return this.call('/directory/run', input as Record<string, unknown>, timeoutMs)\n }\n\n workflowList(_input: WorkflowListInput): Promise<CallToolResult> {\n return this.getJson('/workflows/definitions')\n }\n\n workflowRun(input: WorkflowRunInput): Promise<CallToolResult> {\n const timeoutMs = this.httpTimeoutOverrideMs ?? Number(process.env.MCP_SCRAPER_WORKFLOW_TIMEOUT_MS ?? 900_000)\n return this.call('/workflows/run', {\n workflowId: input.workflowId,\n input: input.input ?? {},\n webhookUrl: input.webhookUrl,\n }, Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : 900_000)\n }\n\n workflowStep(input: WorkflowStepInput): Promise<CallToolResult> {\n const timeoutMs = this.httpTimeoutOverrideMs ?? Number(process.env.MCP_SCRAPER_WORKFLOW_TIMEOUT_MS ?? 900_000)\n return this.call(`/workflows/runs/${encodeURIComponent(input.runId)}/step`, {}, Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : 900_000)\n }\n\n workflowStatus(input: WorkflowStatusInput): Promise<CallToolResult> {\n return this.getJson(`/workflows/runs/${encodeURIComponent(input.runId)}`)\n }\n\n workflowArtifactRead(input: WorkflowArtifactReadInput): Promise<CallToolResult> {\n return this.getTextArtifact(\n `/workflows/runs/${encodeURIComponent(input.runId)}/artifacts/${encodeURIComponent(input.artifactId)}`,\n input.maxBytes ?? 200_000,\n )\n }\n\n creditsInfo(input: CreditsInfoInput): Promise<CallToolResult> {\n return this.call('/billing/credits', input as Record<string, unknown>)\n }\n\n captureSerpSnapshot(input: CaptureSerpSnapshotInput): Promise<CallToolResult> {\n return this.call('/serp-intelligence/capture', input as Record<string, unknown>, this.serpIntelligenceTimeoutMs)\n }\n\n captureSerpPageSnapshots(input: CaptureSerpPageSnapshotsInput): Promise<CallToolResult> {\n return this.call('/serp-intelligence/page-snapshots', input as Record<string, unknown>, this.serpIntelligenceTimeoutMs)\n }\n\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { browserServiceProfileName, browserServiceProfileSaveChanges } from '../lib/browser-service-env.js'\nimport { exportFanout } from '../services/fanout/export.js'\nimport type { EnrichedFanout } from '../services/fanout/classify.js'\nimport { PACKAGE_VERSION } from '../version.js'\nimport {\n BrowserOpenInputSchema,\n BrowserProfileConnectInputSchema,\n BrowserProfileListInputSchema,\n BrowserCaptureFanoutInputSchema,\n BrowserCaptureFanoutOutputSchema,\n BrowserSessionInputSchema,\n BrowserLocateInputSchema,\n BrowserGotoInputSchema,\n BrowserClickInputSchema,\n BrowserTypeInputSchema,\n BrowserScrollInputSchema,\n BrowserPressInputSchema,\n BrowserReplayStopInputSchema,\n BrowserReplayDownloadInputSchema,\n BrowserReplayMarkInputSchema,\n BrowserReplayAnnotateInputSchema,\n BrowserListInputSchema,\n BrowserOpenOutputSchema,\n BrowserScreenshotOutputSchema,\n BrowserReadOutputSchema,\n BrowserLocateOutputSchema,\n BrowserActionOutputSchema,\n BrowserReplayStartOutputSchema,\n BrowserReplayStopOutputSchema,\n BrowserListReplaysOutputSchema,\n BrowserReplayDownloadOutputSchema,\n BrowserReplayMarkOutputSchema,\n BrowserReplayAnnotateOutputSchema,\n BrowserCloseOutputSchema,\n BrowserListSessionsOutputSchema,\n BrowserProfileConnectOutputSchema,\n BrowserProfileListOutputSchema,\n} from './browser-agent-tool-schemas.js'\nimport { annotateReplayVideo } from './replay-annotator.js'\nimport { sanitizeOutboundDiagnostics } from '../api/outbound-sanitize.js'\n\nexport interface BrowserAgentHttpOptions {\n baseUrl: string\n apiKey: string\n consoleBaseUrl?: string\n timeoutMs?: number\n}\n\nfunction structuredResult(value: Record<string, unknown>, isError = false): CallToolResult {\n const safe = sanitizeOutboundDiagnostics(value)\n return {\n content: [{ type: 'text', text: JSON.stringify(safe) }],\n structuredContent: safe,\n isError,\n }\n}\n\nfunction errorMessage(value: unknown): string {\n if (value && typeof value === 'object') {\n const data = value as Record<string, unknown>\n if (typeof data.error === 'string') return data.error\n if (typeof data.message === 'string') return data.message\n }\n return typeof value === 'string' ? value : 'Browser Agent request failed'\n}\n\nfunction errorResult(tool: string, value: unknown, sessionId: string | null = null, replayId: string | null = null): CallToolResult {\n return structuredResult({\n ok: false,\n tool,\n session_id: sessionId,\n ...(replayId !== null ? { replay_id: replayId } : {}),\n error: errorMessage(value),\n raw: value && typeof value === 'object' ? value as Record<string, unknown> : { value },\n }, true)\n}\n\nfunction actionResult(\n tool: string,\n sessionId: string,\n ok: boolean,\n data: unknown,\n nextRecommendedTool: string | null = 'browser_screenshot',\n): CallToolResult {\n if (!ok) return errorResult(tool, data, sessionId)\n return structuredResult({\n ok: true,\n tool,\n session_id: sessionId,\n result: data && typeof data === 'object' ? data as Record<string, unknown> : { value: data },\n nextRecommendedTool,\n })\n}\n\nfunction outputBaseDir(): string {\n return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || join(homedir(), 'Downloads', 'mcp-scraper')\n}\n\nfunction safeFilePart(value: string): string {\n return value.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 120) || 'replay'\n}\n\nfunction replayFilePath(sessionId: string, replayId: string, filename?: string): string {\n const requested = filename?.trim()\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const name = requested\n ? safeFilePart(requested).replace(/\\.mp4$/i, '')\n : `${stamp}-${safeFilePart(sessionId)}-${safeFilePart(replayId)}`\n return join(outputBaseDir(), 'browser-replays', `${name}.mp4`)\n}\n\nfunction slugPart(value?: string): string | null {\n const trimmed = value?.trim().toLowerCase()\n if (!trimmed) return null\n return trimmed\n .replace(/^https?:\\/\\//, '')\n .replace(/^www\\./, '')\n .replace(/\\/.*$/, '')\n .replace(/[^a-z0-9._-]+/g, '-')\n .replace(/[._-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\nfunction savedProfileNameFromEmail(email?: string): string | null {\n const value = slugPart(email)\n if (!value) return null\n return value.slice(0, 80) || null\n}\n\nfunction isEnrichedFanout(value: unknown): value is EnrichedFanout {\n if (!value || typeof value !== 'object') return false\n const candidate = value as Partial<EnrichedFanout>\n return (\n typeof candidate.platform === 'string' &&\n typeof candidate.capturedAt === 'string' &&\n typeof candidate.prompt === 'string' &&\n Array.isArray(candidate.queries) &&\n Array.isArray(candidate.browsedUrls) &&\n Array.isArray(candidate.citedUrls) &&\n Array.isArray(candidate.browsedOnly) &&\n Array.isArray(candidate.snippets) &&\n !!candidate.counts &&\n !!candidate.aggregates\n )\n}\n\nfunction annotatedReplayFilePath(sessionId: string, replayId: string, filename?: string): string {\n const requested = filename?.trim()\n if (requested) return replayFilePath(sessionId, replayId, requested)\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n return replayFilePath(sessionId, replayId, `${stamp}-${safeFilePart(sessionId)}-${safeFilePart(replayId)}-annotated`)\n}\n\nfunction finiteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value)\n}\n\nfunction expandElementBounds(\n element: { left: number; top: number; width: number; height: number },\n viewport: { width?: number; height?: number } | undefined,\n padding: number,\n) {\n const sourceWidth = finiteNumber(viewport?.width) && viewport!.width > 0 ? viewport!.width : 1920\n const sourceHeight = finiteNumber(viewport?.height) && viewport!.height > 0 ? viewport!.height : 1080\n const left = Math.max(0, element.left - padding)\n const top = Math.max(0, element.top - padding)\n const right = Math.min(sourceWidth, element.left + element.width + padding)\n const bottom = Math.min(sourceHeight, element.top + element.height + padding)\n return {\n left,\n top,\n width: Math.max(1, right - left),\n height: Math.max(1, bottom - top),\n sourceWidth,\n sourceHeight,\n }\n}\n\nexport function buildBrowserAgentMcpServer(opts: BrowserAgentHttpOptions): McpServer {\n const server = new McpServer({ name: 'browser-agent', version: PACKAGE_VERSION })\n registerBrowserAgentMcpTools(server, opts)\n return server\n}\n\nexport function registerBrowserAgentMcpTools(server: McpServer, opts: BrowserAgentHttpOptions): void {\n const baseUrl = opts.baseUrl.replace(/\\/$/, '')\n const consoleBase = (opts.consoleBaseUrl ?? opts.baseUrl).replace(/\\/$/, '')\n const timeoutMs = opts.timeoutMs ?? 90_000\n\n async function req(\n method: string,\n path: string,\n body?: Record<string, unknown>,\n requestTimeoutMs = timeoutMs,\n ): Promise<{ ok: boolean; data: any }> {\n try {\n const res = await fetch(`${baseUrl}${path}`, {\n method,\n headers: { 'Content-Type': 'application/json', 'x-api-key': opts.apiKey },\n body: body ? JSON.stringify(body) : undefined,\n signal: AbortSignal.timeout(requestTimeoutMs),\n })\n const data = await res.json().catch(() => ({}))\n return { ok: res.ok, data }\n } catch (err) {\n return { ok: false, data: { error: err instanceof Error ? err.message : String(err) } }\n }\n }\n\n async function downloadReplay(\n sessionId: string,\n replayId: string,\n filename?: string,\n ): Promise<{ ok: boolean; data: any }> {\n const path = `/agent/sessions/${encodeURIComponent(sessionId)}/replays/${encodeURIComponent(replayId)}/download`\n try {\n const res = await fetch(`${baseUrl}${path}`, {\n method: 'GET',\n headers: { 'x-api-key': opts.apiKey },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (!res.ok) {\n const data = await res.json().catch(async () => ({ error: await res.text().catch(() => `HTTP ${res.status}`) }))\n return { ok: false, data }\n }\n const bytes = Buffer.from(await res.arrayBuffer())\n const filePath = replayFilePath(sessionId, replayId, filename)\n mkdirSync(join(outputBaseDir(), 'browser-replays'), { recursive: true })\n writeFileSync(filePath, bytes)\n return {\n ok: true,\n data: {\n replay_id: replayId,\n file_path: filePath,\n bytes: bytes.length,\n mime_type: res.headers.get('content-type') ?? 'video/mp4',\n download_url: `${baseUrl}${path}`,\n },\n }\n } catch (err) {\n return { ok: false, data: { error: err instanceof Error ? err.message : String(err) } }\n }\n }\n\n const annotations = (title: string, readOnly = false) => ({\n title,\n readOnlyHint: readOnly,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n })\n\n function normalizeLogin(conn: any) {\n return {\n connection_id: conn.connection_id ?? null,\n domain: conn.domain,\n status: conn.status,\n account_email: conn.account_email ?? null,\n note: conn.note ?? null,\n watch_url: conn.connection_id && conn.status !== 'AUTHENTICATED' ? `${consoleBase}/console/auth/${conn.connection_id}` : null,\n last_connected_at: conn.last_connected_at ?? null,\n }\n }\n\n async function fetchConnectedLogins(profile: string): Promise<unknown[]> {\n const list = await req('POST', '/agent/profiles/list', { profile })\n return list.ok && Array.isArray(list.data?.connections) ? list.data.connections.map(normalizeLogin) : []\n }\n\n server.registerTool(\n 'browser_profile_connect',\n {\n title: 'Save a Site Login to a Profile',\n description:\n 'Save a logged-in browser session so this server can reuse a site the user is signed into (ChatGPT, Claude, Reddit, or any account-gated site). Returns an mcpscraper.dev watch_url — give it to the user, they sign in once, and the cookies are saved to a named profile for later browser_open calls. ONE profile holds MANY logins: call this again with the SAME profile and a DIFFERENT domain to stack another account (e.g. add claude.ai to a profile that already has chatgpt.com). Pass note to record what each login is. Side effects: opens a short-lived sign-in session and persists cookies to the profile; it does NOT import the user\\'s existing browser cookies (they log in fresh). NOT for one-off scraping of public pages (use extract_url) and NOT a way to drive the browser (use browser_open). Sample asks: \"save my ChatGPT login\", \"connect my Reddit account\", \"add my Claude login to the same profile\". After the user signs in, poll browser_profile_list until the login reads AUTHENTICATED, then browser_open with the profile.',\n inputSchema: BrowserProfileConnectInputSchema,\n outputSchema: BrowserProfileConnectOutputSchema,\n annotations: annotations('Save a Site Login to a Profile'),\n },\n async input => {\n const domain = slugPart(input.domain) || 'chatgpt.com'\n const setupUrl = input.login_url ?? input.url ?? (domain === 'chatgpt.com' ? 'https://chatgpt.com/' : `https://${domain}/`)\n const profile = input.profile?.trim() || savedProfileNameFromEmail(input.email) || browserServiceProfileName()\n if (!profile) {\n return errorResult('browser_profile_connect', {\n error: 'profile or email is required when BROWSER_AGENT_PROFILE_NAME is not available',\n })\n }\n const accountEmail = input.email?.trim() || null\n const note = input.note?.trim() || null\n const open = await req('POST', '/agent/profiles/onboard', {\n label: input.label ?? `Login setup: ${domain} → ${profile}`,\n profile,\n domain,\n login_url: setupUrl,\n ...(accountEmail ? { account_email: accountEmail } : {}),\n ...(note ? { note } : {}),\n })\n if (!open.ok) return errorResult('browser_profile_connect', open.data)\n const connectedLogins = await fetchConnectedLogins(profile).catch(() => [])\n return structuredResult({\n ok: true,\n tool: 'browser_profile_connect',\n session_id: null,\n auth_connection_id: open.data.connection_id,\n watch_url: `${consoleBase}/console/auth/${open.data.connection_id}`,\n live_view_url: null,\n profile,\n domain,\n setup_url: setupUrl,\n account_email: accountEmail,\n note,\n status: open.data.status ?? null,\n flow_status: open.data.flow_status ?? null,\n flow_step: open.data.flow_step ?? null,\n flow_expires_at: open.data.flow_expires_at ?? null,\n post_login_url: open.data.post_login_url ?? null,\n connected_logins: connectedLogins,\n next_steps: [\n `Give the user watch_url so they can sign in to ${domain}.`,\n 'Poll browser_profile_list (with this profile) until the login reads AUTHENTICATED.',\n 'To add another account to this same profile, call browser_profile_connect again with the same profile and a different domain.',\n 'When authenticated, call browser_open with this profile to drive the logged-in session.',\n ],\n raw: open.data,\n })\n },\n )\n\n server.registerTool(\n 'browser_profile_list',\n {\n title: 'List Saved Logins in a Profile',\n description:\n 'List every site login saved in a profile, each with its current auth status (NEEDS_AUTH / AUTHENTICATED), account email, and note. Use it to (1) see what a profile is connected to before opening a session, and (2) poll a just-saved login until it flips to AUTHENTICATED. Read-only, no cost. Pass profile (or email to derive it); narrow with domain or connection_id to poll a single login. Sample asks: \"what\\'s connected in my profile\", \"is my ChatGPT login ready yet\", \"which accounts are saved\". Pairs with browser_profile_connect (which adds logins) and browser_open (which uses them).',\n inputSchema: BrowserProfileListInputSchema,\n outputSchema: BrowserProfileListOutputSchema,\n annotations: annotations('List Saved Logins in a Profile', true),\n },\n async input => {\n const profile = input.profile?.trim() || savedProfileNameFromEmail(input.email) || browserServiceProfileName()\n if (!profile) {\n return errorResult('browser_profile_list', {\n error: 'profile or email is required when BROWSER_AGENT_PROFILE_NAME is not available',\n })\n }\n const domain = slugPart(input.domain) || undefined\n const res = await req('POST', '/agent/profiles/list', {\n profile,\n ...(domain ? { domain } : {}),\n ...(input.connection_id ? { connection_id: input.connection_id } : {}),\n })\n if (!res.ok) return errorResult('browser_profile_list', res.data)\n const connections = (Array.isArray(res.data?.connections) ? res.data.connections : []).map(normalizeLogin)\n return structuredResult({\n ok: true,\n tool: 'browser_profile_list',\n session_id: null,\n profile,\n connections,\n count: connections.length,\n })\n },\n )\n\n server.registerTool(\n 'browser_open',\n {\n title: 'Open Browser Session',\n description:\n 'Open a direct no-proxy hosted browser session you can drive. Pass a saved profile name to load a session that is already logged into the sites saved in that profile (one profile can hold several logins). To set up or refresh a login first, use browser_profile_connect, then poll browser_profile_list until it reads AUTHENTICATED. Returns a session_id used by all other browser_* tools.',\n inputSchema: BrowserOpenInputSchema,\n outputSchema: BrowserOpenOutputSchema,\n annotations: annotations('Open Browser Session'),\n },\n async input => {\n const profile = input.profile ?? browserServiceProfileName()\n const saveProfileChanges = input.save_profile_changes ?? browserServiceProfileSaveChanges()\n const open = await req('POST', '/agent/sessions', {\n label: input.label,\n ...(profile ? { profile } : {}),\n ...(profile && typeof saveProfileChanges === 'boolean' ? { save_profile_changes: saveProfileChanges } : {}),\n disable_default_proxy: true,\n timeout_seconds: input.timeout_seconds,\n ...(input.url ? { url: input.url } : {}),\n })\n if (!open.ok) return errorResult('browser_open', open.data)\n const session = open.data\n return structuredResult({\n ok: true,\n tool: 'browser_open',\n session_id: session.session_id,\n watch_url: `${consoleBase}/console/${session.session_id}`,\n live_view_url: null,\n url: input.url ?? null,\n hint: 'Call browser_screenshot to see the page. Click by the x,y of an element from the snapshot.',\n raw: session,\n })\n },\n )\n\n server.registerTool(\n 'browser_screenshot',\n {\n title: 'See Page (Screenshot + Elements)',\n description:\n 'Capture what the browser currently shows. Returns a screenshot image PLUS a text snapshot listing interactive elements with their center x,y coordinates, the page url and title, and visible text. This is your primary way to perceive the page. Click elements by their listed x,y. If a Cloudflare/CAPTCHA challenge is visible, wait and screenshot again rather than clicking it.',\n inputSchema: BrowserSessionInputSchema,\n outputSchema: BrowserScreenshotOutputSchema,\n annotations: annotations('See Page', true),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/screenshot`)\n if (!res.ok) return errorResult('browser_screenshot', res.data, input.session_id)\n const { image_base64, mime_type, url, title, elements, text } = res.data\n const content: CallToolResult['content'] = []\n if (image_base64) content.push({ type: 'image', data: image_base64, mimeType: mime_type ?? 'image/png' })\n const structured = {\n ok: true,\n tool: 'browser_screenshot',\n session_id: input.session_id,\n url: url ?? null,\n title: title ?? null,\n text: typeof text === 'string' ? text : '',\n elements: Array.isArray(elements) ? elements : [],\n screenshot: image_base64 ? { mime_type: mime_type ?? 'image/png', inline: true } : null,\n }\n content.push({\n type: 'text',\n text: JSON.stringify(structured),\n })\n return { content, structuredContent: structured }\n },\n )\n\n server.registerTool(\n 'browser_read',\n {\n title: 'Read Page Text + Elements',\n description:\n 'Return the page url, title, visible text, and the list of interactive elements (with x,y) without an image. Cheaper than browser_screenshot when you only need to read content or find a target element to click.',\n inputSchema: BrowserSessionInputSchema,\n outputSchema: BrowserReadOutputSchema,\n annotations: annotations('Read Page', true),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/read`)\n if (!res.ok) return errorResult('browser_read', res.data, input.session_id)\n return structuredResult({\n ok: true,\n tool: 'browser_read',\n session_id: input.session_id,\n url: res.data?.url ?? null,\n title: res.data?.title ?? null,\n text: typeof res.data?.text === 'string' ? res.data.text : '',\n elements: Array.isArray(res.data?.elements) ? res.data.elements : [],\n raw: res.data,\n })\n },\n )\n\n server.registerTool(\n 'browser_locate',\n {\n title: 'Locate DOM Targets',\n description:\n 'Locate exact visible DOM elements or text ranges in the current browser viewport and return left/top/width/height bounds in screenshot pixels. Use this before drawing annotations or when a callout must literally circle, box, underline, or point to a real element. Prefer CSS selectors for exact UI elements; use text when selector is unknown. When a replay is actively recording, the result includes replay_elapsed_seconds for timing.',\n inputSchema: BrowserLocateInputSchema,\n outputSchema: BrowserLocateOutputSchema,\n annotations: annotations('Locate DOM Targets', true),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/locate`, { targets: input.targets })\n if (!res.ok) return errorResult('browser_locate', res.data, input.session_id)\n return structuredResult({\n ok: true,\n tool: 'browser_locate',\n session_id: input.session_id,\n url: res.data?.url ?? null,\n title: res.data?.title ?? null,\n viewport: res.data?.viewport ?? null,\n replay: res.data?.replay ?? null,\n targets: Array.isArray(res.data?.targets) ? res.data.targets : [],\n raw: res.data,\n })\n },\n )\n\n server.registerTool(\n 'browser_goto',\n {\n title: 'Navigate To URL',\n description: 'Navigate an existing browser session to a URL when the user asks you to go to another page or continue browsing in the same session. Use browser_open first if no session exists. Follow with browser_screenshot to see redirects, login walls, CAPTCHA/Cloudflare state, or the loaded page.',\n inputSchema: BrowserGotoInputSchema,\n outputSchema: BrowserActionOutputSchema,\n annotations: annotations('Navigate To URL'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/goto`, { url: input.url })\n return actionResult('browser_goto', input.session_id, res.ok, res.data, 'browser_screenshot')\n },\n )\n\n server.registerTool(\n 'browser_click',\n {\n title: 'Click',\n description: 'Click a visible page target using screenshot pixel coordinates. Use this when the user asks you to press a button, open a menu, choose a result, or activate a visible UI element. Use x/y only from the latest browser_screenshot, browser_read, or browser_locate result; do not guess coordinates. Follow with browser_screenshot when the click may change the page.',\n inputSchema: BrowserClickInputSchema,\n outputSchema: BrowserActionOutputSchema,\n annotations: annotations('Click'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/click`, {\n x: input.x,\n y: input.y,\n button: input.button,\n num_clicks: input.num_clicks,\n })\n return actionResult('browser_click', input.session_id, res.ok, res.data, 'browser_screenshot')\n },\n )\n\n server.registerTool(\n 'browser_type',\n {\n title: 'Type Text',\n description: 'Type text into the currently focused browser field. Use this when the user asks you to fill a search box, form field, login field, or editable text area. Click or Tab to the field first if focus is uncertain. Use browser_press with [\"Return\"] to submit, and browser_screenshot afterward when page state matters.',\n inputSchema: BrowserTypeInputSchema,\n outputSchema: BrowserActionOutputSchema,\n annotations: annotations('Type Text'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/type`, { text: input.text, delay: input.delay })\n return actionResult('browser_type', input.session_id, res.ok, res.data, 'browser_screenshot')\n },\n )\n\n server.registerTool(\n 'browser_scroll',\n {\n title: 'Scroll',\n description: 'Scroll the page to reveal more content before reading, clicking, or locating elements. Positive delta_y scrolls down; negative delta_y scrolls up. Follow with browser_screenshot or browser_read to inspect newly revealed content.',\n inputSchema: BrowserScrollInputSchema,\n outputSchema: BrowserActionOutputSchema,\n annotations: annotations('Scroll'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/scroll`, {\n delta_y: input.delta_y,\n delta_x: input.delta_x,\n x: input.x,\n y: input.y,\n })\n return actionResult('browser_scroll', input.session_id, res.ok, res.data, 'browser_screenshot')\n },\n )\n\n server.registerTool(\n 'browser_press',\n {\n title: 'Press Keys',\n description: 'Press keyboard keys or combinations in the active browser session. Use this for submit, Escape, Tab navigation, select-all, or keyboard shortcuts. Examples: [\"Return\"], [\"Escape\"], [\"Tab\"], [\"Ctrl+a\"], [\"Ctrl+Shift+Tab\"]. Use browser_type for text entry and browser_screenshot after keypresses that may change the page.',\n inputSchema: BrowserPressInputSchema,\n outputSchema: BrowserActionOutputSchema,\n annotations: annotations('Press Keys'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/press`, { keys: input.keys })\n return actionResult('browser_press', input.session_id, res.ok, res.data, 'browser_screenshot')\n },\n )\n\n server.registerTool(\n 'browser_replay_start',\n {\n title: 'Start Recording',\n description: 'Start recording an MP4 replay of the session. Returns replay_id, view_url when available, and a download_url. Use to capture a task for later review; stop with browser_replay_stop.',\n inputSchema: BrowserSessionInputSchema,\n outputSchema: BrowserReplayStartOutputSchema,\n annotations: annotations('Start Recording'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/replay/start`)\n if (!res.ok) return errorResult('browser_replay_start', res.data, input.session_id)\n return structuredResult({\n ok: true,\n tool: 'browser_replay_start',\n session_id: input.session_id,\n replay_id: res.data?.replay_id ?? res.data?.replayId ?? null,\n view_url: res.data?.view_url ?? res.data?.viewUrl ?? null,\n download_url: res.data?.download_url ?? res.data?.downloadUrl ?? null,\n raw: res.data,\n })\n },\n )\n\n server.registerTool(\n 'browser_replay_stop',\n {\n title: 'Stop Recording',\n description: 'Stop a replay recording and expose the final view_url and download_url. Use browser_replay_download to save the MP4 to the configured output directory.',\n inputSchema: BrowserReplayStopInputSchema,\n outputSchema: BrowserReplayStopOutputSchema,\n annotations: annotations('Stop Recording'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/replay/stop`, { replay_id: input.replay_id })\n if (!res.ok) return errorResult('browser_replay_stop', res.data, input.session_id, input.replay_id)\n return structuredResult({\n ok: true,\n tool: 'browser_replay_stop',\n session_id: input.session_id,\n replay_id: res.data?.replay_id ?? res.data?.replayId ?? input.replay_id,\n view_url: res.data?.view_url ?? res.data?.viewUrl ?? null,\n download_url: res.data?.download_url ?? res.data?.downloadUrl ?? null,\n raw: res.data,\n })\n },\n )\n\n server.registerTool(\n 'browser_list_replays',\n {\n title: 'List Replay Videos',\n description: 'List replay recordings for a browser session, including final view_url and authenticated download_url values when available.',\n inputSchema: BrowserSessionInputSchema,\n outputSchema: BrowserListReplaysOutputSchema,\n annotations: annotations('List Replay Videos', true),\n },\n async input => {\n const res = await req('GET', `/agent/sessions/${input.session_id}/replays`)\n if (!res.ok) return errorResult('browser_list_replays', res.data, input.session_id)\n const replays = Array.isArray(res.data?.replays) ? res.data.replays : []\n return structuredResult({\n ok: true,\n tool: 'browser_list_replays',\n session_id: input.session_id,\n replays,\n count: replays.length,\n })\n },\n )\n\n server.registerTool(\n 'browser_replay_download',\n {\n title: 'Download Replay MP4',\n description: 'Download a replay recording through MCP Scraper and save the MP4 under MCP_SCRAPER_OUTPUT_DIR/browser-replays. Use after browser_replay_stop or browser_list_replays.',\n inputSchema: BrowserReplayDownloadInputSchema,\n outputSchema: BrowserReplayDownloadOutputSchema,\n annotations: annotations('Download Replay MP4'),\n },\n async input => {\n const res = await downloadReplay(input.session_id, input.replay_id, input.filename)\n if (!res.ok) return errorResult('browser_replay_download', res.data, input.session_id, input.replay_id)\n return structuredResult({\n ok: true,\n tool: 'browser_replay_download',\n session_id: input.session_id,\n replay_id: input.replay_id,\n file_path: res.data?.file_path ?? null,\n bytes: typeof res.data?.bytes === 'number' ? res.data.bytes : null,\n mime_type: res.data?.mime_type ?? null,\n download_url: res.data?.download_url ?? null,\n })\n },\n )\n\n server.registerTool(\n 'browser_replay_mark',\n {\n title: 'Mark Replay Annotation',\n description:\n 'While a replay is actively recording, locate one exact DOM target and return a ready-to-use annotation object with DOM bounds and replay-relative timing. Use this instead of guessing start_seconds or drawing rough rectangles. Workflow: start browser_replay_start, navigate until the target is visible and stable, call browser_replay_mark for each callout, then stop the replay and pass the returned annotations to browser_replay_annotate.',\n inputSchema: BrowserReplayMarkInputSchema,\n outputSchema: BrowserReplayMarkOutputSchema,\n annotations: annotations('Mark Replay Annotation', true),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/locate`, { targets: [input.target] })\n if (!res.ok) return errorResult('browser_replay_mark', res.data, input.session_id)\n const target = res.data?.targets?.[0]\n const element = target?.element\n const elapsed = res.data?.replay?.replay_elapsed_seconds\n if (!target?.found || !element) {\n return errorResult('browser_replay_mark', { error: target?.error ?? 'target not found in current viewport', target }, input.session_id)\n }\n if (!finiteNumber(elapsed)) {\n return errorResult('browser_replay_mark', { error: 'no active replay clock found; call browser_replay_start before browser_replay_mark' }, input.session_id)\n }\n const padded = expandElementBounds(element, res.data?.viewport, input.padding ?? 8)\n const start = Math.max(0, elapsed + (input.start_offset_seconds ?? -0.25))\n const duration = input.duration_seconds ?? 4\n const annotation = {\n type: input.type ?? 'box',\n start_seconds: Number(start.toFixed(3)),\n end_seconds: Number((start + duration).toFixed(3)),\n left: Math.round(padded.left),\n top: Math.round(padded.top),\n width: Math.round(padded.width),\n height: Math.round(padded.height),\n ...(input.label ? { label: input.label } : {}),\n ...(input.color ? { color: input.color } : {}),\n ...(input.thickness ? { thickness: input.thickness } : {}),\n }\n return structuredResult({\n ok: true,\n tool: 'browser_replay_mark',\n session_id: input.session_id,\n replay_id: res.data?.replay?.replay_id ?? res.data?.replay?.replayId ?? null,\n annotation,\n source_width: padded.sourceWidth,\n source_height: padded.sourceHeight,\n replay: res.data.replay,\n target,\n hint: 'Append annotation to your annotations array. Use source_width/source_height with browser_replay_annotate.',\n })\n },\n )\n\n server.registerTool(\n 'browser_replay_annotate',\n {\n title: 'Annotate Replay MP4',\n description:\n 'Download a browser replay MP4, render visual annotations over it, and save a new annotated MP4 under MCP_SCRAPER_OUTPUT_DIR/browser-replays. Use this after browser_replay_stop when the user wants proof videos with circles, boxes, arrows, underlines, or labels. For accurate timing and placement, prefer annotations returned by browser_replay_mark while the replay is recording; otherwise use exact left/top/width/height bounds from browser_locate. If the replay video size differs from the screenshot coordinate space, pass source_width and source_height.',\n inputSchema: BrowserReplayAnnotateInputSchema,\n outputSchema: BrowserReplayAnnotateOutputSchema,\n annotations: annotations('Annotate Replay MP4'),\n },\n async input => {\n const sourceName = input.filename ? `${input.filename}-source` : undefined\n const downloaded = await downloadReplay(input.session_id, input.replay_id, sourceName)\n if (!downloaded.ok) return errorResult('browser_replay_annotate', downloaded.data, input.session_id, input.replay_id)\n try {\n const sourcePath = String(downloaded.data.file_path)\n const outputPath = annotatedReplayFilePath(input.session_id, input.replay_id, input.filename)\n mkdirSync(join(outputBaseDir(), 'browser-replays'), { recursive: true })\n const result = await annotateReplayVideo(sourcePath, outputPath, {\n annotations: input.annotations,\n sourceWidth: input.source_width,\n sourceHeight: input.source_height,\n sourceLeftOffset: input.source_left_offset,\n sourceTopOffset: input.source_top_offset,\n })\n return structuredResult({\n ok: true,\n tool: 'browser_replay_annotate',\n session_id: input.session_id,\n replay_id: input.replay_id,\n source_file_path: sourcePath,\n annotated_file_path: result.filePath,\n bytes: result.bytes,\n width: result.width,\n height: result.height,\n annotation_count: result.annotationCount,\n mime_type: 'video/mp4',\n })\n } catch (err) {\n return errorResult('browser_replay_annotate', { error: err instanceof Error ? err.message : String(err) }, input.session_id, input.replay_id)\n }\n },\n )\n\n server.registerTool(\n 'browser_close',\n {\n title: 'Close Browser Session',\n description: 'Close and release a browser session when the task is done, when the user asks to stop the browser, or when active browser billing should end. Use browser_list_sessions first if you need to recover the session_id.',\n inputSchema: BrowserSessionInputSchema,\n outputSchema: BrowserCloseOutputSchema,\n annotations: { title: 'Close Browser Session', readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },\n },\n async input => {\n const res = await req('DELETE', `/agent/sessions/${input.session_id}`)\n if (!res.ok) return errorResult('browser_close', res.data, input.session_id)\n return structuredResult({\n ok: true,\n tool: 'browser_close',\n session_id: input.session_id,\n closed: true,\n raw: res.data,\n })\n },\n )\n\n server.registerTool(\n 'browser_list_sessions',\n {\n title: 'List Browser Sessions',\n description: 'List browser sessions and their status, with a watch_url for each. Use this to recover a session_id, find an active browser, or decide which session to close. Use browser_open to create a new session.',\n inputSchema: BrowserListInputSchema,\n outputSchema: BrowserListSessionsOutputSchema,\n annotations: annotations('List Browser Sessions', true),\n },\n async input => {\n const res = await req('GET', `/agent/sessions${input.include_closed ? '?all=1' : ''}`)\n if (!res.ok) return errorResult('browser_list_sessions', res.data)\n const sessions = (res.data.sessions ?? []).map((s: any) => ({ ...s, watch_url: `${consoleBase}/console/${s.session_id}` }))\n return structuredResult({\n ok: true,\n tool: 'browser_list_sessions',\n session_id: null,\n sessions,\n count: sessions.length,\n })\n },\n )\n\n server.registerTool(\n 'query_fanout_workflow',\n {\n title: 'Capture AI Search Fan-Out',\n description:\n 'Capture the query fan-out behind a ChatGPT or Claude web-search answer for Answer Engine Optimization (AEO): the exact sub-queries the model issued, every researched URL split into cited vs browsed-only (with citation frequency and snippet), each source tagged by category (First-party/vendor, News/media, Reddit, Social/video, Encyclopedia, Review site, Docs, Blog), plus top sourced sites and citation order. Set export=true for durable JSON, CSV, TSV, and HTML artifacts; export paths are returned relative to MCP_SCRAPER_OUTPUT_DIR. This returns the raw structured data; YOU analyze it — classify each sub-query by funnel stage (Problem-aware, Solution-aware, Decision-aware, Retention) and type (BoFu, Branded, Comparison, How-to, Search operator), name the brands the model researched, and give AEO insights. Sample asks: \"capture the fan-out for this ChatGPT answer\", \"what did Claude search and cite for best CRM\", \"show the sub-queries and sources behind this AI answer\". WRITE NOTE: passing prompt submits a real message in the user\\'s logged-in account (a new conversation turn) — only send when the user wants that; omit prompt to capture a prompt the user just ran. Setup, if not already connected or if the profile disconnected: call browser_profile_connect, give the user the watch_url, let them complete login, then poll browser_profile_list until status is AUTHENTICATED. After that, browser_open the saved direct no-proxy profile and go to chatgpt.com or claude.ai. Fan-out is captured only as it streams, so the session must be open when the prompt runs. NOT for Google AI Overview citations — use harvest_paa for those; this tool is ChatGPT and Claude only.',\n inputSchema: BrowserCaptureFanoutInputSchema,\n outputSchema: BrowserCaptureFanoutOutputSchema,\n annotations: annotations('Capture AI Search Fan-Out'),\n },\n async input => {\n const emit = (result: Record<string, unknown>, exports: unknown) => structuredResult({\n ok: true,\n tool: 'query_fanout_workflow',\n session_id: input.session_id,\n platform: result.platform,\n captured_at: result.capturedAt,\n prompt: result.prompt,\n meta: result.meta,\n queries: result.queries,\n browsed_urls: result.browsedUrls,\n cited_urls: result.citedUrls,\n browsed_only: result.browsedOnly,\n snippets: result.snippets,\n counts: result.counts,\n aggregates: result.aggregates,\n first_party_domain: result.firstPartyDomain,\n exports: exports ?? null,\n ...(result.debug ? { debug: result.debug } : {}),\n })\n const res = await req('POST', `/agent/sessions/${input.session_id}/capture-fanout`, {\n prompt: input.prompt,\n wait_ms: input.wait_ms,\n first_party_domain: input.first_party_domain,\n reset: input.reset,\n export: input.export,\n }, Math.max(timeoutMs, (input.wait_ms ?? (input.prompt ? 90_000 : 8_000)) + 30_000))\n if (!res.ok) return errorResult('query_fanout_workflow', res.data, input.session_id)\n const hosted = (res.data?.result ?? res.data) as Record<string, unknown>\n let exports = res.data?.exports ?? null\n if (input.export && !exports && isEnrichedFanout(hosted)) {\n try {\n exports = exportFanout(hosted)\n } catch (err) {\n return errorResult(\n 'query_fanout_workflow',\n {\n error: `Fan-out captured but local export failed: ${err instanceof Error ? err.message : String(err)}`,\n result: hosted,\n },\n input.session_id,\n )\n }\n }\n return emit(hosted, exports)\n },\n )\n\n}\n","import { mkdirSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport Papa from 'papaparse'\nimport type { EnrichedFanout } from './classify.js'\n\nexport interface FanoutExportPaths {\n relativeTo: string\n dir: string\n json: string\n queriesCsv: string\n queriesTsv: string\n citationsCsv: string\n sourcesCsv: string\n browsedOnlyCsv: string\n snippetsCsv: string\n domainsCsv: string\n report: string\n}\n\nfunction outputBaseDir(): string {\n return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || join(homedir(), 'Downloads', 'mcp-scraper')\n}\n\nfunction safe(value: string): string {\n return value.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 80) || 'capture'\n}\n\nfunction writeTable(path: string, rows: Array<Record<string, unknown>>, delimiter: ','): void\nfunction writeTable(path: string, rows: Array<Record<string, unknown>>, delimiter: '\\t'): void\nfunction writeTable(path: string, rows: Array<Record<string, unknown>>, delimiter: string): void {\n writeFileSync(path, Papa.unparse(rows.length ? rows : [{}], { delimiter }))\n}\n\nexport function exportFanout(enriched: EnrichedFanout): FanoutExportPaths {\n const stamp = safe(enriched.capturedAt.replace(/[:.]/g, '-'))\n const outputDir = outputBaseDir()\n const relativeDir = join('fanout', `${stamp}-${safe(enriched.platform)}`)\n const dir = join(outputDir, relativeDir)\n mkdirSync(dir, { recursive: true })\n\n const queryRows = enriched.queries.map((q, i) => ({ index: i + 1, query: q }))\n const citationRows = enriched.aggregates.citationOrder.map((c) => {\n const src = enriched.citedUrls.find((s) => s.url === c.url)\n return { rank: c.rank, domain: c.domain, url: c.url, timesCited: c.timesCited, siteType: src?.siteType ?? '', title: src?.title ?? '' }\n })\n const sourceRows = enriched.browsedUrls.map((s) => ({ domain: s.domain, url: s.url, cited: s.cited, timesCited: s.timesCited, siteType: s.siteType, title: s.title, round: s.round ?? '' }))\n const browsedOnlyRows = enriched.browsedOnly.map((s) => ({ domain: s.domain, url: s.url, cited: s.cited, timesCited: s.timesCited, siteType: s.siteType, title: s.title, round: s.round ?? '' }))\n const snippetRows = enriched.snippets.map((s) => ({ domain: s.domain, url: s.url, title: s.title, text: s.text }))\n const domainRows = enriched.aggregates.topSites.map((d) => ({ domain: d.domain, count: d.count, cited: d.cited, timesCited: d.timesCited, siteType: d.siteType }))\n\n const relativePaths: FanoutExportPaths = {\n relativeTo: 'MCP_SCRAPER_OUTPUT_DIR or ~/Downloads/mcp-scraper',\n dir: relativeDir,\n json: join(relativeDir, 'fanout.json'),\n queriesCsv: join(relativeDir, 'queries.csv'),\n queriesTsv: join(relativeDir, 'queries.tsv'),\n citationsCsv: join(relativeDir, 'citations.csv'),\n sourcesCsv: join(relativeDir, 'sources.csv'),\n browsedOnlyCsv: join(relativeDir, 'browsed-only.csv'),\n snippetsCsv: join(relativeDir, 'snippets.csv'),\n domainsCsv: join(relativeDir, 'domains.csv'),\n report: join(relativeDir, 'report.html'),\n }\n\n writeFileSync(join(outputDir, relativePaths.json), JSON.stringify(enriched, null, 2))\n writeTable(join(outputDir, relativePaths.queriesCsv), queryRows, ',')\n writeTable(join(outputDir, relativePaths.queriesTsv), queryRows, '\\t')\n writeTable(join(outputDir, relativePaths.citationsCsv), citationRows, ',')\n writeTable(join(outputDir, relativePaths.sourcesCsv), sourceRows, ',')\n writeTable(join(outputDir, relativePaths.browsedOnlyCsv), browsedOnlyRows, ',')\n writeTable(join(outputDir, relativePaths.snippetsCsv), snippetRows, ',')\n writeTable(join(outputDir, relativePaths.domainsCsv), domainRows, ',')\n writeFileSync(join(outputDir, relativePaths.report), renderReportHtml(enriched))\n\n return relativePaths\n}\n\nfunction esc(s: string): string {\n return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;')\n}\n\nexport function renderReportHtml(enriched: EnrichedFanout): string {\n const data = JSON.stringify(enriched).replace(/</g, '\\\\u003c')\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>AI Search Fan-Out — ${esc(enriched.platform)}</title>\n<style>\n:root{--bg:#0b0d12;--panel:#151922;--line:#252b38;--ink:#e8ecf3;--mut:#8b95a7;--acc:#5b9dff;--cite:#39d98a;--browse:#5a6677}\n*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.5 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}\n.wrap{max-width:980px;margin:0 auto;padding:28px 20px 80px}\nh1{font-size:20px;margin:0 0 2px}.sub{color:var(--mut);margin:0 0 20px;font-size:13px}\n.stat{font-size:30px;font-weight:700}.stat small{font-size:13px;font-weight:400;color:var(--mut)}\n.cards{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin:18px 0}\n.card{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:12px 14px}\n.card b{font-size:22px;display:block}.card span{color:var(--mut);font-size:12px}\n.bars{margin:8px 0 22px}.bar{display:flex;align-items:center;gap:8px;margin:4px 0}\n.bar .lab{width:150px;color:var(--mut);font-size:12px;text-align:right}.bar .track{flex:1;background:#10141c;border-radius:5px;overflow:hidden}\n.bar .fill{background:var(--acc);height:16px}.bar .n{width:34px;font-size:12px;color:var(--mut)}\n.tabs{display:flex;gap:8px;margin:22px 0 12px}.tab{background:var(--panel);border:1px solid var(--line);color:var(--ink);padding:7px 14px;border-radius:8px;cursor:pointer}\n.tab.on{background:var(--acc);border-color:var(--acc);color:#04101f;font-weight:600}\n.chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px}\n.chip{background:var(--panel);border:1px solid var(--line);color:var(--mut);padding:4px 10px;border-radius:20px;cursor:pointer;font-size:12px}\n.chip.on{border-color:var(--acc);color:var(--ink)}.chip b{color:var(--ink)}\n.row{background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:10px 12px;margin:6px 0;display:flex;gap:10px;align-items:flex-start}\n.row .idx{color:var(--mut);min-width:22px}.row .main{flex:1}\n.tag{font-size:11px;padding:2px 7px;border-radius:6px;border:1px solid var(--line);color:var(--mut);margin-right:5px}\n.dom{font-weight:600}.url{color:var(--mut);font-size:12px;word-break:break-all}\n.pill{font-size:11px;padding:2px 7px;border-radius:6px}.pill.cite{background:rgba(57,217,138,.15);color:var(--cite)}.pill.brow{background:rgba(90,102,119,.2);color:#aeb8c8}\n.copy{background:none;border:1px solid var(--line);color:var(--mut);border-radius:6px;cursor:pointer;font-size:11px;padding:2px 8px}\n.hide{display:none}\n</style>\n</head>\n<body><div class=\"wrap\">\n<h1>AI Search Fan-Out</h1>\n<p class=\"sub\" id=\"sub\"></p>\n<div class=\"stat\" id=\"stat\"></div>\n<div class=\"cards\" id=\"cards\"></div>\n<div id=\"charts\"></div>\n<div class=\"tabs\"><button class=\"tab on\" data-tab=\"q\">Queries</button><button class=\"tab\" data-tab=\"u\">URLs</button></div>\n<div class=\"chips\" id=\"chips\"></div>\n<div id=\"list\"></div>\n</div>\n<script>\nconst D=${data};\nconst el=(t,c,h)=>{const e=document.createElement(t);if(c)e.className=c;if(h!=null)e.innerHTML=h;return e};\ndocument.getElementById('sub').textContent=D.platform+' · '+(D.meta.model||'model n/a')+' · '+D.meta.rounds+' search round(s) · prompt: '+(D.prompt||'');\ndocument.getElementById('stat').innerHTML='Total Fan-Out: '+D.counts.subQueries+' <small>sub-queries · '+D.counts.browsed+' URLs researched · '+D.counts.cited+' cited</small>';\nconst cards=[['Sub-queries',D.counts.subQueries],['Researched',D.counts.browsed],['Cited',D.counts.cited],['Browsed-only',D.counts.browsedOnly]];\nconst cc=document.getElementById('cards');cards.forEach(([k,v])=>{const c=el('div','card');c.appendChild(el('b',null,v));c.appendChild(el('span',null,k));cc.appendChild(c)});\nfunction barChart(title,obj){const max=Math.max(1,...Object.values(obj));const box=el('div','bars');box.appendChild(el('div',null,'<b>'+title+'</b>'));Object.entries(obj).forEach(([k,v])=>{const r=el('div','bar');r.appendChild(el('div','lab',k));const t=el('div','track');const f=el('div','fill');f.style.width=(v/max*100)+'%';t.appendChild(f);r.appendChild(t);r.appendChild(el('div','n',v));box.appendChild(r)});return box}\nconst charts=document.getElementById('charts');\ncharts.appendChild(barChart('URL Categories',D.aggregates.byCategory));\nlet tab='q',filter=null;\nconst chips=document.getElementById('chips'),list=document.getElementById('list');\nfunction render(){\n chips.innerHTML='';list.innerHTML='';\n if(tab==='q'){\n D.queries.forEach((q,i)=>{const r=el('div','row');r.appendChild(el('div','idx',i+1));const m=el('div','main');m.appendChild(el('div',null,esc(q)));r.appendChild(m);const b=el('button','copy','copy');b.onclick=()=>navigator.clipboard.writeText(q);r.appendChild(b);list.appendChild(r)});\n } else {\n const counts={};D.browsedUrls.forEach(s=>{counts[s.siteType]=(counts[s.siteType]||0)+1});\n Object.entries(counts).forEach(([k,v])=>{const c=el('button','chip'+(filter===k?' on':''),k+' <b>'+v+'</b>');c.onclick=()=>{filter=filter===k?null:k;render()};chips.appendChild(c)});\n D.browsedUrls.forEach(s=>{if(filter&&s.siteType!==filter)return;const r=el('div','row');const m=el('div','main');m.appendChild(el('div',null,'<span class=\"dom\">'+esc(s.domain)+'</span> <span class=\"pill '+(s.cited?'cite':'brow')+'\">'+(s.cited?'cited '+s.timesCited+'×':'browsed')+'</span> <span class=\"tag\">'+s.siteType+'</span>'));m.appendChild(el('div','url',esc(s.url)));r.appendChild(m);list.appendChild(r)});\n }\n}\nfunction esc(s){return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')}\ndocument.querySelectorAll('.tab').forEach(t=>t.onclick=()=>{document.querySelectorAll('.tab').forEach(x=>x.classList.remove('on'));t.classList.add('on');tab=t.dataset.tab;filter=null;render()});\nrender();\n</script>\n</body></html>`\n}\n","export const PACKAGE_VERSION = '0.3.40'\n","import { z } from 'zod'\n\nconst NullableString = z.string().nullable()\nconst BrowserRawObject = z.record(z.unknown())\n\nconst BrowserElementOutput = z.record(z.unknown())\n\nconst BrowserBaseOutput = {\n ok: z.boolean().describe('Whether the browser-agent action succeeded.'),\n tool: z.string().describe('Browser Agent MCP tool that produced this response.'),\n session_id: NullableString.describe('Browser session id when the response is scoped to a session.'),\n}\n\nconst BrowserReplayBaseOutput = {\n ...BrowserBaseOutput,\n replay_id: NullableString.describe('Replay id when the response is scoped to a replay.'),\n}\n\nexport const BrowserOpenInputSchema = {\n label: z.string().optional().describe('Optional human label for this session, shown in the watch console.'),\n url: z.string().url().optional().describe('Optional URL to navigate to immediately after opening.'),\n profile: z.string().optional().describe('Optional saved hosted profile name to load a logged-in session for a site.'),\n save_profile_changes: z.boolean().optional().describe('Persist cookies and browser storage back to the named profile when the session is closed. Use this for profile setup or intentional auth refreshes; avoid parallel sessions writing to the same profile.'),\n timeout_seconds: z.number().int().min(60).max(259200).optional().describe('How long the direct no-proxy browser session may live before auto-termination. Defaults to 600. The browser idles into a zero-cost standby between actions, so a longer timeout is cheap.'),\n}\nexport type BrowserOpenInput = z.infer<ReturnType<typeof z.object<typeof BrowserOpenInputSchema>>>\n\nexport const BrowserProfileConnectInputSchema = {\n email: z.string().optional().describe('Account email for the login being saved. Used to derive a stable, reusable profile name AND recorded as a note of who is connected. Does NOT import existing cookies — the user signs in fresh via the returned watch_url.'),\n profile: z.string().optional().describe('Profile to add this login to. Omit to derive one from email. A single profile holds MANY site logins — pass the same profile name again with a different domain to stack another account (e.g. add claude.ai to a profile that already has chatgpt.com).'),\n domain: z.string().optional().describe('Site to log into, e.g. chatgpt.com, claude.ai, reddit.com. Defaults to chatgpt.com. Each domain is a separate login inside the profile.'),\n login_url: z.string().url().optional().describe('Login page for the domain. Defaults to https://<domain>/ (https://chatgpt.com/ when domain is omitted).'),\n url: z.string().url().optional().describe('Deprecated alias for login_url. Use login_url.'),\n note: z.string().optional().describe('Free-text note describing this login, e.g. \"ChatGPT Plus, work account\". Surfaced by browser_profile_list so you can see what the profile holds.'),\n label: z.string().optional().describe('Optional human label for this sign-in setup session.'),\n timeout_seconds: z.number().int().min(60).max(259200).optional().describe('How long the sign-in setup session may live before auto-termination. Defaults to 600.'),\n}\nexport type BrowserProfileConnectInput = z.infer<ReturnType<typeof z.object<typeof BrowserProfileConnectInputSchema>>>\n\nexport const BrowserProfileListInputSchema = {\n profile: z.string().optional().describe('Profile whose saved logins to list. Omit to derive from email.'),\n email: z.string().optional().describe('Account email used to derive the profile name when profile is not given.'),\n domain: z.string().optional().describe('Restrict to one site login, e.g. chatgpt.com. Use this to poll a single login until its status reads AUTHENTICATED.'),\n connection_id: z.string().optional().describe('A specific login connection id returned by browser_profile_connect, to poll just that one.'),\n}\nexport type BrowserProfileListInput = z.infer<ReturnType<typeof z.object<typeof BrowserProfileListInputSchema>>>\n\nexport const BrowserSessionInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n}\nexport type BrowserSessionInput = z.infer<ReturnType<typeof z.object<typeof BrowserSessionInputSchema>>>\n\nexport const BrowserLocateTargetSchema = z.object({\n name: z.string().optional().describe('Optional label for this target, echoed in the result.'),\n selector: z.string().optional().describe('CSS selector for the exact DOM element to locate, for example h1, input[name=\"q\"], or [data-testid=\"result\"].'),\n text: z.string().optional().describe('Visible text to locate when a selector is not known. The tool returns the text range bounds when possible.'),\n match: z.enum(['contains', 'exact']).default('contains').describe('How to match text targets. Defaults to contains.'),\n index: z.number().int().min(0).default(0).describe('Zero-based match index when multiple elements match.'),\n}).refine(value => Boolean(value.selector || value.text), {\n message: 'target requires selector or text',\n})\n\nexport const BrowserLocateInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n targets: z.array(BrowserLocateTargetSchema).min(1).max(20).describe('DOM targets to locate in the current viewport. Use selectors for exact elements, or text for visible text ranges.'),\n}\nexport type BrowserLocateInput = z.infer<ReturnType<typeof z.object<typeof BrowserLocateInputSchema>>>\n\nexport const BrowserGotoInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n url: z.string().url().describe('URL to navigate the browser to.'),\n}\nexport type BrowserGotoInput = z.infer<ReturnType<typeof z.object<typeof BrowserGotoInputSchema>>>\n\nexport const BrowserClickInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n x: z.number().describe('X coordinate to click, in screenshot pixels. Use only coordinates from the latest browser_screenshot, browser_read, or browser_locate result; do not guess.'),\n y: z.number().describe('Y coordinate to click, in screenshot pixels. Use only coordinates from the latest browser_screenshot, browser_read, or browser_locate result; do not guess.'),\n button: z.enum(['left', 'right', 'middle']).default('left').describe('Mouse button.'),\n num_clicks: z.number().int().min(1).max(3).optional().describe('Number of clicks, e.g. 2 for double-click.'),\n}\nexport type BrowserClickInput = z.infer<ReturnType<typeof z.object<typeof BrowserClickInputSchema>>>\n\nexport const BrowserTypeInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n text: z.string().describe('Text to type at the current focus. Click a field first to focus it.'),\n delay: z.number().int().min(0).max(500).optional().describe('Optional per-keystroke delay in ms for human-like typing.'),\n}\nexport type BrowserTypeInput = z.infer<ReturnType<typeof z.object<typeof BrowserTypeInputSchema>>>\n\nexport const BrowserScrollInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n delta_y: z.number().default(5).describe('Vertical scroll in wheel units. Positive scrolls down, negative up.'),\n delta_x: z.number().default(0).describe('Horizontal scroll in wheel units.'),\n x: z.number().optional().describe('X position to scroll at. Defaults to screen center.'),\n y: z.number().optional().describe('Y position to scroll at. Defaults to screen center.'),\n}\nexport type BrowserScrollInput = z.infer<ReturnType<typeof z.object<typeof BrowserScrollInputSchema>>>\n\nexport const BrowserPressInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n keys: z.array(z.string()).min(1).describe('Keys or combinations to press, e.g. [\"Return\"], [\"Ctrl+a\"], [\"Ctrl+Shift+Tab\"].'),\n}\nexport type BrowserPressInput = z.infer<ReturnType<typeof z.object<typeof BrowserPressInputSchema>>>\n\nexport const BrowserReplayStopInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n replay_id: z.string().describe('The replay id returned by browser_replay_start or browser_list_replays. Use only a returned replay_id; do not construct one yourself.'),\n}\nexport type BrowserReplayStopInput = z.infer<ReturnType<typeof z.object<typeof BrowserReplayStopInputSchema>>>\n\nexport const BrowserReplayDownloadInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n replay_id: z.string().describe('The replay id returned by browser_replay_start or browser_list_replays. Use only a returned replay_id; do not construct one yourself.'),\n filename: z.string().optional().describe('Optional local MP4 filename. Defaults to a timestamped replay filename.'),\n}\nexport type BrowserReplayDownloadInput = z.infer<ReturnType<typeof z.object<typeof BrowserReplayDownloadInputSchema>>>\n\nexport const BrowserReplayAnnotationSchema = z.object({\n type: z.enum(['box', 'circle', 'underline', 'arrow', 'label']).default('box').describe('Annotation style to draw over the replay.'),\n start_seconds: z.number().min(0).default(0).describe('When the annotation should appear in the replay.'),\n end_seconds: z.number().min(0).optional().describe('When the annotation should disappear. Defaults to two seconds after start_seconds.'),\n left: z.number().optional().describe('Target left edge in browser screenshot pixels. Use element.left from browser_screenshot/browser_read.'),\n top: z.number().optional().describe('Target top edge in browser screenshot pixels. Use element.top from browser_screenshot/browser_read.'),\n width: z.number().positive().optional().describe('Target width in browser screenshot pixels. Use element.width from browser_screenshot/browser_read.'),\n height: z.number().positive().optional().describe('Target height in browser screenshot pixels. Use element.height from browser_screenshot/browser_read.'),\n x: z.number().optional().describe('Point target x coordinate in browser screenshot pixels when no box is available.'),\n y: z.number().optional().describe('Point target y coordinate in browser screenshot pixels when no box is available.'),\n from_x: z.number().optional().describe('Arrow start x coordinate in browser screenshot pixels. Defaults near the target.'),\n from_y: z.number().optional().describe('Arrow start y coordinate in browser screenshot pixels. Defaults near the target.'),\n to_x: z.number().optional().describe('Arrow target x coordinate in browser screenshot pixels. Defaults to the target box center.'),\n to_y: z.number().optional().describe('Arrow target y coordinate in browser screenshot pixels. Defaults to the target box center.'),\n label: z.string().max(120).optional().describe('Optional text callout to render near the annotation.'),\n color: z.string().regex(/^#?[0-9a-fA-F]{6}$/).optional().describe('Annotation color as hex, for example #ff3b30.'),\n thickness: z.number().min(1).max(24).optional().describe('Stroke thickness in pixels. Defaults to 5.'),\n})\n\nexport const BrowserReplayMarkInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself. A replay must already be recording.'),\n target: BrowserLocateTargetSchema.describe('The exact DOM element or text range to mark in the current viewport.'),\n type: z.enum(['box', 'circle', 'underline', 'arrow']).default('box').describe('Annotation style to generate. Labels are included on the returned annotation when label is provided.'),\n label: z.string().max(120).optional().describe('Optional callout text to render near the target.'),\n color: z.string().regex(/^#?[0-9a-fA-F]{6}$/).optional().describe('Annotation color as hex, for example #ff3b30.'),\n thickness: z.number().min(1).max(24).optional().describe('Stroke thickness in pixels. Defaults to 5.'),\n padding: z.number().min(0).max(80).default(8).describe('Pixels to expand the DOM bounds so the highlight does not touch the text edge.'),\n start_offset_seconds: z.number().min(-5).max(10).default(-0.25).describe('Offset from the current replay time. Negative values make the callout appear just before the mark action is captured.'),\n duration_seconds: z.number().min(0.5).max(30).default(4).describe('How long the generated annotation should remain visible.'),\n}\nexport type BrowserReplayMarkInput = z.infer<ReturnType<typeof z.object<typeof BrowserReplayMarkInputSchema>>>\n\nexport const BrowserReplayAnnotateInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.'),\n replay_id: z.string().describe('The replay id returned by browser_replay_start or browser_list_replays. Use only a returned replay_id; do not construct one yourself.'),\n annotations: z.array(BrowserReplayAnnotationSchema).min(1).max(50).describe('Timed overlay annotations to render on the replay. Prefer annotations returned by browser_replay_mark; otherwise use exact DOM bounds from browser_locate/browser_screenshot/browser_read.'),\n filename: z.string().optional().describe('Optional output MP4 filename. Defaults to a timestamped annotated replay filename.'),\n source_width: z.number().positive().optional().describe('Width of the screenshot coordinate space used for annotations. Defaults to the replay video width.'),\n source_height: z.number().positive().optional().describe('Height of the coordinate space used for annotations. When this is a page viewport height smaller than the replay video height, the annotator infers the browser chrome top offset.'),\n source_left_offset: z.number().min(0).optional().describe('Optional explicit X offset from annotation coordinates to replay video coordinates. Usually omitted.'),\n source_top_offset: z.number().min(0).optional().describe('Optional explicit Y offset from annotation coordinates to replay video coordinates. Usually omitted because browser chrome offset is inferred when source_height is a page viewport height.'),\n}\nexport type BrowserReplayAnnotateInput = z.infer<ReturnType<typeof z.object<typeof BrowserReplayAnnotateInputSchema>>>\n\nexport const BrowserListInputSchema = {\n include_closed: z.boolean().default(false).describe('Include closed sessions in the list.'),\n}\nexport type BrowserListInput = z.infer<ReturnType<typeof z.object<typeof BrowserListInputSchema>>>\n\nexport const BrowserCaptureFanoutInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open or browser_list_sessions. The session must be on chatgpt.com or claude.ai and logged in through a saved hosted profile. Use only a returned session_id; do not construct one yourself.'),\n prompt: z.string().optional().describe('Optional prompt to type into the chat composer and submit before capturing. Omit to passively capture the fan-out of a prompt the user just ran in the visible browser. The prompt must trigger web search for there to be a fan-out.'),\n wait_ms: z.number().int().min(0).max(180000).optional().describe('How long to wait for the answer stream to finish before parsing. Defaults to 90000 when a prompt is sent, 8000 for passive capture. Capture ends as soon as the answer stream finishes.'),\n first_party_domain: z.string().optional().describe('The brand/site being researched, for example example.com. Sources on this domain are tagged First-party/vendor. Set this when the prompt is about a specific business.'),\n reset: z.boolean().default(false).describe('Clear any previously buffered stream for this page before capturing. Use when re-running to avoid mixing turns.'),\n export: z.boolean().default(false).describe('When true, write JSON, CSV, TSV exports (queries, citations, all sources, browsed-only sources, snippets, domains) and a self-contained HTML report to MCP_SCRAPER_OUTPUT_DIR/fanout, returning paths relative to MCP_SCRAPER_OUTPUT_DIR.'),\n}\nexport type BrowserCaptureFanoutInput = z.infer<ReturnType<typeof z.object<typeof BrowserCaptureFanoutInputSchema>>>\n\nconst FanoutSourceOutput = z.object({\n url: z.string(),\n domain: z.string(),\n title: z.string(),\n cited: z.boolean(),\n timesCited: z.number().int().min(0),\n snippet: z.string(),\n round: z.number().int().nullable(),\n siteType: z.string().describe('URL category: First-party/vendor, News/media, Reddit, Social/video, Encyclopedia, Review site, Docs, or Blog.'),\n})\n\nexport const BrowserCaptureFanoutOutputSchema = {\n ...BrowserBaseOutput,\n tool: z.literal('query_fanout_workflow'),\n platform: z.enum(['ChatGPT', 'Claude']).describe('Which AI-search surface the fan-out was captured from.'),\n captured_at: z.string(),\n prompt: z.string().describe('The user prompt that triggered the captured fan-out, when recoverable.'),\n meta: z.object({\n model: z.string(),\n finishType: z.string(),\n title: z.string(),\n rounds: z.number().int().min(0),\n }),\n queries: z.array(z.string()).describe('Every web-search sub-query the model issued, in capture order. Classify these by funnel stage and type yourself from the text.'),\n browsed_urls: z.array(FanoutSourceOutput).describe('Every researched URL (cited and browsed-only), cited first.'),\n cited_urls: z.array(FanoutSourceOutput).describe('The subset of researched URLs actually cited in the final answer.'),\n browsed_only: z.array(FanoutSourceOutput).describe('Researched URLs the model pulled but did not cite.'),\n snippets: z.array(z.object({ url: z.string(), domain: z.string(), title: z.string(), text: z.string() })),\n counts: z.object({\n subQueries: z.number().int().min(0),\n browsed: z.number().int().min(0),\n cited: z.number().int().min(0),\n browsedOnly: z.number().int().min(0),\n }),\n aggregates: z.object({\n topSites: z.array(z.object({ domain: z.string(), count: z.number().int(), cited: z.boolean(), timesCited: z.number().int(), siteType: z.string() })),\n citationOrder: z.array(z.object({ rank: z.number().int(), domain: z.string(), url: z.string(), timesCited: z.number().int() })),\n byCategory: z.record(z.number().int()),\n }).describe('Objective aggregates: top sourced sites by frequency, citation order, and URL-category counts.'),\n first_party_domain: z.string().nullable(),\n exports: z.object({\n relativeTo: z.string(),\n dir: z.string(),\n json: z.string(),\n queriesCsv: z.string(),\n queriesTsv: z.string(),\n citationsCsv: z.string(),\n sourcesCsv: z.string(),\n browsedOnlyCsv: z.string(),\n snippetsCsv: z.string(),\n domainsCsv: z.string(),\n report: z.string(),\n }).nullable().describe('Relative export paths when export=true, otherwise null. Paths are relative to MCP_SCRAPER_OUTPUT_DIR, or ~/Downloads/mcp-scraper when that env var is not set.'),\n debug: z.object({\n interceptorReady: z.boolean(),\n rawBytes: z.number().int().min(0),\n unmappedKeys: z.array(z.string()),\n note: z.string(),\n }).optional(),\n}\n\nexport const BrowserOpenOutputSchema = {\n ok: z.boolean(),\n tool: z.literal('browser_open'),\n session_id: z.string().describe('Session id returned by browser_open. Use only this exact value in later browser_* calls; do not construct one yourself.'),\n watch_url: z.string().describe('Human watch/takeover URL for this browser session on mcpscraper.dev.'),\n live_view_url: NullableString.describe('Deprecated; always null. Open watch_url to view the live session.'),\n url: NullableString.describe('Initial URL requested by the caller, when provided.'),\n hint: z.string(),\n raw: BrowserRawObject.optional(),\n}\n\nconst BrowserProfileLogin = z.object({\n connection_id: NullableString.describe('Auth connection id for this login.'),\n domain: z.string().describe('Site this login is for, e.g. chatgpt.com.'),\n status: z.string().describe('Auth status, e.g. NEEDS_AUTH or AUTHENTICATED.'),\n account_email: NullableString.describe('Account email recorded for this login, when known.'),\n note: NullableString.describe('Free-text note describing this login.'),\n watch_url: NullableString.describe('mcpscraper.dev sign-in link when this login still needs the user to authenticate.'),\n last_connected_at: NullableString.describe('When this login was last saved or refreshed.'),\n})\n\nexport const BrowserProfileConnectOutputSchema = {\n ok: z.boolean(),\n tool: z.literal('browser_profile_connect'),\n session_id: NullableString,\n auth_connection_id: z.string(),\n watch_url: z.string().describe('mcpscraper.dev sign-in link to give the user so they can complete this login.'),\n live_view_url: NullableString.describe('Deprecated; always null. Open watch_url to view the sign-in.'),\n profile: z.string().describe('Profile this login was added to. Reuse it to stack more logins or to open a session.'),\n domain: z.string(),\n setup_url: z.string(),\n account_email: NullableString,\n note: NullableString,\n status: z.string(),\n flow_status: NullableString,\n flow_step: NullableString,\n flow_expires_at: NullableString,\n post_login_url: NullableString,\n connected_logins: z.array(BrowserProfileLogin).describe('Every login currently saved in this profile, so you can see what else is connected.'),\n next_steps: z.array(z.string()),\n raw: BrowserRawObject.optional(),\n}\n\nexport const BrowserProfileListOutputSchema = {\n ok: z.boolean(),\n tool: z.literal('browser_profile_list'),\n session_id: z.null(),\n profile: z.string().describe('Profile these logins belong to.'),\n connections: z.array(BrowserProfileLogin).describe('All site logins saved in this profile, each with its current auth status and note.'),\n count: z.number().int().min(0),\n}\n\nexport const BrowserScreenshotOutputSchema = {\n ...BrowserBaseOutput,\n tool: z.literal('browser_screenshot'),\n url: NullableString,\n title: NullableString,\n text: z.string(),\n elements: z.array(BrowserElementOutput),\n screenshot: z.object({\n mime_type: z.string(),\n inline: z.boolean(),\n }).nullable(),\n}\n\nexport const BrowserReadOutputSchema = {\n ...BrowserBaseOutput,\n tool: z.literal('browser_read'),\n url: NullableString,\n title: NullableString,\n text: z.string(),\n elements: z.array(BrowserElementOutput),\n raw: BrowserRawObject.optional(),\n}\n\nexport const BrowserLocateOutputSchema = {\n ...BrowserBaseOutput,\n tool: z.literal('browser_locate'),\n url: NullableString,\n title: NullableString,\n viewport: BrowserRawObject.nullable(),\n replay: BrowserRawObject.nullable(),\n targets: z.array(BrowserRawObject),\n raw: BrowserRawObject.optional(),\n}\n\nexport const BrowserActionOutputSchema = {\n ...BrowserBaseOutput,\n result: BrowserRawObject.describe('Provider action result. Check ok and follow with browser_screenshot/browser_read when page state matters.'),\n nextRecommendedTool: z.string().nullable(),\n}\n\nexport const BrowserReplayStartOutputSchema = {\n ...BrowserReplayBaseOutput,\n tool: z.literal('browser_replay_start'),\n view_url: NullableString,\n download_url: NullableString,\n raw: BrowserRawObject.optional(),\n}\n\nexport const BrowserReplayStopOutputSchema = {\n ...BrowserReplayBaseOutput,\n tool: z.literal('browser_replay_stop'),\n view_url: NullableString,\n download_url: NullableString,\n raw: BrowserRawObject.optional(),\n}\n\nexport const BrowserListReplaysOutputSchema = {\n ...BrowserBaseOutput,\n tool: z.literal('browser_list_replays'),\n replays: z.array(BrowserRawObject),\n count: z.number().int().min(0),\n}\n\nexport const BrowserReplayDownloadOutputSchema = {\n ...BrowserReplayBaseOutput,\n tool: z.literal('browser_replay_download'),\n file_path: NullableString,\n bytes: z.number().int().min(0).nullable(),\n mime_type: NullableString,\n download_url: NullableString,\n}\n\nexport const BrowserReplayMarkOutputSchema = {\n ...BrowserReplayBaseOutput,\n tool: z.literal('browser_replay_mark'),\n annotation: BrowserRawObject,\n source_width: z.number().nullable(),\n source_height: z.number().nullable(),\n target: BrowserRawObject.nullable(),\n hint: z.string(),\n}\n\nexport const BrowserReplayAnnotateOutputSchema = {\n ...BrowserReplayBaseOutput,\n tool: z.literal('browser_replay_annotate'),\n source_file_path: NullableString,\n annotated_file_path: NullableString,\n bytes: z.number().int().min(0).nullable(),\n width: z.number().int().min(0).nullable(),\n height: z.number().int().min(0).nullable(),\n annotation_count: z.number().int().min(0).nullable(),\n mime_type: NullableString,\n}\n\nexport const BrowserCloseOutputSchema = {\n ...BrowserBaseOutput,\n tool: z.literal('browser_close'),\n closed: z.boolean(),\n raw: BrowserRawObject.optional(),\n}\n\nexport const BrowserListSessionsOutputSchema = {\n ok: z.boolean(),\n tool: z.literal('browser_list_sessions'),\n session_id: z.null(),\n sessions: z.array(BrowserRawObject),\n count: z.number().int().min(0),\n}\n","import { execFile } from 'node:child_process'\nimport { mkdtemp, rm, stat, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { promisify } from 'node:util'\n\nconst execFileAsync = promisify(execFile)\n\nexport type ReplayAnnotationType = 'box' | 'circle' | 'underline' | 'arrow' | 'label'\n\nexport interface ReplayAnnotation {\n type?: ReplayAnnotationType\n start_seconds?: number\n end_seconds?: number\n left?: number\n top?: number\n width?: number\n height?: number\n x?: number\n y?: number\n from_x?: number\n from_y?: number\n to_x?: number\n to_y?: number\n label?: string\n color?: string\n thickness?: number\n}\n\nexport interface AnnotateReplayOptions {\n annotations: ReplayAnnotation[]\n sourceWidth?: number\n sourceHeight?: number\n sourceLeftOffset?: number\n sourceTopOffset?: number\n}\n\ninterface Size {\n width: number\n height: number\n}\n\ninterface Rect {\n left: number\n top: number\n width: number\n height: number\n}\n\ninterface CoordinateTransform {\n scaleX: number\n scaleY: number\n offsetX: number\n offsetY: number\n}\n\nexport interface AnnotatedReplayResult {\n filePath: string\n bytes: number\n width: number\n height: number\n annotationCount: number\n}\n\nfunction finiteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value)\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value))\n}\n\nfunction formatAssTime(seconds: number): string {\n const safe = Math.max(0, seconds)\n const hours = Math.floor(safe / 3600)\n const minutes = Math.floor((safe % 3600) / 60)\n const wholeSeconds = Math.floor(safe % 60)\n const centiseconds = Math.floor((safe - Math.floor(safe)) * 100)\n return `${hours}:${String(minutes).padStart(2, '0')}:${String(wholeSeconds).padStart(2, '0')}.${String(centiseconds).padStart(2, '0')}`\n}\n\nfunction cssHexToAssColor(color?: string): string {\n const normalized = color?.trim().match(/^#?([0-9a-fA-F]{6})$/)?.[1] ?? 'ff3b30'\n const red = normalized.slice(0, 2)\n const green = normalized.slice(2, 4)\n const blue = normalized.slice(4, 6)\n return `&H${blue}${green}${red}&`\n}\n\nfunction escapeAssText(value: string): string {\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\\{/g, '\\\\{')\n .replace(/\\}/g, '\\\\}')\n .replace(/\\r?\\n/g, '\\\\N')\n}\n\nfunction resolveCoordinateTransform(video: Size, source: Size, options: AnnotateReplayOptions): CoordinateTransform {\n const explicitOffsetX = finiteNumber(options.sourceLeftOffset) ? options.sourceLeftOffset : null\n const explicitOffsetY = finiteNumber(options.sourceTopOffset) ? options.sourceTopOffset : null\n const inferredTopOffset =\n explicitOffsetY == null &&\n Math.round(source.width) === Math.round(video.width) &&\n source.height < video.height &&\n video.height - source.height <= 220\n ? video.height - source.height\n : 0\n const offsetX = explicitOffsetX ?? 0\n const offsetY = explicitOffsetY ?? inferredTopOffset\n return {\n scaleX: (video.width - offsetX) / source.width,\n scaleY: (video.height - offsetY) / source.height,\n offsetX,\n offsetY,\n }\n}\n\nfunction transformPoint(x: number, y: number, transform: CoordinateTransform): { x: number; y: number } {\n return {\n x: x * transform.scaleX + transform.offsetX,\n y: y * transform.scaleY + transform.offsetY,\n }\n}\n\nfunction scaleRect(annotation: ReplayAnnotation, transform: CoordinateTransform): Rect {\n if (\n finiteNumber(annotation.left) &&\n finiteNumber(annotation.top) &&\n finiteNumber(annotation.width) &&\n finiteNumber(annotation.height)\n ) {\n const origin = transformPoint(annotation.left, annotation.top, transform)\n return {\n left: origin.x,\n top: origin.y,\n width: annotation.width * transform.scaleX,\n height: annotation.height * transform.scaleY,\n }\n }\n if (finiteNumber(annotation.x) && finiteNumber(annotation.y)) {\n const radius = finiteNumber(annotation.width) ? annotation.width / 2 : 28\n const point = transformPoint(annotation.x, annotation.y, transform)\n return {\n left: point.x - radius * transform.scaleX,\n top: point.y - radius * transform.scaleY,\n width: radius * 2 * transform.scaleX,\n height: radius * 2 * transform.scaleY,\n }\n }\n throw new Error('annotation needs either left/top/width/height or x/y')\n}\n\nfunction rectPath(rect: Rect): string {\n const x1 = Math.round(rect.left)\n const y1 = Math.round(rect.top)\n const x2 = Math.round(rect.left + rect.width)\n const y2 = Math.round(rect.top + rect.height)\n return `m ${x1} ${y1} l ${x2} ${y1} l ${x2} ${y2} l ${x1} ${y2} l ${x1} ${y1}`\n}\n\nfunction ellipsePath(rect: Rect): string {\n const cx = rect.left + rect.width / 2\n const cy = rect.top + rect.height / 2\n const rx = Math.max(4, rect.width / 2)\n const ry = Math.max(4, rect.height / 2)\n const points: string[] = []\n for (let i = 0; i <= 32; i += 1) {\n const t = (Math.PI * 2 * i) / 32\n const x = Math.round(cx + Math.cos(t) * rx)\n const y = Math.round(cy + Math.sin(t) * ry)\n points.push(`${i === 0 ? 'm' : 'l'} ${x} ${y}`)\n }\n return points.join(' ')\n}\n\nfunction filledRectPath(left: number, top: number, width: number, height: number): string {\n return rectPath({ left, top, width, height })\n}\n\nfunction arrowPath(fromX: number, fromY: number, toX: number, toY: number, thickness: number): string {\n const dx = toX - fromX\n const dy = toY - fromY\n const length = Math.max(1, Math.hypot(dx, dy))\n const ux = dx / length\n const uy = dy / length\n const px = -uy\n const py = ux\n const half = thickness / 2\n const head = Math.max(14, thickness * 4)\n const baseX = toX - ux * head\n const baseY = toY - uy * head\n const p1x = Math.round(fromX + px * half)\n const p1y = Math.round(fromY + py * half)\n const p2x = Math.round(baseX + px * half)\n const p2y = Math.round(baseY + py * half)\n const p3x = Math.round(baseX + px * head * 0.55)\n const p3y = Math.round(baseY + py * head * 0.55)\n const p4x = Math.round(toX)\n const p4y = Math.round(toY)\n const p5x = Math.round(baseX - px * head * 0.55)\n const p5y = Math.round(baseY - py * head * 0.55)\n const p6x = Math.round(baseX - px * half)\n const p6y = Math.round(baseY - py * half)\n const p7x = Math.round(fromX - px * half)\n const p7y = Math.round(fromY - py * half)\n return `m ${p1x} ${p1y} l ${p2x} ${p2y} l ${p3x} ${p3y} l ${p4x} ${p4y} l ${p5x} ${p5y} l ${p6x} ${p6y} l ${p7x} ${p7y} l ${p1x} ${p1y}`\n}\n\nfunction eventLine(start: number, end: number, body: string): string {\n return `Dialogue: 0,${formatAssTime(start)},${formatAssTime(end)},Default,,0,0,0,,${body}`\n}\n\nfunction labelLine(start: number, end: number, x: number, y: number, label: string): string {\n const safeX = Math.round(x)\n const safeY = Math.round(y)\n return eventLine(\n start,\n end,\n `{\\\\an7\\\\pos(${safeX},${safeY})\\\\fs30\\\\bord4\\\\shad0\\\\c&HFFFFFF&\\\\3c&H000000&}${escapeAssText(label)}`,\n )\n}\n\nfunction shapeLine(start: number, end: number, path: string, color: string, thickness: number, filled = false): string {\n const fillAlpha = filled ? '&H00&' : '&HFF&'\n const border = filled ? 0 : thickness\n return eventLine(\n start,\n end,\n `{\\\\an7\\\\pos(0,0)\\\\p1\\\\bord${border}\\\\shad0\\\\1a${fillAlpha}\\\\1c${color}\\\\3c${color}}${path}`,\n )\n}\n\nexport function buildAssSubtitle(options: AnnotateReplayOptions, video: Size): string {\n const source = {\n width: options.sourceWidth && options.sourceWidth > 0 ? options.sourceWidth : video.width,\n height: options.sourceHeight && options.sourceHeight > 0 ? options.sourceHeight : video.height,\n }\n const transform = resolveCoordinateTransform(video, source, options)\n const lines: string[] = []\n for (const annotation of options.annotations) {\n const start = Math.max(0, annotation.start_seconds ?? 0)\n const end = annotation.end_seconds && annotation.end_seconds > start ? annotation.end_seconds : start + 2\n const type = annotation.type ?? 'box'\n const color = cssHexToAssColor(annotation.color)\n const thickness = Math.round(clamp(annotation.thickness ?? 5, 2, 24))\n if (type === 'label') {\n if (!annotation.label) throw new Error('label annotation needs label')\n const rect = scaleRect(annotation, transform)\n lines.push(labelLine(start, end, rect.left, Math.max(8, rect.top), annotation.label))\n continue\n }\n if (type === 'arrow') {\n const rect = finiteNumber(annotation.to_x) && finiteNumber(annotation.to_y)\n ? null\n : scaleRect(annotation, transform)\n const toPoint = finiteNumber(annotation.to_x) && finiteNumber(annotation.to_y)\n ? transformPoint(annotation.to_x, annotation.to_y, transform)\n : null\n const toX = toPoint ? toPoint.x : rect!.left + rect!.width / 2\n const toY = toPoint ? toPoint.y : rect!.top + rect!.height / 2\n const fromPoint = finiteNumber(annotation.from_x) && finiteNumber(annotation.from_y)\n ? transformPoint(annotation.from_x, annotation.from_y, transform)\n : null\n const fromX = fromPoint ? fromPoint.x : clamp(toX - 120, 12, video.width - 12)\n const fromY = fromPoint ? fromPoint.y : clamp(toY - 90, 12, video.height - 12)\n lines.push(shapeLine(start, end, arrowPath(fromX, fromY, toX, toY, thickness), color, thickness, true))\n if (annotation.label) lines.push(labelLine(start, end, fromX + 8, Math.max(96, fromY - 36), annotation.label))\n continue\n }\n const rect = scaleRect(annotation, transform)\n if (type === 'underline') {\n const underlineTop = rect.top + rect.height + thickness\n lines.push(shapeLine(start, end, filledRectPath(rect.left, underlineTop, rect.width, thickness), color, 0, true))\n } else if (type === 'circle') {\n lines.push(shapeLine(start, end, ellipsePath(rect), color, thickness))\n } else {\n lines.push(shapeLine(start, end, rectPath(rect), color, thickness))\n }\n if (annotation.label) lines.push(labelLine(start, end, rect.left, Math.max(8, rect.top - 38), annotation.label))\n }\n\n return [\n '[Script Info]',\n 'ScriptType: v4.00+',\n `PlayResX: ${Math.round(video.width)}`,\n `PlayResY: ${Math.round(video.height)}`,\n 'ScaledBorderAndShadow: yes',\n '',\n '[V4+ Styles]',\n 'Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding',\n 'Style: Default,Arial,30,&H00FFFFFF,&H000000FF,&H00000000,&H90000000,0,0,0,0,100,100,0,0,1,2,0,7,0,0,0,1',\n '',\n '[Events]',\n 'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text',\n ...lines,\n '',\n ].join('\\n')\n}\n\nasync function videoSize(inputFilePath: string): Promise<Size> {\n const { stdout } = await execFileAsync('ffprobe', [\n '-v',\n 'error',\n '-select_streams',\n 'v:0',\n '-show_entries',\n 'stream=width,height',\n '-of',\n 'json',\n inputFilePath,\n ], { maxBuffer: 1024 * 1024 })\n const parsed = JSON.parse(stdout) as { streams?: Array<{ width?: number; height?: number }> }\n const stream = parsed.streams?.[0]\n if (!stream?.width || !stream.height) throw new Error('could not read replay video dimensions')\n return { width: stream.width, height: stream.height }\n}\n\nfunction ffmpegFilterPath(path: string): string {\n return path.replace(/\\\\/g, '\\\\\\\\').replace(/:/g, '\\\\:')\n}\n\nexport async function annotateReplayVideo(\n inputFilePath: string,\n outputFilePath: string,\n options: AnnotateReplayOptions,\n): Promise<AnnotatedReplayResult> {\n if (!options.annotations.length) throw new Error('annotations must include at least one item')\n const size = await videoSize(inputFilePath)\n const tmp = await mkdtemp(join(tmpdir(), 'mcp-scraper-ass-'))\n const assPath = join(tmp, 'annotations.ass')\n try {\n await writeFile(assPath, buildAssSubtitle(options, size), 'utf8')\n await execFileAsync('ffmpeg', [\n '-y',\n '-i',\n inputFilePath,\n '-vf',\n `ass=${ffmpegFilterPath(assPath)}`,\n '-c:v',\n 'libx264',\n '-pix_fmt',\n 'yuv420p',\n '-movflags',\n '+faststart',\n '-c:a',\n 'copy',\n outputFilePath,\n ], { maxBuffer: 1024 * 1024 * 20 })\n const out = await stat(outputFilePath)\n return {\n filePath: outputFilePath,\n bytes: out.size,\n width: size.width,\n height: size.height,\n annotationCount: options.annotations.length,\n }\n } finally {\n await rm(tmp, { recursive: true, force: true })\n }\n}\n","export const RECAPTCHA_INSTRUCTIONS = 'Google returned a CAPTCHA. Run with --headless=false to re-warm the browser profile, then retry.'\n\nexport function sanitizeVendorName(message: string): string {\n return message\n .replace(/kernel\\.sh\\s+sessions?/gi, 'sessions')\n .replace(/kernel\\.sh\\s+session/gi, 'this session')\n .replace(/kernel\\.sh/gi, 'the service')\n .replace(/kernel\\s+sessions?/gi, 'sessions')\n .replace(/kernel\\s+session/gi, 'this session')\n .replace(/\\bkernel\\b/gi, 'the service')\n .replace(/ +/g, ' ')\n .trim()\n}\n\nexport class CaptchaError extends Error {\n readonly name = 'CaptchaError'\n constructor(public readonly instructions: string) {\n super(`CAPTCHA detected. ${instructions}`)\n }\n}\n\nexport class ExtractionError extends Error {\n readonly name = 'ExtractionError'\n constructor(message: string, public readonly cause?: unknown) {\n super(message)\n }\n}\n\nexport class RequestAbortedError extends Error {\n readonly name = 'RequestAbortedError'\n constructor(message = 'Request aborted before harvest completed') {\n super(message)\n }\n}\n\nexport class LocationMismatchError extends Error {\n readonly name = 'LocationMismatchError'\n constructor(message = 'Google returned results for a different location than requested') {\n super(message)\n }\n}\n","import { sanitizeVendorName } from '../errors.js'\n\nconst KEY_RENAMES: Record<string, string> = {\n kernel: 'browserRuntime',\n kernel_session_id: 'browser_session_id',\n kernel_delete_started: 'session_cleanup_started',\n kernel_delete_succeeded: 'session_cleanup_succeeded',\n kernel_delete_error: 'session_cleanup_error',\n kernelSessionId: 'browserSessionId',\n kernelDeleteStarted: 'sessionCleanupStarted',\n kernelDeleteSucceeded: 'sessionCleanupSucceeded',\n kernelDeleteError: 'sessionCleanupError',\n kernelProxyId: 'proxyId',\n}\n\nconst SANITIZED_VALUE_KEYS = /error|message/i\n\nconst VENDOR_URL_KEYS = new Set([\n 'hosted_url',\n 'hostedUrl',\n 'live_view_url',\n 'liveViewUrl',\n 'cdp_ws_url',\n 'cdpWsUrl',\n 'browser_live_view_url',\n])\nconst VENDOR_URL_RE = /\\b(?:wss?|https?):\\/\\/[^\\s\"'<>]*\\bonkernel\\.com[^\\s\"'<>]*/gi\n\nfunction redactVendorUrls(value: string): string {\n return value.replace(VENDOR_URL_RE, '[browser-service]')\n}\n\nexport function sanitizeOutboundDiagnostics<T>(value: T, parentKey = ''): T {\n if (typeof value === 'string') {\n let out = redactVendorUrls(value)\n if (SANITIZED_VALUE_KEYS.test(parentKey) && /kernel/i.test(out)) {\n out = sanitizeVendorName(out)\n }\n return out as T\n }\n if (Array.isArray(value)) return value.map(v => sanitizeOutboundDiagnostics(v, parentKey)) as T\n if (value !== null && typeof value === 'object') {\n const out: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n const renamed = KEY_RENAMES[key] ?? key\n if (VENDOR_URL_KEYS.has(key)) {\n out[renamed] = null\n continue\n }\n out[renamed] = sanitizeOutboundDiagnostics(val, key)\n }\n return out as T\n }\n return value\n}\n\nexport function sanitizeAttempts<T>(attempts: T[]): T[] {\n return attempts.map(a => sanitizeOutboundDiagnostics(a))\n}\n\nexport function sanitizeHarvestResult<T extends Record<string, unknown>>(result: T): T {\n const diagnostics = result?.diagnostics as Record<string, unknown> | undefined\n if (!diagnostics?.debug) return result\n return {\n ...result,\n diagnostics: {\n ...diagnostics,\n debug: sanitizeOutboundDiagnostics(diagnostics.debug),\n },\n }\n}\n","import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { readdirSync, readFileSync, statSync } from 'node:fs'\nimport { basename, join } from 'node:path'\nimport type { IMcpToolExecutor } from './IMcpToolExecutor.js'\nimport { PACKAGE_VERSION } from '../version.js'\nimport { outputBaseDir } from './mcp-response-formatter.js'\nimport { SERVER_INSTRUCTIONS } from './server-instructions.js'\nimport {\n HarvestPaaInputSchema,\n SearchSerpInputSchema,\n ExtractUrlInputSchema,\n HarvestPaaOutputSchema,\n SearchSerpOutputSchema,\n ExtractUrlOutputSchema,\n ExtractSiteOutputSchema,\n AuditSiteOutputSchema,\n MapsPlaceIntelOutputSchema,\n CreditsInfoOutputSchema,\n MapSiteUrlsInputSchema,\n MapSiteUrlsOutputSchema,\n ExtractSiteInputSchema,\n AuditSiteInputSchema,\n YoutubeHarvestInputSchema,\n YoutubeHarvestOutputSchema,\n YoutubeTranscribeInputSchema,\n YoutubeTranscribeOutputSchema,\n FacebookPageIntelInputSchema,\n FacebookPageIntelOutputSchema,\n FacebookAdSearchInputSchema,\n FacebookAdSearchOutputSchema,\n RedditThreadInputSchema,\n RedditThreadOutputSchema,\n FacebookAdTranscribeInputSchema,\n FacebookAdTranscribeOutputSchema,\n FacebookVideoTranscribeInputSchema,\n FacebookVideoTranscribeOutputSchema,\n GoogleAdsSearchInputSchema,\n GoogleAdsSearchOutputSchema,\n GoogleAdsPageIntelInputSchema,\n GoogleAdsPageIntelOutputSchema,\n GoogleAdsTranscribeInputSchema,\n GoogleAdsTranscribeOutputSchema,\n InstagramProfileContentInputSchema,\n InstagramProfileContentOutputSchema,\n InstagramMediaDownloadInputSchema,\n InstagramMediaDownloadOutputSchema,\n MapsPlaceIntelInputSchema,\n MapsSearchInputSchema,\n MapsSearchOutputSchema,\n DirectoryWorkflowInputSchema,\n DirectoryWorkflowOutputSchema,\n WorkflowListInputSchema,\n WorkflowListOutputSchema,\n WorkflowSuggestInputSchema,\n WorkflowSuggestOutputSchema,\n WorkflowRunInputSchema,\n WorkflowRunOutputSchema,\n WorkflowStepInputSchema,\n WorkflowStepOutputSchema,\n WorkflowStatusInputSchema,\n WorkflowStatusOutputSchema,\n WorkflowArtifactReadInputSchema,\n WorkflowArtifactReadOutputSchema,\n RankTrackerBlueprintInputSchema,\n RankTrackerBlueprintOutputSchema,\n CreditsInfoInputSchema,\n CaptureSerpSnapshotInputSchema,\n CaptureSerpSnapshotOutputSchema,\n CaptureSerpPageSnapshotsInputSchema,\n CaptureSerpPageSnapshotsOutputSchema,\n} from './mcp-tool-schemas.js'\nimport type { ISerpIntelligenceToolExecutor } from './IMcpToolExecutor.js'\nimport { buildRankTrackerBlueprint } from './rank-tracker-blueprint.js'\nimport {\n formatHarvestPaa,\n formatSearchSerp,\n formatExtractUrl,\n formatMapSiteUrls,\n formatExtractSite,\n formatAuditSite,\n formatYoutubeHarvest,\n formatYoutubeTranscribe,\n formatFacebookPageIntel,\n formatFacebookAdSearch,\n formatGoogleAdsSearch,\n formatGoogleAdsPageIntel,\n formatGoogleAdsTranscribe,\n formatRedditThread,\n formatFacebookAdTranscribe,\n formatFacebookVideoTranscribe,\n formatInstagramProfileContent,\n formatInstagramMediaDownload,\n formatMapsPlaceIntel,\n formatMapsSearch,\n formatDirectoryWorkflow,\n formatWorkflowList,\n formatWorkflowSuggest,\n formatWorkflowRun,\n formatWorkflowStep,\n formatWorkflowStatus,\n formatWorkflowArtifactRead,\n formatCreditsInfo,\n formatCaptureSerpSnapshot,\n formatCaptureSerpPageSnapshots,\n} from './mcp-response-formatter.js'\n\nexport interface BuildMcpServerOptions {\n savesReportsLocally?: boolean\n}\n\nexport function liveWebToolAnnotations(title: string) {\n return {\n title,\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n }\n}\n\nexport function registerSerpIntelligenceCaptureTools(\n server: ReturnType<typeof buildPaaExtractorMcpServer>,\n executor: ISerpIntelligenceToolExecutor,\n) {\n server.registerTool('capture_serp_snapshot', {\n title: 'SERP Intelligence Snapshot',\n description: 'Capture a structured SERP Intelligence Google snapshot through POST /serp-intelligence/capture, the same product capture path used by Phoenix. Split query from location and infer gl/hl. Routing is automatic — leave proxyMode unset. Set debug true when investigating location evidence, proxy behavior, CAPTCHA, or capture reliability.',\n inputSchema: CaptureSerpSnapshotInputSchema,\n outputSchema: CaptureSerpSnapshotOutputSchema,\n annotations: liveWebToolAnnotations('SERP Intelligence Snapshot'),\n }, async (input) => formatCaptureSerpSnapshot(await executor.captureSerpSnapshot(input), input))\n\n server.registerTool('capture_serp_page_snapshots', {\n title: 'SERP Intelligence Page Snapshots',\n description: 'Capture public ranking-page evidence through POST /serp-intelligence/page-snapshots, the same product page snapshot path used by Phoenix. Provide urls for simple captures or targets when preserving organic, AI citation, local-pack, configured target, or site-subject source metadata. Private IPs, localhost, file URLs, and internal URLs are rejected by the service. Use timeoutMs for slow pages and debug true for sanitized proxy/browser diagnostics.',\n inputSchema: CaptureSerpPageSnapshotsInputSchema,\n outputSchema: CaptureSerpPageSnapshotsOutputSchema,\n annotations: liveWebToolAnnotations('SERP Intelligence Page Snapshots'),\n }, async (input) => formatCaptureSerpPageSnapshots(await executor.captureSerpPageSnapshots(input), input))\n}\n\nfunction localPlanningToolAnnotations(title: string) {\n return {\n title,\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n }\n}\n\nfunction listSavedReports(): Array<{ filename: string; mtimeMs: number }> {\n try {\n const dir = outputBaseDir()\n return readdirSync(dir)\n .filter(f => f.endsWith('.md'))\n .map(f => ({ filename: f, mtimeMs: statSync(join(dir, f)).mtimeMs }))\n .sort((a, b) => b.mtimeMs - a.mtimeMs)\n .slice(0, 100)\n } catch {\n return []\n }\n}\n\nfunction registerSavedReportResources(server: McpServer): void {\n server.registerResource(\n 'saved-report',\n new ResourceTemplate('report://{filename}', {\n list: () => ({\n resources: listSavedReports().map(r => ({\n uri: `report://${encodeURIComponent(r.filename)}`,\n name: r.filename,\n mimeType: 'text/markdown',\n })),\n }),\n }),\n {\n title: 'Saved MCP Scraper Reports',\n description: 'Markdown research reports saved by previous MCP Scraper tool calls. Read a report to reuse prior research without re-scraping or spending credits.',\n mimeType: 'text/markdown',\n },\n async (uri, variables) => {\n const requested = Array.isArray(variables.filename) ? variables.filename[0] : variables.filename\n const filename = basename(decodeURIComponent(String(requested ?? '')))\n if (!filename.endsWith('.md')) throw new Error('Only saved .md reports can be read')\n const text = readFileSync(join(outputBaseDir(), filename), 'utf8')\n return { contents: [{ uri: uri.href, mimeType: 'text/markdown', text }] }\n },\n )\n}\n\nexport function buildPaaExtractorMcpServer(\n executor: IMcpToolExecutor,\n options: BuildMcpServerOptions = {},\n): McpServer {\n const server = new McpServer({ name: 'mcp-scraper', version: PACKAGE_VERSION }, { instructions: SERVER_INSTRUCTIONS })\n registerPaaExtractorMcpTools(server, executor, options)\n return server\n}\n\nexport function registerPaaExtractorMcpTools(\n server: McpServer,\n executor: IMcpToolExecutor,\n options: BuildMcpServerOptions = {},\n): void {\n const savesReports = options.savesReportsLocally !== false\n const reportNote = savesReports\n ? ' Saves a full Markdown report to disk.'\n : ' Reports are returned inline; no files are saved on this hosted endpoint.'\n const withReportNote = (description: string) => `${description}${reportNote}`\n\n if (savesReports) registerSavedReportResources(server)\n\n server.registerTool('harvest_paa', {\n title: 'Google PAA + SERP Harvest',\n description: withReportNote('Best default tool for Google search research. Extracts People Also Ask questions plus answers/source URLs, organic SERP, local pack when present, entity IDs (CID/GCID/KG MID), and AI Overview. Infer the user language: split topic from location (e.g. \"best hvac company in Denver CO\" => query \"best hvac company\", location \"Denver, CO\", gl \"us\", hl \"en\"). Routing is automatic — leave proxyMode unset. If a deep harvest exceeds the time budget it returns the questions gathered so far (partial), billed per returned question. Use maxQuestions 30 normally, 100-200 for \"full\", \"deep\", \"all\", or comprehensive research. Deep harvests above 100 questions can run for several minutes with no interim progress — warn the user before starting one and keep maxQuestions at or below 100 unless they explicitly want a deep harvest. Credits are charged by extracted question; unused request hold is refunded.'),\n inputSchema: HarvestPaaInputSchema,\n outputSchema: HarvestPaaOutputSchema,\n annotations: liveWebToolAnnotations('Google PAA + SERP Harvest'),\n }, async (input) => formatHarvestPaa(await executor.harvestPaa(input), input))\n\n server.registerTool('search_serp', {\n title: 'Google SERP Lookup',\n description: withReportNote('Fast Google SERP lookup without PAA expansion. Use when the user asks for rankings, organic results, local pack, quick SERP, or positions. Split topic from location and infer gl/hl from the user request. Routing is automatic — leave proxyMode unset; set location only to force local-pack targeting.'),\n inputSchema: SearchSerpInputSchema,\n outputSchema: SearchSerpOutputSchema,\n annotations: liveWebToolAnnotations('Google SERP Lookup'),\n }, async (input) => formatSearchSerp(await executor.searchSerp(input), input))\n\n server.registerTool('extract_url', {\n title: 'Single URL Extract',\n description: withReportNote('Extract structured data from one public URL when the user provides one page, asks to inspect/scrape a page, or needs page content, schema, headings, metadata, screenshots, branding, or media assets. Returns structured page fields plus artifact handles for saved reports/screenshots/media when requested. Set depositToVault:true to also save the full page into the user\\'s MCP Memory vault server-side (the full body is NOT returned to chat). Use map_site_urls before extracting a site inventory; use extract_site for multi-page crawling.'),\n inputSchema: ExtractUrlInputSchema,\n outputSchema: ExtractUrlOutputSchema,\n annotations: liveWebToolAnnotations('Single URL Extract'),\n }, async (input) => formatExtractUrl(await executor.extractUrl(input), input))\n\n server.registerTool('map_site_urls', {\n title: 'Site URL Map',\n description: withReportNote('Map/crawl a public website when the user asks for a sitemap, URL inventory, broken-link scan, redirect scan, or crawl planning. Returns internal URLs with HTTP status and truncation metadata. Supports up to maxUrls=10000; maps over 500 URLs write the complete inventory to a local CSV file and return a summary plus the file path instead of the full list inline. Use this before extract_site when choosing pages for an audit; use extract_url for one known page.'),\n inputSchema: MapSiteUrlsInputSchema,\n outputSchema: MapSiteUrlsOutputSchema,\n annotations: liveWebToolAnnotations('Site URL Map'),\n }, async (input) => formatMapSiteUrls(await executor.mapSiteUrls(input), input))\n\n server.registerTool('extract_site', {\n title: 'Multi-Page Site Content Crawl',\n description: withReportNote('Crawl a public website and return the page CONTENT across multiple pages (map + scrape). Returns per-page titles and Markdown content. Supports up to maxPages=10000; bulk crawls over 25 pages switch to folder mode: each page is saved as its own Markdown file in a local folder and the response returns a summary plus the folder path instead of inlining all content. This tool returns content only — for a technical SEO audit (issues, internal link graph, indexability, heading breakdown, image sizes/formats) use audit_site. Use map_site_urls first when URL selection matters; use extract_url for one page.'),\n inputSchema: ExtractSiteInputSchema,\n outputSchema: ExtractSiteOutputSchema,\n annotations: liveWebToolAnnotations('Multi-Page Site Content Crawl'),\n }, async (input) => formatExtractSite(await executor.extractSite(input), input))\n\n server.registerTool('audit_site', {\n title: 'Technical SEO Audit',\n description: withReportNote('Run a full technical SEO audit (Screaming-Frog-style) on a public website. Crawls up to maxPages and produces a complete on-page + crawl analysis: per-page title/meta lengths, heading breakdown, indexability and canonical status, schema, an internal link graph (inlinks/orphans/crawl-depth), a link analysis (top internal pages by inlinks, top external domains by link count, broken/orphan counts), an issues report, and an image audit (byte size, format, over-100KB and legacy-format flags). Writes everything to a local folder (report.md, issues.json, pages.jsonl, links.jsonl, link-metrics.jsonl, link-report.md, links-summary.json, external-domains.json, images.jsonl) plus per-page content, and returns a headline summary plus the folder path. Use this when the user wants an audit or analysis; use extract_site when they just want page content.'),\n inputSchema: AuditSiteInputSchema,\n outputSchema: AuditSiteOutputSchema,\n annotations: liveWebToolAnnotations('Technical SEO Audit'),\n }, async (input) => formatAuditSite(await executor.auditSite(input), input))\n\n server.registerTool('youtube_harvest', {\n title: 'YouTube Video Harvest',\n description: withReportNote('Harvest YouTube video metadata when the user wants to find videos by topic, inspect a channel library, compare video angles, or get videoIds for later transcription. Use mode \"search\" for keyword/topic requests and mode \"channel\" for @handles, channel IDs, or channel URLs. Returns titles, views, durations, URLs, and videoIds for follow-up transcription. Use youtube_transcribe after selecting one video.'),\n inputSchema: YoutubeHarvestInputSchema,\n outputSchema: YoutubeHarvestOutputSchema,\n annotations: liveWebToolAnnotations('YouTube Video Harvest'),\n }, async (input) => formatYoutubeHarvest(await executor.youtubeHarvest(input), input))\n\n server.registerTool('youtube_transcribe', {\n title: 'YouTube Transcription',\n description: withReportNote('Fetch and transcribe captions from a YouTube video. Use this when the user asks what was said in a YouTube video, wants claims/offers/lessons extracted from a video, or provides a YouTube URL for transcript work. Returns full transcript, timestamped chunks, word count, and resolvedInputs. Pass videoId from youtube_harvest results, or pass url when the user pasted a YouTube URL. Use youtube_harvest first when you need to discover videos by topic/channel.'),\n inputSchema: YoutubeTranscribeInputSchema,\n outputSchema: YoutubeTranscribeOutputSchema,\n annotations: liveWebToolAnnotations('YouTube Transcription'),\n }, async (input) => formatYoutubeTranscribe(await executor.youtubeTranscribe(input), input))\n\n server.registerTool('facebook_page_intel', {\n title: 'Facebook Advertiser Ad Intel',\n description: withReportNote('Harvest ads from a Facebook advertiser when the user wants current ad copy, creative angles, CTAs, video URLs, or competitive ad intelligence for one brand/page. Returns ad copy, headlines, CTAs, creative type, status, landing URLs, and direct ad video URLs ready for facebook_ad_transcribe. Accepts pageId, libraryId, or a brand/advertiser name as query. Use facebook_ad_search first when the advertiser handle is unknown. For normal public Facebook reels/posts/watch/share URLs, use facebook_video_transcribe instead.'),\n inputSchema: FacebookPageIntelInputSchema,\n outputSchema: FacebookPageIntelOutputSchema,\n annotations: liveWebToolAnnotations('Facebook Advertiser Ad Intel'),\n }, async (input) => formatFacebookPageIntel(await executor.facebookPageIntel(input), input))\n\n server.registerTool('facebook_ad_search', {\n title: 'Facebook Ad Library Search',\n description: withReportNote('Search Facebook Ad Library when the user wants to find advertisers by brand, competitor, niche, or keyword. Returns advertisers with ad counts and library IDs. Use this to discover competitor/page handles, then pass libraryId or pageId to facebook_page_intel for ad details.'),\n inputSchema: FacebookAdSearchInputSchema,\n outputSchema: FacebookAdSearchOutputSchema,\n annotations: liveWebToolAnnotations('Facebook Ad Library Search'),\n }, async (input) => formatFacebookAdSearch(await executor.facebookAdSearch(input), input))\n\n server.registerTool('reddit_thread', {\n title: 'Reddit Thread + Comments',\n description: withReportNote('Capture a Reddit post and its comment tree from any reddit.com thread URL. Use this when the user wants Reddit comments, opinions, discussion, or audience voice from a specific thread (find threads first with search_serp, which surfaces reddit.com/comments links). Returns the post title, author, score, body, and a list of comments with author, score, nesting depth, and text. Handles Reddit\\'s bot protection automatically (fetches via old.reddit through a residential proxy with retries); pass maxComments to cap the list.'),\n inputSchema: RedditThreadInputSchema,\n outputSchema: RedditThreadOutputSchema,\n annotations: liveWebToolAnnotations('Reddit Thread + Comments'),\n }, async (input) => formatRedditThread(await executor.redditThread(input), input))\n\n server.registerTool('facebook_ad_transcribe', {\n title: 'Facebook Ad Transcription',\n description: 'Transcribe audio from a Facebook ad video CDN URL. Use this when facebook_page_intel returned a direct videoUrl and the user asks what the ad says, what claims it makes, or wants ad-message extraction. Returns full transcript, timestamped chunks, word count, and resolvedInputs. Use only with the direct videoUrl value from facebook_page_intel results; do not pass public Facebook post/reel/share URLs. Use facebook_video_transcribe for organic Facebook URLs, and facebook_page_intel first when you only have a brand/page/ad library handle.',\n inputSchema: FacebookAdTranscribeInputSchema,\n outputSchema: FacebookAdTranscribeOutputSchema,\n annotations: liveWebToolAnnotations('Facebook Ad Transcription'),\n }, async (input) => formatFacebookAdTranscribe(await executor.facebookAdTranscribe(input), input))\n\n server.registerTool('google_ads_search', {\n title: 'Google Ads Transparency Search',\n description: withReportNote('Search the Google Ads Transparency Center to find advertisers running Google ads (Search, Display, YouTube) by domain or brand/advertiser name. Pass a domain like getviktor.com to see every advertiser account pointing ads at that site, or an advertiser name. Returns advertisers with their advertiser ID and an approximate ad count. Use this to discover an advertiserId, then pass it (or the domain) to google_ads_page_intel for the actual ad creatives.'),\n inputSchema: GoogleAdsSearchInputSchema,\n outputSchema: GoogleAdsSearchOutputSchema,\n annotations: liveWebToolAnnotations('Google Ads Transparency Search'),\n }, async (input) => formatGoogleAdsSearch(await executor.googleAdsSearch(input), input))\n\n server.registerTool('google_ads_page_intel', {\n title: 'Google Ads Advertiser Intel',\n description: withReportNote('Harvest an advertiser\\'s ads from the Google Ads Transparency Center when the user wants a competitor\\'s Google/YouTube ad creatives, copy angles, image URLs, or video ads. Accepts an advertiserId (from google_ads_search) or a domain directly. Returns each creative\\'s format (text/image/video), image URLs, landing info, a detail URL, and — for video ads — the YouTube video ID and/or a direct video URL ready for transcription. Use google_ads_search first when you only have a brand name. Transcribe video ads with google_ads_transcribe (video URL) or youtube_transcribe (YouTube ID).'),\n inputSchema: GoogleAdsPageIntelInputSchema,\n outputSchema: GoogleAdsPageIntelOutputSchema,\n annotations: liveWebToolAnnotations('Google Ads Advertiser Intel'),\n }, async (input) => formatGoogleAdsPageIntel(await executor.googleAdsPageIntel(input), input))\n\n server.registerTool('google_ads_transcribe', {\n title: 'Google Ad Video Transcription',\n description: 'Transcribe audio from a Google video ad. Use this when google_ads_page_intel returned a direct videoUrl (a googlevideo.com playback URL) for a video creative and the user asks what the ad says or wants its claims/messaging. Returns full transcript, timestamped chunks, and word count. For YouTube-hosted ads, pass the returned youtubeVideoId to youtube_transcribe instead; run google_ads_page_intel first when you only have an advertiser/domain.',\n inputSchema: GoogleAdsTranscribeInputSchema,\n outputSchema: GoogleAdsTranscribeOutputSchema,\n annotations: liveWebToolAnnotations('Google Ad Video Transcription'),\n }, async (input) => formatGoogleAdsTranscribe(await executor.googleAdsTranscribe(input), input))\n\n server.registerTool('facebook_video_transcribe', {\n title: 'Facebook Organic Video Transcription',\n description: withReportNote('Transcribe audio from an organic Facebook reel, video, watch, post, or share URL, including fb.watch links. Use this when the user pastes a normal Facebook video page URL and wants the transcript or downloadable MP4. Renders the Facebook page in a browser, selects the best matching public Facebook CDN MP4 URL from page state, then returns sourceUrl, resolved pageUrl, videoId, ownerName, selectedQuality, bitrate, videoDurationSec, extracted MP4 URL, full transcript, and timestamped chunks.'),\n inputSchema: FacebookVideoTranscribeInputSchema,\n outputSchema: FacebookVideoTranscribeOutputSchema,\n annotations: liveWebToolAnnotations('Facebook Organic Video Transcription'),\n }, async (input) => formatFacebookVideoTranscribe(await executor.facebookVideoTranscribe(input), input))\n\n server.registerTool('instagram_profile_content', {\n title: 'Instagram Profile Content Discovery',\n description: withReportNote('Discover Instagram profile grid content links for a handle or profile URL. Use this when the user wants a person or brand account content inventory before selecting posts/reels to download. Returns profile stats, collected post/reel/tv URLs, shortcodes, type counts, browser details, pagination attempts, stop reason, and limitations.'),\n inputSchema: InstagramProfileContentInputSchema,\n outputSchema: InstagramProfileContentOutputSchema,\n annotations: liveWebToolAnnotations('Instagram Profile Content Discovery'),\n }, async (input) => formatInstagramProfileContent(await executor.instagramProfileContent(input), input))\n\n server.registerTool('instagram_media_download', {\n title: 'Instagram Post/Reel Media Download',\n description: withReportNote('Extract and download media from one Instagram post, reel, or tv URL. Use after instagram_profile_content or when the user gives a specific Instagram URL and wants the image, caption/text, reel audio/video tracks, optional muxed MP4, or optional transcript. Reels commonly expose separate video-only and audio-only MP4 tracks; this tool selects the best video and audio tracks and attempts muxing when ffmpeg is available.'),\n inputSchema: InstagramMediaDownloadInputSchema,\n outputSchema: InstagramMediaDownloadOutputSchema,\n annotations: liveWebToolAnnotations('Instagram Post/Reel Media Download'),\n }, async (input) => formatInstagramMediaDownload(await executor.instagramMediaDownload(input), input))\n\n server.registerTool('maps_place_intel', {\n title: 'Google Maps Business Profile Details',\n description: withReportNote('Extract Google Maps business intelligence for one known/named business: rating, review count, category, address, phone, website, hours, booking URL, review histogram, review topics, about attributes, entity IDs, and optional review cards. Do not use this for category searches, local market prospect lists, or requests for multiple GMB/GBP profiles; use maps_search first for those. Split business name from location (e.g. \"Elite Roofing Denver CO\" => businessName \"Elite Roofing\", location \"Denver, CO\"). Pass includeReviews true when the user asks for reviews/customer pain.'),\n inputSchema: MapsPlaceIntelInputSchema,\n outputSchema: MapsPlaceIntelOutputSchema,\n annotations: liveWebToolAnnotations('Google Maps Business Profile Details'),\n }, async (input) => formatMapsPlaceIntel(await executor.mapsPlaceIntel(input), input))\n\n server.registerTool('maps_search', {\n title: 'Google Maps Business Search',\n description: withReportNote('Search Google Maps for multiple businesses/profiles by category, niche, keyword, or local market. Use this when the user asks for several Google Business Profiles, GMBs, GBPs, leads, prospects, competitors, or \"more than the 3-pack.\" Routing is automatic and location-aware — leave proxyMode unset; pass proxyZip only to force a specific ZIP. Returns up to 50 candidates with names, place URLs, CIDs when available, ratings, review counts, profile metadata, and sanitized attempt telemetry. Default maxResults is 10; maximum is 50. Use maps_place_intel afterward only when a selected business needs full details and reviews.'),\n inputSchema: MapsSearchInputSchema,\n outputSchema: MapsSearchOutputSchema,\n annotations: liveWebToolAnnotations('Google Maps Business Search'),\n }, async (input) => formatMapsSearch(await executor.mapsSearch(input), input))\n\n server.registerTool('directory_workflow', {\n title: 'Directory Workflow: Markets + Maps',\n description: withReportNote('Build directory/prospecting datasets by selecting US city markets from the free Census Population Estimates city/place dataset, optionally joining configured US ZIPS/Lead Magician ZIP groups, then running Google Maps business searches for each city in parallel. Use this when the user wants \"all cities over 100k population in a state\", \"build a directory CSV\", \"find markets then get Maps data\", or similar location-database + Maps workflows. Set minPopulation, state, query, maxResultsPerCity, and concurrency. Routing is automatic per city. Saved CSV rows include source_location, result_position, business_name, review_stars, review_count, category, address, phone, hours_status, website_url, directions_url, place_url, cid, cid_decimal, city population, and ZIP groups. Structured city results include sanitized attempt telemetry. Use maps_place_intel only when a selected profile needs deeper review topics, profile review count confirmation, or review cards. For local Lead Magician ZIP enrichment, set MCP_SCRAPER_USZIPS_CSV_PATH on the API server or pass usZipsCsvPath only in local/test mode.'),\n inputSchema: DirectoryWorkflowInputSchema,\n outputSchema: DirectoryWorkflowOutputSchema,\n annotations: liveWebToolAnnotations('Directory Workflow: Markets + Maps'),\n }, async (input) => formatDirectoryWorkflow(await executor.directoryWorkflow(input), input))\n\n server.registerTool('workflow_list', {\n title: 'Workflow Catalog',\n description: 'List MCP Scraper higher-level workflows and AI-facing recipes. Use this when the user asks what MCP Scraper can do beyond single tools, or asks for market analysis, ICP research, forum/review acquisition, full brand design briefings, CRO audits, competitive positioning, content gap briefs, or AI search visibility audits. Returns runnable workflow ids plus recipe guidance for the best tool chain.',\n inputSchema: WorkflowListInputSchema,\n outputSchema: WorkflowListOutputSchema,\n annotations: localPlanningToolAnnotations('Workflow Catalog'),\n }, async (input) => formatWorkflowList(await executor.workflowList(input), input))\n\n server.registerTool('workflow_suggest', {\n title: 'Workflow Intent Router',\n description: 'Route a high-level business or research goal to the right MCP Scraper workflow/tool chain. Use before running work when the user says things like \"do market analysis\", \"research my ICP\", \"acquire forum and review language\", \"build a brand design brief\", \"run a CRO audit\", \"compare competitors\", \"make a content gap brief\", or \"audit AI search visibility\". This tool does not spend credits; it tells the AI exactly which workflow/tool chain to run next.',\n inputSchema: WorkflowSuggestInputSchema,\n outputSchema: WorkflowSuggestOutputSchema,\n annotations: localPlanningToolAnnotations('Workflow Intent Router'),\n }, async (input) => formatWorkflowSuggest(input))\n\n server.registerTool('workflow_run', {\n title: 'Run Workflow',\n description: withReportNote('Start a higher-level MCP Scraper workflow. Use after workflow_suggest or workflow_list. Runnable workflow ids: directory, agent-packet, local-competitive-audit, map-comparison, serp-comparison, paa-expansion-brief, ai-overview-language. This is the main MCP tool for market analysis, ICP evidence packets, local competitive audits, Maps/SERP comparisons, content gap briefs, and AI Overview language guidance. Stepwise workflows (e.g. agent-packet) run ONE leg per call and return runId, the step output, and nextStep — when nextStep is present, call workflow_step with the runId to run the next leg, and keep calling it until done is true. This keeps each call short instead of one long blocking run, so report each step result to the user as it arrives.'),\n inputSchema: WorkflowRunInputSchema,\n outputSchema: WorkflowRunOutputSchema,\n annotations: liveWebToolAnnotations('Run Workflow'),\n }, async (input) => formatWorkflowRun(await executor.workflowRun(input), input))\n\n server.registerTool('workflow_step', {\n title: 'Advance Workflow Step',\n description: withReportNote('Run the next leg of a stepwise MCP Scraper workflow started with workflow_run. Pass the runId. Each call executes exactly one logical step (typically one live harvest), persists that step\\'s artifacts, and returns the step output plus nextStep. Keep calling workflow_step with the same runId until done is true, reporting each step result to the user as it lands. Use this instead of waiting on one long workflow call — it avoids client timeouts on long multi-step jobs.'),\n inputSchema: WorkflowStepInputSchema,\n outputSchema: WorkflowStepOutputSchema,\n annotations: liveWebToolAnnotations('Advance Workflow Step'),\n }, async (input) => formatWorkflowStep(await executor.workflowStep(input), input))\n\n server.registerTool('workflow_status', {\n title: 'Workflow Status',\n description: 'Fetch a hosted workflow run by id and list its current status and artifacts. Use when a workflow may still be running, when the model needs to re-open a run, inspect artifact ids, recover from a long workflow, or decide whether to call workflow_step or workflow_artifact_read next. Use only a runId returned by workflow_run/workflow_step/workflow_status; do not construct one yourself.',\n inputSchema: WorkflowStatusInputSchema,\n outputSchema: WorkflowStatusOutputSchema,\n annotations: liveWebToolAnnotations('Workflow Status'),\n }, async (input) => formatWorkflowStatus(await executor.workflowStatus(input), input))\n\n server.registerTool('workflow_artifact_read', {\n title: 'Read Workflow Artifact',\n description: 'Read a workflow artifact back into MCP context by run id and artifact id. Use this before writing final deliverables so the answer is grounded in generated evidence.json, CSVs, Markdown briefs, reports, and task files instead of memory. Use workflow_status first when artifact ids are unknown. Use only artifactId values returned by workflow_run/workflow_step/workflow_status; do not construct one yourself. Use maxBytes to limit large CSV/JSON artifacts.',\n inputSchema: WorkflowArtifactReadInputSchema,\n outputSchema: WorkflowArtifactReadOutputSchema,\n annotations: liveWebToolAnnotations('Read Workflow Artifact'),\n }, async (input) => formatWorkflowArtifactRead(await executor.workflowArtifactRead(input), input))\n\n server.registerTool('rank_tracker_workflow', {\n title: 'Rank Tracker Blueprint Builder',\n description: 'Generate a build-ready database, cron/heartbeat, ingestion, metrics, and AI implementation prompt for a rank tracker powered by MCP Scraper. Supports Maps rankings through directory_workflow/maps_search, organic rankings through search_serp, AI Overview citation tracking, and People Also Ask source presence tracking. This tool is local planning only; it does not call the web or spend credits.',\n inputSchema: RankTrackerBlueprintInputSchema,\n outputSchema: RankTrackerBlueprintOutputSchema,\n annotations: localPlanningToolAnnotations('Rank Tracker Blueprint Builder'),\n }, async (input) => buildRankTrackerBlueprint(input))\n\n server.registerTool('credits_info', {\n title: 'MCP Scraper Credits & Costs',\n description: 'Answer questions about MCP Scraper credits, usage limits, and concurrency upgrades: current credit balance, what a specific tool/action costs, the full cost table, current concurrency limit, the extra-slot price, billing URL, and the terminal checkout command. Does not expose payment methods or credit card information.',\n inputSchema: CreditsInfoInputSchema,\n outputSchema: CreditsInfoOutputSchema,\n annotations: {\n title: 'MCP Scraper Credits & Costs',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n }, async (input) => formatCreditsInfo(await executor.creditsInfo(input), input))\n\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { sanitizeVendorName } from '../errors.js'\nimport { WORKFLOW_RECIPES, suggestWorkflowRecipes, type WorkflowRecipe } from './workflow-catalog.js'\nimport { buildLinkGraph } from '../api/seo-link-graph.js'\nimport { buildLinkReport, renderLinkReport, type LinkReport } from '../api/seo-link-report.js'\nimport { computeIssues, renderIssueReport } from '../api/seo-issues.js'\nimport { auditImages, renderImageSection, type ImageAudit } from '../api/image-audit.js'\nimport type { PageData } from '../api/site-extractor.js'\n\nlet reportSavingEnabled = true\n\nexport function configureReportSaving(enabled: boolean): void {\n reportSavingEnabled = enabled\n}\n\nfunction sanitizeVendorText(text: string): string {\n return sanitizeVendorName(\n text\n .replace(/kernel_session_id/gi, 'browser_session_id')\n .replace(/kernel_delete_succeeded/gi, 'session_cleanup_succeeded')\n .replace(/kernel_delete_started/gi, 'session_cleanup_started')\n .replace(/kernel_delete_error/gi, 'session_cleanup_error')\n .replace(/kernelSessionId/g, 'browserSessionId')\n .replace(/kernelProxyId/g, 'proxyId')\n .replace(/KERNEL_API_KEY/g, 'BROWSER_SERVICE_API_KEY')\n .replace(/\"kernel\"\\s*:/gi, '\"browserRuntime\":'),\n )\n}\n\nfunction slugifyReportName(input: string): string {\n return input\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 80) || 'mcp-scraper-report'\n}\n\nfunction reportTitle(full: string): string {\n const title = full.split('\\n').find(line => line.startsWith('# '))\n return title?.replace(/^#\\s+/, '').trim() || 'MCP Scraper Report'\n}\n\nexport function outputBaseDir(): string {\n return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || join(homedir(), 'Downloads', 'mcp-scraper')\n}\n\nfunction saveFullReport(full: string): string | null {\n if (!reportSavingEnabled || process.env.MCP_SCRAPER_SAVE_REPORTS === 'false') return null\n const outDir = outputBaseDir()\n try {\n mkdirSync(outDir, { recursive: true })\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const file = join(outDir, `${stamp}-${slugifyReportName(reportTitle(full))}.md`)\n writeFileSync(file, full, 'utf8')\n return file\n } catch {\n return null\n }\n}\n\nconst BULK_PAGE_THRESHOLD = 25\nconst BULK_URL_THRESHOLD = 500\n\nfunction reportSavingActive(): boolean {\n return reportSavingEnabled && process.env.MCP_SCRAPER_SAVE_REPORTS !== 'false'\n}\n\ninterface BulkPage { url: string; title?: string | null; bodyMarkdown?: string | null; metaDescription?: string | null; schemaTypes?: string[] }\n\ninterface SeoExport {\n pageRows: Array<Record<string, unknown>>\n edges: Array<Record<string, unknown>>\n metrics: Array<Record<string, unknown>>\n issues: Record<string, { count: number; urls: string[] }>\n reportMd: string\n linkReport: LinkReport\n branding?: unknown\n}\n\nfunction saveBulkSite(siteUrl: string, pages: BulkPage[], seo?: SeoExport, imageAudit?: ImageAudit | null): { dir: string; indexFile: string; fileCount: number; seoFiles?: string[] } | null {\n if (!reportSavingActive()) return null\n try {\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const dir = join(outputBaseDir(), `extract-${slugifyReportName(siteUrl)}-${stamp}`)\n const pagesDir = join(dir, 'pages')\n mkdirSync(pagesDir, { recursive: true })\n\n const indexRows = pages.map((p, i) => {\n const num = String(i + 1).padStart(4, '0')\n const slug = slugifyReportName(p.url.replace(/^https?:\\/\\//, '')).slice(0, 60) || 'page'\n const fname = `${num}-${slug}.md`\n const body = (p.bodyMarkdown ?? '').trim()\n const content = [\n `# ${p.title ?? 'Untitled'}`,\n `- **URL:** ${p.url}`,\n p.metaDescription ? `- **Description:** ${p.metaDescription}` : '',\n p.schemaTypes?.length ? `- **Schema:** ${p.schemaTypes.join(', ')}` : '',\n '',\n body || '_(no content extracted)_',\n ].filter(Boolean).join('\\n')\n writeFileSync(join(pagesDir, fname), content, 'utf8')\n return `| ${i + 1} | ${cell(p.title ?? 'Untitled')} | ${p.url} | pages/${fname} |`\n })\n\n const dataFilesSection = seo ? [\n `\\n## Data files (in this folder)`,\n `- \\`report.md\\` — SEO issues summary (counts + example URLs)`,\n `- \\`issues.json\\` — every finding with the full list of offender URLs`,\n `- \\`pages.jsonl\\` — per-page SEO fields, one JSON object per page`,\n `- \\`links.jsonl\\` — internal/external link edges (anchor, rel, target status)`,\n `- \\`link-metrics.jsonl\\` — inlinks, crawl depth, orphan flags per page`,\n `- \\`link-report.md\\` — link analysis: top internal pages by inlinks, top external domains, distribution`,\n `- \\`links-summary.json\\` — link totals + top-20 internal pages + top-20 external domains`,\n `- \\`external-domains.json\\` — every external domain linked to, ordered by link count`,\n ...(imageAudit ? [\n `- \\`images.jsonl\\` — every image with byte size, format, over-100KB and legacy-format flags`,\n `- \\`images-summary.json\\` — image totals (count, total weight, over-100KB, legacy)`,\n ] : []),\n ...(seo.branding ? [`- \\`branding.json\\` — site logo, colors, fonts`] : []),\n ].join('\\n') : ''\n\n const index = [\n `# Site Extract: ${siteUrl}`,\n `**${pages.length} pages** crawled. Everything is in this folder.`,\n `- Page content: one Markdown file per page under \\`pages/\\` (listed in the table below).`,\n seo ? `- SEO crawl data: the data files listed below.` : '',\n dataFilesSection,\n `\\n## Pages\\n| # | Title | URL | File |\\n|---|-------|-----|------|\\n${indexRows.join('\\n')}`,\n ].filter(Boolean).join('\\n')\n const indexFile = join(dir, 'index.md')\n writeFileSync(indexFile, index, 'utf8')\n\n let seoFiles: string[] | undefined\n if (seo) {\n const toJsonl = (rows: Array<Record<string, unknown>>) => rows.map(r => JSON.stringify(r)).join('\\n')\n const pagesJsonl = join(dir, 'pages.jsonl')\n const linksJsonl = join(dir, 'links.jsonl')\n const metricsJsonl = join(dir, 'link-metrics.jsonl')\n const issuesFile = join(dir, 'issues.json')\n const reportFile = join(dir, 'report.md')\n writeFileSync(pagesJsonl, toJsonl(seo.pageRows), 'utf8')\n writeFileSync(linksJsonl, toJsonl(seo.edges), 'utf8')\n writeFileSync(metricsJsonl, toJsonl(seo.metrics), 'utf8')\n writeFileSync(issuesFile, JSON.stringify(seo.issues, null, 2), 'utf8')\n writeFileSync(reportFile, seo.reportMd + (imageAudit ? `\\n\\n${renderImageSection(imageAudit)}` : ''), 'utf8')\n const linkReportFile = join(dir, 'link-report.md')\n const linksSummaryFile = join(dir, 'links-summary.json')\n const externalDomainsFile = join(dir, 'external-domains.json')\n writeFileSync(linkReportFile, renderLinkReport(seo.linkReport), 'utf8')\n writeFileSync(linksSummaryFile, JSON.stringify(seo.linkReport.summary, null, 2), 'utf8')\n writeFileSync(externalDomainsFile, JSON.stringify(seo.linkReport.externalDomains, null, 2), 'utf8')\n seoFiles = [pagesJsonl, linksJsonl, metricsJsonl, issuesFile, reportFile, linkReportFile, linksSummaryFile, externalDomainsFile]\n if (imageAudit) {\n const imagesJsonl = join(dir, 'images.jsonl')\n const imagesSummary = join(dir, 'images-summary.json')\n writeFileSync(imagesJsonl, imageAudit.rows.map(r => JSON.stringify(r)).join('\\n'), 'utf8')\n writeFileSync(imagesSummary, JSON.stringify(imageAudit.summary, null, 2), 'utf8')\n seoFiles.push(imagesJsonl, imagesSummary)\n }\n if (seo.branding) {\n const brandingFile = join(dir, 'branding.json')\n writeFileSync(brandingFile, JSON.stringify(seo.branding, null, 2), 'utf8')\n seoFiles.push(brandingFile)\n }\n }\n\n return { dir, indexFile, fileCount: pages.length, seoFiles }\n } catch {\n return null\n }\n}\n\nfunction saveUrlInventory(siteUrl: string, urls: Array<{ url: string; status: number | null }>): string | null {\n if (!reportSavingActive()) return null\n try {\n const outDir = outputBaseDir()\n mkdirSync(outDir, { recursive: true })\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const file = join(outDir, `${stamp}-urlmap-${slugifyReportName(siteUrl.replace(/^https?:\\/\\//, ''))}.csv`)\n const csv = (v: string) => /[\",\\n]/.test(v) ? `\"${v.replace(/\"/g, '\"\"')}\"` : v\n const rows = ['url,status', ...urls.map(u => `${csv(u.url)},${u.status ?? ''}`)]\n writeFileSync(file, rows.join('\\n'), 'utf8')\n return file\n } catch {\n return null\n }\n}\n\nfunction persistScreenshotLocally(base64: string, url: string): string | null {\n if (!reportSavingEnabled || process.env.MCP_SCRAPER_SAVE_REPORTS === 'false') return null\n try {\n const dir = join(outputBaseDir(), 'screenshots')\n mkdirSync(dir, { recursive: true })\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const slug = url.replace(/^https?:\\/\\//, '').replace(/[^a-z0-9]+/gi, '-').replace(/^-+|-+$/g, '').slice(0, 60)\n const filePath = join(dir, `${stamp}-${slug}.png`)\n writeFileSync(filePath, Buffer.from(base64, 'base64'))\n return filePath\n } catch {\n return null\n }\n}\n\nfunction oneBlock(content: string, diskContent?: string): CallToolResult {\n const filePath = saveFullReport(diskContent ?? content)\n const text = filePath ? `${content}\\n\\n📄 Saved: \\`${filePath}\\`` : content\n return { content: [{ type: 'text', text }] }\n}\n\nexport function passthrough(raw: CallToolResult): CallToolResult {\n return raw\n}\n\nfunction workflowRecipeTable(recipes: WorkflowRecipe[]): string {\n if (!recipes.length) return ''\n return [\n '| Recipe | Best workflow | What it produces |',\n '|---|---|---|',\n ...recipes.map(recipe => `| ${cell(recipe.title)} | ${recipe.primaryWorkflowId ? `\\`${recipe.primaryWorkflowId}\\`` : 'tool chain'} | ${cell(recipe.produces.slice(0, 4).join(', '))} |`),\n ].join('\\n')\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 formatStructuredError(body: Record<string, unknown>, fallback: string): string {\n if (body.error === 'insufficient_balance') {\n return `Insufficient credits. Balance: ${body.balance_credits} credits. This call requires ${body.required_credits} credits. Top up at ${body.topup_url}`\n }\n if (body.error === 'mcp_request_timeout') {\n return typeof body.message === 'string' ? body.message : 'MCP Scraper request timed out and was cancelled.'\n }\n if (typeof body.error_code === 'string') {\n const message = typeof body.error === 'string'\n ? body.error\n : typeof body.message === 'string'\n ? body.message\n : fallback\n const retryable = body.retryable === true ? ' Retryable: yes.' : ''\n return `${body.error_code}: ${message}${retryable}${errorAttemptsSection(body)}`\n }\n if (typeof body.error === 'string') return body.error\n return fallback || 'Tool error'\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 (raw.isError || parsed.error || parsed.error_code) return { error: sanitizeVendorText(formatStructuredError(parsed, text)) }\n const data = (parsed.result as Record<string, unknown>) ?? parsed\n return { data }\n } catch {\n if (raw.isError) return { error: sanitizeVendorText(text || 'Tool error') }\n return { error: 'Failed to parse tool response' }\n }\n}\n\ninterface EntityIdRecord { name: string; kgId: string | null; cid: string | null; gcid: string | null }\ninterface EntityIdsData { entities?: EntityIdRecord[]; kgIds?: string[]; cids?: string[]; gcids?: string[] }\n\nfunction entityIdsSection(ids?: EntityIdsData): string {\n if (!ids) return ''\n const lines: string[] = []\n if (ids.entities?.length) {\n for (const e of ids.entities) {\n const idParts = [e.kgId && `MID ${e.kgId}`, e.cid && `CID ${e.cid}`, e.gcid && `GCID ${e.gcid}`].filter(Boolean)\n if (idParts.length) lines.push(`- **${e.name}** — ${idParts.join(', ')}`)\n }\n }\n const linkedNames = new Set((ids.entities ?? []).map(e => e.name))\n if (!linkedNames.size) {\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 }\n return lines.length ? `\\n## Entity IDs\\n${lines.join('\\n')}` : ''\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\nexport function cell(s: string | null | undefined): string {\n return String(s ?? '')\n .replace(/\\r?\\n+/g, ' ')\n .replace(/\\|/g, '\\\\|')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\nfunction debugSection(debug: any): string {\n if (!debug || typeof debug !== 'object') return ''\n const request = debug.request ?? {}\n const browser = debug.browser ?? {}\n const kernel = browser.browserRuntime ?? browser.kernel ?? {}\n const network = browser.networkLocation ?? {}\n const nav = browser.serpNavigation ?? {}\n const proxyResolution = kernel.proxyResolution ?? {}\n const locationEvidence = debug.locationEvidence\n const candidates = Array.isArray(locationEvidence?.candidates)\n ? locationEvidence.candidates.slice(0, 4).map((c: any) => `${c.city}, ${c.regionCode} (${c.count})`).join(', ')\n : ''\n const lines = [\n '\\n## Debug',\n `- Proxy mode: ${request.proxyMode ?? kernel.proxyMode ?? 'unknown'} · requested proxy: ${kernel.requestedProxyIdPresent === true ? `yes (${kernel.requestedProxyIdSuffix ?? 'redacted'})` : 'no'}`,\n `- Proxy resolution: ${proxyResolution.source ?? 'unknown'}${proxyResolution.target ? ` · ${proxyResolution.target.level ?? 'city'} ${proxyResolution.target.city}, ${proxyResolution.target.state}` : ''}${proxyResolution.error ? ` · ${truncate(proxyResolution.error, 180)}` : ''}`,\n `- Browser session: ${kernel.sessionId ?? 'unknown'} · retrieved proxy: ${kernel.retrievedProxyIdPresent === true ? `yes (${kernel.retrievedProxyIdSuffix ?? 'redacted'})` : kernel.retrievedProxyIdPresent === false ? 'no' : 'unknown'}`,\n `- Browser IP geo: ${[network.ip, network.city, network.region, network.country].filter(Boolean).join(' · ') || network.error || 'unknown'}`,\n `- Google URL: ${truncate(nav.requestedUrl, 240) || 'unknown'}`,\n `- Final URL: ${truncate(nav.finalUrl, 240) || 'unknown'} · CAPTCHA: ${nav.captchaDetected === true ? 'yes' : nav.captchaDetected === false ? 'no' : 'unknown'} · redirected: ${nav.redirected === true ? 'yes' : nav.redirected === false ? 'no' : 'unknown'}`,\n ]\n if (locationEvidence) {\n lines.push(`- Location evidence: ${locationEvidence.status}${locationEvidence.expected ? ` · expected ${locationEvidence.expected.city}${locationEvidence.expected.regionCode ? `, ${locationEvidence.expected.regionCode}` : ''}` : ''}${candidates ? ` · candidates ${candidates}` : ''}`)\n }\n return sanitizeVendorText(lines.join('\\n'))\n}\n\nfunction errorAttemptsSection(body: Record<string, unknown>): string {\n const attempts = Array.isArray(body.attempts) ? body.attempts as Array<Record<string, any>> : []\n if (attempts.length === 0) return ''\n const lines = attempts.slice(0, 5).map((attempt) => {\n const debug = attempt.debug ?? {}\n const browser = debug.browser ?? {}\n const kernel = browser.browserRuntime ?? browser.kernel ?? {}\n const proxyResolution = kernel.proxyResolution ?? {}\n const network = browser.networkLocation ?? {\n ip: attempt.observedIp ?? attempt.observed_ip,\n city: attempt.observedCity ?? attempt.observed_city,\n region: attempt.observedRegion ?? attempt.observed_region,\n }\n const nav = browser.serpNavigation ?? {}\n const geo = [network.ip, network.city, network.region].filter(Boolean).join(' / ') || 'geo unknown'\n const sessionId = attempt.browser_session_id ?? attempt.browserSessionIdSuffix ?? attempt.kernel_session_id ?? kernel.sessionId ?? 'unknown'\n const cleanupSucceeded = attempt.session_cleanup_succeeded ?? attempt.kernel_delete_succeeded\n const proxySource = proxyResolution.source ?? attempt.proxyResolutionSource\n return `- Attempt ${attempt.attempt_number ?? attempt.attemptNumber ?? '?'}: ${attempt.outcome ?? attempt.status ?? 'unknown'} · session ${sessionId} · proxy ${debug.request?.proxyMode ?? kernel.proxyMode ?? attempt.proxyMode ?? 'unknown'}${proxySource ? `/${proxySource}` : ''} · ${geo} · CAPTCHA ${nav.captchaDetected === true ? 'yes' : nav.captchaDetected === false ? 'no' : 'unknown'} · cleanup ${cleanupSucceeded === true ? 'yes' : cleanupSucceeded === false ? 'no' : 'unknown'}`\n })\n return `\\n\\nAttempts:\\n${lines.join('\\n')}`\n}\n\ninterface FlatRow { question: string; answer?: string; source_site?: string; source_title?: string }\ninterface OrganicResult { position: number; title: string; url: string; domain: string; snippet?: string | null }\ninterface AIOverview { detected: boolean; text?: string | null; shareUrl?: string | null }\ninterface HarvestDiagnostics { completionStatus?: string; debug?: unknown }\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 EntityIdsData | undefined\n const aiOvw = d.aiOverview as AIOverview | undefined\n const diagnostics = d.diagnostics as HarvestDiagnostics | undefined\n const durationMs = (d.stats as { durationMs?: number } | undefined)?.durationMs\n\n const paaRows = flat.map((r, i) =>\n `| ${i + 1} | ${cell(r.question)} | ${cell(truncate(r.answer, 120))} | ${cell(r.source_title || 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*Google did not return a People Also Ask block for this query/location. SERP data was extracted successfully when available.*'\n\n const serpRows = organic.map(r =>\n `| ${r.position} | ${cell(r.title)} | [${cell(r.domain)}](${r.url}) | ${cell(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)}`+(aiOvw.shareUrl ? `\\n\\n**Shareable link:** ${aiOvw.shareUrl}` : '')\n : ''\n\n const statsLine = durationMs\n ? `\\n## Stats\\n- Status: ${diagnostics?.completionStatus ?? (flat.length ? 'paa_found' : 'no_paa')} · Questions: ${flat.length} · Duration: ${(durationMs / 1000).toFixed(1)}s`\n : ''\n\n const tips = `\\n---\\n💡 **Tips**\\n- Max questions: \\`maxQuestions: 200\\` (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 = `# PAA Report: \"${input.query}\"${input.location ? ` · ${input.location}` : ''}\\n\\n${paaTable}${serpTable}${entityIdsSection(entityIds)}${aiSection}${statsLine}${debugSection(diagnostics?.debug)}${tips}`\n\n return {\n ...oneBlock(full),\n structuredContent: {\n query: input.query,\n location: input.location ?? null,\n questionCount: flat.length,\n completionStatus: diagnostics?.completionStatus ?? null,\n questions: flat.map(r => ({\n question: String(r.question ?? ''),\n answer: r.answer ?? null,\n sourceTitle: r.source_title ?? null,\n sourceSite: r.source_site ?? null,\n })),\n organicResults: organic.map(r => ({\n position: Number(r.position) || 0,\n title: String(r.title ?? ''),\n url: String(r.url ?? ''),\n domain: String(r.domain ?? ''),\n snippet: r.snippet ?? null,\n })),\n aiOverview: aiOvw ? { detected: aiOvw.detected === true, text: aiOvw.text ?? null, shareUrl: aiOvw.shareUrl ?? null } : null,\n entityIds: entityIds\n ? { entities: entityIds.entities ?? [], kgIds: entityIds.kgIds ?? [], cids: entityIds.cids ?? [], gcids: entityIds.gcids ?? [] }\n : null,\n durationMs: durationMs ?? null,\n },\n }\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 EntityIdsData | undefined\n const aiOvw = d.aiOverview as AIOverview | undefined\n const diagnostics = d.diagnostics as HarvestDiagnostics | undefined\n\n const serpRows = organic.map(r =>\n `| ${r.position} | ${cell(r.title)} | [${cell(r.domain)}](${r.url}) | ${cell(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} | ${cell(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)}`+(aiOvw.shareUrl ? `\\n\\n**Shareable link:** ${aiOvw.shareUrl}` : '')\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 = `# SERP Report: \"${input.query}\"${input.location ? ` · ${input.location}` : ''}\\n\\n${serpTable}${localSection}${entityIdsSection(entityIds)}${aiSection}${debugSection(diagnostics?.debug)}${tips}`\n\n return {\n ...oneBlock(full),\n structuredContent: {\n query: input.query,\n location: input.location ?? null,\n organicResults: organic.map(r => ({\n position: Number(r.position) || 0,\n title: String(r.title ?? ''),\n url: String(r.url ?? ''),\n domain: String(r.domain ?? ''),\n snippet: r.snippet ?? null,\n })),\n localPack: localPack.map(b => ({\n position: Number(b.position) || 0,\n name: String(b.name ?? ''),\n rating: b.rating ?? null,\n reviewCount: b.reviewCount ?? null,\n websiteUrl: b.websiteUrl ?? null,\n })),\n aiOverview: aiOvw ? { detected: aiOvw.detected === true, text: aiOvw.text ?? null, shareUrl: aiOvw.shareUrl ?? null } : null,\n entityIds: entityIds\n ? { entities: entityIds.entities ?? [], kgIds: entityIds.kgIds ?? [], cids: entityIds.cids ?? [], gcids: entityIds.gcids ?? [] }\n : null,\n },\n }\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 const screenshotMeta = d.screenshot as { base64: string; sizeBytes: number; device: string } | null | undefined\n const screenshotPath = screenshotMeta?.base64 ? persistScreenshotLocally(screenshotMeta.base64, url) : null\n const branding = d.branding as { colorScheme: string | null; colors: Record<string, string | null>; fonts: Record<string, string | null>; assets: Record<string, string | null> } | null | undefined\n const media = d.media as { outputDir: string | null; assets: unknown[]; filteredCount: number; totalFound: number } | null | undefined\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 to 3,000 of ${bodyMd.length.toLocaleString()} chars — full content in the saved report)*` : ''}`\n : ''\n const bodySectionFull = bodyMd ? `\\n## Page Content\\n${bodyMd}` : ''\n\n const mem = (d.memory as { deposited?: boolean; vault?: string; noteId?: string; chunks?: number; fileUrl?: string; fileExpiresAt?: string; error?: string } | null | undefined) ?? null\n const memSection = mem?.deposited\n ? `\\n## ✅ Saved to memory\\nFull content stored in vault \\`${mem.vault ?? '—'}\\` as note \\`${mem.noteId ?? '—'}\\`${mem.chunks !== undefined ? ` (${mem.chunks} chunks indexed)` : ''}. Recall it later with memory search — no need to re-scrape.`\n : mem?.fileUrl\n ? `\\n## 📄 Saved as a temporary file\\nMemory vault was unavailable${mem.error ? ` (${mem.error})` : ''}, so the full content was saved to a download link instead:\\n- **Link:** ${mem.fileUrl}\\n- **Expires:** ${mem.fileExpiresAt ?? 'in 24 hours'} (auto-deleted)`\n : mem\n ? `\\n## ⚠️ Memory deposit skipped\\n${mem.error ?? 'unknown error'} — the page content is still in the truncated preview above.`\n : ''\n\n const screenshotSection = screenshotMeta\n ? `\\n## Screenshot\\n- **File:** ${screenshotPath ?? '(returned inline only — disk write unavailable in this environment)'}\\n- **Size:** ${(screenshotMeta.sizeBytes / 1024).toFixed(1)} KB\\n- **Device:** ${screenshotMeta.device}`\n : ''\n\n const brandingSection = branding\n ? [\n `\\n## Branding`,\n branding.colorScheme ? `- **Color scheme:** ${branding.colorScheme}` : '',\n `- **Colors:**${Object.entries(branding.colors ?? {}).filter(([,v]) => v).map(([k,v]) => ` ${k}=${v}`).join(',') || ' (none extracted)'}`,\n `- **Fonts:**${Object.entries(branding.fonts ?? {}).filter(([,v]) => v).map(([k,v]) => ` ${k}=${v}`).join(',') || ' (none extracted)'}`,\n branding.assets?.logo ? `- **Logo:** ${branding.assets.logo}` : '',\n branding.assets?.favicon ? `- **Favicon:** ${branding.assets.favicon}` : '',\n ].filter(Boolean).join('\\n')\n : ''\n\n const mediaSection = media\n ? [\n `\\n## Media Assets`,\n `- **Found:** ${media.totalFound} total, ${media.filteredCount} filtered (ads/noise), ${media.assets.length} downloaded`,\n media.outputDir ? `- **Saved to:** ${media.outputDir}` : '',\n ].filter(Boolean).join('\\n')\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 = `# URL Extract: ${url}\\n**${title}**\\n${headingSection}${kpoSection}${brandingSection}${bodySection}${memSection}${screenshotSection}${mediaSection}${tips}`\n const diskReport = `# URL Extract: ${url}\\n**${title}**\\n${headingSection}${kpoSection}${brandingSection}${bodySectionFull}${memSection}${screenshotSection}${mediaSection}${tips}`\n\n const textResult = oneBlock(full, diskReport)\n const structuredContent = {\n url,\n title: (d.title as string | null) ?? null,\n headings: headings.map(h => ({ level: Number(h.level) || 0, text: String(h.text ?? '') })),\n schemaBlockCount: schemaCount,\n entityName: kpo?.entityName ?? null,\n entityTypes: kpo?.type ?? [],\n napScore: kpo?.napScore ?? null,\n missingSchemaFields: kpo?.missingFields ?? [],\n screenshotSaved: screenshotPath ?? null,\n branding: branding ?? null,\n mediaAssets: media?.assets ?? null,\n memory: mem ?? undefined,\n }\n\n if (screenshotMeta?.base64) {\n return {\n content: [\n ...(textResult.content),\n { type: 'image', data: screenshotMeta.base64, mimeType: 'image/png' },\n ],\n structuredContent,\n }\n }\n\n return { ...textResult, structuredContent }\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 isBulk = urls.length > BULK_URL_THRESHOLD\n const inventoryFile = isBulk ? saveUrlInventory(input.url, urls.map(u => ({ url: u.url, status: u.status ?? null }))) : null\n const inlineCount = isBulk ? BULK_URL_THRESHOLD : 200\n const urlRows = urls.slice(0, inlineCount).map((u, i) => `| ${i + 1} | ${u.url} | ${u.status ?? '—'} |`).join('\\n')\n\n const inventoryNote = isBulk\n ? inventoryFile\n ? `\\n## 📁 Full inventory saved\\n- **File:** \\`${inventoryFile}\\` (CSV: url, status — all ${urls.length} URLs)\\nShowing the first ${inlineCount} below; read the file for the complete list.`\n : `\\n## ⚠️ Full inventory not saved\\nReport saving is disabled, so only the first ${inlineCount} of ${urls.length} URLs are shown. Enable \\`MCP_SCRAPER_SAVE_REPORTS\\` to capture the full inventory.`\n : ''\n\n const full = [\n `# 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 inventoryNote,\n `\\n## URL Inventory${isBulk ? ` (first ${inlineCount} of ${urls.length})` : ''}\\n| # | URL | Status |\\n|---|-----|--------|\\n${urlRows}`,\n !isBulk && 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 return {\n ...oneBlock(full),\n structuredContent: {\n startUrl: d.startUrl ?? input.url,\n totalFound: d.totalFound ?? urls.length,\n truncated: d.truncated === true,\n okCount: ok.length,\n redirectCount: redirects.length,\n brokenCount: broken.length,\n inventoryFile: inventoryFile ?? null,\n urls: urls.map(u => ({ url: u.url, status: u.status ?? null })),\n durationMs: d.durationMs ?? 0,\n },\n }\n}\n\ninterface SitePageResult { url: string; title?: string | null; kpo?: KpoResult; schema?: unknown[]; bodyMarkdown?: string | null; metaDescription?: string | null }\ninterface ExtractSiteResult { pages: SitePageResult[]; durationMs?: number; branding?: unknown }\n\nfunction buildSeoExport(siteUrl: string, pages: PageData[], branding?: unknown): SeoExport {\n const { edges, metrics } = buildLinkGraph(pages, siteUrl)\n const pageRows = pages.map(p => {\n const { bodyMarkdown: _b, schema: _s, outlinks: _o, ...rest } = p\n const m = metrics.get(p.url)\n return { ...rest, inlinks: m?.inlinks ?? 0, crawlDepth: m?.crawlDepth ?? null, orphan: m?.orphan ?? false }\n })\n const issues = computeIssues(pages, metrics)\n return {\n pageRows: pageRows as unknown as Array<Record<string, unknown>>,\n edges: edges as unknown as Array<Record<string, unknown>>,\n metrics: [...metrics.values()] as unknown as Array<Record<string, unknown>>,\n issues,\n reportMd: renderIssueReport(siteUrl, pages, issues, metrics),\n linkReport: buildLinkReport(edges, [...metrics.values()], siteUrl),\n branding: branding ?? undefined,\n }\n}\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 schemaTypesOf = (p: SitePageResult) =>\n p.kpo?.type ?? (Array.isArray(p.schema) && p.schema.length ? [`${p.schema.length} block(s)`] : [])\n\n const pageRow = (p: SitePageResult, i: number) => {\n const schemaInfo = schemaTypesOf(p).join(', ') || '—'\n return `| ${i + 1} | ${cell(p.title ?? 'Untitled')} | ${p.url} | ${schemaInfo} |`\n }\n\n const tips = `\\n---\\n💡 **Tips**\\n- Map URLs first: use \\`map_site_urls\\`\\n- Inspect a single page: use \\`extract_url\\``\n const durationLine = `**${pages.length} pages** · ${(((d.durationMs ?? 0)) / 1000).toFixed(1)}s`\n\n const structuredContent = {\n url: input.url,\n pageCount: pages.length,\n pages: pages.map(p => ({\n url: String(p.url ?? ''),\n title: p.title ?? null,\n schemaTypes: schemaTypesOf(p),\n })),\n durationMs: d.durationMs ?? 0,\n }\n\n if (pages.length > BULK_PAGE_THRESHOLD) {\n const bulk = saveBulkSite(input.url, pages.map(p => ({\n url: String(p.url ?? ''),\n title: p.title ?? null,\n bodyMarkdown: p.bodyMarkdown ?? null,\n metaDescription: p.metaDescription ?? null,\n schemaTypes: schemaTypesOf(p),\n })))\n const preview = pages.slice(0, BULK_PAGE_THRESHOLD).map(pageRow).join('\\n')\n const location = bulk\n ? `\\n## 📁 Bulk scrape saved\\n- **Folder:** \\`${bulk.dir}\\` ← all scraped page content is here\\n- **Start here:** \\`${bulk.indexFile}\\` — lists every page and its file\\n- **Page content:** ${bulk.fileCount} Markdown files under \\`pages/\\` (one per page)\\n\\nThe page content is NOT inlined here to keep the context window clear — it is saved to disk. Open \\`index.md\\`, then open the page file you need from \\`pages/\\`.\\n\\n💡 Want the full technical SEO audit (headings, link graph, indexability, image sizes/formats, issues)? Run \\`audit_site\\` on this URL instead.`\n : `\\n## ⚠️ Bulk scrape not saved\\nReport saving is disabled in this environment, so the ${pages.length} pages of content could not be written to disk and are omitted to protect the context window. Enable \\`MCP_SCRAPER_SAVE_REPORTS\\` to capture bulk crawls.`\n const full = [\n `# Site Extract: ${input.url}`,\n durationLine,\n location,\n `\\n## Pages (first ${Math.min(BULK_PAGE_THRESHOLD, pages.length)} of ${pages.length})\\n| # | Title | URL | Schema |\\n|---|-------|-----|--------|\\n${preview}`,\n tips,\n ].join('\\n')\n return { content: [{ type: 'text', text: full }], structuredContent: { ...structuredContent, bulkFolder: bulk?.dir ?? null } }\n }\n\n const header = [\n `# Site Extract: ${input.url}`,\n durationLine,\n `\\n## Pages\\n| # | Title | URL | Schema |\\n|---|-------|-----|--------|\\n${pages.map(pageRow).join('\\n')}`,\n ].join('\\n')\n\n const full = `${header}${tips}`\n\n const pageDetails = pages.map((p, i) => {\n const body = (p.bodyMarkdown ?? '').trim()\n return [\n `\\n## ${i + 1}. ${p.title ?? 'Untitled'}`,\n `- **URL:** ${p.url}`,\n p.metaDescription ? `- **Description:** ${p.metaDescription}` : '',\n body ? `\\n${body}` : '_(no content extracted)_',\n ].filter(Boolean).join('\\n')\n }).join('\\n')\n\n const diskReport = `${header}\\n\\n---\\n# Full Page Content\\n${pageDetails}${tips}`\n\n return { ...oneBlock(full, diskReport), structuredContent }\n}\n\nexport async function formatAuditSite(raw: CallToolResult, input: { url: string }): Promise<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 const pages = d.pages ?? []\n const schemaTypesOf = (p: SitePageResult) =>\n p.kpo?.type ?? (Array.isArray(p.schema) && p.schema.length ? [`${p.schema.length} block(s)`] : [])\n\n const seo = buildSeoExport(input.url, pages as unknown as PageData[], d.branding)\n const imageAudit = await auditImages(pages as unknown as PageData[], { concurrency: 12 })\n const bulk = saveBulkSite(input.url, pages.map(p => ({\n url: String(p.url ?? ''),\n title: p.title ?? null,\n bodyMarkdown: p.bodyMarkdown ?? null,\n metaDescription: p.metaDescription ?? null,\n schemaTypes: schemaTypesOf(p),\n })), seo, imageAudit)\n\n const topIssues = Object.entries(seo.issues).sort((a, b) => b[1].count - a[1].count).slice(0, 8)\n .map(([k, v]) => `- \\`${k}\\` — ${v.count}`).join('\\n')\n const img = imageAudit.summary\n const imgLine = `${img.unique} images · ${img.totalSize} total · ${img.over100kb} over 100 KB · ${img.legacyFormat} legacy format`\n const lr = seo.linkReport.summary\n const topExt = lr.external.topDomains.slice(0, 3).map(dm => `${dm.domain} (${dm.links})`).join(', ') || '—'\n const linkLine = `${lr.internal.totalLinks} internal / ${lr.external.totalLinks} external links · ${lr.internal.orphans} orphans · ${lr.internal.brokenInternal} broken · avg ${lr.internal.avgInlinks} inlinks/page · top external: ${topExt}`\n const durationLine = `**${pages.length} pages** · ${(((d.durationMs ?? 0)) / 1000).toFixed(1)}s`\n\n const structuredContent = {\n url: input.url,\n pageCount: pages.length,\n durationMs: d.durationMs ?? 0,\n bulkFolder: bulk?.dir ?? null,\n issues: Object.fromEntries(Object.entries(seo.issues).map(([k, v]) => [k, v.count])),\n images: { unique: img.unique, totalBytes: img.totalBytes, over100kb: img.over100kb, legacyFormat: img.legacyFormat },\n links: { internal: lr.internal.totalLinks, external: lr.external.totalLinks, orphans: lr.internal.orphans, brokenInternal: lr.internal.brokenInternal, externalDomains: lr.external.uniqueDomains },\n }\n\n const location = bulk\n ? `\\n## 📁 Technical audit saved\\n- **Folder:** \\`${bulk.dir}\\` ← full audit + page content here\\n- **Start here:** \\`${bulk.indexFile}\\` — maps every file in the folder\\n- **Data:** \\`report.md\\` (issues + image audit), \\`issues.json\\`, \\`pages.jsonl\\` (per-page fields), \\`links.jsonl\\`, \\`link-metrics.jsonl\\`, \\`images.jsonl\\`\\n\\nDetail is saved to disk, not inlined. Open \\`report.md\\` for the audit, \\`pages.jsonl\\` for per-page fields (headings, canonical, indexability), \\`images.jsonl\\` for image sizes/formats.`\n : `\\n## ⚠️ Audit not saved\\nReport saving is disabled in this environment. Enable \\`MCP_SCRAPER_SAVE_REPORTS\\` to capture the technical audit.`\n\n const full = [\n `# Technical SEO Audit: ${input.url}`,\n durationLine,\n location,\n `\\n## Top issues\\n${topIssues || '_none found_'}`,\n `\\n## Links\\n${linkLine}`,\n `\\n## Images\\n${imgLine}`,\n ].join('\\n')\n return { content: [{ type: 'text', text: full }], structuredContent }\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} | ${cell(truncate(v.title, 70))} | ${cell(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 `# 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 return {\n ...oneBlock(full),\n structuredContent: {\n mode: input.mode,\n videoCount: videos.length,\n channel: d.channelMeta\n ? { title: d.channelMeta.title ?? null, subscriberCount: d.channelMeta.subscriberCount ?? null }\n : null,\n videos: videos.map(v => ({\n videoId: String(v.videoId ?? ''),\n title: String(v.title ?? ''),\n channelName: v.channelName ?? null,\n views: v.views ?? null,\n duration: v.duration ?? null,\n url: v.url ?? null,\n })),\n },\n }\n}\n\ninterface TranscriptChunk { timestamp: [number, number]; text: string }\ninterface TranscriptResult { videoId?: string | null; text: string; chunks?: TranscriptChunk[]; durationMs?: number }\n\nfunction structuredTranscriptChunks(chunks: TranscriptChunk[]): Array<{ startSec: number; endSec: number; text: string }> {\n return chunks.map(c => ({\n startSec: Number.isFinite(c.timestamp?.[0]) ? c.timestamp[0] : 0,\n endSec: Number.isFinite(c.timestamp?.[1]) ? c.timestamp[1] : 0,\n text: c.text,\n }))\n}\n\nfunction wordCount(text: string): number {\n return text.trim() ? text.trim().split(/\\s+/).length : 0\n}\n\nexport function formatYoutubeTranscribe(raw: CallToolResult, input: { videoId?: string; 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 TranscriptResult\n\n const text = d.text ?? ''\n const chunks = d.chunks ?? []\n const videoId = d.videoId ?? input.videoId ?? null\n const durSec = d.durationMs ? (d.durationMs / 1000).toFixed(0) : '—'\n const words = wordCount(text)\n\n const chunkRows = chunks.slice(0, 50).map(c => {\n const sec = Number.isFinite(c.timestamp[0]) ? Math.floor(c.timestamp[0]) : 0\n const mm = String(Math.floor(sec / 60)).padStart(2, '0')\n const ss = String(sec % 60).padStart(2, '0')\n return `| ${mm}:${ss} | ${cell(truncate(c.text, 120))} |`\n }).join('\\n')\n\n const full = [\n `# YouTube Transcript: \\`${videoId ?? input.url ?? 'video'}\\``,\n `**Duration:** ${durSec}s · **${words} 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 return {\n ...oneBlock(full),\n structuredContent: {\n videoId,\n url: videoId ? `https://www.youtube.com/watch?v=${videoId}` : input.url ?? null,\n wordCount: words,\n chunkCount: chunks.length,\n durationMs: typeof d.durationMs === 'number' ? d.durationMs : null,\n transcriptText: text,\n chunks: structuredTranscriptChunks(chunks),\n resolvedInputs: {\n videoId,\n url: input.url ?? null,\n },\n },\n }\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; started?: string | null\n landingUrl?: string | null; domain?: string | null\n videoUrl?: string | null; videoSrc?: string | null\n imageUrl?: string | null; imageSrc?: string | null; videoPoster?: string | null\n variations?: number; clusterCount?: number | null\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 ?? ad.started ?? '—'}`,\n ad.headline ? `**Headline:** ${ad.headline}` : '',\n ad.primaryText ? `**Copy:** ${truncate(ad.primaryText, 200)}` : '',\n ad.cta ? `**CTA:** ${ad.cta}` : '',\n ad.landingUrl ? `**Landing URL:** ${ad.landingUrl}` : '',\n (ad.videoUrl ?? ad.videoSrc) ? `**Video URL:** \\`${ad.videoUrl ?? ad.videoSrc}\\`` : '',\n (ad.variations ?? ad.clusterCount) ? `**Variations:** ${ad.variations ?? ad.clusterCount}` : '',\n ].filter(Boolean).join('\\n')).join('\\n\\n---\\n\\n')\n\n const full = [\n `# 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 direct \\`videoUrl\\` above\\n- Transcribe organic Facebook reels/posts: use \\`facebook_video_transcribe\\` with the public Facebook URL\\n- Find other advertisers: use \\`facebook_ad_search\\``,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n advertiserName: d.advertiserName ?? null,\n totalAds: s.totalAds ?? 0,\n activeCount: s.activeCount ?? 0,\n videoCount: s.videoCount ?? 0,\n imageCount: s.imageCount ?? 0,\n ads: ads.map(ad => ({\n libraryId: ad.libraryId ?? null,\n status: ad.status ?? null,\n creativeType: ad.creativeType ?? null,\n primaryText: ad.primaryText ?? null,\n headline: ad.headline ?? null,\n cta: ad.cta ?? null,\n startDate: ad.startDate ?? ad.started ?? null,\n landingUrl: ad.landingUrl ?? null,\n domain: ad.domain ?? null,\n videoUrl: ad.videoUrl ?? ad.videoSrc ?? null,\n imageUrl: ad.imageUrl ?? ad.imageSrc ?? null,\n videoPoster: ad.videoPoster ?? null,\n variations: typeof ad.variations === 'number'\n ? ad.variations\n : typeof ad.clusterCount === 'number'\n ? ad.clusterCount\n : null,\n })),\n },\n }\n}\n\ninterface FbAdvertiserResult { name?: string; pageName?: string; pageId?: string; pageUrl?: string; adCount?: number; libraryId?: string; sampleLibraryId?: string }\ninterface FbSearchResult { results?: FbAdvertiserResult[]; advertisers?: FbAdvertiserResult[] }\n\nexport function formatRedditThread(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 {\n title?: string; author?: string; score?: string; postBody?: string; numComments?: number\n comments?: Array<{ author?: string; score?: string; depth?: number; body?: string }>\n sourceUrl?: string; oldRedditUrl?: string\n }\n const comments = d.comments ?? []\n const commentMd = comments.map(cm => {\n const indent = ' '.repeat(Math.min(Number(cm.depth ?? 0), 6))\n return `${indent}- **u/${cm.author || '[unknown]'}** (${cm.score || '—'}): ${(cm.body || '').replace(/\\s+/g, ' ').trim()}`\n }).join('\\n')\n const full = [\n `# ${d.title || 'Reddit thread'}`,\n `**u/${d.author || '[unknown]'}** · ${d.score || '—'} · ${comments.length} comments captured`,\n d.postBody ? `\\n${d.postBody}` : '',\n `\\n## Comments\\n${commentMd || '_No comments captured._'}`,\n ].join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n sourceUrl: d.sourceUrl ?? input.url ?? null,\n oldRedditUrl: d.oldRedditUrl ?? null,\n title: d.title ?? null,\n author: d.author ?? null,\n score: d.score ?? null,\n postBody: d.postBody ?? null,\n numComments: comments.length,\n comments: comments.map(cm => ({ author: cm.author ?? null, score: cm.score ?? null, depth: Number(cm.depth ?? 0), body: cm.body ?? '' })),\n },\n }\n}\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} | ${cell(a.pageName ?? a.name)} | ${a.adCount ?? '—'} | \\`${a.sampleLibraryId ?? a.libraryId ?? '—'}\\` |`,\n ).join('\\n')\n\n const full = [\n `# 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 return {\n ...oneBlock(full),\n structuredContent: {\n query: input.query,\n advertiserCount: advertisers.length,\n advertisers: advertisers.map(a => ({\n name: a.pageName ?? a.name ?? null,\n pageId: a.pageId ?? null,\n pageUrl: a.pageUrl ?? null,\n adCount: typeof a.adCount === 'number' ? a.adCount : null,\n libraryId: a.sampleLibraryId ?? a.libraryId ?? null,\n sampleLibraryId: a.sampleLibraryId ?? null,\n })),\n },\n }\n}\n\ninterface GoogleAdsAdvertiserRow { advertiserId: string | null; name: string | null; domain: string | null; approxAdCount: number | null; detailUrl: string | null }\ninterface GoogleAdsCreativeRow { creativeId: string | null; advertiserId: string | null; format: string | null; lastShown: string | null; detailUrl: string | null; landingDomain: string | null; imageUrls: string[]; youtubeVideoId: string | null; videoUrl: string | null; variations: number | null }\n\nexport function formatGoogleAdsSearch(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 { region?: string; advertisers?: GoogleAdsAdvertiserRow[] }\n const advertisers = d.advertisers ?? []\n\n const rows = advertisers.map((a, i) =>\n `| ${i + 1} | ${cell(a.name)} | ${cell(a.domain)} | ${a.approxAdCount ?? '—'} | \\`${a.advertiserId ?? '—'}\\` |`,\n ).join('\\n')\n\n const full = [\n `# Google Ads Transparency Search: \"${input.query}\"`,\n `**${advertisers.length} advertisers found**${d.region ? ` · ${d.region}` : ''}`,\n `\\n## Advertisers\\n| # | Name | Domain | ~Ads | Advertiser ID |\\n|---|------|--------|------|---------------|\\n${rows}`,\n `\\n---\\n💡 **Tips**\\n- Pull an advertiser's ads: use \\`google_ads_page_intel\\` with \\`advertiserId\\`\\n- Or pass a \\`domain\\` directly to \\`google_ads_page_intel\\``,\n ].join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n query: input.query,\n region: d.region ?? 'US',\n advertiserCount: advertisers.length,\n advertisers: advertisers.map(a => ({\n advertiserId: a.advertiserId ?? null,\n name: a.name ?? null,\n domain: a.domain ?? null,\n approxAdCount: typeof a.approxAdCount === 'number' ? a.approxAdCount : null,\n detailUrl: a.detailUrl ?? null,\n })),\n },\n }\n}\n\nexport function formatGoogleAdsPageIntel(raw: CallToolResult, input: { advertiserId?: string; domain?: 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 {\n advertiserId?: string | null; advertiserName?: string | null; domain?: string | null; region?: string\n totalCreatives?: number; videoCount?: number; imageCount?: number; textCount?: number; ads?: GoogleAdsCreativeRow[]\n }\n const ads = d.ads ?? []\n\n const rows = ads.map((a, i) => {\n const media = a.youtubeVideoId ? `yt:${a.youtubeVideoId}` : a.videoUrl ? 'video' : a.imageUrls.length ? `${a.imageUrls.length} img` : '—'\n return `| ${i + 1} | ${cell(a.format)} | ${media} | \\`${a.creativeId ?? '—'}\\` |`\n }).join('\\n')\n\n const label = d.advertiserName ?? input.advertiserId ?? input.domain ?? ''\n const full = [\n `# Google Ads Transparency: ${label}`,\n `**${ads.length} creatives** · ${d.videoCount ?? 0} video · ${d.imageCount ?? 0} image · ${d.textCount ?? 0} text${d.region ? ` · ${d.region}` : ''}`,\n `\\n## Creatives\\n| # | Format | Media | Creative ID |\\n|---|--------|-------|-------------|\\n${rows}`,\n `\\n---\\n💡 **Tips**\\n- Transcribe a video ad: pass its \\`videoUrl\\` to \\`google_ads_transcribe\\`, or its \\`youtubeVideoId\\` to \\`youtube_transcribe\\`\\n- Full ad detail is at each creative's \\`detailUrl\\``,\n ].join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n advertiserId: d.advertiserId ?? null,\n advertiserName: d.advertiserName ?? null,\n domain: d.domain ?? null,\n region: d.region ?? 'US',\n totalCreatives: typeof d.totalCreatives === 'number' ? d.totalCreatives : ads.length,\n videoCount: d.videoCount ?? 0,\n imageCount: d.imageCount ?? 0,\n textCount: d.textCount ?? 0,\n ads: ads.map(a => ({\n creativeId: a.creativeId ?? null,\n advertiserId: a.advertiserId ?? null,\n format: a.format ?? null,\n lastShown: a.lastShown ?? null,\n detailUrl: a.detailUrl ?? null,\n landingDomain: a.landingDomain ?? null,\n imageUrls: Array.isArray(a.imageUrls) ? a.imageUrls : [],\n youtubeVideoId: a.youtubeVideoId ?? null,\n videoUrl: a.videoUrl ?? null,\n variations: typeof a.variations === 'number' ? a.variations : null,\n })),\n },\n }\n}\n\nexport function formatGoogleAdsTranscribe(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 const words = wordCount(text)\n\n const chunkRows = chunks.slice(0, 50).map(c => {\n const sec = Number.isFinite(c.timestamp[0]) ? Math.floor(c.timestamp[0]) : 0\n const mm = String(Math.floor(sec / 60)).padStart(2, '0')\n const ss = String(sec % 60).padStart(2, '0')\n return `| ${mm}:${ss} | ${cell(truncate(c.text, 120))} |`\n }).join('\\n')\n\n const full = [\n `# Google Ad Transcript`,\n `**Duration:** ${durSec}s · **${words} 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 \\`google_ads_page_intel\\`.`,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n videoUrl: input.videoUrl,\n wordCount: words,\n chunkCount: chunks.length,\n durationMs: typeof d.durationMs === 'number' ? d.durationMs : null,\n transcriptText: text,\n chunks: structuredTranscriptChunks(chunks),\n resolvedInputs: { videoUrl: input.videoUrl },\n },\n }\n}\n\ninterface MapsReviewCard { author: string | null; stars: string | null; date: string | null; text: string | null }\ntype ReviewsStatus = 'collected' | 'none_exist' | 'unavailable' | 'not_requested'\ninterface MapsHistogramEntry { stars: number; count: string }\ninterface MapsTopicEntry { label: string; count: string }\ninterface MapsAboutEntry { section: string; attribute: string }\ninterface MapsSearchBusiness {\n position: number\n name: string\n placeUrl: string\n cid: string | null\n cidDecimal: string | null\n rating: string | null\n reviewCount: string | null\n category: string | null\n address: string | null\n phone: string | null\n hoursStatus: string | null\n websiteUrl: string | null\n directionsUrl: string | null\n metadata: string[]\n}\ninterface MapsSearchAttempt {\n attemptNumber?: number\n attempt_number?: number\n maxAttempts?: number\n max_attempts?: number\n status?: 'ok' | 'failed'\n outcome?: string\n willRetry?: boolean\n will_retry?: boolean\n durationMs?: number\n duration_ms?: number\n resultCount?: number\n result_count?: number\n error?: string | null\n proxyMode?: 'location' | 'configured' | 'none'\n proxy_mode?: 'location' | 'configured' | 'none'\n proxyResolutionSource?: string | null\n proxy_resolution_source?: string | null\n proxyIdSuffix?: string | null\n proxy_id_suffix?: string | null\n proxyTargetLevel?: 'zip' | 'city' | 'state' | null\n proxy_target_level?: 'zip' | 'city' | 'state' | null\n proxyTargetLocation?: string | null\n proxy_target_location?: string | null\n proxyTargetZip?: string | null\n proxy_target_zip?: string | null\n browserSessionIdSuffix?: string | null\n browser_session_id?: string | null\n observedIp?: string | null\n observed_ip?: string | null\n observedCity?: string | null\n observed_city?: string | null\n observedRegion?: string | null\n observed_region?: string | null\n}\ninterface DirectoryWorkflowCity {\n city: string\n state: string\n location: string\n cityKey: string\n censusName: string\n population: number\n populationYear: number\n zips: string[]\n counties: string[]\n status: 'ok' | 'empty' | 'failed'\n error: string | null\n resultCount: number\n durationMs: number\n attempts?: MapsSearchAttempt[]\n results: MapsSearchBusiness[]\n}\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\nfunction normalizeMapsAttempts(value: unknown): Array<{\n attemptNumber: number\n maxAttempts: number\n status: 'ok' | 'failed'\n outcome: string\n willRetry: boolean\n durationMs: number\n resultCount: number\n error: string | null\n proxyMode: 'location' | 'configured' | 'none'\n proxyResolutionSource: string | null\n proxyIdSuffix: string | null\n proxyTargetLevel: 'zip' | 'city' | 'state' | null\n proxyTargetLocation: string | null\n proxyTargetZip: string | null\n browserSessionIdSuffix: string | null\n observedIp: string | null\n observedCity: string | null\n observedRegion: string | null\n}> {\n const attempts = Array.isArray(value) ? value as MapsSearchAttempt[] : []\n return attempts.map((attempt, index) => ({\n attemptNumber: attempt.attemptNumber ?? attempt.attempt_number ?? index + 1,\n maxAttempts: attempt.maxAttempts ?? attempt.max_attempts ?? attempts.length,\n status: attempt.status === 'ok' ? 'ok' : 'failed',\n outcome: attempt.outcome ?? attempt.status ?? 'unknown',\n willRetry: attempt.willRetry ?? attempt.will_retry ?? false,\n durationMs: attempt.durationMs ?? attempt.duration_ms ?? 0,\n resultCount: attempt.resultCount ?? attempt.result_count ?? 0,\n error: attempt.error ? sanitizeVendorText(attempt.error) : null,\n proxyMode: attempt.proxyMode ?? attempt.proxy_mode ?? 'location',\n proxyResolutionSource: attempt.proxyResolutionSource ?? attempt.proxy_resolution_source ?? null,\n proxyIdSuffix: attempt.proxyIdSuffix ?? attempt.proxy_id_suffix ?? null,\n proxyTargetLevel: attempt.proxyTargetLevel ?? attempt.proxy_target_level ?? null,\n proxyTargetLocation: attempt.proxyTargetLocation ?? attempt.proxy_target_location ?? null,\n proxyTargetZip: attempt.proxyTargetZip ?? attempt.proxy_target_zip ?? null,\n browserSessionIdSuffix: attempt.browserSessionIdSuffix ?? attempt.browser_session_id ?? null,\n observedIp: attempt.observedIp ?? attempt.observed_ip ?? null,\n observedCity: attempt.observedCity ?? attempt.observed_city ?? null,\n observedRegion: attempt.observedRegion ?? attempt.observed_region ?? null,\n }))\n}\n\nfunction workflowArtifactsFrom(run: Record<string, unknown> | undefined): Array<Record<string, unknown>> {\n return Array.isArray(run?.artifacts) ? run.artifacts as Array<Record<string, unknown>> : []\n}\n\nfunction workflowArtifactRows(artifacts: Array<Record<string, unknown>>): string {\n if (!artifacts.length) return ''\n return [\n '| Artifact | Type | ID | Rows/Bytes |',\n '|---|---|---|---|',\n ...artifacts.map(artifact => {\n const rows = artifact.rows_count ?? artifact.rows ?? ''\n const bytes = artifact.bytes ?? ''\n const size = [rows ? `${rows} rows` : '', bytes ? `${bytes} bytes` : ''].filter(Boolean).join(' / ')\n return `| ${cell(String(artifact.label ?? artifact.path ?? 'artifact'))} | ${cell(String(artifact.kind ?? artifact.content_type ?? 'file'))} | \\`${String(artifact.id ?? '')}\\` | ${cell(size || '—')} |`\n }),\n ].join('\\n')\n}\n\nexport function formatWorkflowList(raw: CallToolResult, input: { includeRecipes?: boolean }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const workflows = Array.isArray(parsed.data.workflows) ? parsed.data.workflows as Array<Record<string, unknown>> : []\n const workflowRows = [\n '| Workflow ID | Title | Use |',\n '|---|---|---|',\n ...workflows.map(workflow => `| \\`${String(workflow.id ?? '')}\\` | ${cell(String(workflow.title ?? ''))} | ${cell(String(workflow.description ?? ''))} |`),\n ].join('\\n')\n const recipes = input.includeRecipes === false ? [] : WORKFLOW_RECIPES\n const full = [\n '# MCP Scraper Workflows',\n 'Use `workflow_suggest` when the user describes a high-level job. Use `workflow_run` when the workflow id and input are known. Use `workflow_status` and `workflow_artifact_read` to inspect completed runs and pull evidence back into context.',\n workflows.length ? `\\n## Runnable Workflows\\n${workflowRows}` : '',\n recipes.length ? `\\n## High-Level Recipes\\n${workflowRecipeTable(recipes)}` : '',\n recipes.length ? '\\nThese recipes cover market analysis, ICP research, forum and review acquisition, brand design briefings, CRO audits, competitive positioning, content gaps, and AI search visibility audits.' : '',\n ].filter(Boolean).join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n workflows: workflows.map(workflow => ({\n id: String(workflow.id ?? ''),\n title: String(workflow.title ?? ''),\n description: String(workflow.description ?? ''),\n })),\n recipes,\n },\n }\n}\n\nexport function formatWorkflowSuggest(input: { goal: string; maxSuggestions?: number }): CallToolResult {\n const suggestions = suggestWorkflowRecipes(input.goal, input.maxSuggestions ?? 3)\n const full = [\n `# Workflow Suggestions`,\n `**Goal:** ${input.goal}`,\n '',\n workflowRecipeTable(suggestions),\n '',\n '## How To Execute',\n '1. Pick the closest recipe.',\n '2. If it has a `primaryWorkflowId`, call `workflow_run` with that id and the required inputs.',\n '3. After the run completes, use `workflow_artifact_read` on the most relevant CSV/JSON/Markdown artifacts before writing the final answer.',\n ].join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n goal: input.goal,\n suggestions,\n },\n }\n}\n\nfunction workflowStepLines(data: Record<string, unknown>): string[] {\n const step = data.step as Record<string, unknown> | undefined\n const nextStep = data.nextStep as Record<string, unknown> | null | undefined\n const done = data.done === true\n const lines: string[] = []\n if (step) {\n const index = Number(step.index ?? 0)\n const totalSteps = step.totalSteps != null ? Number(step.totalSteps) : undefined\n const stepLabel = totalSteps ? `${index + 1}/${totalSteps}` : `${index + 1}`\n lines.push(`\\n## Step ${stepLabel}: ${step.title ?? step.id ?? ''}`)\n const output = step.output as Record<string, unknown> | undefined\n if (output && Object.keys(output).length) {\n lines.push(Object.entries(output).map(([k, v]) => `- ${k}: ${typeof v === 'object' ? JSON.stringify(v) : String(v)}`).join('\\n'))\n }\n const warnings = Array.isArray(step.warnings) ? step.warnings as string[] : []\n if (warnings.length) lines.push(`\\n**Warnings:**\\n${warnings.map(w => `- ${w}`).join('\\n')}`)\n }\n if (done) {\n lines.push('\\n**Done.** All steps complete.')\n } else if (nextStep && typeof nextStep === 'object') {\n lines.push(`\\n**Next step:** \\`${nextStep.id ?? nextStep.index}\\` — call \\`workflow_step\\` with this run id to continue.`)\n }\n return lines\n}\n\nexport function formatWorkflowRun(raw: CallToolResult, input: { workflowId: string; input?: Record<string, unknown> }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const run = parsed.data.run as Record<string, unknown> | undefined\n const summary = parsed.data.summary as Record<string, unknown> | undefined\n const artifacts = workflowArtifactsFrom(run)\n const runId = String(run?.id ?? '')\n const status = String(run?.status ?? summary?.status ?? 'unknown')\n const full = [\n `# Workflow Run: ${input.workflowId}`,\n `**Run ID:** \\`${runId || 'unknown'}\\``,\n `**Status:** ${status}`,\n summary?.title ? `**Title:** ${summary.title}` : '',\n ...workflowStepLines(parsed.data),\n summary?.summary ? `\\n## Summary\\n${summary.summary}` : '',\n artifacts.length ? `\\n## Artifacts\\n${workflowArtifactRows(artifacts)}` : '',\n artifacts.length ? '\\nUse `workflow_artifact_read` with the run id and artifact id to pull CSV, JSON, Markdown, or report content into context.' : '',\n ].filter(Boolean).join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n workflowId: input.workflowId,\n input: input.input ?? {},\n run,\n summary,\n step: parsed.data.step,\n nextStep: parsed.data.nextStep ?? null,\n done: parsed.data.done === true,\n artifacts,\n },\n }\n}\n\nexport function formatWorkflowStep(raw: CallToolResult, input: { runId: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const run = parsed.data.run as Record<string, unknown> | undefined\n const summary = parsed.data.summary as Record<string, unknown> | undefined\n const artifacts = workflowArtifactsFrom(run)\n const done = parsed.data.done === true\n const full = [\n `# Workflow Step`,\n `**Run ID:** \\`${input.runId}\\``,\n `**Status:** ${run?.status ?? (done ? 'done' : 'running')}`,\n ...workflowStepLines(parsed.data),\n done && summary?.summary ? `\\n## Summary\\n${summary.summary}` : '',\n artifacts.length ? `\\n## Artifacts\\n${workflowArtifactRows(artifacts)}` : '',\n done && artifacts.length ? '\\nUse `workflow_artifact_read` with the run id and artifact id to pull CSV, JSON, Markdown, or report content into context.' : '',\n ].filter(Boolean).join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n runId: input.runId,\n run,\n summary: summary ?? null,\n step: parsed.data.step,\n nextStep: parsed.data.nextStep ?? null,\n done,\n artifacts,\n },\n }\n}\n\nexport function formatWorkflowStatus(raw: CallToolResult, input: { runId: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const run = parsed.data.run as Record<string, unknown> | undefined\n const artifacts = workflowArtifactsFrom(run)\n const full = [\n `# Workflow Status`,\n `**Run ID:** \\`${input.runId}\\``,\n `**Workflow:** ${run?.workflow_id ?? 'unknown'}`,\n `**Status:** ${run?.status ?? 'unknown'}`,\n run?.error_message ? `\\n## Error\\n${run.error_message}` : '',\n artifacts.length ? `\\n## Artifacts\\n${workflowArtifactRows(artifacts)}` : '',\n ].filter(Boolean).join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n run,\n artifacts,\n },\n }\n}\n\nexport function formatWorkflowArtifactRead(raw: CallToolResult, input: { runId: string; artifactId: string; maxBytes?: number }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const text = typeof parsed.data.text === 'string' ? parsed.data.text : ''\n const contentType = String(parsed.data.contentType ?? 'text/plain')\n const bytes = Number(parsed.data.bytes ?? 0)\n const truncated = parsed.data.truncated === true\n const full = [\n `# Workflow Artifact`,\n `**Run ID:** \\`${input.runId}\\``,\n `**Artifact ID:** \\`${input.artifactId}\\``,\n `**Content-Type:** ${contentType}`,\n `**Bytes:** ${bytes}${truncated ? ` (truncated to ${input.maxBytes ?? 200000})` : ''}`,\n '',\n '```',\n text,\n '```',\n ].join('\\n')\n return {\n ...oneBlock(full),\n structuredContent: {\n runId: input.runId,\n artifactId: input.artifactId,\n contentType,\n bytes,\n truncated,\n text,\n },\n }\n}\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 const concurrencyRaw = d.concurrency as Record<string, unknown> | undefined\n const upgradeRaw = concurrencyRaw?.upgrade as Record<string, unknown> | 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 concurrencySection = concurrencyRaw\n ? [\n `\\n## Concurrency`,\n `**Current limit:** ${concurrencyRaw.current_limit ?? 'unknown'} concurrent operation${concurrencyRaw.current_limit === 1 ? '' : 's'}`,\n `**Extra slots:** ${concurrencyRaw.current_extra_slots ?? 'unknown'}`,\n `**Extra concurrency slot:** ${upgradeRaw?.price_label ?? '$5/month'}`,\n `**Upgrade in terminal:** \\`${upgradeRaw?.terminal_command ?? 'npx -y -p mcp-scraper@latest mcp-scraper-cli billing concurrency checkout'}\\``,\n `**Billing URL:** ${upgradeRaw?.billing_url ?? 'https://mcpscraper.dev/billing'}`,\n ].join('\\n')\n : ''\n\n const full = [\n `# Credits`,\n `**Balance:** ${balance ?? 'unknown'} credits`,\n matchedSection,\n concurrencySection,\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 return {\n ...oneBlock(full),\n structuredContent: {\n balanceCredits: typeof balance === 'number' ? balance : null,\n matchedCost: matched\n ? { label: matched.label, credits: matched.credits, unit: matched.unit, notes: matched.notes ?? null }\n : null,\n costs: costs.map(c => ({\n key: c.key,\n label: c.label,\n credits: c.credits,\n unit: c.unit,\n notes: c.notes ?? null,\n })),\n ledger: ledger.map(row => ({\n createdAt: String(row.created_at ?? ''),\n operation: String(row.operation ?? ''),\n credits: row.amount_mc / 1000,\n description: row.description ?? null,\n })),\n concurrency: concurrencyRaw && upgradeRaw\n ? {\n currentExtraSlots: Number(concurrencyRaw.current_extra_slots ?? 0),\n currentLimit: Number(concurrencyRaw.current_limit ?? 1),\n hasSubscription: concurrencyRaw.has_subscription === true,\n upgrade: {\n product: String(upgradeRaw.product ?? 'Extra concurrency slot'),\n priceLabel: String(upgradeRaw.price_label ?? '$5/month'),\n unitAmountUsd: Number(upgradeRaw.unit_amount_usd ?? 5),\n currency: String(upgradeRaw.currency ?? 'usd'),\n interval: String(upgradeRaw.interval ?? 'month'),\n billingUrl: String(upgradeRaw.billing_url ?? 'https://mcpscraper.dev/billing'),\n terminalCommand: String(upgradeRaw.terminal_command ?? 'npx -y -p mcp-scraper@latest mcp-scraper-cli billing concurrency checkout'),\n terminalCommandWithApiKeyEnv: String(upgradeRaw.terminal_command_with_api_key_env ?? 'MCP_SCRAPER_API_KEY=sk_live_your_key npx -y -p mcp-scraper@latest mcp-scraper-cli billing concurrency checkout'),\n },\n }\n : null,\n },\n }\n}\n\nexport function formatMapsSearch(\n raw: CallToolResult,\n input: { query: string; location?: string; maxResults?: number },\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 const results = (d.results as MapsSearchBusiness[]) ?? []\n const normalizedResults = results.map(result => ({\n ...result,\n phone: result.phone ?? null,\n hoursStatus: result.hoursStatus ?? null,\n }))\n const searchQuery = (d.searchQuery as string | undefined) ?? [input.query, input.location].filter(Boolean).join(' ')\n const requestedMax = (d.requestedMaxResults as number | undefined) ?? input.maxResults ?? 10\n const durationMs = d.durationMs as number | undefined\n const attempts = normalizeMapsAttempts(d.attempts)\n const lastAttempt = attempts.at(-1)\n\n const rows = results.map((r) => {\n const rating = [r.rating, r.reviewCount ? `(${r.reviewCount})` : null].filter(Boolean).join(' ')\n return `| ${r.position} | ${cell(r.name)} | ${cell(r.category)} | ${cell(rating)} | ${cell(r.address)} | ${r.cidDecimal ? `\\`${r.cidDecimal}\\`` : '—'} | ${r.websiteUrl ? `[site](${r.websiteUrl})` : '—'} | [maps](${r.placeUrl}) |`\n }).join('\\n')\n\n const metadataSection = results.length\n ? `\\n## Candidate Metadata\\n${results.map(r => {\n const meta = r.metadata?.length ? r.metadata.slice(0, 8).map(m => ` - ${m}`).join('\\n') : ' - none'\n return `### ${r.position}. ${r.name}\\n${meta}`\n }).join('\\n\\n')}`\n : ''\n\n const full = [\n `# Google Maps Search: \"${searchQuery}\"`,\n `**Returned:** ${results.length} profile candidate${results.length === 1 ? '' : 's'} · **Requested max:** ${requestedMax} · **Limit:** 50`,\n attempts.length ? `**Attempts:** ${attempts.length}/${lastAttempt?.maxAttempts ?? attempts.length} · **Proxy:** ${lastAttempt?.proxyMode ?? 'unknown'}${lastAttempt?.proxyResolutionSource ? `/${lastAttempt.proxyResolutionSource}` : ''} · **Observed:** ${[lastAttempt?.observedCity, lastAttempt?.observedRegion].filter(Boolean).join(', ') || 'unknown'}` : null,\n `\\n## Results\\n| # | Name | Category | Rating | Address | CID | Website | Maps |\\n|---|------|----------|--------|---------|-----|---------|------|\\n${rows}`,\n metadataSection,\n `\\n---\\n💡 **Next step:** use \\`maps_place_intel\\` with a selected business name and location to hydrate full hours, phone, review topics, and optional review cards.`,\n durationMs != null ? `\\n*Extracted in ${(durationMs / 1000).toFixed(1)}s*` : null,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n query: d.query,\n location: d.location ?? null,\n searchQuery: d.searchQuery,\n searchUrl: d.searchUrl,\n extractedAt: d.extractedAt,\n requestedMaxResults: requestedMax,\n resultCount: results.length,\n results: normalizedResults,\n attempts,\n durationMs: durationMs ?? 0,\n },\n }\n}\n\nexport function formatDirectoryWorkflow(\n raw: CallToolResult,\n input: { query: string; state?: string; minPopulation?: number; maxResultsPerCity?: number },\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 const cities = ((d.cities as DirectoryWorkflowCity[]) ?? []).map(city => ({\n ...city,\n attempts: normalizeMapsAttempts(city.attempts),\n results: city.results.map(result => ({\n ...result,\n phone: result.phone ?? null,\n hoursStatus: result.hoursStatus ?? null,\n })),\n }))\n const warnings = (d.warnings as string[] | undefined) ?? []\n const csvPath = (d.csvPath as string | null | undefined) ?? null\n const totalResultCount = (d.totalResultCount as number | undefined) ?? cities.reduce((sum, city) => sum + city.resultCount, 0)\n const durationMs = d.durationMs as number | undefined\n\n const marketRows = cities.map((city) => {\n const zips = city.zips?.length ? city.zips.slice(0, 8).join(' ') + (city.zips.length > 8 ? ` +${city.zips.length - 8}` : '') : '—'\n return `| ${cell(city.city)} | ${city.population.toLocaleString()} | ${city.zips?.length ?? 0} | ${city.resultCount} | ${city.status} | ${cell(zips)} |`\n }).join('\\n')\n\n const businessRows = cities\n .flatMap(city => city.results.slice(0, 3).map(result => ({ city, result })))\n .map(({ city, result }) => {\n const rating = [result.rating, result.reviewCount ? `(${result.reviewCount})` : null].filter(Boolean).join(' ')\n return `| ${cell(city.city)} | ${result.position} | ${cell(result.name)} | ${cell(result.category)} | ${cell(rating)} | ${result.websiteUrl ? `[site](${result.websiteUrl})` : '—'} | [maps](${result.placeUrl}) |`\n }).join('\\n')\n\n const warningText = warnings.length ? `\\n## Warnings\\n${warnings.map(w => `- ${w}`).join('\\n')}` : ''\n const csvText = csvPath ? `\\n**CSV:** \\`${csvPath}\\`` : ''\n const full = [\n `# Directory Workflow: ${input.query}`,\n `**Markets:** ${cities.length} · **Maps results:** ${totalResultCount} · **State:** ${d.state ?? input.state ?? 'US'} · **Population threshold:** ${d.minPopulation ?? input.minPopulation ?? 100000}`,\n csvText,\n `\\n## Markets\\n| City | Population | ZIPs | Maps Results | Status | ZIP Sample |\\n|---|---:|---:|---:|---|---|\\n${marketRows}`,\n businessRows ? `\\n## Top Candidates By City\\n| City | # | Name | Category | Rating | Website | Maps |\\n|---|---:|---|---|---|---|---|\\n${businessRows}` : null,\n warningText,\n `\\n## Sources\\n- Population: ${d.censusSourceUrl ?? 'Census Population Estimates Program'}\\n- ZIP groups: ${d.usZipsSourcePath ?? 'not configured'}`,\n durationMs != null ? `\\n*Completed in ${(durationMs / 1000).toFixed(1)}s*` : null,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n query: d.query,\n state: d.state,\n minPopulation: d.minPopulation,\n populationYear: d.populationYear,\n maxResultsPerCity: d.maxResultsPerCity,\n concurrency: d.concurrency,\n censusSourceUrl: d.censusSourceUrl,\n usZipsSourcePath: d.usZipsSourcePath ?? null,\n warnings,\n extractedAt: d.extractedAt,\n selectedCityCount: d.selectedCityCount,\n totalResultCount,\n csvPath,\n cities,\n durationMs: durationMs ?? 0,\n },\n }\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 const reviewsStatus = (d.reviewsStatus as ReviewsStatus | undefined) ?? 'not_requested'\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 = (() => {\n if (reviewsStatus === 'not_requested') return ''\n if (reviewsStatus === 'unavailable') return '\\n## Reviews\\n> Reviews could not be retrieved this run — retry with `includeReviews: true`.'\n if (reviewsStatus === 'none_exist') return '\\n## Reviews\\n*This business has no reviews on Google Maps.*'\n if (reviews.length === 0) return '\\n## Reviews\\n*0 reviews collected.*'\n return `\\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 `# ${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 return {\n ...oneBlock(full),\n structuredContent: {\n name,\n rating: rating ?? null,\n reviewCount: reviewCount ?? null,\n category: category ?? null,\n address: address ?? null,\n phone: phone ?? null,\n website: website ?? null,\n hoursSummary: hoursSummary ?? null,\n bookingUrl: bookingUrl ?? null,\n kgmid: kgmid ?? null,\n cidDecimal: cidDecimal ?? null,\n cidUrl: cidUrl ?? null,\n lat: lat ?? null,\n lng: lng ?? null,\n reviewsStatus,\n reviewsCollected: reviews.length,\n reviewTopics: topics.map(t => ({ label: String(t.label ?? ''), count: String(t.count ?? '') })),\n },\n }\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 const words = wordCount(text)\n\n const chunkRows = chunks.slice(0, 50).map(c => {\n const sec = Number.isFinite(c.timestamp[0]) ? Math.floor(c.timestamp[0]) : 0\n const mm = String(Math.floor(sec / 60)).padStart(2, '0')\n const ss = String(sec % 60).padStart(2, '0')\n return `| ${mm}:${ss} | ${cell(truncate(c.text, 120))} |`\n }).join('\\n')\n\n const full = [\n `# Facebook Ad Transcript`,\n `**Duration:** ${durSec}s · **${words} 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\\`. For public Facebook reel/post URLs, use \\`facebook_video_transcribe\\`.`,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n videoUrl: input.videoUrl,\n wordCount: words,\n chunkCount: chunks.length,\n durationMs: typeof d.durationMs === 'number' ? d.durationMs : null,\n transcriptText: text,\n chunks: structuredTranscriptChunks(chunks),\n resolvedInputs: {\n videoUrl: input.videoUrl,\n },\n },\n }\n}\n\ninterface FacebookVideoTranscriptResult extends TranscriptResult {\n sourceUrl?: string\n pageUrl?: string\n videoId?: string | null\n ownerName?: string | null\n selectedQuality?: string\n bitrate?: number | null\n videoDurationSec?: number | null\n videoUrl?: string\n}\n\nexport function formatFacebookVideoTranscribe(raw: CallToolResult, input: { url: string; quality?: 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 FacebookVideoTranscriptResult\n\n const text = d.text ?? ''\n const chunks = d.chunks ?? []\n const wordCount = text.trim() ? text.trim().split(/\\s+/).length : 0\n const durSec = d.durationMs ? (d.durationMs / 1000).toFixed(0) : '—'\n const videoDuration = typeof d.videoDurationSec === 'number' ? `${Math.round(d.videoDurationSec)}s` : '—'\n const label = d.videoId ? `Facebook Organic Video \\`${d.videoId}\\`` : 'Facebook Organic Video'\n\n const chunkRows = chunks.slice(0, 50).map(c => {\n const sec = Number.isFinite(c.timestamp[0]) ? Math.floor(c.timestamp[0]) : 0\n const mm = String(Math.floor(sec / 60)).padStart(2, '0')\n const ss = String(sec % 60).padStart(2, '0')\n return `| ${mm}:${ss} | ${cell(truncate(c.text, 120))} |`\n }).join('\\n')\n\n const full = [\n `# ${label} Transcript`,\n d.ownerName ? `**Owner:** ${d.ownerName}` : '',\n `**Video duration:** ${videoDuration} · **Transcribed in:** ${durSec}s · **${wordCount} words**`,\n d.pageUrl ? `**Page URL:** ${d.pageUrl}` : `**Page URL:** ${input.url}`,\n d.videoUrl ? `**Extracted MP4:** \\`${d.videoUrl}\\`` : '',\n `\\n## Full Transcript\\n${text}`,\n chunks.length ? `\\n## Timestamped Chunks\\n| Time | Text |\\n|------|------|\\n${chunkRows}` : '',\n `\\n---\\n💡 Use \\`videoUrl\\` as the extracted MP4 for download or follow-up processing. Use \\`facebook_ad_transcribe\\` only for Ad Library videoUrl values.`,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n sourceUrl: d.sourceUrl ?? input.url,\n pageUrl: d.pageUrl ?? input.url,\n videoId: d.videoId ?? null,\n ownerName: d.ownerName ?? null,\n selectedQuality: d.selectedQuality ?? input.quality ?? 'best',\n bitrate: typeof d.bitrate === 'number' ? d.bitrate : null,\n videoDurationSec: typeof d.videoDurationSec === 'number' ? d.videoDurationSec : null,\n videoUrl: d.videoUrl ?? '',\n wordCount,\n chunkCount: chunks.length,\n transcriptText: text,\n chunks: chunks.map(c => ({\n startSec: Number.isFinite(c.timestamp[0]) ? c.timestamp[0] : 0,\n endSec: Number.isFinite(c.timestamp[1]) ? c.timestamp[1] : 0,\n text: c.text,\n })),\n },\n }\n}\n\ninterface InstagramProfileItem {\n url: string\n type: 'post' | 'reel' | 'tv'\n shortcode: string\n anchorText?: string | null\n firstSeenStage?: string\n}\n\ninterface InstagramMediaTrack {\n url: string\n streamType: 'video' | 'audio' | 'unknown'\n bitrate?: number | null\n durationSec?: number | null\n vencodeTag?: string | null\n width?: number | null\n height?: number | null\n}\n\ninterface InstagramDownload {\n kind: 'text' | 'image' | 'video' | 'audio' | 'muxed_video'\n url: string | null\n savedPath: string | null\n sizeBytes: number | null\n mimeType: string | null\n error: string | null\n}\n\ninterface StructuredInstagramBrowser {\n mode: 'hosted'\n requestedMode: 'hosted'\n profileName: string | null\n profileSource: 'hosted'\n profileDirConfigured: boolean\n executablePathConfigured: boolean\n}\n\ninterface StructuredInstagramPagination {\n maxItems: number\n maxScrolls: number\n attemptedScrolls: number\n stableScrolls: number\n stableScrollLimit: number\n scrollDelayMs: number\n reachedMaxItems: boolean\n reachedReportedPostCount: boolean\n finalScrollHeight: number | null\n stoppedReason: 'max_items' | 'reported_post_count' | 'stable_scrolls' | 'max_scrolls' | 'no_scrolls'\n stages: Array<{\n stage: string\n itemCount: number\n addedCount: number\n scrollY: number | null\n scrollHeight: number | null\n }>\n}\n\nfunction structuredInstagramBrowser(raw: unknown): StructuredInstagramBrowser {\n const browser = raw && typeof raw === 'object' ? raw as Record<string, unknown> : {}\n return {\n mode: 'hosted',\n requestedMode: 'hosted',\n profileName: typeof browser.profileName === 'string' ? browser.profileName : null,\n profileSource: 'hosted',\n profileDirConfigured: false,\n executablePathConfigured: false,\n }\n}\n\nfunction structuredInstagramPagination(raw: unknown, input: { maxItems?: number; maxScrolls?: number; scrollDelayMs?: number; stableScrollLimit?: number }): StructuredInstagramPagination {\n const pagination = raw && typeof raw === 'object' ? raw as Record<string, unknown> : {}\n const stages = Array.isArray(pagination.stages) ? pagination.stages : []\n const stoppedReason = (typeof pagination.stoppedReason === 'string'\n && ['max_items', 'reported_post_count', 'stable_scrolls', 'max_scrolls', 'no_scrolls'].includes(pagination.stoppedReason)\n ? pagination.stoppedReason\n : 'no_scrolls') as StructuredInstagramPagination['stoppedReason']\n return {\n maxItems: typeof pagination.maxItems === 'number' ? pagination.maxItems : Number(input.maxItems ?? 50),\n maxScrolls: typeof pagination.maxScrolls === 'number' ? pagination.maxScrolls : Number(input.maxScrolls ?? 10),\n attemptedScrolls: typeof pagination.attemptedScrolls === 'number' ? pagination.attemptedScrolls : 0,\n stableScrolls: typeof pagination.stableScrolls === 'number' ? pagination.stableScrolls : 0,\n stableScrollLimit: typeof pagination.stableScrollLimit === 'number' ? pagination.stableScrollLimit : Number(input.stableScrollLimit ?? 4),\n scrollDelayMs: typeof pagination.scrollDelayMs === 'number' ? pagination.scrollDelayMs : Number(input.scrollDelayMs ?? 1200),\n reachedMaxItems: pagination.reachedMaxItems === true,\n reachedReportedPostCount: pagination.reachedReportedPostCount === true,\n finalScrollHeight: typeof pagination.finalScrollHeight === 'number' ? pagination.finalScrollHeight : null,\n stoppedReason,\n stages: stages.map((stage) => {\n const row = stage && typeof stage === 'object' ? stage as Record<string, unknown> : {}\n return {\n stage: String(row.stage ?? ''),\n itemCount: typeof row.itemCount === 'number' ? row.itemCount : 0,\n addedCount: typeof row.addedCount === 'number' ? row.addedCount : 0,\n scrollY: typeof row.scrollY === 'number' ? row.scrollY : null,\n scrollHeight: typeof row.scrollHeight === 'number' ? row.scrollHeight : null,\n }\n }),\n }\n}\n\nexport function formatInstagramProfileContent(\n raw: CallToolResult,\n input: { handle?: string; url?: string; maxItems?: number; maxScrolls?: number; scrollDelayMs?: number; stableScrollLimit?: number },\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 const items = (Array.isArray(d.items) ? d.items : []) as InstagramProfileItem[]\n const typeCounts = d.typeCounts as Record<string, number> | undefined\n const limitations = Array.isArray(d.limitations) ? d.limitations.map(String) : []\n const browser = structuredInstagramBrowser(d.browser)\n const pagination = structuredInstagramPagination(d.pagination, input)\n const itemRows = items.slice(0, 100).map((item, i) =>\n `| ${i + 1} | ${item.type} | \\`${item.shortcode}\\` | ${item.url} | ${cell(item.firstSeenStage ?? '')} |`,\n ).join('\\n')\n const browserLabel = browser.profileName ? `hosted browser profile ${browser.profileName}` : 'hosted browser'\n\n const full = [\n `# Instagram Profile Content: ${d.handle ?? input.handle ?? input.url ?? 'profile'}`,\n `**Collected:** ${items.length} items · posts ${typeCounts?.post ?? 0} · reels ${typeCounts?.reel ?? 0} · tv ${typeCounts?.tv ?? 0}`,\n `**Browser:** ${browserLabel}`,\n `**Pagination:** ${pagination.attemptedScrolls} scrolls · stopped: ${pagination.stoppedReason}`,\n d.reportedPostCountText ? `**Profile count:** ${d.reportedPostCountText}` : '',\n d.followerCountText ? `**Followers:** ${d.followerCountText}` : '',\n `\\n## Content Links\\n| # | Type | Shortcode | URL | First Seen |\\n|---|------|-----------|-----|------------|\\n${itemRows || '| — | — | — | — | — |'}`,\n limitations.length ? `\\n## Limits\\n${limitations.map(l => `- ${l}`).join('\\n')}` : '',\n `\\n---\\n💡 Use \\`instagram_media_download\\` with one of these URLs to download text, image, reel tracks, and optional transcript.`,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n handle: String(d.handle ?? input.handle ?? ''),\n profileUrl: String(d.profileUrl ?? input.url ?? ''),\n pageUrl: String(d.pageUrl ?? d.profileUrl ?? input.url ?? ''),\n browser,\n profileName: typeof d.profileName === 'string' ? d.profileName : null,\n reportedPostCount: typeof d.reportedPostCount === 'number' ? d.reportedPostCount : null,\n reportedPostCountText: typeof d.reportedPostCountText === 'string' ? d.reportedPostCountText : null,\n followerCountText: typeof d.followerCountText === 'string' ? d.followerCountText : null,\n followingCountText: typeof d.followingCountText === 'string' ? d.followingCountText : null,\n collectedContentCount: items.length,\n typeCounts: {\n post: Number(typeCounts?.post ?? 0),\n reel: Number(typeCounts?.reel ?? 0),\n tv: Number(typeCounts?.tv ?? 0),\n },\n pagination,\n limited: d.limited === true,\n limitations,\n items: items.map(item => ({\n url: String(item.url ?? ''),\n type: item.type,\n shortcode: String(item.shortcode ?? ''),\n anchorText: item.anchorText ?? null,\n firstSeenStage: String(item.firstSeenStage ?? ''),\n })),\n },\n }\n}\n\nfunction structuredInstagramTrack(track: InstagramMediaTrack | null | undefined): Record<string, unknown> | null {\n if (!track) return null\n return {\n url: String(track.url ?? ''),\n streamType: track.streamType ?? 'unknown',\n bitrate: typeof track.bitrate === 'number' ? track.bitrate : null,\n durationSec: typeof track.durationSec === 'number' ? track.durationSec : null,\n vencodeTag: track.vencodeTag ?? null,\n width: typeof track.width === 'number' ? track.width : null,\n height: typeof track.height === 'number' ? track.height : null,\n }\n}\n\nexport function formatInstagramMediaDownload(\n raw: CallToolResult,\n input: { url: string; includeTranscript?: 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\n const tracks = (Array.isArray(d.tracks) ? d.tracks : []) as InstagramMediaTrack[]\n const downloads = (Array.isArray(d.downloads) ? d.downloads : []) as InstagramDownload[]\n const warnings = Array.isArray(d.warnings) ? d.warnings.map(String) : []\n const limitations = Array.isArray(d.limitations) ? d.limitations.map(String) : []\n const transcript = d.transcript as TranscriptResult | null | undefined\n const transcriptText = transcript?.text ?? ''\n const chunks = transcript?.chunks ?? []\n const browser = structuredInstagramBrowser(d.browser)\n const browserLabel = browser.profileName ? `hosted browser profile ${browser.profileName}` : 'hosted browser'\n\n const downloadRows = downloads.map((download, i) => {\n const status = download.error ? `error: ${cell(download.error)}` : `${download.sizeBytes ?? 0} bytes`\n return `| ${i + 1} | ${download.kind} | ${download.savedPath ? `\\`${download.savedPath}\\`` : '—'} | ${status} |`\n }).join('\\n')\n const trackRows = tracks.slice(0, 20).map((track, i) =>\n `| ${i + 1} | ${track.streamType} | ${track.bitrate ?? '—'} | ${track.durationSec ?? '—'} | ${cell(track.vencodeTag ?? '')} |`,\n ).join('\\n')\n\n const full = [\n `# Instagram Media Download`,\n `**URL:** ${d.pageUrl ?? input.url}`,\n `**Browser:** ${browserLabel}`,\n d.ownerName ? `**Owner:** ${d.ownerName}` : '',\n d.shortcode ? `**Shortcode:** \\`${d.shortcode}\\`` : '',\n d.caption ? `\\n## Caption\\n${truncate(String(d.caption), 1200)}` : '',\n d.imageUrl ? `\\n## Image\\n${d.imageUrl}` : '',\n tracks.length ? `\\n## Media Tracks\\n| # | Type | Bitrate | Duration | Tag |\\n|---|------|---------|----------|-----|\\n${trackRows}` : '\\n## Media Tracks\\n*None captured.*',\n downloads.length ? `\\n## Downloads\\n| # | Kind | File | Status |\\n|---|------|------|--------|\\n${downloadRows}` : '',\n d.outputDir ? `\\n**Output directory:** \\`${d.outputDir}\\`` : '',\n transcript ? `\\n## Transcript\\n**${wordCount(transcriptText)} words** · ${chunks.length} chunks\\n\\n${transcriptText}` : '',\n warnings.length ? `\\n## Warnings\\n${warnings.map(w => `- ${w}`).join('\\n')}` : '',\n limitations.length ? `\\n## Limits\\n${limitations.map(l => `- ${l}`).join('\\n')}` : '',\n `\\n---\\n💡 Reels may expose separate video-only and audio-only MP4 tracks. Use the muxed file when present; otherwise use the selected video/audio track URLs or saved files.`,\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n sourceUrl: String(d.sourceUrl ?? input.url),\n pageUrl: String(d.pageUrl ?? input.url),\n browser,\n type: d.type === 'post' || d.type === 'reel' || d.type === 'tv' ? d.type : null,\n shortcode: typeof d.shortcode === 'string' ? d.shortcode : null,\n ownerName: typeof d.ownerName === 'string' ? d.ownerName : null,\n caption: typeof d.caption === 'string' ? d.caption : null,\n imageUrl: typeof d.imageUrl === 'string' ? d.imageUrl : null,\n trackCount: tracks.length,\n selectedVideoTrack: structuredInstagramTrack(d.selectedVideoTrack as InstagramMediaTrack | null | undefined),\n selectedAudioTrack: structuredInstagramTrack(d.selectedAudioTrack as InstagramMediaTrack | null | undefined),\n downloads: downloads.map(download => ({\n kind: download.kind,\n url: download.url ?? null,\n savedPath: download.savedPath ?? null,\n sizeBytes: typeof download.sizeBytes === 'number' ? download.sizeBytes : null,\n mimeType: download.mimeType ?? null,\n error: download.error ?? null,\n })),\n outputDir: typeof d.outputDir === 'string' ? d.outputDir : null,\n warnings,\n limitations,\n transcript: transcript ? {\n wordCount: wordCount(transcriptText),\n chunkCount: chunks.length,\n durationMs: typeof transcript.durationMs === 'number' ? transcript.durationMs : null,\n transcriptText,\n chunks: structuredTranscriptChunks(chunks),\n } : null,\n },\n }\n}\n\nexport function formatCaptureSerpSnapshot(\n raw: CallToolResult,\n input: Record<string, unknown>,\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 const providerPayload = d\n const organic = Array.isArray(d.organicResults) ? d.organicResults : Array.isArray(d.organic) ? d.organic : []\n const localPack = Array.isArray(d.localPack) ? d.localPack : []\n const artifacts = Array.isArray(d.artifacts) ? d.artifacts as Array<Record<string, unknown>> : []\n const status = String(d.status ?? d.captureStatus ?? 'captured')\n const query = typeof d.query === 'string' ? d.query : typeof input.query === 'string' ? input.query : null\n const location = typeof d.location === 'string' ? d.location : typeof input.location === 'string' ? input.location : null\n const capturedAt = typeof d.capturedAt === 'string'\n ? d.capturedAt\n : typeof d.extractedAt === 'string'\n ? d.extractedAt\n : null\n const resultCount = organic.length + localPack.length\n\n const full = [\n `# SERP Intelligence Snapshot: ${query ?? 'query'}`,\n `**Status:** ${status}`,\n location ? `**Location:** ${location}` : '',\n `**Result count:** ${resultCount}`,\n artifacts.length ? `**Artifacts:** ${artifacts.length}` : '',\n '',\n 'Use `capture_serp_page_snapshots` when you need page-level evidence for ranking URLs.',\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n schemaVersion: 'serp-intelligence.capture.v1',\n status,\n query,\n location,\n capturedAt,\n resultCount,\n snapshotId: typeof d.snapshotId === 'string'\n ? d.snapshotId\n : typeof d.snapshot_id === 'string'\n ? d.snapshot_id\n : typeof d.id === 'string'\n ? d.id\n : null,\n resolvedInputs: {\n query: input.query ?? null,\n location: input.location ?? null,\n gl: input.gl ?? null,\n hl: input.hl ?? null,\n device: input.device ?? null,\n proxyMode: input.proxyMode ?? null,\n proxyZip: input.proxyZip ?? null,\n pages: input.pages ?? null,\n },\n artifacts,\n diagnostics: d.diagnostics && typeof d.diagnostics === 'object' ? d.diagnostics as Record<string, unknown> : null,\n providerPayload,\n },\n }\n}\n\nexport function formatCaptureSerpPageSnapshots(\n raw: CallToolResult,\n input: Record<string, unknown>,\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 const captures = Array.isArray(d.captures)\n ? d.captures as Array<Record<string, unknown>>\n : Array.isArray(d.results)\n ? d.results as Array<Record<string, unknown>>\n : []\n const failedCount = captures.filter(c => c.status === 'failed' || c.error).length\n const status = String(d.status ?? (failedCount ? 'partial' : 'captured'))\n\n const rows = captures.slice(0, 25).map((capture, i) => {\n const url = typeof capture.url === 'string' ? capture.url : ''\n const sourceKind = typeof capture.sourceKind === 'string' ? capture.sourceKind : typeof capture.source_kind === 'string' ? capture.source_kind : 'configured_target'\n return `| ${i + 1} | ${cell(url)} | ${cell(sourceKind)} | ${cell(String(capture.status ?? (capture.error ? 'failed' : 'ok')))} |`\n }).join('\\n')\n\n const full = [\n '# SERP Intelligence Page Snapshots',\n `**Status:** ${status}`,\n `**Captured:** ${captures.length}`,\n `**Failed:** ${failedCount}`,\n captures.length ? `\\n| # | URL | Source | Status |\\n|---|-----|--------|--------|\\n${rows}` : '',\n ].filter(Boolean).join('\\n')\n\n return {\n ...oneBlock(full),\n structuredContent: {\n schemaVersion: 'serp-intelligence.page-snapshots.v1',\n status,\n count: captures.length,\n failedCount,\n captures,\n resolvedInputs: {\n urls: input.urls ?? null,\n targets: input.targets ?? null,\n maxConcurrency: input.maxConcurrency ?? null,\n timeoutMs: input.timeoutMs ?? null,\n debug: input.debug ?? null,\n },\n diagnostics: d.diagnostics && typeof d.diagnostics === 'object' ? d.diagnostics as Record<string, unknown> : null,\n providerPayload: d,\n },\n }\n}\n","export type WorkflowRecipe = {\n id: string\n title: string\n description: string\n primaryWorkflowId: string | null\n recommendedTools: string[]\n requiredInputs: string[]\n optionalInputs: string[]\n produces: string[]\n runHint: string\n}\n\nexport const WORKFLOW_RECIPES: WorkflowRecipe[] = [\n {\n id: 'market_analysis',\n title: 'Market Analysis',\n description: 'Compare a niche across a city, state, or market set using Google Maps competitors, SERP evidence, review counts, categories, and opportunity signals.',\n primaryWorkflowId: 'local-competitive-audit',\n recommendedTools: ['workflow_run', 'directory_workflow', 'maps_search', 'maps_place_intel', 'search_serp', 'harvest_paa'],\n requiredInputs: ['query', 'state or location'],\n optionalInputs: ['domain', 'minPopulation', 'maxCities', 'maxResultsPerCity', 'hydrateTop', 'maxReviews'],\n produces: ['city summary', 'competitor CSV', 'review insight CSV', 'market difficulty/opportunity notes', 'HTML report'],\n runHint: 'Use workflow_run with workflowId local-competitive-audit for state-wide market batches, or map-comparison for one city/location comparison.',\n },\n {\n id: 'lead_generation',\n title: 'Lead Generation',\n description: 'Build an outreach-ready local lead list for a niche in one market: Google Maps businesses with confirmed review counts and booking URLs, enriched with email and social links scraped from each business website (proxy/browser-backed so blocked sites still resolve).',\n primaryWorkflowId: 'get-leads',\n recommendedTools: ['workflow_run', 'maps_search', 'maps_place_intel', 'extract_url'],\n requiredInputs: ['query', 'location'],\n optionalInputs: ['maxResults', 'enrichWebsites', 'hydrateReviewCounts', 'concurrency', 'proxyMode'],\n produces: ['leads CSV (name, phone, website, email, socials, review count, booking URL)', 'evidence JSON', 'HTML report', 'outreach task list'],\n runHint: 'Use workflow_run with workflowId get-leads. Put the niche in query (e.g. \"roofers\") and the market in location (e.g. \"Houston, TX\"); do not combine them.',\n },\n {\n id: 'icp_research',\n title: 'ICP Research',\n description: 'Build an evidence packet for ideal-customer-profile research from real search demand, PAA language, competing pages, AI Overview citations, and source domains.',\n primaryWorkflowId: 'agent-packet',\n recommendedTools: ['workflow_run', 'harvest_paa', 'search_serp', 'extract_url', 'youtube_harvest', 'facebook_ad_search'],\n requiredInputs: ['keyword or audience problem'],\n optionalInputs: ['domain', 'location', 'maxQuestions'],\n produces: ['evidence JSON', 'sources CSV', 'competitor CSV', 'brief markdown', 'agent task list'],\n runHint: 'Use workflow_run with workflowId agent-packet. Treat keyword as the buyer problem, job-to-be-done, niche, or service category.',\n },\n {\n id: 'forum_review_research',\n title: 'Forum And Review Research',\n description: 'Acquire customer language from Google PAA, forum/Perspectives SERP surfaces, Google Maps reviews, review topics, Facebook ads, and video transcripts.',\n primaryWorkflowId: 'local-competitive-audit',\n recommendedTools: ['workflow_run', 'harvest_paa', 'maps_search', 'maps_place_intel', 'facebook_page_intel', 'facebook_video_transcribe', 'youtube_transcribe'],\n requiredInputs: ['query', 'state or location'],\n optionalInputs: ['maxReviews', 'maxQuestions', 'competitors', 'facebookUrl', 'youtubeVideoId'],\n produces: ['review insight CSV', 'PAA/source language', 'competitor review topics', 'transcripts where supplied', 'pain/theme summary'],\n runHint: 'Use local-competitive-audit for review acquisition, then harvest_paa for forum/Perspectives language and transcript tools for supplied videos.',\n },\n {\n id: 'brand_design_brief',\n title: 'Brand Design Brief',\n description: 'Create a design briefing grounded in a brand site, competitor pages, SERP language, audience pains, visual assets, colors, fonts, screenshots, and positioning evidence.',\n primaryWorkflowId: 'serp-comparison',\n recommendedTools: ['workflow_run', 'extract_url', 'extract_site', 'capture_serp_page_snapshots', 'search_serp', 'harvest_paa', 'browser_open'],\n requiredInputs: ['url or domain', 'keyword or market category'],\n optionalInputs: ['competitorUrls', 'location', 'extractTop'],\n produces: ['page comparison CSV', 'content gaps', 'branding/asset evidence', 'SERP positioning evidence', 'designer-ready brief'],\n runHint: 'Use workflow_run with workflowId serp-comparison for market/page evidence, then extract_url with extractBranding:true for brand assets and colors.',\n },\n {\n id: 'cro_audit',\n title: 'CRO Audit',\n description: 'Audit conversion clarity using page extraction, screenshots, browser DOM inspection, competitor SERP/page comparisons, forms/buttons, proof, offer, trust, and friction evidence.',\n primaryWorkflowId: 'serp-comparison',\n recommendedTools: ['workflow_run', 'extract_url', 'extract_site', 'capture_serp_page_snapshots', 'browser_open', 'browser_screenshot', 'browser_locate'],\n requiredInputs: ['url'],\n optionalInputs: ['keyword', 'domain', 'location', 'competitorUrls'],\n produces: ['page extraction', 'SERP/page comparison', 'screenshot evidence', 'friction checklist', 'CRO recommendations'],\n runHint: 'Use workflow_run with workflowId serp-comparison when a keyword/domain is known; use extract_url and browser tools for page-level CRO evidence.',\n },\n {\n id: 'competitive_positioning_brief',\n title: 'Competitive Positioning Brief',\n description: 'Compare competitors across SERP, PAA, AI Overview citations, page headings, Facebook ads, YouTube angles, Maps proof, and website claims.',\n primaryWorkflowId: 'serp-comparison',\n recommendedTools: ['workflow_run', 'facebook_ad_search', 'facebook_page_intel', 'youtube_harvest', 'youtube_transcribe', 'maps_search', 'extract_url'],\n requiredInputs: ['keyword or query', 'domain or url'],\n optionalInputs: ['location', 'extractTop', 'competitorUrls', 'brandNames'],\n produces: ['SERP comparison', 'content gap CSV', 'AI Overview citation table', 'competitor message map', 'positioning brief'],\n runHint: 'Use workflow_run with workflowId serp-comparison, then enrich with Facebook, YouTube, and Maps tools when the user asks for campaign or offer positioning.',\n },\n {\n id: 'content_gap_brief',\n title: 'Content Gap Brief',\n description: 'Turn live SERP, page extraction, PAA questions, AI Overview citations, and source-domain evidence into a writer-ready content brief.',\n primaryWorkflowId: 'serp-comparison',\n recommendedTools: ['workflow_run', 'paa-expansion-brief', 'harvest_paa', 'extract_url'],\n requiredInputs: ['keyword'],\n optionalInputs: ['domain', 'url', 'location', 'maxQuestions', 'extractTop'],\n produces: ['content gaps', 'page comparison CSV', 'PAA questions CSV', 'section map', 'writer brief'],\n runHint: 'Use workflow_run with workflowId serp-comparison for competitor gaps or paa-expansion-brief when the user mainly wants a section map from PAA data.',\n },\n {\n id: 'ai_search_visibility_audit',\n title: 'AI Search Visibility Audit',\n description: 'Audit whether a brand/domain appears in AI Overview citations, PAA sources, organic results, local pack, and source pages, then produce language guidance.',\n primaryWorkflowId: 'ai-overview-language',\n recommendedTools: ['workflow_run', 'search_serp', 'harvest_paa', 'extract_url', 'capture_serp_snapshot'],\n requiredInputs: ['keyword', 'domain or url'],\n optionalInputs: ['location', 'maxQuestions', 'extractTop'],\n produces: ['AI Overview citations CSV', 'claim patterns', 'language guidance', 'citation hooks', 'visibility gaps'],\n runHint: 'Use workflow_run with workflowId ai-overview-language. Use serp-comparison when the user also wants ranking-page gaps.',\n },\n]\n\nfunction normalize(value: string): string {\n return value.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim()\n}\n\nexport function suggestWorkflowRecipes(goal: string, limit = 3): WorkflowRecipe[] {\n const normalized = normalize(goal)\n const scored = WORKFLOW_RECIPES.map(recipe => {\n const haystack = normalize([\n recipe.id,\n recipe.title,\n recipe.description,\n recipe.requiredInputs.join(' '),\n recipe.optionalInputs.join(' '),\n recipe.produces.join(' '),\n ].join(' '))\n let score = 0\n for (const token of normalized.split(/\\s+/).filter(Boolean)) {\n if (haystack.includes(token)) score += 1\n }\n if (haystack.includes(normalized)) score += 5\n return { recipe, score }\n })\n return scored\n .sort((a, b) => b.score - a.score || a.recipe.title.localeCompare(b.recipe.title))\n .slice(0, Math.max(1, limit))\n .map(item => item.recipe)\n}\n","import type { PageData } from './site-extractor.js'\n\nexport interface LinkEdge {\n from: string\n to: string\n anchor: string\n rel: string | null\n internal: boolean\n nofollow: boolean\n targetStatus: number | null\n}\n\nexport interface PageLinkMetrics {\n url: string\n inlinks: number\n uniqueInlinks: number\n outlinksInternal: number\n outlinksExternal: number\n crawlDepth: number | null\n orphan: boolean\n topAnchors: string[]\n}\n\nfunction normalize(u: string): string {\n return u.split('#')[0].replace(/\\/$/, '')\n}\n\nexport function buildLinkGraph(\n pages: PageData[],\n startUrl: string,\n): { edges: LinkEdge[]; metrics: Map<string, PageLinkMetrics> } {\n const statusByUrl = new Map<string, number | null>()\n for (const p of pages) statusByUrl.set(normalize(p.url), p.status)\n\n const edges: LinkEdge[] = []\n for (const p of pages) {\n for (const l of p.outlinks ?? []) {\n const nofollow = (l.rel ?? '').split(/\\s+/).includes('nofollow')\n edges.push({\n from: p.url,\n to: l.href,\n anchor: l.anchor,\n rel: l.rel,\n internal: l.internal,\n nofollow,\n targetStatus: statusByUrl.get(normalize(l.href)) ?? null,\n })\n }\n }\n\n const inboundFrom = new Map<string, Set<string>>()\n const inboundAnchors = new Map<string, string[]>()\n const adjacency = new Map<string, Set<string>>()\n for (const e of edges) {\n if (!e.internal) continue\n const to = normalize(e.to)\n const from = normalize(e.from)\n if (!inboundFrom.has(to)) inboundFrom.set(to, new Set())\n inboundFrom.get(to)!.add(from)\n if (e.anchor) {\n if (!inboundAnchors.has(to)) inboundAnchors.set(to, [])\n inboundAnchors.get(to)!.push(e.anchor)\n }\n if (!e.nofollow && (statusByUrl.get(to) === 200 || !statusByUrl.has(to))) {\n if (!adjacency.has(from)) adjacency.set(from, new Set())\n adjacency.get(from)!.add(to)\n }\n }\n\n const depth = new Map<string, number>()\n const start = normalize(startUrl)\n const queue: string[] = [start]\n depth.set(start, 0)\n while (queue.length > 0) {\n const cur = queue.shift()!\n const d = depth.get(cur)!\n for (const next of adjacency.get(cur) ?? []) {\n if (!depth.has(next)) { depth.set(next, d + 1); queue.push(next) }\n }\n }\n\n const topAnchorsFor = (url: string): string[] => {\n const counts = new Map<string, number>()\n for (const a of inboundAnchors.get(url) ?? []) counts.set(a, (counts.get(a) ?? 0) + 1)\n return [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3).map(e => e[0])\n }\n\n const metrics = new Map<string, PageLinkMetrics>()\n for (const p of pages) {\n const key = normalize(p.url)\n const inbound = inboundFrom.get(key) ?? new Set()\n metrics.set(p.url, {\n url: p.url,\n inlinks: inbound.size,\n uniqueInlinks: inbound.size,\n outlinksInternal: (p.outlinks ?? []).filter(l => l.internal).length,\n outlinksExternal: (p.outlinks ?? []).filter(l => !l.internal).length,\n crawlDepth: depth.has(key) ? depth.get(key)! : null,\n orphan: inbound.size === 0 && key !== start,\n topAnchors: topAnchorsFor(key),\n })\n }\n\n return { edges, metrics }\n}\n","import type { LinkEdge, PageLinkMetrics } from './seo-link-graph.js'\n\nexport interface ExtDomainRow { domain: string; links: number; nofollow: number; pages: number }\n\nexport interface LinkReportSummary {\n internal: {\n totalLinks: number\n pages: number\n orphans: number\n brokenInternal: number\n avgInlinks: number\n avgOutlinks: number\n distribution: { zero: number; oneToTwo: number; threeToTen: number; elevenPlus: number }\n topByInlinks: Array<{ url: string; inlinks: number; outlinksInternal: number; outlinksExternal: number }>\n }\n external: {\n totalLinks: number\n uniqueDomains: number\n topDomains: ExtDomainRow[]\n }\n}\n\nexport interface LinkReport {\n summary: LinkReportSummary\n externalDomains: ExtDomainRow[]\n}\n\nfunction registrableDomain(host: string): string {\n const h = host.replace(/^www\\./, '').toLowerCase()\n const parts = h.split('.')\n return parts.length <= 2 ? h : parts.slice(-2).join('.')\n}\n\nexport function buildLinkReport(edges: LinkEdge[], metrics: PageLinkMetrics[], siteUrl: string): LinkReport {\n let siteReg = ''\n try { siteReg = registrableDomain(new URL(siteUrl).hostname) } catch { siteReg = '' }\n const internalEdges = edges.filter(e => e.internal)\n const pages = metrics.length\n const orphans = metrics.filter(m => m.orphan).length\n const brokenInternal = internalEdges.filter(e => e.targetStatus != null && e.targetStatus >= 400).length\n const sumInlinks = metrics.reduce((a, m) => a + m.inlinks, 0)\n const sumOutlinks = metrics.reduce((a, m) => a + m.outlinksInternal + m.outlinksExternal, 0)\n\n const distribution = { zero: 0, oneToTwo: 0, threeToTen: 0, elevenPlus: 0 }\n for (const m of metrics) {\n if (m.inlinks === 0) distribution.zero++\n else if (m.inlinks <= 2) distribution.oneToTwo++\n else if (m.inlinks <= 10) distribution.threeToTen++\n else distribution.elevenPlus++\n }\n\n const topByInlinks = [...metrics].sort((a, b) => b.inlinks - a.inlinks).slice(0, 20)\n .map(m => ({ url: m.url, inlinks: m.inlinks, outlinksInternal: m.outlinksInternal, outlinksExternal: m.outlinksExternal }))\n\n const domMap = new Map<string, { links: number; nofollow: number; pages: Set<string> }>()\n let externalTotal = 0\n for (const e of edges) {\n let domain: string\n try { domain = registrableDomain(new URL(e.to).hostname) } catch { continue }\n if (!domain || domain === siteReg) continue\n externalTotal++\n const d = domMap.get(domain) ?? { links: 0, nofollow: 0, pages: new Set<string>() }\n d.links++\n if (e.nofollow) d.nofollow++\n d.pages.add(e.from)\n domMap.set(domain, d)\n }\n const externalDomains: ExtDomainRow[] = [...domMap.entries()]\n .map(([domain, d]) => ({ domain, links: d.links, nofollow: d.nofollow, pages: d.pages.size }))\n .sort((a, b) => b.links - a.links)\n\n const round = (n: number) => Math.round(n * 10) / 10\n return {\n summary: {\n internal: {\n totalLinks: internalEdges.length,\n pages, orphans, brokenInternal,\n avgInlinks: pages ? round(sumInlinks / pages) : 0,\n avgOutlinks: pages ? round(sumOutlinks / pages) : 0,\n distribution,\n topByInlinks,\n },\n external: {\n totalLinks: externalTotal,\n uniqueDomains: externalDomains.length,\n topDomains: externalDomains.slice(0, 20),\n },\n },\n externalDomains,\n }\n}\n\nexport function renderLinkReport(r: LinkReport): string {\n const s = r.summary\n const lines = [\n `## Link analysis`,\n `**Internal:** ${s.internal.totalLinks} links · ${s.internal.pages} pages · avg ${s.internal.avgInlinks} inlinks/page · ${s.internal.orphans} orphans · ${s.internal.brokenInternal} broken`,\n `**External:** ${s.external.totalLinks} links to ${s.external.uniqueDomains} domains`,\n ``,\n `### Inlink distribution`,\n `- 0 inlinks (orphans): ${s.internal.distribution.zero}`,\n `- 1–2: ${s.internal.distribution.oneToTwo}`,\n `- 3–10: ${s.internal.distribution.threeToTen}`,\n `- 11+: ${s.internal.distribution.elevenPlus}`,\n ``,\n `### Top 20 internal pages by inlinks`,\n `| inlinks | out (int/ext) | URL |`,\n `|---|---|---|`,\n ...s.internal.topByInlinks.map(p => `| ${p.inlinks} | ${p.outlinksInternal}/${p.outlinksExternal} | ${p.url} |`),\n ``,\n `### Top 20 external domains by links`,\n `| links | nofollow | from pages | domain |`,\n `|---|---|---|---|`,\n ...s.external.topDomains.map(d => `| ${d.links} | ${d.nofollow} | ${d.pages} | ${d.domain} |`),\n ]\n return lines.join('\\n')\n}\n","import type { PageData } from './site-extractor.js'\nimport type { PageLinkMetrics } from './seo-link-graph.js'\n\nexport interface IssueGroup { count: number; urls: string[] }\nexport type IssueReport = Record<string, IssueGroup>\n\nconst THIN_WORDS = 200\nconst TITLE_MAX = 60\nconst TITLE_PX_MAX = 561\nconst TITLE_MIN = 30\nconst META_MAX = 155\nconst META_MIN = 70\nconst H1_MAX = 70\nconst URL_MAX = 115\n\nfunction dupes<T>(pages: PageData[], key: (p: PageData) => T | null | undefined): string[] {\n const groups = new Map<string, string[]>()\n for (const p of pages) {\n const k = key(p)\n if (k === null || k === undefined || k === '') continue\n const ks = String(k)\n if (!groups.has(ks)) groups.set(ks, [])\n groups.get(ks)!.push(p.url)\n }\n return [...groups.values()].filter(g => g.length > 1).flat()\n}\n\nexport function computeIssues(pages: PageData[], metrics: Map<string, PageLinkMetrics>): IssueReport {\n const group = (urls: string[]): IssueGroup => ({ count: urls.length, urls: urls.slice(0, 200) })\n const where = (fn: (p: PageData) => boolean) => pages.filter(fn).map(p => p.url)\n const ok = (p: PageData) => p.status === 200\n const pathname = (u: string) => { try { return new URL(u).pathname } catch { return '' } }\n\n const report: IssueReport = {\n 'title.missing': group(where(p => ok(p) && !p.title)),\n 'title.duplicate': group(dupes(pages.filter(ok), p => p.title)),\n 'title.tooLong': group(where(p => (p.titleLength ?? 0) > TITLE_MAX || (p.titlePixels ?? 0) > TITLE_PX_MAX)),\n 'title.tooShort': group(where(p => p.title != null && (p.titleLength ?? 0) < TITLE_MIN)),\n 'title.sameAsH1': group(where(p => !!p.title && !!p.h1 && p.title.trim() === p.h1.trim())),\n 'meta.missing': group(where(p => ok(p) && !p.metaDescription)),\n 'meta.duplicate': group(dupes(pages.filter(ok), p => p.metaDescription)),\n 'meta.tooLong': group(where(p => (p.metaDescLength ?? 0) > META_MAX)),\n 'meta.tooShort': group(where(p => p.metaDescription != null && (p.metaDescLength ?? 0) < META_MIN)),\n 'h1.missing': group(where(p => ok(p) && !p.h1)),\n 'h1.multiple': group(where(p => !!p.h1_2)),\n 'h1.duplicate': group(dupes(pages.filter(ok), p => p.h1)),\n 'h1.tooLong': group(where(p => (p.h1?.length ?? 0) > H1_MAX)),\n 'h2.missing': group(where(p => ok(p) && p.h2Count === 0)),\n 'indexability.nonIndexable': group(where(p => !p.indexable)),\n 'indexability.noindex': group(where(p => p.indexabilityReason === 'noindex')),\n 'canonical.missing': group(where(p => ok(p) && !p.canonicalUrl)),\n 'canonical.canonicalised': group(where(p => p.indexabilityReason === 'canonicalised')),\n 'response.broken4xx': group(where(p => (p.status ?? 0) >= 400 && (p.status ?? 0) < 500)),\n 'response.error5xx': group(where(p => (p.status ?? 0) >= 500)),\n 'response.redirect3xx': group(where(p => (p.status ?? 0) >= 300 && (p.status ?? 0) < 400)),\n 'response.noResponse': group(where(p => p.status === null)),\n 'content.thin': group(where(p => ok(p) && p.wordCount > 0 && p.wordCount < THIN_WORDS)),\n 'content.exactDuplicate': group(dupes(pages.filter(p => ok(p) && p.contentHash), p => p.contentHash)),\n 'images.missingAlt': group(where(p => p.imagesMissingAlt > 0)),\n 'schema.missing': group(where(p => ok(p) && p.schemaTypes.length === 0)),\n 'url.tooLong': group(where(p => p.url.length > URL_MAX)),\n 'url.uppercase': group(where(p => /[A-Z]/.test(pathname(p.url)))),\n 'url.underscores': group(where(p => pathname(p.url).includes('_'))),\n 'links.orphan': group([...metrics.values()].filter(m => m.orphan).map(m => m.url)),\n }\n\n const normUrl = (u: string) => { try { const x = new URL(u); x.hash = ''; return (x.origin + x.pathname).replace(/\\/+$/, '') + x.search } catch { return u.replace(/#.*$/, '').replace(/\\/+$/, '') } }\n const statusByUrl = new Map(pages.map(p => [normUrl(p.url), p.status]))\n const brokenLinkPages = new Set<string>()\n for (const p of pages) {\n for (const l of p.outlinks ?? []) {\n if (!l.internal) continue\n const st = statusByUrl.get(normUrl(l.href))\n if (st != null && st >= 400) brokenLinkPages.add(p.url)\n }\n }\n report['links.brokenInternal'] = group([...brokenLinkPages])\n\n return report\n}\n\nexport function renderIssueReport(siteUrl: string, pages: PageData[], report: IssueReport, metrics: Map<string, PageLinkMetrics>): string {\n const total = pages.length\n const sev = (key: string): string => (\n key.startsWith('response.broken') || key.startsWith('response.error') || key.startsWith('links.broken') ? '🔴'\n : key.startsWith('title.missing') || key.startsWith('h1.missing') || key.startsWith('indexability') || key.startsWith('canonical.missing') ? '🟠'\n : '🟡'\n )\n const rows = Object.entries(report)\n .filter(([, g]) => g.count > 0)\n .sort((a, b) => b[1].count - a[1].count)\n .map(([k, g]) => `| ${sev(k)} | \\`${k}\\` | ${g.count} | ${g.urls.slice(0, 3).join(' · ')}${g.urls.length > 3 ? ' …' : ''} |`)\n\n const depths = [...metrics.values()].map(m => m.crawlDepth).filter((d): d is number => d != null)\n const maxDepth = depths.length ? Math.max(...depths) : 0\n const orphans = [...metrics.values()].filter(m => m.orphan).length\n const topLinked = [...metrics.values()].sort((a, b) => b.inlinks - a.inlinks).slice(0, 5)\n\n return [\n `# SEO Crawl Report: ${siteUrl}`,\n `**${total} pages crawled** · max crawl depth ${maxDepth} · ${orphans} orphan page(s)`,\n `\\n## Issues\\n| | Issue | Count | Examples |\\n|---|-------|-------|----------|\\n${rows.join('\\n') || '| ✅ | none | 0 | — |'}`,\n `\\n## Most-linked pages\\n${topLinked.map(m => `- ${m.inlinks} inlinks · depth ${m.crawlDepth ?? '—'} · ${m.url}`).join('\\n')}`,\n `\\n_Thresholds: title ${TITLE_MAX}ch/${TITLE_PX_MAX}px, meta ${META_MAX}ch, H1 ${H1_MAX}ch, thin <${THIN_WORDS} words, URL ${URL_MAX}ch. Pixel widths are estimates._`,\n ].join('\\n')\n}\n","import type { PageData } from './site-extractor.js'\n\nexport interface ImageRow {\n url: string\n status: number | null\n bytes: number | null\n size: string | null\n contentType: string | null\n format: string\n over100kb: boolean\n legacyFormat: boolean\n error?: string\n}\n\nexport interface ImageAuditSummary {\n unique: number\n sized: number\n totalBytes: number\n totalSize: string\n avgSize: string\n over100kb: number\n legacyFormat: number\n formatCounts: Record<string, number>\n}\n\nexport interface ImageAudit {\n rows: ImageRow[]\n summary: ImageAuditSummary\n}\n\nconst OVER_BYTES = 100 * 1024\nconst MODERN = new Set(['webp', 'avif', 'svg', 'svg+xml'])\n\nexport function formatBytes(n: number | null): string | null {\n if (n == null) return null\n if (n < 1024) return `${n} B`\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`\n return `${(n / (1024 * 1024)).toFixed(2)} MB`\n}\n\nconst decodeEntities = (u: string): string =>\n u.replace(/&amp;/g, '&').replace(/&#0?38;/g, '&').replace(/&#x26;/gi, '&').trim()\n\nconst dedupKey = (u: string): string => u.replace(/^https?:\\/\\//i, '//').replace(/\\/$/, '')\n\nconst formatOf = (ct: string | null, url: string): string => {\n if (ct) { const m = ct.split(';')[0].trim().toLowerCase(); if (m.startsWith('image/')) return m.replace('image/', '') }\n return (url.split('?')[0].match(/\\.([a-z0-9]+)$/i)?.[1] || 'unknown').toLowerCase()\n}\n\nfunction collectUrls(pages: PageData[]): string[] {\n const byKey = new Map<string, string>()\n for (const p of pages) for (const raw of (p.imageLinks || [])) {\n const u = decodeEntities(raw)\n if (!/^https?:\\/\\//i.test(u)) continue\n if (/[{}]|%7[bd]/i.test(u)) continue\n const k = dedupKey(u)\n const prev = byKey.get(k)\n if (!prev || (/^https:/i.test(u) && /^http:/i.test(prev))) byKey.set(k, u)\n }\n return [...byKey.values()]\n}\n\nasync function sizeAndType(url: string, timeoutMs: number): Promise<Omit<ImageRow, 'size' | 'format' | 'over100kb' | 'legacyFormat'>> {\n const ctrl = new AbortController()\n const t = setTimeout(() => ctrl.abort(), timeoutMs)\n const read = (res: Response) => ({\n len: res.headers.get('content-length'),\n cr: res.headers.get('content-range'),\n ct: res.headers.get('content-type'),\n status: res.status,\n })\n try {\n let bytes: number | null = null\n let ct: string | null = null\n let status: number | null = null\n try {\n const h = read(await fetch(url, { method: 'HEAD', redirect: 'follow', signal: ctrl.signal }))\n status = h.status; ct = h.ct\n if (h.len) bytes = Number(h.len)\n } catch { /* fall through to ranged GET */ }\n if (bytes == null) {\n const g = await fetch(url, { method: 'GET', headers: { Range: 'bytes=0-0' }, redirect: 'follow', signal: ctrl.signal })\n const r = read(g)\n status = status ?? r.status; ct = ct ?? r.ct\n if (r.cr && r.cr.includes('/')) { const tail = r.cr.split('/')[1]; if (tail && tail !== '*') bytes = Number(tail) }\n else if (r.len) bytes = Number(r.len)\n try { await g.body?.cancel() } catch { /* ignore */ }\n }\n return { url, status, bytes: Number.isFinite(bytes as number) ? bytes : null, contentType: ct }\n } catch (e) {\n return { url, status: null, bytes: null, contentType: null, error: String((e as Error).message || e) }\n } finally {\n clearTimeout(t)\n }\n}\n\nasync function pool<T, R>(items: T[], n: number, fn: (item: T) => Promise<R>): Promise<R[]> {\n const out = new Array<R>(items.length)\n let i = 0\n await Promise.all(Array.from({ length: Math.min(n, items.length) }, async () => {\n while (i < items.length) { const idx = i++; out[idx] = await fn(items[idx]) }\n }))\n return out\n}\n\nexport async function auditImages(\n pages: PageData[],\n opts: { concurrency?: number; timeoutMs?: number; max?: number } = {},\n): Promise<ImageAudit> {\n const concurrency = opts.concurrency ?? 12\n const timeoutMs = opts.timeoutMs ?? 12_000\n const urls = collectUrls(pages).slice(0, opts.max ?? 5000)\n\n const heads = await pool(urls, concurrency, (u) => sizeAndType(u, timeoutMs))\n const rows: ImageRow[] = heads.map(r => {\n const format = formatOf(r.contentType, r.url)\n return {\n ...r,\n size: formatBytes(r.bytes),\n format,\n over100kb: r.bytes != null && r.bytes > OVER_BYTES,\n legacyFormat: format !== 'unknown' && !MODERN.has(format),\n }\n })\n\n const sized = rows.filter(r => r.bytes != null)\n const totalBytes = sized.reduce((a, r) => a + (r.bytes as number), 0)\n const formatCounts: Record<string, number> = {}\n for (const r of rows) formatCounts[r.format] = (formatCounts[r.format] || 0) + 1\n\n return {\n rows: rows.sort((a, b) => (b.bytes ?? 0) - (a.bytes ?? 0)),\n summary: {\n unique: rows.length,\n sized: sized.length,\n totalBytes,\n totalSize: formatBytes(totalBytes) ?? '0 B',\n avgSize: formatBytes(Math.round(totalBytes / (sized.length || 1))) ?? '0 B',\n over100kb: rows.filter(r => r.over100kb).length,\n legacyFormat: rows.filter(r => r.legacyFormat).length,\n formatCounts,\n },\n }\n}\n\nexport function renderImageSection(audit: ImageAudit): string {\n const s = audit.summary\n const fmt = Object.entries(s.formatCounts).sort((a, b) => b[1] - a[1]).map(([k, v]) => `${k}:${v}`).join(' ')\n const heaviest = audit.rows.filter(r => r.over100kb).slice(0, 15)\n const lines = [\n `## Images`,\n `**${s.unique} unique images** · ${s.totalSize} total · ${s.avgSize} avg · ${s.over100kb} over 100 KB · ${s.legacyFormat} legacy format`,\n `Formats: ${fmt}`,\n ]\n if (heaviest.length) {\n lines.push('', '| Size | Format | URL |', '|------|--------|-----|')\n for (const r of heaviest) lines.push(`| ${r.size} | ${r.format} | ${r.url} |`)\n }\n return lines.join('\\n')\n}\n","export const SERVER_INSTRUCTIONS = `\n# MCP Scraper\n\nScrapes and analyzes web, search, maps, social, and site data. **Pick a tool by NAME from the map\nbelow, then load its schema before calling.** Where a tool needs a value another tool produces, the\nseam is noted so you can chain them.\n\n## Search & research\n- Organic Google results, rankings, local pack -> **search_serp**.\n- Full SERP plus People-Also-Ask and AI-Overview detail -> **harvest_paa**.\n- \\`search_serp\\` returns \\`organicResults[].url\\` (often including reddit.com threads) — feed those into\n \\`extract_url\\` or \\`reddit_thread\\`.\n\n## Pages & sites\n- One page -> **extract_url** (takes a url).\n- Whole site, crawl + SEO report -> **extract_site** (takes a url).\n- Just the URL list/inventory -> **map_site_urls** (takes a url).\n- \\`map_site_urls\\` returns urls you can feed straight into \\`extract_url\\`.\n\n## Google Maps\n- Find multiple places/competitors/prospects -> **maps_search** (returns \\`results[]\\` with name,\n placeUrl, cid).\n- One business deep-dive + reviews -> **maps_place_intel** (takes businessName + location, NOT an id —\n call it directly with a name from a \\`maps_search\\` result or from the user).\n\n## YouTube\n- Find or list videos -> **youtube_harvest** (returns \\`videos[].videoId\\`).\n- Transcribe one video -> **youtube_transcribe** (takes a videoId from \\`youtube_harvest\\`, or a url).\n\n## Facebook\n- Find advertisers -> **facebook_ad_search** (returns \\`advertisers[]\\` with pageId, libraryId).\n- One advertiser's ads -> **facebook_page_intel** (takes pageId, libraryId, or query; returns\n \\`ads[].videoUrl\\`).\n- Transcribe an ad video -> **facebook_ad_transcribe** (takes a videoUrl from \\`facebook_page_intel\\`).\n- Transcribe an organic reel/video/post -> **facebook_video_transcribe** (takes the Facebook url directly).\n\n## Google Ads (Ads Transparency Center)\n- Find advertisers by domain or brand -> **google_ads_search** (returns \\`advertisers[]\\` with advertiserId).\n- One advertiser's ads -> **google_ads_page_intel** (takes advertiserId or domain; returns \\`ads[]\\` with\n format, imageUrls, youtubeVideoId, and videoUrl).\n- Transcribe a video ad -> **google_ads_transcribe** (takes a googlevideo \\`videoUrl\\` from\n \\`google_ads_page_intel\\`), or **youtube_transcribe** for a returned \\`youtubeVideoId\\`.\n\n## Instagram\n- Profile inventory -> **instagram_profile_content** (returns post/reel/tv urls).\n- One post or reel -> **instagram_media_download** (takes a url from \\`instagram_profile_content\\`, or a\n url the user gives).\n\n## Reddit\n- A reddit.com thread/post URL -> **reddit_thread**. Returns the post plus its comment tree and handles\n Reddit's bot wall itself (no login needed). Find threads first with \\`search_serp\\`.\n\n## Other sites & logins (browser agent)\nFor an arbitrary site or a logged-in dashboard with no dedicated tool, use the browser_* agent. **First\ndecide whether the site needs a login:**\n- **Needs a login** (ChatGPT, Claude, any account) -> save it first: **browser_profile_connect** returns\n an mcpscraper.dev sign-in link for the user; one profile holds MANY logins (call it again with the same\n profile + a new domain to add accounts). Poll **browser_profile_list** until AUTHENTICATED, then\n **browser_open** with that profile.\n- **No login** -> **browser_open**, then navigate/read.\n\n## Workflows\nMulti-step orchestrations — prefer these over hand-chaining primitives when the whole job is one of these:\n- Build a local business directory for a niche across a state/region -> **directory_workflow**.\n- Stand up a rank-tracking blueprint (database + cron + ingestion plan) -> **rank_tracker_workflow**.\n- Find which sources an AI answer cites for a query (AEO) -> **query_fanout_workflow** (open a browser\n session on chatgpt.com or claude.ai FIRST, then run it against that session).\n\n## Notes\n- Bulk / full-site crawls: call \\`extract_site\\` with \\`rotateProxies:true\\` for blocked or rate-limited\n sites. It returns a saved folder/artifact plus a summary, not the full content inline.\n- Browser sessions and media transcription cost credits and take longer — prefer the cheapest tool that\n answers the question (plain search/extract before browser agents).\n- Large results are saved to disk or an artifact and returned as a summary plus a path; read the path for\n full detail rather than expecting the whole payload inline.\n`.trim()\n","import { z } from 'zod'\nimport { DEFAULT_MAPS_PROXY_MODE, DEFAULT_PROXY_MODE } from '../schemas.js'\n\nexport const HarvestPaaInputSchema = {\n query: z.string().min(1).describe('Core search topic only. If the user says \"best hvac company in Denver CO\", use query=\"best hvac company\" and location=\"Denver, CO\". Do not include the location in query when it can be separated.'),\n location: z.string().optional().describe('City, region, or country for geo-targeted results, inferred from the user request when present, e.g. \"Denver, CO\", \"Tokyo, Japan\", \"London, UK\".'),\n maxQuestions: z.number().int().min(1).max(200).default(30).describe('Number of PAA questions to extract. Default 30. Maximum 200. Use 10 for quick probes, 30 for normal research, 100-200 when the user asks for everything/full/deep research. Larger harvests get a longer server time budget (151-200 questions → up to 280s). Credits are charged by extracted question; unused request hold is refunded.'),\n gl: z.string().length(2).default('us').describe('Google country code inferred from location or user language. Examples: United States us, United Kingdom gb, Japan jp, Canada ca, Australia au.'),\n hl: z.string().default('en').describe('Google interface/content language inferred from the user request. Use en unless the user asks for another language or locale.'),\n device: z.enum(['desktop', 'mobile']).default('desktop').describe('SERP device context. Use desktop by default; use mobile only when the user asks for mobile rankings.'),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_PROXY_MODE).describe('Leave unset — routing is automatic (clean egress by default; residential only when a location is given, with fallback). Set \"location\" only to force local-pack targeting.'),\n proxyZip: z.string().regex(/^\\d{5}$/).optional().describe('Optional US ZIP override for residential location proxy targeting. Use only with proxyMode location when the user gives a specific ZIP or city-center targeting needs to be forced.'),\n debug: z.boolean().default(false).describe('Include sanitized browser/session/location diagnostics in the response. Use true when debugging localization, CAPTCHA, or proxy behavior.'),\n}\nexport type HarvestPaaInput = z.infer<ReturnType<typeof z.object<typeof HarvestPaaInputSchema>>>\n\nexport const ExtractUrlInputSchema = {\n url: z.string().url().describe('Public http/https URL to extract. Use this when the user provides one specific page URL.'),\n screenshot: z.boolean().default(false).describe('Also capture a full-page screenshot of the URL. Saved to ~/Downloads/mcp-scraper/screenshots/ and returned inline. Use when the user asks to see or capture the page visually.'),\n screenshotDevice: z.enum(['desktop', 'mobile']).default('desktop').describe('Viewport for screenshot. desktop = 1440×900. mobile = 390×844. Default desktop.'),\n extractBranding: z.boolean().default(false).describe('Extract brand colors, fonts, logo, and favicon using a rendered browser session. Returns colorScheme (light/dark), colors (primary/accent/background/text/heading as hex), fonts (heading/body family names), and assets (logo URL, favicon URL). Use when the user asks about brand colors, site theme, or brand assets.'),\n downloadMedia: z.boolean().default(false).describe('Extract and download all page media (images, video, audio) to ~/Downloads/mcp-scraper/media/. Ad networks, tracking pixels, and noise URLs are filtered automatically. Use when the user asks to download or harvest assets from a page.'),\n mediaTypes: z.array(z.enum(['image', 'video', 'audio'])).default(['image', 'video', 'audio']).describe('Which media types to download. Default all three.'),\n allowLocal: z.boolean().default(false).describe('Allow localhost and private-network URLs. For local development only.'),\n depositToVault: z.boolean().default(false).describe('Also save the full page content into the user\\'s MCP Memory Library vault, server-side. The complete body is stored and embedded for semantic recall WITHOUT passing through this conversation — the tool result only confirms the saved note. Use when the user asks to save/remember/store a page, or to build a knowledge base from scrapes.'),\n vaultName: z.string().trim().min(1).max(120).optional().describe('Optional vault to deposit into. Defaults to the user\\'s personal vault.'),\n}\nexport type ExtractUrlInput = z.infer<ReturnType<typeof z.object<typeof ExtractUrlInputSchema>>>\n\nexport const MapSiteUrlsInputSchema = {\n url: z.string().url().describe('Public website URL or domain to crawl for internal URLs. Use before extract_site when the user asks to audit/map/crawl a site.'),\n maxUrls: z.number().int().min(1).max(10000).optional().describe('Maximum URLs to discover. Use 100 for normal maps, up to 10000 for a full inventory. Large maps (over 500 URLs) write the complete inventory to a local file and return only a summary plus the file path instead of the full list inline.'),\n}\nexport type MapSiteUrlsInput = z.infer<ReturnType<typeof z.object<typeof MapSiteUrlsInputSchema>>>\n\nexport const ExtractSiteInputSchema = {\n url: z.string().url().describe('Public website URL or domain to crawl for page CONTENT across multiple pages (map + scrape). Use when the user wants the content/text/markdown of a site\\'s pages. For a technical SEO audit (issues, link graph, indexability, headings, image weights) use audit_site instead — extract_site returns content only, not analysis.'),\n maxPages: z.number().int().min(1).max(10000).optional().describe('Maximum pages to extract. Use 50 for a normal crawl, up to 10000 for a full-site bulk scrape. Bulk crawls (over 25 pages) switch to folder mode: every page is saved as its own Markdown file in a local folder and the response returns only a summary plus the folder path, so the full content never floods the context window.'),\n rotateProxies: z.boolean().optional().describe('Route page fetches through rotating residential proxies in headful browsers to defeat rate-limiting and bot blocks (403/429). Discovers URLs from the sitemap, fetches in batches with a fresh proxy per batch, retries failures on a new proxy, and automatically parallelizes across the account\\'s concurrency slots. Slower and pricier than the default fetch path, so use only when a site blocks normal crawling.'),\n rotateProxyEvery: z.number().int().min(1).max(100).optional().describe('When rotateProxies is on, how many pages to fetch per browser/proxy before discarding it and minting a fresh one. Default 30. Lower values rotate IPs more aggressively against strict rate limits.'),\n formats: z.array(z.enum(['markdown', 'links', 'json', 'images', 'branding'])).optional().describe('Which data formats to include in the per-page output. markdown=page content as Markdown, links=internal/external link graph, json=structured data/schema, images=per-page image URLs (links only, no downloads), branding=site-level logo/colors/fonts captured once from the homepage (requires a browser, adds time). markdown, links, json, and images are always captured cheaply from the HTML; branding is the only opt-in capture. Defaults to markdown+links when omitted.'),\n}\nexport type ExtractSiteInput = z.infer<ReturnType<typeof z.object<typeof ExtractSiteInputSchema>>>\n\nexport const AuditSiteInputSchema = {\n url: z.string().url().describe('Public website URL or domain to run a full technical SEO audit on. Use when the user asks for a technical audit, SEO audit, site health check, or a Screaming-Frog-style crawl — i.e. they want ANALYSIS (issues, internal link graph, indexability, heading breakdown, image sizes/formats), not just page content. For plain content scraping use extract_site instead.'),\n maxPages: z.number().int().min(1).max(10000).optional().describe('Maximum pages to crawl and audit. Use 50 for a normal audit, up to 10000 for a full-site audit. The audit always writes a folder of analysis files (report.md, issues.json, pages.jsonl, links.jsonl, link-metrics.jsonl, images.jsonl) plus per-page content, and returns a headline summary plus the folder path.'),\n rotateProxies: z.boolean().optional().describe('Route page fetches through rotating residential proxies to defeat rate-limiting and bot blocks (403/429). Slower and pricier than the default fetch path, so use only when a site blocks normal crawling.'),\n rotateProxyEvery: z.number().int().min(1).max(100).optional().describe('When rotateProxies is on, how many pages to fetch per browser/proxy before discarding it and minting a fresh one. Default 30.'),\n}\nexport type AuditSiteInput = z.infer<ReturnType<typeof z.object<typeof AuditSiteInputSchema>>>\n\nexport const YoutubeHarvestInputSchema = {\n mode: z.enum(['search', 'channel']).describe('Use search for topic/keyword requests. Use channel when the user provides @handle, channel ID, or channel URL.'),\n query: z.string().optional().describe('Required when mode is search. The YouTube search topic in the user’s words.'),\n channelHandle: z.string().optional().describe('YouTube channel handle, channel ID, or URL. Examples: @mkbhd, UC..., https://youtube.com/@mkbhd.'),\n maxVideos: z.number().int().min(1).max(500).default(50).describe('Number of videos to return. Default 50, maximum 500. Use 10-25 for quick topic discovery, 50 for normal channel/search harvests, and larger values only when the user asks for full channel/history because large responses consume more context.'),\n}\nexport type YoutubeHarvestInput = z.infer<ReturnType<typeof z.object<typeof YoutubeHarvestInputSchema>>>\n\nexport const YoutubeTranscribeInputSchema = {\n videoId: z.string().min(1).optional().describe('YouTube video ID, e.g. dQw4w9WgXcQ. Use only an ID returned by youtube_harvest or visible in a YouTube URL; do not invent one.'),\n url: z.string().url().optional().describe('Full YouTube URL, e.g. https://www.youtube.com/watch?v=dQw4w9WgXcQ or https://youtu.be/dQw4w9WgXcQ. Use this when the user pasted a URL instead of an ID. Provide videoId or url.'),\n}\nexport type YoutubeTranscribeInput = z.infer<ReturnType<typeof z.object<typeof YoutubeTranscribeInputSchema>>>\n\nexport const FacebookPageIntelInputSchema = {\n pageId: z.string().optional().describe('Facebook advertiser/page ID. Use only a pageId returned by facebook_ad_search/facebook_page_intel or copied from Facebook Ad Library; do not construct one yourself.'),\n libraryId: z.string().optional().describe('Facebook Ad Library archive ID for a known ad or advertiser sample. Use a libraryId returned by facebook_ad_search, or a libraryId/adArchiveId visible in Ad Library.'),\n query: z.string().optional().describe('Advertiser or brand name when pageId/libraryId is not known. One of pageId, libraryId, or query is required.'),\n maxAds: z.number().int().min(1).max(200).default(50).describe('Maximum ads to inspect. Default 50, maximum 200. Prefer 25-50 for focused advertiser scans; use 100-200 only when the user asks for a broad ad archive sweep.'),\n country: z.string().length(2).default('US').describe('Two-letter Ad Library country code. Default US. Examples: US, CA, GB, AU. Infer from the user request when they name a country.'),\n}\nexport type FacebookPageIntelInput = z.infer<ReturnType<typeof z.object<typeof FacebookPageIntelInputSchema>>>\n\nexport const FacebookAdSearchInputSchema = {\n query: z.string().min(1).describe('Advertiser, brand, competitor, niche, or keyword to search in Facebook Ad Library.'),\n country: z.string().length(2).default('US').describe('Two-letter Ad Library country code. Default US. Examples: US, CA, GB, AU.'),\n maxResults: z.number().int().min(1).max(20).default(10).describe('Maximum advertisers to return. Default 10, maximum 20. Prefer tighter search terms over maxing this out.'),\n}\nexport type FacebookAdSearchInput = z.infer<ReturnType<typeof z.object<typeof FacebookAdSearchInputSchema>>>\n\nexport const RedditThreadInputSchema = {\n url: z.string().min(1).describe('A reddit.com thread/post URL (www, old, or new Reddit, or a redd.it link). The service fetches it via old.reddit through a residential proxy and returns the post plus its comment tree.'),\n maxComments: z.number().int().min(1).max(2000).optional().describe('Optional cap on comments returned. Omit to return all captured comments.'),\n}\nexport type RedditThreadInput = z.infer<ReturnType<typeof z.object<typeof RedditThreadInputSchema>>>\n\nexport const FacebookAdTranscribeInputSchema = {\n videoUrl: z.string().url().describe('Direct Facebook CDN video URL from a facebook_page_intel ad result. Do not pass a public Facebook reel/post/share URL here; use facebook_video_transcribe for organic Facebook URLs.'),\n}\nexport type FacebookAdTranscribeInput = z.infer<ReturnType<typeof z.object<typeof FacebookAdTranscribeInputSchema>>>\n\nexport const FacebookVideoTranscribeInputSchema = {\n url: z.string().url().describe('Organic Facebook reel, video, watch, post, or share URL from facebook.com, m.facebook.com, or fb.watch. The tool renders the page, extracts the best matching public Facebook CDN MP4 URL, then transcribes it. Use this when the user pastes a normal Facebook video page URL and asks for the transcript or downloadable MP4.'),\n quality: z.enum(['best', 'hd', 'sd']).default('best').describe('Preferred progressive MP4 quality. Use best by default; hd prefers the highest HD progressive URL; sd forces the SD URL.'),\n}\nexport type FacebookVideoTranscribeInput = z.infer<ReturnType<typeof z.object<typeof FacebookVideoTranscribeInputSchema>>>\n\nexport const GoogleAdsSearchInputSchema = {\n query: z.string().min(1).describe('A domain (e.g. getviktor.com) or advertiser/brand name to look up in the Google Ads Transparency Center. Domains resolve to the advertisers running ads that point to that site.'),\n region: z.string().length(2).default('US').describe('Two-letter region code for where the ads are shown. Default US. Examples: US, CA, GB, AU.'),\n maxResults: z.number().int().min(1).max(20).default(10).describe('Maximum advertisers to return. Default 10, maximum 20.'),\n}\nexport type GoogleAdsSearchInput = z.infer<ReturnType<typeof z.object<typeof GoogleAdsSearchInputSchema>>>\n\nexport const GoogleAdsPageIntelInputSchema = {\n advertiserId: z.string().optional().describe('Google Ads Transparency advertiser ID (starts with AR...). Use one returned by google_ads_search; do not construct one yourself.'),\n domain: z.string().optional().describe('A domain (e.g. getviktor.com) whose primary advertiser to inspect when advertiserId is unknown. One of advertiserId or domain is required.'),\n region: z.string().length(2).default('US').describe('Two-letter region code for where the ads are shown. Default US.'),\n maxAds: z.number().int().min(1).max(200).default(50).describe('Maximum creatives to inspect and hydrate. Default 50, maximum 200. Prefer 25-50 for focused scans.'),\n}\nexport type GoogleAdsPageIntelInput = z.infer<ReturnType<typeof z.object<typeof GoogleAdsPageIntelInputSchema>>>\n\nexport const GoogleAdsTranscribeInputSchema = {\n videoUrl: z.string().url().describe('Direct googlevideo.com playback URL from a google_ads_page_intel video ad result (the videoUrl field). For YouTube-hosted ads use youtube_transcribe with the returned youtubeVideoId instead.'),\n}\nexport type GoogleAdsTranscribeInput = z.infer<ReturnType<typeof z.object<typeof GoogleAdsTranscribeInputSchema>>>\n\nexport const InstagramProfileContentInputSchema = {\n handle: z.string().min(1).optional().describe('Instagram handle, with or without @. Provide handle or url.'),\n url: z.string().url().optional().describe('Instagram profile URL, e.g. https://www.instagram.com/nasaartemis/. Provide handle or url.'),\n profile: z.string().min(1).optional().describe('Optional saved hosted browser profile name to load authenticated Instagram access. If omitted, the server uses its configured default profile when present.'),\n saveProfileChanges: z.boolean().optional().describe('Whether to save browser changes back to the hosted profile. Leave unset unless intentionally updating the saved login session.'),\n maxItems: z.number().int().min(1).max(2000).default(50).describe('Maximum profile grid post/reel/tv URLs to collect. Default 50, maximum 2000. Use higher values only when the user asks for a fuller archive.'),\n maxScrolls: z.number().int().min(0).max(250).default(10).describe('Maximum pagination scroll attempts. Default 10, maximum 250. Increase for long profiles when Instagram continues loading more grid links.'),\n scrollDelayMs: z.number().int().min(250).max(5000).default(1200).describe('Delay after each pagination scroll before collecting newly loaded links. Default 1200ms. Increase to 2000-3000ms when Instagram loads slowly.'),\n stableScrollLimit: z.number().int().min(1).max(10).default(4).describe('Stop after this many consecutive scrolls with no new links or scroll progress. Default 4.'),\n}\nexport type InstagramProfileContentInput = z.infer<ReturnType<typeof z.object<typeof InstagramProfileContentInputSchema>>>\n\nexport const InstagramMediaDownloadInputSchema = {\n url: z.string().url().describe('Instagram post, reel, or tv URL, e.g. https://www.instagram.com/reel/SHORTCODE/. The tool renders the page, extracts text, image metadata, and Instagram CDN media tracks.'),\n profile: z.string().min(1).optional().describe('Optional saved hosted browser profile name to load authenticated Instagram access. If omitted, the server uses its configured default profile when present.'),\n saveProfileChanges: z.boolean().optional().describe('Whether to save browser changes back to the hosted profile. Leave unset unless intentionally updating the saved login session.'),\n mediaTypes: z.array(z.enum(['image', 'video', 'audio'])).default(['image', 'video', 'audio']).describe('Which media types to download when downloadMedia is true. Reels commonly expose separate video-only and audio-only MP4 tracks.'),\n downloadMedia: z.boolean().default(true).describe('Download extracted text/media files to the MCP Scraper output directory when the API server can write files. Always returns extracted media URLs even when false.'),\n downloadAllTracks: z.boolean().default(false).describe('Download every captured Instagram MP4 track instead of only the selected best video and audio tracks. Use false by default to avoid duplicate bitrates.'),\n includeTranscript: z.boolean().default(false).describe('Transcribe the selected audio track when available. This adds transcription cost and may take longer.'),\n mux: z.boolean().default(true).describe('When video and audio tracks are downloaded separately, try to mux them into a single MP4 if ffmpeg is available. Returns separate tracks when muxing is unavailable.'),\n}\nexport type InstagramMediaDownloadInput = z.infer<ReturnType<typeof z.object<typeof InstagramMediaDownloadInputSchema>>>\n\nexport const MapsPlaceIntelInputSchema = {\n businessName: z.string().min(1).describe('Business name only. If user says \"Elite Roofing Denver CO\", use businessName=\"Elite Roofing\" and location=\"Denver, CO\".'),\n location: z.string().min(1).describe('City/region/country where the business should be searched, e.g. \"Denver, CO\". Infer from the user request when possible.'),\n gl: z.string().length(2).default('us').describe('Google country code inferred from location.'),\n hl: z.string().length(2).default('en').describe('Language inferred from user request.'),\n includeReviews: z.boolean().default(false).describe('Whether to fetch individual review cards. Use true when the user asks for reviews, customer pain, complaints, praise, themes, or review evidence.'),\n maxReviews: z.number().int().min(1).max(500).default(50).describe('Max review cards to return when includeReviews is true. Default 50, maximum 500. Use 50 for normal review analysis and larger values only for deep review mining.'),\n}\nexport type MapsPlaceIntelInput = z.infer<ReturnType<typeof z.object<typeof MapsPlaceIntelInputSchema>>>\n\nexport const MapsSearchInputSchema = {\n query: z.string().min(1).describe('Business category, niche, keyword, or search term. If the user says \"roofers in Denver CO\", use query=\"roofers\" and location=\"Denver, CO\". Do not put the location here when it can be separated.'),\n location: z.string().optional().describe('City, region, country, or service area for the Maps search, e.g. \"Denver, CO\". Infer from the user request when present.'),\n gl: z.string().length(2).default('us').describe('Google country code inferred from location.'),\n hl: z.string().length(2).default('en').describe('Language inferred from user request.'),\n maxResults: z.number().int().min(1).max(50).default(10).describe('Number of Google Maps business/profile candidates to return. Default 10. Maximum 50. Use 10 unless the user asks for more.'),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_MAPS_PROXY_MODE).describe('Proxy targeting mode. Maps defaults to location so local market searches get city/state residential proxy targeting and rotation. Use configured to force the service proxy without city/ZIP targeting, and none only for local direct-network debugging.'),\n proxyZip: z.string().regex(/^\\d{5}$/).optional().describe('Optional US ZIP override for residential location proxy targeting. Use when the user gives a specific ZIP or city-center ZIP.'),\n debug: z.boolean().default(false).describe('Include sanitized browser/proxy diagnostics when debugging Maps localization, CAPTCHA, or proxy behavior.'),\n}\nexport type MapsSearchInput = z.infer<ReturnType<typeof z.object<typeof MapsSearchInputSchema>>>\n\nexport const DirectoryWorkflowInputSchema = {\n query: z.string().min(1).describe('Business category, niche, or keyword to search on Google Maps for every selected market, e.g. roofers, dentists, med spas. Do not include the city here.'),\n state: z.string().min(2).default('TN').describe('US state abbreviation or state name used to select Census places, e.g. TN or Tennessee.'),\n minPopulation: z.number().int().min(0).default(100000).describe('Minimum Census place population for market selection. Use 100000 for \"cities above 100k population\".'),\n populationYear: z.number().int().min(2020).max(2025).default(2025).describe('Census population estimate year from the 2020-2025 Population Estimates Program city/place dataset.'),\n maxCities: z.number().int().min(1).max(100).default(25).describe('Maximum number of markets to process after sorting by population descending.'),\n maxResultsPerCity: z.number().int().min(1).max(50).default(50).describe('Google Maps business/profile candidates to collect for each city. Maximum 50.'),\n concurrency: z.number().int().min(1).max(5).default(5).describe('How many city Maps searches to run in parallel. Use 5 for broad directory batches unless debugging.'),\n includeZipGroups: z.boolean().default(true).describe('Attach ZIP groups from a configured US ZIPS CSV when available. Set MCP_SCRAPER_USZIPS_CSV_PATH on the API server or pass usZipsCsvPath in local/test mode.'),\n usZipsCsvPath: z.string().optional().describe('Local/test-only path to a US ZIPS CSV with state_abbr, zipcode, county, city columns, such as Lead Magician tools/analytics/data/uszips.csv. Deployed APIs should use MCP_SCRAPER_USZIPS_CSV_PATH instead.'),\n saveCsv: z.boolean().default(true).describe('Save a directory-ready CSV to the MCP Scraper output directory and return its path. CSV rows include source_location, result_position, business_name, review_stars, review_count, category, address, phone, hours_status, website_url, directions_url, place_url, CID fields, population, and ZIP groups.'),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_MAPS_PROXY_MODE).describe('Proxy targeting mode for every city Maps search. Maps workflows default to location so each city can use city/state or ZIP-group residential proxy targeting. Use configured to force the service proxy without city/ZIP targeting, and none only for local direct-network debugging.'),\n proxyZip: z.string().regex(/^\\d{5}$/).optional().describe('Optional ZIP override for proxy targeting. Normally omit it so each city can use its ZIP group or city/state location.'),\n debug: z.boolean().default(false).describe('Include sanitized browser/proxy diagnostics in each Maps browser session when supported.'),\n}\nexport type DirectoryWorkflowInput = z.infer<ReturnType<typeof z.object<typeof DirectoryWorkflowInputSchema>>>\n\nexport const RankTrackerModeSchema = z.enum(['maps', 'organic', 'ai_overview', 'paa'])\nexport type RankTrackerMode = z.infer<typeof RankTrackerModeSchema>\n\nexport const RankTrackerBlueprintInputSchema = {\n projectName: z.string().min(1).optional().describe('Optional name for the rank tracker project, client, or campaign.'),\n targetDomain: z.string().min(1).optional().describe('Primary domain to track in organic results, AI Overview citations, and PAA sources, e.g. example.com.'),\n targetBusinessName: z.string().min(1).optional().describe('Primary Google Business Profile or brand/business name to match in Maps results. Required for reliable Maps rank tracking.'),\n trackingModes: z.array(RankTrackerModeSchema).min(1).max(4).default(['maps', 'organic', 'ai_overview', 'paa']).describe('Rank tracker surfaces to build. maps uses directory_workflow/maps_search. organic uses search_serp. ai_overview uses search_serp/harvest_paa. paa uses harvest_paa source presence.'),\n keywords: z.array(z.string().min(1)).max(200).default([]).describe('Seed keywords or service queries to track. Leave empty when the downstream AI should create the keyword table from user input.'),\n locations: z.array(z.string().min(1)).max(100).default([]).describe('Markets, cities, ZIPs, or service areas to track. Use city/state strings like Denver, CO for localized SERP and Maps checks.'),\n competitors: z.array(z.string().min(1)).max(100).default([]).describe('Optional competitor domains or business names to persist as comparison targets.'),\n database: z.enum(['postgres', 'neon', 'supabase', 'sqlite', 'mysql']).default('postgres').describe('Database family the downstream AI should target when generating migrations.'),\n scheduleCadence: z.enum(['daily', 'weekly', 'monthly', 'custom']).default('weekly').describe('Default recurring rank check cadence for the generated cron/heartbeat plan.'),\n customCron: z.string().min(1).optional().describe('Cron expression to use when scheduleCadence is custom.'),\n timezone: z.string().min(1).default('UTC').describe('IANA timezone for scheduled rank checks, e.g. America/Denver.'),\n includeCron: z.boolean().default(true).describe('Include a cron or heartbeat worker plan. Keep true for production rank trackers.'),\n includeDashboard: z.boolean().default(true).describe('Include dashboard/reporting requirements in the generated prompt.'),\n includeAlerts: z.boolean().default(true).describe('Include alert rules for rank movement and SERP feature gains/losses.'),\n notes: z.string().max(4000).optional().describe('Extra product, client, stack, or hosting requirements to include in the implementation prompt.'),\n}\nexport type RankTrackerBlueprintInput = z.infer<ReturnType<typeof z.object<typeof RankTrackerBlueprintInputSchema>>>\n\nconst NullableString = z.string().nullable()\n\nconst MapsSearchAttemptOutput = z.object({\n attemptNumber: z.number().int().min(1),\n maxAttempts: z.number().int().min(1),\n status: z.enum(['ok', 'failed']),\n outcome: z.string(),\n willRetry: z.boolean(),\n durationMs: z.number().int().min(0),\n resultCount: z.number().int().min(0),\n error: NullableString,\n proxyMode: z.enum(['location', 'configured', 'none']),\n proxyResolutionSource: z.enum(['disabled', 'location_reused', 'location_created', 'configured_fallback', 'unavailable']).nullable(),\n proxyIdSuffix: NullableString,\n proxyTargetLevel: z.enum(['zip', 'city', 'state']).nullable(),\n proxyTargetLocation: NullableString,\n proxyTargetZip: NullableString,\n browserSessionIdSuffix: NullableString,\n observedIp: NullableString,\n observedCity: NullableString,\n observedRegion: NullableString,\n})\n\nexport const MapsSearchOutputSchema = {\n query: z.string(),\n location: z.string().nullable(),\n searchQuery: z.string(),\n searchUrl: z.string().url(),\n extractedAt: z.string(),\n requestedMaxResults: z.number().int().min(1).max(50),\n resultCount: z.number().int().min(0).max(50),\n results: z.array(z.object({\n position: z.number().int().min(1),\n name: z.string(),\n placeUrl: z.string().url(),\n cid: NullableString,\n cidDecimal: NullableString,\n rating: NullableString,\n reviewCount: NullableString,\n category: NullableString,\n address: NullableString,\n phone: NullableString,\n hoursStatus: NullableString,\n websiteUrl: NullableString,\n directionsUrl: NullableString,\n metadata: z.array(z.string()),\n })),\n attempts: z.array(MapsSearchAttemptOutput),\n durationMs: z.number().int().min(0),\n}\n\nconst DirectoryMapsBusinessOutput = z.object({\n position: z.number().int().min(1),\n name: z.string(),\n placeUrl: z.string().url(),\n cid: NullableString,\n cidDecimal: NullableString,\n rating: NullableString,\n reviewCount: NullableString,\n category: NullableString,\n address: NullableString,\n phone: NullableString,\n hoursStatus: NullableString,\n websiteUrl: NullableString,\n directionsUrl: NullableString,\n metadata: z.array(z.string()),\n})\n\nexport const DirectoryWorkflowOutputSchema = {\n query: z.string(),\n state: z.string(),\n minPopulation: z.number().int().min(0),\n populationYear: z.number().int().min(2020).max(2025),\n maxResultsPerCity: z.number().int().min(1).max(50),\n concurrency: z.number().int().min(1).max(5),\n censusSourceUrl: z.string().url(),\n usZipsSourcePath: NullableString,\n warnings: z.array(z.string()),\n extractedAt: z.string(),\n selectedCityCount: z.number().int().min(0),\n totalResultCount: z.number().int().min(0),\n csvPath: NullableString,\n cities: z.array(z.object({\n city: z.string(),\n state: z.string(),\n location: z.string(),\n cityKey: z.string(),\n censusName: z.string(),\n population: z.number().int().min(0),\n populationYear: z.number().int().min(2020).max(2025),\n zips: z.array(z.string()),\n counties: z.array(z.string()),\n status: z.enum(['ok', 'empty', 'failed']),\n error: NullableString,\n resultCount: z.number().int().min(0),\n durationMs: z.number().int().min(0),\n attempts: z.array(MapsSearchAttemptOutput),\n results: z.array(DirectoryMapsBusinessOutput),\n })),\n durationMs: z.number().int().min(0),\n}\n\nconst RankTrackerToolPlanOutput = z.object({\n tool: z.string(),\n purpose: z.string(),\n})\n\nconst RankTrackerTableOutput = z.object({\n name: z.string(),\n purpose: z.string(),\n keyColumns: z.array(z.string()),\n})\n\nconst RankTrackerCronJobOutput = z.object({\n name: z.string(),\n purpose: z.string(),\n modes: z.array(RankTrackerModeSchema),\n recommendedTools: z.array(z.string()),\n})\n\nexport const RankTrackerBlueprintOutputSchema = {\n projectName: z.string(),\n targetDomain: NullableString,\n targetBusinessName: NullableString,\n trackingModes: z.array(RankTrackerModeSchema),\n database: z.string(),\n recommendedTools: z.array(RankTrackerToolPlanOutput),\n tables: z.array(RankTrackerTableOutput),\n cron: z.object({\n enabled: z.boolean(),\n cadence: z.string(),\n expression: z.string(),\n timezone: z.string(),\n jobs: z.array(RankTrackerCronJobOutput),\n }),\n metrics: z.array(z.string()),\n implementationPrompt: z.string(),\n}\n\nconst OrganicResultOutput = z.object({\n position: z.number().int(),\n title: z.string(),\n url: z.string(),\n domain: z.string(),\n snippet: NullableString,\n})\n\nconst AiOverviewOutput = z.object({\n detected: z.boolean(),\n text: NullableString,\n shareUrl: NullableString.optional(),\n}).nullable()\n\nconst EntityIdsOutput = z.object({\n entities: z.array(z.object({\n name: z.string(),\n kgId: z.string().nullable(),\n cid: z.string().nullable(),\n gcid: z.string().nullable(),\n })).describe('Each entity actually named on the page, with whichever of its kgId/cid/gcid were found — the linked view. kgIds/cids/gcids below are the same IDs as flat deduplicated lists, without the name link, kept for backward compatibility.'),\n kgIds: z.array(z.string()),\n cids: z.array(z.string()),\n gcids: z.array(z.string()),\n}).nullable()\n\nexport const HarvestPaaOutputSchema = {\n query: z.string(),\n location: NullableString,\n questionCount: z.number().int().min(0),\n completionStatus: NullableString,\n questions: z.array(z.object({\n question: z.string(),\n answer: NullableString,\n sourceTitle: NullableString,\n sourceSite: NullableString,\n })),\n organicResults: z.array(OrganicResultOutput),\n aiOverview: AiOverviewOutput,\n entityIds: EntityIdsOutput,\n durationMs: z.number().min(0).nullable(),\n}\n\nexport const SearchSerpOutputSchema = {\n query: z.string(),\n location: NullableString,\n organicResults: z.array(OrganicResultOutput),\n localPack: z.array(z.object({\n position: z.number().int(),\n name: z.string(),\n rating: NullableString,\n reviewCount: NullableString,\n websiteUrl: NullableString,\n })),\n aiOverview: AiOverviewOutput,\n entityIds: EntityIdsOutput,\n}\n\nexport const ExtractUrlOutputSchema = {\n url: z.string(),\n title: NullableString,\n headings: z.array(z.object({\n level: z.number().int(),\n text: z.string(),\n })),\n schemaBlockCount: z.number().int().min(0),\n entityName: NullableString,\n entityTypes: z.array(z.string()),\n napScore: z.number().nullable(),\n missingSchemaFields: z.array(z.string()),\n screenshotSaved: NullableString,\n memory: z.object({\n deposited: z.boolean(),\n vault: z.string().optional(),\n noteId: z.string().optional(),\n path: z.string().optional(),\n chunks: z.number().int().optional(),\n fileUrl: z.string().optional(),\n fileExpiresAt: z.string().optional(),\n error: z.string().optional(),\n }).optional(),\n}\n\nexport const ExtractSiteOutputSchema = {\n url: z.string(),\n pageCount: z.number().int().min(0),\n pages: z.array(z.object({\n url: z.string(),\n title: NullableString,\n schemaTypes: z.array(z.string()),\n })),\n durationMs: z.number().min(0),\n}\n\nexport const AuditSiteOutputSchema = {\n url: z.string(),\n pageCount: z.number().int().min(0),\n durationMs: z.number().min(0),\n bulkFolder: z.string().nullable(),\n issues: z.record(z.string(), z.number()),\n images: z.object({\n unique: z.number().int().min(0),\n totalBytes: z.number().min(0),\n over100kb: z.number().int().min(0),\n legacyFormat: z.number().int().min(0),\n }),\n links: z.object({\n internal: z.number().int().min(0),\n external: z.number().int().min(0),\n orphans: z.number().int().min(0),\n brokenInternal: z.number().int().min(0),\n externalDomains: z.number().int().min(0),\n }),\n}\n\nexport const MapsPlaceIntelOutputSchema = {\n name: z.string(),\n rating: NullableString,\n reviewCount: NullableString,\n category: NullableString,\n address: NullableString,\n phone: NullableString,\n website: NullableString,\n hoursSummary: NullableString,\n bookingUrl: NullableString,\n kgmid: NullableString,\n cidDecimal: NullableString,\n cidUrl: NullableString,\n lat: z.number().nullable(),\n lng: z.number().nullable(),\n reviewsStatus: z.string(),\n reviewsCollected: z.number().int().min(0),\n reviewTopics: z.array(z.object({\n label: z.string(),\n count: z.string(),\n })),\n}\n\nexport const CreditsInfoOutputSchema = {\n balanceCredits: z.number().nullable(),\n matchedCost: z.object({\n label: z.string(),\n credits: z.number(),\n unit: z.string(),\n notes: NullableString,\n }).nullable(),\n costs: z.array(z.object({\n key: z.string(),\n label: z.string(),\n credits: z.number(),\n unit: z.string(),\n notes: NullableString,\n })),\n ledger: z.array(z.object({\n createdAt: z.string(),\n operation: z.string(),\n credits: z.number(),\n description: NullableString,\n })),\n concurrency: z.object({\n currentExtraSlots: z.number().int().min(0),\n currentLimit: z.number().int().min(1),\n hasSubscription: z.boolean(),\n upgrade: z.object({\n product: z.string(),\n priceLabel: z.string(),\n unitAmountUsd: z.number(),\n currency: z.string(),\n interval: z.string(),\n billingUrl: z.string().url(),\n terminalCommand: z.string(),\n terminalCommandWithApiKeyEnv: z.string(),\n }),\n }).nullable(),\n}\n\nexport const MapSiteUrlsOutputSchema = {\n startUrl: z.string(),\n totalFound: z.number().int().min(0),\n truncated: z.boolean(),\n okCount: z.number().int().min(0),\n redirectCount: z.number().int().min(0),\n brokenCount: z.number().int().min(0),\n urls: z.array(z.object({\n url: z.string(),\n status: z.number().int().nullable(),\n })),\n durationMs: z.number().min(0),\n}\n\nexport const YoutubeHarvestOutputSchema = {\n mode: z.string(),\n videoCount: z.number().int().min(0),\n channel: z.object({\n title: NullableString,\n subscriberCount: NullableString,\n }).nullable(),\n videos: z.array(z.object({\n videoId: z.string(),\n title: z.string(),\n channelName: NullableString,\n views: NullableString,\n duration: NullableString,\n url: NullableString,\n })),\n}\n\nexport const FacebookAdSearchOutputSchema = {\n query: z.string(),\n advertiserCount: z.number().int().min(0),\n advertisers: z.array(z.object({\n name: NullableString,\n pageId: NullableString,\n pageUrl: NullableString,\n adCount: z.number().int().nullable(),\n libraryId: NullableString,\n sampleLibraryId: NullableString,\n })),\n}\n\nexport const RedditThreadOutputSchema = {\n sourceUrl: NullableString,\n oldRedditUrl: NullableString,\n title: NullableString,\n author: NullableString,\n score: NullableString,\n postBody: NullableString,\n numComments: z.number().int().min(0),\n comments: z.array(z.object({\n author: NullableString,\n score: NullableString,\n depth: z.number().int().min(0),\n body: z.string(),\n })),\n}\n\nexport const FacebookPageIntelOutputSchema = {\n advertiserName: NullableString,\n totalAds: z.number().int().min(0),\n activeCount: z.number().int().min(0),\n videoCount: z.number().int().min(0),\n imageCount: z.number().int().min(0),\n ads: z.array(z.object({\n libraryId: NullableString,\n status: NullableString,\n creativeType: NullableString,\n primaryText: NullableString,\n headline: NullableString,\n cta: NullableString,\n startDate: NullableString,\n landingUrl: NullableString,\n domain: NullableString,\n videoUrl: NullableString,\n imageUrl: NullableString,\n videoPoster: NullableString,\n variations: z.number().int().nullable(),\n })),\n}\n\nexport const GoogleAdsSearchOutputSchema = {\n query: z.string(),\n region: z.string(),\n advertiserCount: z.number().int().min(0),\n advertisers: z.array(z.object({\n advertiserId: NullableString,\n name: NullableString,\n domain: NullableString,\n approxAdCount: z.number().int().nullable(),\n detailUrl: NullableString,\n })),\n}\n\nexport const GoogleAdsPageIntelOutputSchema = {\n advertiserId: NullableString,\n advertiserName: NullableString,\n domain: NullableString,\n region: z.string(),\n totalCreatives: z.number().int().min(0),\n videoCount: z.number().int().min(0),\n imageCount: z.number().int().min(0),\n textCount: z.number().int().min(0),\n ads: z.array(z.object({\n creativeId: NullableString,\n advertiserId: NullableString,\n format: NullableString,\n lastShown: NullableString,\n detailUrl: NullableString,\n landingDomain: NullableString,\n imageUrls: z.array(z.string()),\n youtubeVideoId: NullableString,\n videoUrl: NullableString,\n variations: z.number().int().nullable(),\n })),\n}\n\nexport const FacebookVideoTranscribeOutputSchema = {\n sourceUrl: z.string().url(),\n pageUrl: z.string().url(),\n videoId: NullableString,\n ownerName: NullableString,\n selectedQuality: z.string(),\n bitrate: z.number().int().nullable(),\n videoDurationSec: z.number().nullable(),\n videoUrl: z.string().url(),\n wordCount: z.number().int().min(0),\n chunkCount: z.number().int().min(0),\n transcriptText: z.string(),\n chunks: z.array(z.object({\n startSec: z.number(),\n endSec: z.number(),\n text: z.string(),\n })),\n}\n\nconst TranscriptChunkOutput = z.object({\n startSec: z.number(),\n endSec: z.number(),\n text: z.string(),\n})\n\nconst InstagramBrowserOutput = z.object({\n mode: z.literal('hosted'),\n requestedMode: z.literal('hosted'),\n profileName: NullableString,\n profileSource: z.literal('hosted'),\n profileDirConfigured: z.boolean(),\n executablePathConfigured: z.boolean(),\n})\n\nconst InstagramPaginationOutput = z.object({\n maxItems: z.number().int().min(1).max(2000),\n maxScrolls: z.number().int().min(0).max(250),\n attemptedScrolls: z.number().int().min(0),\n stableScrolls: z.number().int().min(0),\n stableScrollLimit: z.number().int().min(1).max(10),\n scrollDelayMs: z.number().int().min(250).max(5000),\n reachedMaxItems: z.boolean(),\n reachedReportedPostCount: z.boolean(),\n finalScrollHeight: z.number().int().nullable(),\n stoppedReason: z.enum(['max_items', 'reported_post_count', 'stable_scrolls', 'max_scrolls', 'no_scrolls']),\n stages: z.array(z.object({\n stage: z.string(),\n itemCount: z.number().int().min(0),\n addedCount: z.number().int().min(0),\n scrollY: z.number().nullable(),\n scrollHeight: z.number().nullable(),\n })),\n})\n\nexport const InstagramProfileContentOutputSchema = {\n handle: z.string(),\n profileUrl: z.string().url(),\n pageUrl: z.string().url(),\n browser: InstagramBrowserOutput,\n profileName: NullableString,\n reportedPostCount: z.number().int().nullable(),\n reportedPostCountText: NullableString,\n followerCountText: NullableString,\n followingCountText: NullableString,\n collectedContentCount: z.number().int().min(0),\n typeCounts: z.object({\n post: z.number().int().min(0),\n reel: z.number().int().min(0),\n tv: z.number().int().min(0),\n }),\n pagination: InstagramPaginationOutput,\n limited: z.boolean(),\n limitations: z.array(z.string()),\n items: z.array(z.object({\n url: z.string().url(),\n type: z.enum(['post', 'reel', 'tv']),\n shortcode: z.string(),\n anchorText: NullableString,\n firstSeenStage: z.string(),\n })),\n}\n\nconst InstagramMediaTrackOutput = z.object({\n url: z.string().url(),\n streamType: z.enum(['video', 'audio', 'unknown']),\n bitrate: z.number().int().nullable(),\n durationSec: z.number().nullable(),\n vencodeTag: NullableString,\n width: z.number().int().nullable(),\n height: z.number().int().nullable(),\n})\n\nconst InstagramDownloadOutput = z.object({\n kind: z.enum(['text', 'image', 'video', 'audio', 'muxed_video']),\n url: z.string().url().nullable(),\n savedPath: NullableString,\n sizeBytes: z.number().int().nullable(),\n mimeType: NullableString,\n error: NullableString,\n})\n\nexport const InstagramMediaDownloadOutputSchema = {\n sourceUrl: z.string().url(),\n pageUrl: z.string().url(),\n browser: InstagramBrowserOutput,\n type: z.enum(['post', 'reel', 'tv']).nullable(),\n shortcode: NullableString,\n ownerName: NullableString,\n caption: NullableString,\n imageUrl: z.string().url().nullable(),\n trackCount: z.number().int().min(0),\n selectedVideoTrack: InstagramMediaTrackOutput.nullable(),\n selectedAudioTrack: InstagramMediaTrackOutput.nullable(),\n downloads: z.array(InstagramDownloadOutput),\n outputDir: NullableString,\n warnings: z.array(z.string()),\n limitations: z.array(z.string()),\n transcript: z.object({\n wordCount: z.number().int().min(0),\n chunkCount: z.number().int().min(0),\n durationMs: z.number().nullable(),\n transcriptText: z.string(),\n chunks: z.array(TranscriptChunkOutput),\n }).nullable(),\n}\n\nexport const YoutubeTranscribeOutputSchema = {\n videoId: NullableString,\n url: NullableString,\n wordCount: z.number().int().min(0),\n chunkCount: z.number().int().min(0),\n durationMs: z.number().nullable(),\n transcriptText: z.string(),\n chunks: z.array(TranscriptChunkOutput),\n resolvedInputs: z.object({\n videoId: NullableString,\n url: NullableString,\n }),\n}\n\nexport const FacebookAdTranscribeOutputSchema = {\n videoUrl: z.string().url(),\n wordCount: z.number().int().min(0),\n chunkCount: z.number().int().min(0),\n durationMs: z.number().nullable(),\n transcriptText: z.string(),\n chunks: z.array(TranscriptChunkOutput),\n resolvedInputs: z.object({\n videoUrl: z.string().url(),\n }),\n}\n\nexport const GoogleAdsTranscribeOutputSchema = {\n videoUrl: z.string().url(),\n wordCount: z.number().int().min(0),\n chunkCount: z.number().int().min(0),\n durationMs: z.number().nullable(),\n transcriptText: z.string(),\n chunks: z.array(TranscriptChunkOutput),\n resolvedInputs: z.object({\n videoUrl: z.string().url(),\n }),\n}\n\nexport const CaptureSerpSnapshotOutputSchema = {\n schemaVersion: z.literal('serp-intelligence.capture.v1'),\n status: z.string(),\n query: NullableString,\n location: NullableString,\n capturedAt: NullableString,\n resultCount: z.number().int().min(0).nullable(),\n snapshotId: NullableString,\n resolvedInputs: z.record(z.unknown()),\n artifacts: z.array(z.record(z.unknown())),\n diagnostics: z.record(z.unknown()).nullable(),\n providerPayload: z.record(z.unknown()),\n}\n\nexport const CaptureSerpPageSnapshotsOutputSchema = {\n schemaVersion: z.literal('serp-intelligence.page-snapshots.v1'),\n status: z.string(),\n count: z.number().int().min(0),\n failedCount: z.number().int().min(0),\n captures: z.array(z.record(z.unknown())),\n resolvedInputs: z.record(z.unknown()),\n diagnostics: z.record(z.unknown()).nullable(),\n providerPayload: z.record(z.unknown()),\n}\n\nexport const CreditsInfoInputSchema = {\n item: z.string().optional().describe('Optional tool, action, or feature to look up, e.g. \"maps reviews\", \"extract_url\", \"YouTube transcription\", or \"concurrency\"'),\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 WorkflowIdSchema = z.enum([\n 'directory',\n 'get-leads',\n 'agent-packet',\n 'local-competitive-audit',\n 'map-comparison',\n 'serp-comparison',\n 'paa-expansion-brief',\n 'ai-overview-language',\n])\nexport type WorkflowId = z.infer<typeof WorkflowIdSchema>\n\nexport const WorkflowListInputSchema = {\n includeRecipes: z.boolean().default(true).describe('Include high-level AI-facing recipes such as market analysis, ICP research, forum/review research, brand design briefings, CRO audits, positioning briefs, content gaps, and AI search visibility audits.'),\n}\nexport type WorkflowListInput = z.infer<ReturnType<typeof z.object<typeof WorkflowListInputSchema>>>\n\nexport const WorkflowSuggestInputSchema = {\n goal: z.string().min(1).describe('The user goal or job to route, e.g. \"market analysis for roofers in Tennessee\", \"ICP research for med spas\", \"CRO audit for this URL\", or \"brand design briefing\".'),\n query: z.string().optional().describe('Business category, niche, or Maps query when known.'),\n keyword: z.string().optional().describe('Search keyword, audience problem, or content topic when known.'),\n domain: z.string().optional().describe('Target domain or brand domain when known.'),\n url: z.string().url().optional().describe('Target URL when the workflow should inspect a specific page.'),\n location: z.string().optional().describe('City/region/country for localized research, e.g. Denver, CO.'),\n state: z.string().optional().describe('US state abbreviation or name for state-wide market research.'),\n maxSuggestions: z.number().int().min(1).max(8).default(3).describe('Number of matching workflow recipes to return.'),\n}\nexport type WorkflowSuggestInput = z.infer<ReturnType<typeof z.object<typeof WorkflowSuggestInputSchema>>>\n\nexport const WorkflowRunInputSchema = {\n workflowId: WorkflowIdSchema.describe('Workflow to run: directory, get-leads, agent-packet, local-competitive-audit, map-comparison, serp-comparison, paa-expansion-brief, ai-overview-language. Use only these values; call workflow_list or workflow_suggest first when unsure.'),\n input: z.record(z.unknown()).default({}).describe('Workflow-specific input object. Examples: get-leads uses {query, location, maxResults?, enrichWebsites?, hydrateReviewCounts?}; agent-packet uses {keyword, domain?, location?, maxQuestions?}; local-competitive-audit uses {query, state, minPopulation?, maxCities?, maxResultsPerCity?, hydrateTop?, maxReviews?}; serp-comparison uses {keyword, domain?, url?, location?, extractTop?}.'),\n webhookUrl: z.string().url().optional().describe('Optional HTTPS webhook to receive the completed hosted workflow run event.'),\n}\nexport type WorkflowRunInput = z.infer<ReturnType<typeof z.object<typeof WorkflowRunInputSchema>>>\n\nexport const WorkflowStepInputSchema = {\n runId: z.string().min(1).describe('Workflow run id returned by workflow_run, workflow_step, or workflow_status. Use only a returned runId; do not construct one yourself. Advances the run by exactly one step (one logical leg, e.g. one live harvest).'),\n}\nexport type WorkflowStepInput = z.infer<ReturnType<typeof z.object<typeof WorkflowStepInputSchema>>>\n\nexport const WorkflowStatusInputSchema = {\n runId: z.string().min(1).describe('Workflow run id returned by workflow_run, workflow_step, or workflow_status. Use only a returned runId; do not construct one yourself.'),\n}\nexport type WorkflowStatusInput = z.infer<ReturnType<typeof z.object<typeof WorkflowStatusInputSchema>>>\n\nexport const WorkflowArtifactReadInputSchema = {\n runId: z.string().min(1).describe('Workflow run id returned by workflow_run, workflow_step, or workflow_status. Use only a returned runId; do not construct one yourself.'),\n artifactId: z.string().min(1).describe('Artifact id from the run artifact list returned by workflow_run, workflow_step, or workflow_status. Use only a returned artifactId; do not construct one yourself.'),\n maxBytes: z.number().int().min(1_000).max(1_000_000).default(200_000).describe('Maximum bytes of artifact text to return inline. Use lower values for large CSV/JSON artifacts; call again with the downloadUrl if needed outside MCP.'),\n}\nexport type WorkflowArtifactReadInput = z.infer<ReturnType<typeof z.object<typeof WorkflowArtifactReadInputSchema>>>\n\nconst WorkflowRecipeOutput = z.object({\n id: z.string(),\n title: z.string(),\n description: z.string(),\n primaryWorkflowId: z.string().nullable(),\n recommendedTools: z.array(z.string()),\n requiredInputs: z.array(z.string()),\n optionalInputs: z.array(z.string()),\n produces: z.array(z.string()),\n runHint: z.string(),\n})\n\nconst WorkflowDefinitionOutput = z.object({\n id: z.string(),\n title: z.string(),\n description: z.string(),\n})\n\nconst WorkflowArtifactOutput = z.record(z.unknown())\n\nexport const WorkflowListOutputSchema = {\n workflows: z.array(WorkflowDefinitionOutput),\n recipes: z.array(WorkflowRecipeOutput),\n}\n\nexport const WorkflowSuggestOutputSchema = {\n goal: z.string(),\n suggestions: z.array(WorkflowRecipeOutput),\n}\n\nexport const WorkflowRunOutputSchema = {\n workflowId: z.string(),\n input: z.record(z.unknown()),\n run: z.record(z.unknown()).optional(),\n summary: z.record(z.unknown()).optional(),\n step: z.record(z.unknown()).optional(),\n nextStep: z.record(z.unknown()).nullable().optional(),\n done: z.boolean().optional(),\n artifacts: z.array(WorkflowArtifactOutput),\n}\n\nexport const WorkflowStepOutputSchema = {\n runId: z.string(),\n run: z.record(z.unknown()).optional(),\n summary: z.record(z.unknown()).nullable().optional(),\n step: z.record(z.unknown()).optional(),\n nextStep: z.record(z.unknown()).nullable().optional(),\n done: z.boolean(),\n artifacts: z.array(WorkflowArtifactOutput),\n}\n\nexport const WorkflowStatusOutputSchema = {\n run: z.record(z.unknown()).optional(),\n artifacts: z.array(WorkflowArtifactOutput),\n}\n\nexport const WorkflowArtifactReadOutputSchema = {\n runId: z.string(),\n artifactId: z.string(),\n contentType: z.string(),\n bytes: z.number().int().min(0),\n truncated: z.boolean(),\n text: z.string(),\n}\n\nexport const SearchSerpInputSchema = {\n query: z.string().min(1).describe('Core search topic only. Separate location when possible. If user says \"best dentist in Brooklyn NY serp\", use query=\"best dentist\" and location=\"Brooklyn, NY\".'),\n location: z.string().optional().describe('City, region, or country for geo-targeted results, inferred from user request when present.'),\n gl: z.string().length(2).default('us').describe('Google country code inferred from location or user language.'),\n hl: z.string().default('en').describe('Google interface/content language inferred from user request.'),\n device: z.enum(['desktop', 'mobile']).default('desktop').describe('SERP device context. Use desktop by default; use mobile only when the user asks for mobile rankings.'),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_PROXY_MODE).describe('Leave unset — routing is automatic. Set \"location\" only to force local-pack targeting.'),\n proxyZip: z.string().regex(/^\\d{5}$/).optional().describe('Optional US ZIP override for residential location proxy targeting. Use only with proxyMode location when the user gives a specific ZIP or city-center targeting needs to be forced.'),\n debug: z.boolean().default(false).describe('Include sanitized browser/session/location diagnostics in the response. Use true when debugging localization, CAPTCHA, or proxy behavior.'),\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\nexport const CaptureSerpSnapshotInputSchema = {\n query: z.string().min(1).describe('Core search query to capture as a structured SERP Intelligence snapshot. Separate the place into location when the user gives a city, region, country, or ZIP.'),\n location: z.string().optional().describe('City, region, country, or service area used for localized Google results. MCP Scraper records location evidence; UULE alone is not proof of localization.'),\n gl: z.string().length(2).default('us').describe('Google country code inferred from the requested market, e.g. us, gb, ca, au.'),\n hl: z.string().default('en').describe('Google interface/content language inferred from the user request.'),\n device: z.enum(['desktop', 'mobile']).default('desktop').describe('SERP device context. Use mobile only when the user asks for mobile rankings or mobile SERP evidence.'),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_PROXY_MODE).describe('Leave unset — routing is automatic. Set \"location\" only to force city/ZIP targeting.'),\n proxyZip: z.string().regex(/^\\d{5}$/).optional().describe('Optional US ZIP override for residential location proxy targeting. Use only with proxyMode location when a precise city-center or ZIP proxy is needed.'),\n pages: z.number().int().min(1).max(2).default(1).describe('Number of Google result pages to capture. Use 1 normally and 2 only when the user needs deeper ranking evidence.'),\n debug: z.boolean().default(false).describe('Include sanitized browser, proxy, and location diagnostics. Use true when debugging localization, CAPTCHA, proxy selection, or capture reliability.'),\n includePageSnapshots: z.boolean().default(false).describe('Also capture ranking-page snapshots for selected SERP URLs through the same product capture path.'),\n pageSnapshotLimit: z.number().int().min(0).max(10).default(0).describe('Maximum ranking-page snapshots to capture when includePageSnapshots is true. Use 0 when only SERP evidence is needed.'),\n}\nexport type CaptureSerpSnapshotInput = z.infer<ReturnType<typeof z.object<typeof CaptureSerpSnapshotInputSchema>>>\n\nexport const ScreenshotInputSchema = {\n url: z.string().url().describe('URL to capture as a full-page screenshot. Use http or https. Pass allowLocal: true to capture localhost or private-network URLs during development.'),\n device: z.enum(['desktop', 'mobile']).default('desktop').describe('Viewport profile. desktop = 1440×900. mobile = 390×844. Use desktop by default; use mobile when the user asks for a mobile view.'),\n allowLocal: z.boolean().default(false).describe('Allow localhost and private-network URLs (127.x, 192.168.x, 10.x, etc.). For local development only — not for production use.'),\n}\nexport type ScreenshotInput = z.infer<ReturnType<typeof z.object<typeof ScreenshotInputSchema>>>\n\nexport const CaptureSerpPageSnapshotsInputSchema = {\n urls: z.array(z.string().url()).min(1).max(25).describe('Public HTTP/HTTPS URLs to capture as SERP Intelligence page snapshots. Do not pass localhost, private IPs, file URLs, or internal admin URLs.'),\n targets: z.array(z.object({\n url: z.string().url().describe('Public HTTP/HTTPS URL to capture.'),\n sourceKind: z.enum(['organic', 'ai_citation', 'local_pack_website', 'configured_target', 'site_subject']).default('configured_target').describe('Why this page is being captured for SERP Intelligence evidence.'),\n sourcePosition: z.number().int().min(1).optional().describe('Ranking or citation position when the page came from SERP evidence.'),\n }).strict()).min(1).max(25).optional().describe('Structured page snapshot targets. Use this instead of urls when source kind or position should be preserved.'),\n maxConcurrency: z.number().int().min(1).max(5).default(2).describe('Parallel page captures. Use 2 normally; higher values can increase proxy/browser pressure.'),\n timeoutMs: z.number().int().min(1_000).max(60_000).default(15_000).describe('Per-page capture timeout in milliseconds. Increase for slow pages; timeout artifacts are returned as structured capture failures.'),\n debug: z.boolean().default(false).describe('Include sanitized browser/proxy diagnostics for page snapshot debugging. Use true for capture, network, or proxy troubleshooting.'),\n}\nexport type CaptureSerpPageSnapshotsInput = z.infer<ReturnType<typeof z.object<typeof CaptureSerpPageSnapshotsInputSchema>>>\n","import { z } from 'zod'\n\nexport const DEFAULT_PROXY_MODE = 'none' as const\nexport const DEFAULT_MAPS_PROXY_MODE = 'location' as const\n\nexport const HarvestOptionsSchema = z.object({\n query: z.string().min(1),\n location: z.string().optional(),\n gl: z.string().length(2).default('us'),\n hl: z.string().length(2).default('en'),\n device: z.enum(['desktop', 'mobile']).default('desktop'),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_PROXY_MODE),\n proxyZip: z.string().regex(/^\\d{5}$/).optional(),\n debug: z.boolean().default(false),\n depth: z.number().int().min(1).max(30).default(3),\n maxQuestions: z.number().int().min(1).max(1000).default(100),\n headless: z.boolean().default(false),\n profileDir: z.string().optional(),\n proxy: z.string().url().optional(),\n kernelApiKey: z.string().optional(),\n kernelProxyId: z.string().optional(),\n kernelProxyResolution: z.unknown().optional(),\n outputDir: z.string().default('./paa-output'),\n format: z.enum(['json', 'csv', 'both']).default('both'),\n serpOnly: z.boolean().default(false),\n pages: z.number().int().min(1).max(2).default(1),\n softDeadlineMs: z.number().optional(),\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 MapsSearchOptionsSchema = 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 maxResults: z.number().int().min(1).max(50).default(10),\n proxyMode: z.enum(['location', 'configured', 'none']).default(DEFAULT_MAPS_PROXY_MODE),\n proxyZip: z.string().regex(/^\\d{5}$/).optional(),\n debug: z.boolean().default(false),\n kernelApiKey: z.string().optional(),\n kernelProxyId: z.string().optional(),\n kernelProxyResolution: z.unknown().optional(),\n headless: z.boolean().default(true),\n})\n\nexport const RawPAAItemSchema = z.object({\n question: z.string().min(1),\n answer: z.string().optional(),\n sourceTitle: z.string().optional(),\n sourceSite: z.string().optional(),\n sourceCite: z.string().optional(),\n})\n\nexport const RawMapsOverviewSchema = z.object({\n name: z.string().nullable(),\n rating: z.string().nullable(),\n reviewCount: z.string().nullable(),\n category: z.string().nullable(),\n address: z.string().nullable(),\n hoursSummary: z.string().nullable(),\n phone: z.string().nullable(),\n phoneDisplay: z.string().nullable(),\n website: z.string().nullable(),\n plusCode: z.string().nullable(),\n bookingUrl: z.string().nullable(),\n})\n\nexport const RawMapsHoursRowSchema = z.object({\n day: z.string(),\n hours: z.string(),\n})\n\nexport const RawMapsReviewStatsSchema = z.object({\n reviewHistogram: z.array(z.object({\n stars: z.number(),\n count: z.string(),\n })),\n reviewTopics: z.array(z.object({\n label: z.string(),\n count: z.string(),\n })),\n})\n\nexport const RawMapsReviewCardSchema = z.object({\n reviewId: z.string(),\n author: z.string().nullable(),\n stars: z.string().nullable(),\n date: z.string().nullable(),\n text: z.string().nullable(),\n ownerResponse: z.string().nullable(),\n})\n\nexport const RawMapsAboutAttributeSchema = z.object({\n section: z.string(),\n attribute: z.string(),\n})\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { RankTrackerBlueprintInput, RankTrackerMode } from './mcp-tool-schemas.js'\n\ntype ToolPlan = {\n tool: string\n purpose: string\n}\n\ntype TablePlan = {\n name: string\n purpose: string\n keyColumns: string[]\n}\n\ntype CronJobPlan = {\n name: string\n purpose: string\n modes: RankTrackerMode[]\n recommendedTools: string[]\n}\n\ntype RankTrackerBlueprint = {\n projectName: string\n targetDomain: string | null\n targetBusinessName: string | null\n trackingModes: RankTrackerMode[]\n database: string\n recommendedTools: ToolPlan[]\n tables: TablePlan[]\n cron: {\n enabled: boolean\n cadence: string\n expression: string\n timezone: string\n jobs: CronJobPlan[]\n }\n metrics: string[]\n implementationPrompt: string\n}\n\nconst DEFAULT_MODES: RankTrackerMode[] = ['maps', 'organic', 'ai_overview', 'paa']\n\nfunction normalizeDomain(value?: string): string | null {\n const trimmed = value?.trim()\n if (!trimmed) return null\n try {\n const url = new URL(trimmed.includes('://') ? trimmed : `https://${trimmed}`)\n return url.hostname.replace(/^www\\./, '').toLowerCase()\n } catch {\n return trimmed.replace(/^https?:\\/\\//, '').replace(/^www\\./, '').split('/')[0]?.toLowerCase() || trimmed\n }\n}\n\nfunction uniqueModes(input?: RankTrackerMode[]): RankTrackerMode[] {\n const modes = input?.length ? input : DEFAULT_MODES\n return [...new Set(modes)]\n}\n\nfunction cronExpression(cadence: RankTrackerBlueprintInput['scheduleCadence'], customCron?: string): string {\n if (cadence === 'daily') return '15 6 * * *'\n if (cadence === 'monthly') return '15 6 1 * *'\n if (cadence === 'custom') return customCron?.trim() || 'CUSTOM_CRON_EXPRESSION_REQUIRED'\n return '15 6 * * 1'\n}\n\nfunction includes(modes: RankTrackerMode[], mode: RankTrackerMode): boolean {\n return modes.includes(mode)\n}\n\nfunction buildToolPlan(modes: RankTrackerMode[]): ToolPlan[] {\n const plans: ToolPlan[] = []\n const push = (tool: string, purpose: string) => {\n if (!plans.some((plan) => plan.tool === tool)) plans.push({ tool, purpose })\n }\n\n push('credits_info', 'Check account balance and rates before scheduling recurring rank checks.')\n\n if (includes(modes, 'maps')) {\n push('directory_workflow', 'Seed or refresh city-by-city Maps datasets when building local market coverage.')\n push('maps_search', 'Run recurring Google Maps category checks for each keyword and location.')\n push('maps_place_intel', 'Hydrate selected target or competitor GBP details when profile-level evidence is needed.')\n }\n if (includes(modes, 'organic')) {\n push('search_serp', 'Capture localized organic rankings, local pack data, and AI Overview status without PAA expansion.')\n }\n if (includes(modes, 'ai_overview')) {\n push('search_serp', 'Capture quick AI Overview detection and organic context for each tracked query.')\n push('harvest_paa', 'Use when AI Overview text, PAA context, or source-level evidence needs deeper capture.')\n }\n if (includes(modes, 'paa')) {\n push('harvest_paa', 'Capture People Also Ask questions, answers, and source sites for PAA presence tracking.')\n }\n\n return plans\n}\n\nfunction buildTables(modes: RankTrackerMode[], includeDashboard: boolean, includeAlerts: boolean, hasCompetitors: boolean): TablePlan[] {\n const tables: TablePlan[] = [\n {\n name: 'rank_tracker_projects',\n purpose: 'One row per client, campaign, or tracked property.',\n keyColumns: ['id', 'name', 'target_domain', 'target_business_name', 'database_mode', 'timezone', 'created_at'],\n },\n {\n name: 'rank_tracker_targets',\n purpose: 'Normalized target identities and match rules for domains, URLs, business names, CIDs, and competitors.',\n keyColumns: ['id', 'project_id', 'kind', 'value', 'display_name', 'match_rules_json', 'active'],\n },\n {\n name: 'rank_tracker_keywords',\n purpose: 'Tracked keywords or service queries, separated from location so calls can localize correctly.',\n keyColumns: ['id', 'project_id', 'keyword', 'intent', 'tags_json', 'active'],\n },\n {\n name: 'rank_tracker_locations',\n purpose: 'Markets, cities, ZIPs, country/language settings, and proxy targeting hints.',\n keyColumns: ['id', 'project_id', 'label', 'gl', 'hl', 'proxy_zip', 'device', 'active'],\n },\n {\n name: 'rank_tracker_runs',\n purpose: 'Heartbeat table for every scheduled or manual rank check batch.',\n keyColumns: ['id', 'project_id', 'scheduled_for', 'started_at', 'completed_at', 'status', 'idempotency_key', 'error_message'],\n },\n ]\n\n if (includes(modes, 'organic')) {\n tables.push({\n name: 'rank_tracker_organic_results',\n purpose: 'SERP organic result rows from search_serp, including target-domain matches and competitor rows.',\n keyColumns: ['id', 'run_id', 'keyword_id', 'location_id', 'device', 'position', 'title', 'url', 'domain', 'is_target'],\n })\n }\n\n if (includes(modes, 'maps')) {\n tables.push({\n name: 'rank_tracker_maps_results',\n purpose: 'Google Maps result rows from maps_search and directory_workflow, including GBP identity fields.',\n keyColumns: ['id', 'run_id', 'keyword_id', 'location_id', 'position', 'business_name', 'place_url', 'cid', 'website_url', 'rating', 'review_count', 'is_target'],\n })\n tables.push({\n name: 'rank_tracker_market_seeds',\n purpose: 'Directory workflow city, population, ZIP-group, and market seed records used to build local tracking coverage.',\n keyColumns: ['id', 'project_id', 'query', 'city', 'state', 'population', 'zip_group_json', 'last_seeded_run_id'],\n })\n }\n\n if (includes(modes, 'ai_overview')) {\n tables.push({\n name: 'rank_tracker_ai_overviews',\n purpose: 'AI Overview detection, text snapshot, citation domains, and target citation status per query/location.',\n keyColumns: ['id', 'run_id', 'keyword_id', 'location_id', 'detected', 'target_cited', 'cited_domains_json', 'overview_text'],\n })\n }\n\n if (includes(modes, 'paa')) {\n tables.push({\n name: 'rank_tracker_paa_sources',\n purpose: 'People Also Ask questions, answers, and source sites, with target source presence flags.',\n keyColumns: ['id', 'run_id', 'keyword_id', 'location_id', 'question', 'answer', 'source_title', 'source_site', 'target_present'],\n })\n }\n\n if (hasCompetitors) {\n tables.push({\n name: 'rank_tracker_competitor_snapshots',\n purpose: 'Per-run competitor visibility summaries across organic, Maps, AI Overview, and PAA surfaces.',\n keyColumns: ['id', 'run_id', 'target_id', 'surface', 'best_position', 'presence_count', 'share_of_surface'],\n })\n }\n\n if (includeDashboard) {\n tables.push({\n name: 'rank_tracker_daily_metrics',\n purpose: 'Rollup table for dashboard charts, trend lines, and share-of-visibility summaries.',\n keyColumns: ['id', 'project_id', 'metric_date', 'keyword_id', 'location_id', 'surface', 'metric_name', 'metric_value'],\n })\n }\n\n if (includeAlerts) {\n tables.push({\n name: 'rank_tracker_alert_events',\n purpose: 'Deduplicated gain/loss events for rank movement, Maps top 3, AI Overview citations, and PAA source presence.',\n keyColumns: ['id', 'project_id', 'run_id', 'surface', 'severity', 'event_key', 'message', 'created_at', 'acknowledged_at'],\n })\n }\n\n return tables\n}\n\nfunction buildCronJobs(modes: RankTrackerMode[], includeDashboard: boolean, includeAlerts: boolean): CronJobPlan[] {\n const jobs: CronJobPlan[] = [\n {\n name: 'rank-tracker-dispatch',\n purpose: 'Find due keyword/location/mode combinations, create a rank_tracker_runs row, and enqueue idempotent work items.',\n modes,\n recommendedTools: ['credits_info'],\n },\n ]\n\n if (includes(modes, 'maps')) {\n jobs.push({\n name: 'maps-rank-check',\n purpose: 'Run maps_search per keyword/location and optionally directory_workflow for market seed refreshes.',\n modes: ['maps'],\n recommendedTools: ['maps_search', 'directory_workflow', 'maps_place_intel'],\n })\n }\n\n if (includes(modes, 'organic') || includes(modes, 'ai_overview')) {\n jobs.push({\n name: 'serp-rank-check',\n purpose: 'Run search_serp per keyword/location/device and persist organic ranks, local pack, and AI Overview status.',\n modes: modes.filter((mode) => mode === 'organic' || mode === 'ai_overview'),\n recommendedTools: ['search_serp'],\n })\n }\n\n if (includes(modes, 'paa') || includes(modes, 'ai_overview')) {\n jobs.push({\n name: 'paa-ai-evidence-check',\n purpose: 'Run harvest_paa for PAA source presence and deeper AI Overview/PAA evidence where needed.',\n modes: modes.filter((mode) => mode === 'paa' || mode === 'ai_overview'),\n recommendedTools: ['harvest_paa'],\n })\n }\n\n if (includeDashboard) {\n jobs.push({\n name: 'rank-tracker-rollups',\n purpose: 'Aggregate raw rows into daily metrics for charts, comparison tables, and trend lines.',\n modes,\n recommendedTools: [],\n })\n }\n\n if (includeAlerts) {\n jobs.push({\n name: 'rank-tracker-alerts',\n purpose: 'Compare latest run against prior snapshots and emit deduplicated visibility gain/loss events.',\n modes,\n recommendedTools: [],\n })\n }\n\n return jobs\n}\n\nfunction buildMetrics(modes: RankTrackerMode[], includeDashboard: boolean, includeAlerts: boolean): string[] {\n const metrics: string[] = ['run_success_rate', 'last_successful_run_at', 'stale_keyword_location_count']\n\n if (includes(modes, 'maps')) {\n metrics.push('maps_best_position', 'maps_top_3_presence', 'maps_target_found', 'maps_competitor_count_above_target')\n }\n if (includes(modes, 'organic')) {\n metrics.push('organic_best_position', 'organic_top_3_presence', 'organic_top_10_presence', 'organic_best_url')\n }\n if (includes(modes, 'ai_overview')) {\n metrics.push('ai_overview_detected', 'target_ai_overview_cited', 'ai_overview_citation_domain_count')\n }\n if (includes(modes, 'paa')) {\n metrics.push('paa_question_count', 'target_paa_source_count', 'paa_presence_rate', 'paa_source_domains')\n }\n if (includeDashboard) metrics.push('share_of_visibility', 'position_delta_7d', 'position_delta_30d')\n if (includeAlerts) metrics.push('visibility_gain_events', 'visibility_loss_events')\n\n return metrics\n}\n\nfunction listOrPlaceholder(values: string[] | undefined, fallback: string): string {\n const clean = values?.map((value) => value.trim()).filter(Boolean) ?? []\n if (!clean.length) return fallback\n return clean.map((value) => `- ${value}`).join('\\n')\n}\n\nfunction buildPrompt(\n input: RankTrackerBlueprintInput,\n modes: RankTrackerMode[],\n tools: ToolPlan[],\n tables: TablePlan[],\n jobs: CronJobPlan[],\n metrics: string[],\n expression: string,\n targetDomain: string | null,\n targetBusinessName: string | null,\n): string {\n const keywords = listOrPlaceholder(input.keywords, '- TODO: add tracked keywords')\n const locations = listOrPlaceholder(input.locations, '- TODO: add tracked markets/locations')\n const competitors = listOrPlaceholder(input.competitors, '- Optional: add competitor domains or GBP names')\n const notes = input.notes?.trim() || 'No extra implementation notes.'\n\n return [\n 'You are building a production rank tracker powered by MCP Scraper. Create the database migrations, scheduled worker, ingestion functions, and dashboard/query layer described below.',\n '',\n `Project: ${input.projectName || 'MCP Scraper Rank Tracker'}`,\n `Target domain: ${targetDomain || 'TODO_TARGET_DOMAIN'}`,\n `Target business/GBP name: ${targetBusinessName || 'TODO_TARGET_BUSINESS_NAME'}`,\n `Database target: ${input.database || 'postgres'}`,\n `Tracking modes: ${modes.join(', ')}`,\n '',\n 'Seed keywords:',\n keywords,\n '',\n 'Seed locations:',\n locations,\n '',\n 'Competitors:',\n competitors,\n '',\n 'MCP Scraper calls to use:',\n tools.map((tool) => `- ${tool.tool}: ${tool.purpose}`).join('\\n'),\n '',\n 'Database tables to create:',\n tables.map((table) => `- ${table.name}: ${table.keyColumns.join(', ')}`).join('\\n'),\n '',\n 'Scheduler and heartbeat requirements:',\n `- Use cron expression \"${expression}\" in timezone \"${input.timezone || 'UTC'}\" unless the user changes cadence.`,\n '- Every scheduled batch must insert or update rank_tracker_runs before calling MCP tools.',\n '- Use idempotency_key = project_id + keyword_id + location_id + mode + device + scheduled_date.',\n '- Mark runs as running, succeeded, failed, or skipped; persist error_message on failures.',\n '- Call credits_info first to read the account\\'s real concurrency_limit (most paid accounts have 3, 10, or 20, not 1), then run up to that many MCP calls in parallel — never sequential-by-default and never more than the limit, or calls start failing with 429s.',\n '- Retry retryable upstream failures with backoff, but do not duplicate rows for the same idempotency key.',\n '',\n 'Mode-specific ingestion rules:',\n '- maps: Use directory_workflow to seed/refresh market coverage and maps_search for recurring keyword/location rank checks. Match the target by targetBusinessName, website domain, CID, and place URL when available.',\n '- organic: Use search_serp and persist every organic result row. Compute the best targetDomain position and best ranking URL per keyword/location/device.',\n '- ai_overview: Use search_serp for quick detection and harvest_paa when deeper text/source evidence is needed. Track detected, overview_text, cited domains, and whether targetDomain is cited.',\n '- paa: Use harvest_paa and persist each question/source pair. Track whether sourceSite or answer/source evidence matches targetDomain, then compute PAA presence rate.',\n '',\n 'Metrics to expose:',\n metrics.map((metric) => `- ${metric}`).join('\\n'),\n '',\n 'Alert requirements:',\n input.includeAlerts\n ? '- Emit deduplicated alert_events when target gains/loses Maps top 3, organic top 10, AI Overview citation, or PAA source presence.'\n : '- Alerts are out of scope for this build unless the user asks for them.',\n '',\n 'Dashboard requirements:',\n input.includeDashboard\n ? '- Build views for latest position by keyword/location, trend deltas, competitors above target, AI Overview citations, and PAA source wins/losses.'\n : '- Dashboard is out of scope for this build unless the user asks for it.',\n '',\n 'Extra notes:',\n notes,\n ].join('\\n')\n}\n\nexport function buildRankTrackerBlueprint(input: RankTrackerBlueprintInput): CallToolResult {\n const trackingModes = uniqueModes(input.trackingModes)\n const targetDomain = normalizeDomain(input.targetDomain)\n const targetBusinessName = input.targetBusinessName?.trim() || null\n const projectName = input.projectName?.trim() || 'MCP Scraper Rank Tracker'\n const database = input.database || 'postgres'\n const expression = cronExpression(input.scheduleCadence || 'weekly', input.customCron)\n const tools = buildToolPlan(trackingModes)\n const tables = buildTables(trackingModes, input.includeDashboard !== false, input.includeAlerts !== false, Boolean(input.competitors?.length))\n const jobs = input.includeCron === false ? [] : buildCronJobs(trackingModes, input.includeDashboard !== false, input.includeAlerts !== false)\n const metrics = buildMetrics(trackingModes, input.includeDashboard !== false, input.includeAlerts !== false)\n const implementationPrompt = buildPrompt(input, trackingModes, tools, tables, jobs, metrics, expression, targetDomain, targetBusinessName)\n\n const blueprint: RankTrackerBlueprint = {\n projectName,\n targetDomain,\n targetBusinessName,\n trackingModes,\n database,\n recommendedTools: tools,\n tables,\n cron: {\n enabled: input.includeCron !== false,\n cadence: input.scheduleCadence || 'weekly',\n expression: input.includeCron === false ? 'disabled' : expression,\n timezone: input.timezone || 'UTC',\n jobs,\n },\n metrics,\n implementationPrompt,\n }\n\n const text = [\n `# ${projectName}`,\n '',\n 'Rank tracker build blueprint generated from MCP Scraper tool capabilities.',\n '',\n '## Modes',\n trackingModes.map((mode) => `- ${mode}`).join('\\n'),\n '',\n '## Recommended MCP Tools',\n tools.map((tool) => `- \\`${tool.tool}\\` - ${tool.purpose}`).join('\\n'),\n '',\n '## Database Tables',\n tables.map((table) => `- \\`${table.name}\\` - ${table.purpose}`).join('\\n'),\n '',\n '## Cron / Heartbeat',\n blueprint.cron.enabled\n ? `- Cadence: ${blueprint.cron.cadence}\\n- Cron: \\`${blueprint.cron.expression}\\`\\n- Timezone: ${blueprint.cron.timezone}\\n- Jobs: ${jobs.map((job) => job.name).join(', ')}`\n : '- Disabled by input. Still create rank_tracker_runs for manual runs.',\n '',\n '## Implementation Prompt',\n '```text',\n implementationPrompt,\n '```',\n ].join('\\n')\n\n return {\n content: [{ type: 'text', text }],\n structuredContent: blueprint,\n }\n}\n","export interface InstallTerminalOptions {\n color?: boolean\n version: string\n apiKeyConfigured?: boolean\n}\n\ntype Tone = 'cyan' | 'lime' | 'amber' | 'red' | 'muted' | 'bold'\n\nconst CODES: Record<Tone | 'reset', string> = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n lime: '\\x1b[32m',\n amber: '\\x1b[33m',\n red: '\\x1b[31m',\n muted: '\\x1b[90m',\n bold: '\\x1b[1m',\n}\n\nfunction colorize(value: string, tone: Tone, enabled: boolean): string {\n if (!enabled) return value\n return `${CODES[tone]}${value}${CODES.reset}`\n}\n\nfunction toolRow(label: string, tools: string[], enabled: boolean): string {\n const padded = label.padEnd(9, ' ')\n return ` ${colorize(padded, 'muted', enabled)} ${tools.join(colorize(' . ', 'muted', enabled))}`\n}\n\nexport function renderInstallTerminal(options: InstallTerminalOptions): string {\n const color = options.color ?? true\n const apiKeyValue = options.apiKeyConfigured ? '$MCP_SCRAPER_API_KEY' : 'sk_live_your_key'\n const ascii = String.raw`\n __ __ ____ ____ \n| \\/ |/ ___| _ \\\n| |\\/| | | | |_) |\n| | | | |___| __/\n|_| |_|\\____|_|\n\n ____ ____ ____ _ ____ _____ ____\n/ ___| / ___| _ \\ / \\ | _ \\| ____| _ \\\n\\___ \\| | | |_) | / _ \\ | |_) | _| | |_) |\n ___) | |___| _ < / ___ \\| __/| |___| _ <\n|____/ \\____|_| \\_\\/_/ \\_\\_| |_____|_| \\_\\\n`\n\n const claudeCommand = [\n `MCP_SCRAPER_API_KEY=${apiKeyValue} npx -y -p mcp-scraper@latest \\\\`,\n ' mcp-scraper-cli agent install claude --apply',\n ].join('\\n')\n\n const codexConfig = [\n '[mcp_servers.mcp-scraper]',\n 'command = \"npx\"',\n 'args = [\"-y\", \"-p\", \"mcp-scraper@latest\", \"mcp-scraper\"]',\n `env = { MCP_SCRAPER_API_KEY = \"${apiKeyValue}\" }`,\n ].join('\\n')\n\n return [\n colorize(`mcp-scraper v${options.version}`, 'bold', color),\n colorize('> mcp-scraper-install', 'muted', color),\n colorize(ascii, 'amber', color),\n `${colorize('MCP Scraper Agent', 'cyan', color)} . v${options.version} . mcpscraper.dev`,\n '1/1 install surfaces ready',\n colorize('Newest: saved browser profiles that hold MANY site logins. Share the watch_url, user signs in, then verify with browser_profile_list. Browser sessions are direct/no-proxy by default.', 'lime', color),\n '',\n `${colorize('Tools', 'cyan', color)} ${colorize('(48 MCP tools)', 'muted', color)}`,\n toolRow('search', ['harvest_paa', 'search_serp', 'maps_search', 'maps_place_intel'], color),\n toolRow('extract', ['extract_url', 'map_site_urls', 'extract_site', 'audit_site', 'directory_workflow'], color),\n toolRow('build', ['rank_tracker_workflow', 'cron plan', 'database prompt'], color),\n toolRow('media', ['youtube_harvest', 'youtube_transcribe', 'facebook_ad_search', 'facebook_page_intel', 'facebook_ad_transcribe', 'facebook_video_transcribe', 'instagram_profile_content', 'instagram_media_download', 'reddit_thread'], color),\n toolRow('browser', ['browser_open', 'browser_profile_connect', 'browser_profile_list', 'browser_close', 'browser_screenshot', 'browser_read', 'browser_locate', 'browser_replay_mark', 'browser_replay_annotate'], color),\n toolRow('account', ['credits_info', 'reports', 'MCP resources'], color),\n `${colorize('Workflows', 'cyan', color)} ${colorize('(MCP + CLI + API)', 'muted', color)}`,\n toolRow('route', ['workflow_list', 'workflow_suggest', 'workflow_run', 'workflow_step', 'workflow_status', 'workflow_artifact_read'], color),\n toolRow('seo', ['directory', 'agent-packet', 'competitive audit', 'map/serp comparison', 'PAA/AIO briefs', 'scheduled runs'], color),\n '',\n colorize('Usage tips:', 'amber', color),\n 'Run mcp-scraper-install for this visible card. Run mcp-scraper-cli for setup utilities and subcommands.',\n 'Run mcp-scraper in a human terminal to print this card; MCP clients get the same command as a silent stdio server.',\n 'Explicit card command: npx -y -p mcp-scraper@latest mcp-scraper-install',\n 'Customer auth setup: run browser_profile_connect, send the watch_url, let the user sign in, then call browser_profile_list until AUTHENTICATED.',\n 'Stack logins / reconnect: run browser_profile_connect again with the same profile name and another domain to add accounts or refresh a login.',\n 'Start with workflow_suggest for broad jobs like market analysis, ICP research, CRO audits, brand briefs, content gaps, and AI visibility.',\n 'For MCP clients, use mcp-scraper so one install can mix SERP, Maps, browser, reports, and saved MCP resources.',\n 'If you hit the concurrency limit, add an extra slot for $5/month with mcp-scraper-cli billing concurrency checkout.',\n '',\n `${colorize('Ready.', 'lime', color)} Install the combined MCP server with one command:`,\n '',\n colorize('Setup doctor', 'amber', color),\n 'npx -y -p mcp-scraper@latest mcp-scraper-cli doctor',\n '',\n colorize('Hosted profile setup', 'amber', color),\n 'In your MCP client, call browser_profile_connect with email=\"seo@example.com\" and domain=\"chatgpt.com\".',\n 'Give the returned watch_url to the user. After they sign in, call browser_profile_list, then browser_open with the returned profile. Add more logins by calling browser_profile_connect again with the same profile and a new domain.',\n '',\n colorize('Claude Code one-command setup', 'amber', color),\n claudeCommand,\n 'Then fully exit Claude Code and open a new Claude terminal. Check with: claude mcp list',\n '',\n colorize('Codex config', 'amber', color),\n codexConfig,\n '',\n colorize('Claude Desktop Extension', 'amber', color),\n 'Download: https://mcpscraper.dev/downloads/mcp-scraper.mcpb',\n '',\n colorize('Safety note:', 'muted', color),\n 'mcp-scraper prints this card only when stdin/stdout are an interactive TTY. In MCP clients it writes only JSON-RPC to stdout.',\n 'Use --stdio or MCP_SCRAPER_FORCE_STDIO=1 to force server mode from a terminal.',\n '',\n ].join('\\n')\n}\n"],"mappings":"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","names":["import_node_fs","import_node_os","import_node_path","import_mcp","baseUrl","apiKey","import_node_fs","import_node_os","import_node_path","Papa","import_node_os","import_node_path","safe","rect","safe","outputBaseDir","finiteNumber","server","baseUrl","outputBaseDir","finiteNumber","exports","import_mcp","import_node_fs","import_node_path","import_node_fs","import_node_os","import_node_path","normalize","outputBaseDir","full","wordCount","import_zod","import_zod","NullableString","server","outputBaseDir","server"]}