mcp-scraper 0.2.18 → 0.2.20

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 (71) hide show
  1. package/README.md +17 -11
  2. package/dist/bin/api-server.cjs +1020 -348
  3. package/dist/bin/api-server.cjs.map +1 -1
  4. package/dist/bin/api-server.js +3 -3
  5. package/dist/bin/browser-agent-stdio-server.cjs +314 -55
  6. package/dist/bin/browser-agent-stdio-server.cjs.map +1 -1
  7. package/dist/bin/browser-agent-stdio-server.js +2 -2
  8. package/dist/bin/mcp-scraper-cli.cjs +321 -167
  9. package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
  10. package/dist/bin/mcp-scraper-cli.js +3 -2
  11. package/dist/bin/mcp-scraper-cli.js.map +1 -1
  12. package/dist/bin/mcp-scraper-combined-stdio-server.cjs +1230 -528
  13. package/dist/bin/mcp-scraper-combined-stdio-server.cjs.map +1 -1
  14. package/dist/bin/mcp-scraper-combined-stdio-server.js +19 -3
  15. package/dist/bin/mcp-scraper-combined-stdio-server.js.map +1 -1
  16. package/dist/bin/mcp-scraper-install.cjs +8 -6
  17. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  18. package/dist/bin/mcp-scraper-install.js +5 -92
  19. package/dist/bin/mcp-scraper-install.js.map +1 -1
  20. package/dist/bin/mcp-stdio-server.cjs +726 -387
  21. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  22. package/dist/bin/mcp-stdio-server.js +3 -2
  23. package/dist/bin/mcp-stdio-server.js.map +1 -1
  24. package/dist/bin/paa-harvest.cjs +5 -3
  25. package/dist/bin/paa-harvest.cjs.map +1 -1
  26. package/dist/bin/paa-harvest.js +2 -1
  27. package/dist/bin/paa-harvest.js.map +1 -1
  28. package/dist/{chunk-TL7YTFLH.js → chunk-DBQDG7EH.js} +99 -27
  29. package/dist/chunk-DBQDG7EH.js.map +1 -0
  30. package/dist/{chunk-F44RBOJ5.js → chunk-H2R232HK.js} +216 -108
  31. package/dist/chunk-H2R232HK.js.map +1 -0
  32. package/dist/{chunk-P5PLQU3H.js → chunk-L4OWOUGR.js} +315 -56
  33. package/dist/chunk-L4OWOUGR.js.map +1 -0
  34. package/dist/chunk-LFATOGDF.js +111 -0
  35. package/dist/chunk-LFATOGDF.js.map +1 -0
  36. package/dist/chunk-MLNCKQ2B.js +96 -0
  37. package/dist/chunk-MLNCKQ2B.js.map +1 -0
  38. package/dist/{chunk-RJMCASQH.js → chunk-O5J7E4VX.js} +394 -57
  39. package/dist/chunk-O5J7E4VX.js.map +1 -0
  40. package/dist/{chunk-BSYPATSM.js → chunk-SXTXMFEQ.js} +2 -2
  41. package/dist/{chunk-CQTAKXBN.js → chunk-XGUDTDZ2.js} +7 -104
  42. package/dist/chunk-XGUDTDZ2.js.map +1 -0
  43. package/dist/chunk-XKUDVN2E.js +7 -0
  44. package/dist/chunk-XKUDVN2E.js.map +1 -0
  45. package/dist/{db-P5X6UQ3E.js → db-BE4JVB3V.js} +8 -2
  46. package/dist/index.cjs +5 -3
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.d.cts +2 -2
  49. package/dist/index.d.ts +2 -2
  50. package/dist/index.js +2 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/{server-VVY5K44O.js → server-7NE45K2A.js} +211 -37
  53. package/dist/server-7NE45K2A.js.map +1 -0
  54. package/dist/{worker-OZSWIS3F.js → worker-MIYG2B2I.js} +5 -4
  55. package/dist/{worker-OZSWIS3F.js.map → worker-MIYG2B2I.js.map} +1 -1
  56. package/docs/adr/0001-in-page-graphql-interception-for-anti-bot-scraping.md +2 -2
  57. package/docs/mcp-tool-craft-lint.generated.md +51 -0
  58. package/docs/mcp-tool-manifest.generated.json +1406 -0
  59. package/docs/specs/local-competitive-audit-spec.md +1 -2
  60. package/docs/specs/mcp-tool-definition-quality-audit-spec.md +1602 -0
  61. package/package.json +4 -1
  62. package/dist/chunk-CQTAKXBN.js.map +0 -1
  63. package/dist/chunk-F44RBOJ5.js.map +0 -1
  64. package/dist/chunk-M5SAUO4K.js +0 -7
  65. package/dist/chunk-M5SAUO4K.js.map +0 -1
  66. package/dist/chunk-P5PLQU3H.js.map +0 -1
  67. package/dist/chunk-RJMCASQH.js.map +0 -1
  68. package/dist/chunk-TL7YTFLH.js.map +0 -1
  69. package/dist/server-VVY5K44O.js.map +0 -1
  70. /package/dist/{chunk-BSYPATSM.js.map → chunk-SXTXMFEQ.js.map} +0 -0
  71. /package/dist/{db-P5X6UQ3E.js.map → db-BE4JVB3V.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/workflows/artifact-writer.ts","../src/directory/csv.ts","../src/lib/slugify.ts","../src/workflows/registry.ts","../src/workflows/http-client.ts","../src/workflows/workflows/agent-packet.ts","../src/workflows/report-renderer.ts","../src/workflows/workflows/directory.ts","../src/workflows/workflows/local-competitive-audit.ts","../src/workflows/workflows/comparison-briefs.ts","../src/workflows/workflows/seo-workflow-utils.ts"],"sourcesContent":["import { mkdir, readFile, stat, writeFile } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\nimport { homedir, platform } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { execFile } from 'node:child_process'\nimport { rowsToCsv } from '../directory/csv.js'\nimport { slugify } from '../lib/slugify.js'\nimport type { WorkflowArtifact, WorkflowManifest, WorkflowStatus } from './types.js'\n\nexport function workflowOutputBaseDir(outputDir?: string): string {\n return outputDir?.trim() || process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || join(homedir(), 'Downloads', 'mcp-scraper')\n}\n\nfunction timestamp(): string {\n return new Date().toISOString().replace(/[:.]/g, '-')\n}\n\nfunction safeSlug(value: string): string {\n return slugify(value).replace(/^-+|-+$/g, '').slice(0, 80) || 'run'\n}\n\nexport class ArtifactWriter {\n readonly artifacts: WorkflowArtifact[] = []\n\n constructor(\n readonly workflowId: string,\n readonly title: string,\n readonly runId: string,\n readonly baseDir: string,\n readonly runDir: string,\n readonly startedAt: string,\n readonly input: Record<string, unknown>,\n ) {}\n\n static async create(workflowId: string, title: string, input: Record<string, unknown>, outputDir?: string, forcedRunId?: string): Promise<ArtifactWriter> {\n const startedAt = new Date().toISOString()\n const runId = forcedRunId?.trim() || `${timestamp()}-${safeSlug(workflowId)}-${Math.random().toString(36).slice(2, 8)}`\n const nameSource = String(input.keyword ?? input.query ?? input.domain ?? input.state ?? workflowId)\n const baseDir = workflowOutputBaseDir(outputDir)\n const runDir = join(baseDir, 'workflows', workflowId, `${timestamp()}-${safeSlug(nameSource)}-${safeSlug(runId).slice(0, 20)}`)\n await mkdir(runDir, { recursive: true })\n return new ArtifactWriter(workflowId, title, runId, baseDir, runDir, startedAt, input)\n }\n\n private async remember(kind: WorkflowArtifact['kind'], label: string, path: string, rows?: number): Promise<string> {\n const size = await stat(path).then(s => s.size).catch(() => undefined)\n this.artifacts.push({ kind, label, path, bytes: size, rows })\n return path\n }\n\n async writeJson(label: string, relativePath: string, data: unknown): Promise<string> {\n const path = join(this.runDir, relativePath)\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, JSON.stringify(data, null, 2), 'utf8')\n return this.remember('json', label, path)\n }\n\n async writeText(label: string, relativePath: string, text: string, kind: WorkflowArtifact['kind'] = 'markdown'): Promise<string> {\n const path = join(this.runDir, relativePath)\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, text, 'utf8')\n return this.remember(kind, label, path)\n }\n\n async writeCsv(label: string, relativePath: string, headers: string[], rows: Array<Record<string, unknown>>): Promise<string> {\n const path = join(this.runDir, relativePath)\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, rowsToCsv(headers, rows), 'utf8')\n return this.remember('csv', label, path, rows.length)\n }\n\n async writeHtml(label: string, relativePath: string, html: string): Promise<string> {\n return this.writeText(label, relativePath, html, 'html_report')\n }\n\n async writeManifest(status: WorkflowStatus, counts: Record<string, number>, warnings: string[], errors: string[]): Promise<string> {\n const manifest: WorkflowManifest = {\n workflow: this.workflowId,\n title: this.title,\n runId: this.runId,\n status,\n startedAt: this.startedAt,\n completedAt: status === 'running' ? null : new Date().toISOString(),\n input: this.input,\n artifacts: this.artifacts,\n warnings,\n errors,\n counts,\n }\n const path = join(this.runDir, 'manifest.json')\n await writeFile(path, JSON.stringify(manifest, null, 2), 'utf8')\n await updateWorkflowIndex(manifest, path, this.baseDir)\n return path\n }\n}\n\ninterface WorkflowIndexEntry {\n workflow: string\n runId: string\n status: string\n startedAt: string\n reportPath: string | null\n manifestPath: string\n summary: string\n}\n\ninterface WorkflowIndex {\n runs: WorkflowIndexEntry[]\n}\n\nfunction indexPath(baseDir = workflowOutputBaseDir()): string {\n return join(baseDir, 'workflows', 'index.json')\n}\n\nasync function readIndex(baseDir?: string): Promise<WorkflowIndex> {\n const path = indexPath(baseDir)\n if (!existsSync(path)) return { runs: [] }\n try {\n return JSON.parse(await readFile(path, 'utf8')) as WorkflowIndex\n } catch {\n return { runs: [] }\n }\n}\n\nasync function updateWorkflowIndex(manifest: WorkflowManifest, manifestPath: string, baseDir: string): Promise<void> {\n if (manifest.status === 'running') return\n const path = indexPath(baseDir)\n const index = await readIndex(baseDir)\n const report = manifest.artifacts.find(a => a.kind === 'html_report')?.path ?? null\n const entry: WorkflowIndexEntry = {\n workflow: manifest.workflow,\n runId: manifest.runId,\n status: manifest.status,\n startedAt: manifest.startedAt,\n reportPath: report,\n manifestPath,\n summary: `${manifest.title} (${manifest.status})`,\n }\n index.runs = [entry, ...index.runs.filter(r => r.runId !== manifest.runId)].slice(0, 200)\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, JSON.stringify(index, null, 2), 'utf8')\n}\n\nexport async function listWorkflowReports(outputDir?: string): Promise<WorkflowIndexEntry[]> {\n return (await readIndex(workflowOutputBaseDir(outputDir))).runs\n}\n\nexport async function findWorkflowReport(id: string, outputDir?: string): Promise<WorkflowIndexEntry | null> {\n const runs = await listWorkflowReports(outputDir)\n if (id === 'last') return runs[0] ?? null\n return runs.find(run => run.runId === id) ?? null\n}\n\nexport async function openWorkflowReport(id: string, outputDir?: string): Promise<string> {\n const run = await findWorkflowReport(id, outputDir)\n if (!run?.reportPath) throw new Error(`No report found for \"${id}\"`)\n if (platform() === 'darwin') {\n await new Promise<void>((resolve, reject) => {\n execFile('open', [run.reportPath!], (err) => err ? reject(err) : resolve())\n })\n }\n return run.reportPath\n}\n","export function parseCsv(text: string): string[][] {\n const rows: string[][] = []\n let row: string[] = []\n let field = ''\n let quoted = false\n\n for (let i = 0; i < text.length; i += 1) {\n const ch = text[i]\n const next = text[i + 1]\n\n if (quoted) {\n if (ch === '\"' && next === '\"') {\n field += '\"'\n i += 1\n } else if (ch === '\"') {\n quoted = false\n } else {\n field += ch\n }\n continue\n }\n\n if (ch === '\"') {\n quoted = true\n } else if (ch === ',') {\n row.push(field)\n field = ''\n } else if (ch === '\\n') {\n row.push(field)\n rows.push(row)\n row = []\n field = ''\n } else if (ch !== '\\r') {\n field += ch\n }\n }\n\n if (field.length > 0 || row.length > 0) {\n row.push(field)\n rows.push(row)\n }\n\n return rows\n}\n\nexport function csvRecords(text: string): Array<Record<string, string>> {\n const rows = parseCsv(text).filter(row => row.some(cell => cell.trim() !== ''))\n const header = rows[0]?.map(cell => cell.trim()) ?? []\n return rows.slice(1).map((row) => {\n const record: Record<string, string> = {}\n for (let i = 0; i < header.length; i += 1) {\n record[header[i]] = row[i] ?? ''\n }\n return record\n })\n}\n\nexport function csvCell(value: unknown): string {\n if (value === null || value === undefined) return ''\n const text = String(value)\n return /[\",\\n\\r]/.test(text) ? `\"${text.replace(/\"/g, '\"\"')}\"` : text\n}\n\nexport function rowsToCsv(headers: string[], rows: Array<Record<string, unknown>>): string {\n return [\n headers.join(','),\n ...rows.map(row => headers.map(header => csvCell(row[header])).join(',')),\n ].join('\\n') + '\\n'\n}\n","export function slugify(s: string): string {\n return s.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '');\n}\n","import { z } from 'zod'\nimport { ArtifactWriter, findWorkflowReport, listWorkflowReports, openWorkflowReport } from './artifact-writer.js'\nimport { WorkflowHttpClient } from './http-client.js'\nimport type { WorkflowDefinition, WorkflowRunOptions, WorkflowRunSummary } from './types.js'\nimport { agentPacketWorkflowDefinition } from './workflows/agent-packet.js'\nimport { directoryWorkflowDefinition } from './workflows/directory.js'\nimport { localCompetitiveAuditWorkflowDefinition } from './workflows/local-competitive-audit.js'\nimport {\n aiOverviewLanguageWorkflowDefinition,\n mapComparisonWorkflowDefinition,\n paaExpansionBriefWorkflowDefinition,\n serpComparisonWorkflowDefinition,\n} from './workflows/comparison-briefs.js'\n\nconst DEFINITIONS = [\n directoryWorkflowDefinition,\n agentPacketWorkflowDefinition,\n localCompetitiveAuditWorkflowDefinition,\n mapComparisonWorkflowDefinition,\n serpComparisonWorkflowDefinition,\n paaExpansionBriefWorkflowDefinition,\n aiOverviewLanguageWorkflowDefinition,\n] satisfies WorkflowDefinition<any>[]\n\nexport function listWorkflowDefinitions(): Array<Pick<WorkflowDefinition, 'id' | 'title' | 'description'>> {\n return DEFINITIONS.map(({ id, title, description }) => ({ id, title, description }))\n}\n\nexport function workflowDefinition(id: string): WorkflowDefinition<any> {\n const definition = DEFINITIONS.find(def => def.id === id)\n if (!definition) throw new Error(`Unknown workflow \"${id}\". Available: ${DEFINITIONS.map(def => def.id).join(', ')}`)\n return definition\n}\n\nexport async function runWorkflow(id: string, rawInput: Record<string, unknown>, options: WorkflowRunOptions = {}): Promise<WorkflowRunSummary> {\n const definition = workflowDefinition(id)\n const input = definition.inputSchema.parse(rawInput)\n const apiKey = options.apiKey?.trim() || process.env.MCP_SCRAPER_API_KEY?.trim()\n if (!apiKey) throw new Error('MCP_SCRAPER_API_KEY is required for workflow runs. Pass --api-key or set the environment variable.')\n const apiUrl = options.apiUrl?.trim() || process.env.MCP_SCRAPER_API_URL?.trim() || 'https://mcpscraper.dev'\n const artifacts = await ArtifactWriter.create(definition.id, definition.title, input as Record<string, unknown>, options.outputDir, options.runId)\n const client = new WorkflowHttpClient(apiUrl, apiKey, options.fetchImpl, options.headers)\n try {\n return await definition.run(input, {\n runId: artifacts.runId,\n startedAt: artifacts.startedAt,\n client,\n artifacts,\n signal: options.signal,\n })\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n await artifacts.writeText('Failure', 'summary.md', `# ${definition.title}\\n\\n${message}\\n`)\n await artifacts.writeManifest('failed', {}, [], [message])\n throw err\n }\n}\n\nexport { findWorkflowReport, listWorkflowReports, openWorkflowReport }\nexport { z }\n","import type { WorkflowApiClient } from './types.js'\n\nexport class WorkflowHttpClient implements WorkflowApiClient {\n constructor(\n private readonly apiUrl: string,\n private readonly apiKey: string,\n private readonly fetchImpl: typeof fetch = fetch,\n private readonly extraHeaders: Record<string, string> = {},\n ) {}\n\n async post<T>(path: string, body: Record<string, unknown>, timeoutMs = 180_000): Promise<T> {\n const res = await this.fetchImpl(`${this.apiUrl.replace(/\\/$/, '')}${path}`, {\n method: 'POST',\n headers: {\n ...this.extraHeaders,\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 res.json().catch(() => ({}))\n if (!res.ok) {\n const message = typeof (data as { error?: unknown }).error === 'string'\n ? (data as { error: string }).error\n : `Workflow API ${path} failed with ${res.status}`\n throw new Error(message)\n }\n return data as T\n }\n}\n","import { z } from 'zod'\nimport { rowsToCsv } from '../../directory/csv.js'\nimport { renderWorkflowReport } from '../report-renderer.js'\nimport type { WorkflowDefinition, WorkflowRunContext, WorkflowRunSummary } from '../types.js'\n\nconst AgentPacketInputSchema = z.object({\n keyword: z.string().min(1),\n domain: z.string().optional(),\n location: z.string().optional(),\n maxQuestions: z.number().int().min(1).max(200).default(40),\n includeSerp: z.boolean().default(true),\n includePaa: z.boolean().default(true),\n includeAiOverview: z.boolean().default(true),\n returnPartial: z.boolean().default(true),\n})\n\ntype AgentPacketInput = z.infer<typeof AgentPacketInputSchema>\n\ninterface OrganicResult {\n position: number\n title: string\n url: string\n domain: string\n snippet?: string | null\n}\n\ninterface PaaRow {\n question: string\n answer?: string | null\n source_title?: string | null\n source_site?: string | null\n source_cite?: string | null\n}\n\ninterface HarvestLike {\n organicResults?: OrganicResult[]\n localPack?: Array<{ position: number; name: string; rating?: string | null; reviewCount?: string | null; websiteUrl?: string | null }>\n flat?: PaaRow[]\n aiOverview?: { detected?: boolean; text?: string | null; citations?: Array<{ text?: string; href?: string }> }\n}\n\nfunction normalizeDomain(value?: string | null): string | null {\n if (!value) return null\n try {\n const url = new URL(value.includes('://') ? value : `https://${value}`)\n return url.hostname.replace(/^www\\./, '').toLowerCase()\n } catch {\n return value.replace(/^https?:\\/\\//, '').replace(/^www\\./, '').split('/')[0]?.toLowerCase() || null\n }\n}\n\nfunction domainFromUrl(url: string): string {\n return normalizeDomain(url) ?? ''\n}\n\nfunction sourceRows(input: AgentPacketInput, serp: HarvestLike | null, paa: HarvestLike | null): Array<Record<string, unknown>> {\n const target = normalizeDomain(input.domain)\n const rows: Array<Record<string, unknown>> = []\n for (const result of serp?.organicResults ?? []) {\n const domain = normalizeDomain(result.domain) ?? domainFromUrl(result.url)\n rows.push({\n surface: 'organic',\n position: result.position,\n title: result.title,\n url: result.url,\n domain,\n question: '',\n answer_excerpt: result.snippet ?? '',\n is_target: target ? domain === target : false,\n is_competitor: target ? domain !== target : true,\n })\n }\n for (const row of paa?.flat ?? []) {\n const url = row.source_cite ?? ''\n const domain = normalizeDomain(row.source_site ?? '') ?? (url ? domainFromUrl(url) : '')\n rows.push({\n surface: 'paa',\n position: '',\n title: row.source_title ?? row.source_site ?? '',\n url,\n domain,\n question: row.question,\n answer_excerpt: (row.answer ?? '').slice(0, 240),\n is_target: target ? domain === target : false,\n is_competitor: target ? Boolean(domain && domain !== target) : Boolean(domain),\n })\n }\n for (const [i, cite] of (serp?.aiOverview?.citations ?? []).entries()) {\n const url = cite.href ?? ''\n const domain = url ? domainFromUrl(url) : ''\n rows.push({\n surface: 'ai_overview',\n position: i + 1,\n title: cite.text ?? '',\n url,\n domain,\n question: '',\n answer_excerpt: '',\n is_target: target ? domain === target : false,\n is_competitor: target ? Boolean(domain && domain !== target) : Boolean(domain),\n })\n }\n return rows\n}\n\nfunction competitorRows(rows: Array<Record<string, unknown>>, targetDomain: string | null): Array<Record<string, unknown>> {\n const byDomain = new Map<string, { organic: number[]; paa: number; ai: number; urls: Set<string> }>()\n for (const row of rows) {\n const domain = String(row.domain ?? '')\n if (!domain || domain === targetDomain) continue\n const entry = byDomain.get(domain) ?? { organic: [], paa: 0, ai: 0, urls: new Set<string>() }\n if (row.surface === 'organic' && row.position) entry.organic.push(Number(row.position))\n if (row.surface === 'paa') entry.paa += 1\n if (row.surface === 'ai_overview') entry.ai += 1\n if (row.url) entry.urls.add(String(row.url))\n byDomain.set(domain, entry)\n }\n return [...byDomain.entries()]\n .map(([domain, entry]) => ({\n domain,\n organic_best_position: entry.organic.length ? Math.min(...entry.organic) : '',\n organic_count: entry.organic.length,\n paa_mentions: entry.paa,\n ai_overview_citations: entry.ai,\n source_url_count: entry.urls.size,\n }))\n .sort((a, b) => Number(a.organic_best_position || 999) - Number(b.organic_best_position || 999))\n}\n\nexport const agentPacketWorkflowDefinition: WorkflowDefinition<AgentPacketInput> = {\n id: 'agent-packet',\n title: 'Agent-Ready SEO Packet',\n description: 'Create an evidence folder for AI agents from live SERP/PAA/AI search surfaces.',\n inputSchema: AgentPacketInputSchema,\n async run(input: AgentPacketInput, ctx: WorkflowRunContext): Promise<WorkflowRunSummary> {\n await ctx.artifacts.writeManifest('running', {}, [], [])\n const warnings: string[] = []\n const errors: string[] = []\n let serp: HarvestLike | null = null\n let paa: HarvestLike | null = null\n\n if (input.includeSerp) {\n try {\n serp = await ctx.client.post<HarvestLike>('/harvest/sync', {\n query: input.keyword,\n location: input.location,\n serpOnly: true,\n maxQuestions: 1,\n format: 'json',\n }, 180_000)\n } catch (err) {\n warnings.push(`SERP evidence unavailable: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n\n if (input.includePaa) {\n try {\n paa = await ctx.client.post<HarvestLike>('/harvest/sync', {\n query: input.keyword,\n location: input.location,\n maxQuestions: input.maxQuestions,\n format: 'json',\n }, 280_000)\n } catch (err) {\n warnings.push(`PAA evidence unavailable: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n\n if (!serp && !paa && !input.returnPartial) throw new Error('No SEO evidence was collected')\n const rows = sourceRows(input, serp, paa)\n const target = normalizeDomain(input.domain)\n const competitors = competitorRows(rows, target)\n const evidence = {\n input,\n serp: serp ?? { status: 'skipped' },\n paa: paa ?? { status: 'skipped' },\n target: {\n domain: target,\n organicPositions: rows.filter(r => r.surface === 'organic' && r.is_target).map(r => Number(r.position)),\n citedInAiOverview: rows.some(r => r.surface === 'ai_overview' && r.is_target),\n citedInPaa: rows.some(r => r.surface === 'paa' && r.is_target),\n },\n competitors,\n warnings,\n }\n\n await ctx.artifacts.writeJson('Evidence JSON', 'evidence.json', evidence)\n await ctx.artifacts.writeCsv('Sources CSV', 'sources.csv', ['surface', 'position', 'title', 'url', 'domain', 'question', 'answer_excerpt', 'is_target', 'is_competitor'], rows)\n await ctx.artifacts.writeCsv('Competitors CSV', 'competitors.csv', ['domain', 'organic_best_position', 'organic_count', 'paa_mentions', 'ai_overview_citations', 'source_url_count'], competitors)\n\n const brief = [\n `# SEO Evidence Brief: ${input.keyword}`,\n '',\n `Location: ${input.location ?? 'not specified'}`,\n `Target domain: ${target ?? 'not specified'}`,\n '',\n '## Evidence Summary',\n `- Organic rows: ${rows.filter(r => r.surface === 'organic').length}`,\n `- PAA rows: ${rows.filter(r => r.surface === 'paa').length}`,\n `- AI Overview citations: ${rows.filter(r => r.surface === 'ai_overview').length}`,\n `- Competitor domains: ${competitors.length}`,\n '',\n '## Recommended Use',\n 'Use the CSV files as source of truth. Tie content recommendations to evidence rows and mark unsupported ideas as assumptions.',\n ].join('\\n')\n await ctx.artifacts.writeText('Brief', 'brief.md', brief)\n await ctx.artifacts.writeText('Agent tasks', 'tasks.md', [\n '# Agent Tasks',\n '',\n '- [ ] Read `evidence.json` before writing recommendations.',\n '- [ ] Compare the target domain against `competitors.csv`.',\n '- [ ] Use `sources.csv` for citations and source-grounded page sections.',\n '- [ ] Mark unsupported recommendations as assumptions.',\n ].join('\\n'))\n await ctx.artifacts.writeText('Agent instructions', 'agent-instructions.md', [\n '# Agent Instructions',\n '',\n 'You are working from an MCP Scraper SEO evidence packet. Use `evidence.json` and CSV files as source of truth. Do not invent citations. If a recommendation is not supported by evidence, mark it as an assumption.',\n ].join('\\n'))\n\n const summary = `${rows.length} evidence rows and ${competitors.length} competitor domains collected.`\n const reportPath = await ctx.artifacts.writeHtml('HTML report', 'report.html', renderWorkflowReport({\n title: 'Agent-Ready SEO Packet',\n subtitle: `${input.keyword}${input.location ? ` · ${input.location}` : ''}`,\n summary,\n warnings,\n tables: [\n { title: 'Competitor Domains', columns: ['domain', 'organic_best_position', 'organic_count', 'paa_mentions', 'ai_overview_citations', 'source_url_count'], rows: competitors.slice(0, 50) },\n { title: 'Evidence Sources', columns: ['surface', 'position', 'title', 'domain', 'question', 'is_target'], rows: rows.slice(0, 100) },\n ],\n }))\n const status = warnings.length ? 'partial' : 'succeeded'\n const counts = { sources: rows.length, competitors: competitors.length }\n await ctx.artifacts.writeManifest(status, counts, warnings, errors)\n return { title: 'Agent-Ready SEO Packet', summary, status, counts, warnings, errors, reportPath }\n },\n}\n\n","export interface ReportTable {\n title: string\n columns: string[]\n rows: Array<Record<string, unknown>>\n}\n\nexport interface ReportSection {\n title: string\n body: string\n}\n\nexport interface WorkflowReportInput {\n title: string\n subtitle?: string\n summary: string\n sections?: ReportSection[]\n tables?: ReportTable[]\n warnings?: string[]\n}\n\nexport function escapeHtml(value: unknown): string {\n return String(value ?? '')\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\n}\n\nfunction renderTable(table: ReportTable): string {\n const rows = table.rows.map(row => (\n `<tr>${table.columns.map(col => `<td>${escapeHtml(row[col])}</td>`).join('')}</tr>`\n )).join('\\n')\n return [\n `<section>`,\n `<h2>${escapeHtml(table.title)}</h2>`,\n `<div class=\"table-wrap\"><table>`,\n `<thead><tr>${table.columns.map(col => `<th>${escapeHtml(col)}</th>`).join('')}</tr></thead>`,\n `<tbody>${rows || `<tr><td colspan=\"${table.columns.length}\">No rows</td></tr>`}</tbody>`,\n `</table></div>`,\n `</section>`,\n ].join('\\n')\n}\n\nexport function renderWorkflowReport(input: WorkflowReportInput): string {\n const warnings = input.warnings?.length\n ? `<section class=\"warnings\"><h2>Warnings</h2><ul>${input.warnings.map(w => `<li>${escapeHtml(w)}</li>`).join('')}</ul></section>`\n : ''\n const sections = (input.sections ?? []).map(section => (\n `<section><h2>${escapeHtml(section.title)}</h2><p>${escapeHtml(section.body)}</p></section>`\n )).join('\\n')\n const tables = (input.tables ?? []).map(renderTable).join('\\n')\n\n return [\n '<!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>${escapeHtml(input.title)}</title>`,\n '<style>',\n ':root{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;color:#172026;background:#f6f7f8}',\n 'body{margin:0;padding:32px}main{max-width:1180px;margin:0 auto;background:#fff;border:1px solid #d9dee3;border-radius:8px;padding:28px}',\n 'h1{font-size:30px;line-height:1.15;margin:0 0 8px}h2{font-size:18px;margin:28px 0 12px}p{line-height:1.55;color:#3d4952}.sub{color:#66737f;margin:0 0 20px}',\n '.summary{background:#eef6f8;border-left:4px solid #12829a;padding:14px 16px;margin:20px 0}.warnings{background:#fff7e8;border-left:4px solid #c87b00;padding:12px 16px}',\n '.table-wrap{overflow:auto;border:1px solid #dfe5ea;border-radius:8px}table{border-collapse:collapse;width:100%;font-size:13px}th,td{border-bottom:1px solid #edf0f2;padding:9px 10px;text-align:left;vertical-align:top}th{background:#f3f5f7;color:#31404c;position:sticky;top:0}tr:last-child td{border-bottom:0}',\n '</style>',\n '</head>',\n '<body><main>',\n `<h1>${escapeHtml(input.title)}</h1>`,\n input.subtitle ? `<p class=\"sub\">${escapeHtml(input.subtitle)}</p>` : '',\n `<div class=\"summary\">${escapeHtml(input.summary)}</div>`,\n warnings,\n sections,\n tables,\n '</main></body></html>',\n ].join('\\n')\n}\n\n","import { z } from 'zod'\nimport { renderWorkflowReport } from '../report-renderer.js'\nimport type { WorkflowDefinition, WorkflowRunContext, WorkflowRunSummary } from '../types.js'\n\nconst DirectoryWorkflowCliInputSchema = z.object({\n query: z.string().min(1),\n state: z.string().min(2).default('TN'),\n minPopulation: z.number().int().min(0).default(100_000),\n maxCities: z.number().int().min(1).max(100).default(25),\n maxResultsPerCity: z.number().int().min(1).max(50).default(20),\n concurrency: z.number().int().min(1).max(5).default(5),\n proxyMode: z.enum(['location', 'configured', 'none']).default('location'),\n saveCsv: z.boolean().default(true),\n})\n\ntype DirectoryWorkflowCliInput = z.infer<typeof DirectoryWorkflowCliInputSchema>\n\ninterface DirectoryBusiness {\n position: number\n name: string\n rating: string | null\n reviewCount: string | null\n category: string | null\n address: string | null\n phone: string | null\n websiteUrl: string | null\n placeUrl: string\n cid: string | null\n cidDecimal: string | null\n}\n\ninterface DirectoryCity {\n city: string\n state: string\n location: string\n population: number\n status: 'ok' | 'empty' | 'failed'\n error: string | null\n resultCount: number\n results: DirectoryBusiness[]\n}\n\nexport interface DirectoryWorkflowApiResult {\n query: string\n state: string\n selectedCityCount: number\n totalResultCount: number\n warnings: string[]\n csvPath: string | null\n cities: DirectoryCity[]\n}\n\nexport function directoryRows(result: DirectoryWorkflowApiResult): Array<Record<string, unknown>> {\n const rows: Array<Record<string, unknown>> = []\n for (const city of result.cities) {\n if (!city.results.length) {\n rows.push({\n source_query: result.query,\n source_location: city.location,\n city: city.city,\n state: city.state,\n population: city.population,\n result_position: null,\n business_name: null,\n review_stars: null,\n review_count: null,\n category: null,\n address: null,\n phone: null,\n website_url: null,\n place_url: null,\n cid: null,\n cid_decimal: null,\n result_status: city.status,\n error: city.error,\n })\n continue\n }\n for (const business of city.results) {\n rows.push({\n source_query: result.query,\n source_location: city.location,\n city: city.city,\n state: city.state,\n population: city.population,\n result_position: business.position,\n business_name: business.name,\n review_stars: business.rating,\n review_count: business.reviewCount,\n category: business.category,\n address: business.address,\n phone: business.phone,\n website_url: business.websiteUrl,\n place_url: business.placeUrl,\n cid: business.cid,\n cid_decimal: business.cidDecimal,\n result_status: city.status,\n error: city.error,\n })\n }\n }\n return rows\n}\n\nexport const DIRECTORY_CSV_HEADERS = [\n 'source_query',\n 'source_location',\n 'city',\n 'state',\n 'population',\n 'result_position',\n 'business_name',\n 'review_stars',\n 'review_count',\n 'category',\n 'address',\n 'phone',\n 'website_url',\n 'place_url',\n 'cid',\n 'cid_decimal',\n 'result_status',\n 'error',\n]\n\nexport const directoryWorkflowDefinition: WorkflowDefinition<DirectoryWorkflowCliInput> = {\n id: 'directory',\n title: 'Directory Workflow',\n description: 'Select city markets and export Google Maps business candidates.',\n inputSchema: DirectoryWorkflowCliInputSchema,\n async run(input: DirectoryWorkflowCliInput, ctx: WorkflowRunContext): Promise<WorkflowRunSummary> {\n await ctx.artifacts.writeManifest('running', {}, [], [])\n const result = await ctx.client.post<DirectoryWorkflowApiResult>('/directory/run', input as Record<string, unknown>, 900_000)\n await ctx.artifacts.writeJson('Directory evidence', 'evidence.json', result)\n const rows = directoryRows(result)\n await ctx.artifacts.writeCsv('Directory CSV', 'exports/directory.csv', DIRECTORY_CSV_HEADERS, rows)\n\n const cityRows = result.cities.map(city => ({\n city: city.city,\n state: city.state,\n population: city.population,\n status: city.status,\n result_count: city.resultCount,\n error: city.error ?? '',\n }))\n const topRows = rows\n .filter(row => row.business_name)\n .slice(0, 100)\n .map(row => ({\n city: row.city,\n position: row.result_position,\n business: row.business_name,\n rating: row.review_stars,\n reviews: row.review_count,\n category: row.category,\n website: row.website_url,\n }))\n\n const summary = `${result.selectedCityCount} cities processed with ${result.totalResultCount} Maps results.`\n await ctx.artifacts.writeText('Summary', 'summary.md', `# Directory Workflow\\n\\n${summary}\\n`)\n const reportPath = await ctx.artifacts.writeHtml('HTML report', 'report.html', renderWorkflowReport({\n title: 'Directory Workflow',\n subtitle: `${input.query} · ${input.state}`,\n summary,\n warnings: result.warnings,\n tables: [\n { title: 'Cities', columns: ['city', 'state', 'population', 'status', 'result_count', 'error'], rows: cityRows },\n { title: 'Top Results', columns: ['city', 'position', 'business', 'rating', 'reviews', 'category', 'website'], rows: topRows },\n ],\n }))\n const status = result.cities.some(city => city.status === 'failed') ? 'partial' : 'succeeded'\n const counts = { cities: result.selectedCityCount, results: result.totalResultCount, rows: rows.length }\n await ctx.artifacts.writeManifest(status, counts, result.warnings, [])\n return { title: 'Directory Workflow', summary, status, counts, warnings: result.warnings, errors: [], reportPath }\n },\n}\n\n","import { z } from 'zod'\nimport { renderWorkflowReport } from '../report-renderer.js'\nimport type { WorkflowDefinition, WorkflowRunContext, WorkflowRunSummary } from '../types.js'\nimport { DIRECTORY_CSV_HEADERS, directoryRows, type DirectoryWorkflowApiResult } from './directory.js'\n\nconst LocalCompetitiveAuditInputSchema = z.object({\n query: z.string().min(1),\n state: z.string().min(2).default('TN'),\n minPopulation: z.number().int().min(0).default(100_000),\n maxCities: z.number().int().min(1).max(100).default(25),\n maxResultsPerCity: z.number().int().min(1).max(50).default(20),\n hydrateTop: z.number().int().min(0).max(10).default(5),\n maxReviews: z.number().int().min(0).max(500).default(50),\n concurrency: z.number().int().min(1).max(5).default(5),\n proxyMode: z.enum(['location', 'configured', 'none']).default('location'),\n returnPartial: z.boolean().default(true),\n})\n\ntype LocalCompetitiveAuditInput = z.infer<typeof LocalCompetitiveAuditInputSchema>\n\ninterface MapsPlaceIntelResult {\n name: string | null\n rating: string | null\n reviewCount: string | null\n category: string | null\n website: string | null\n reviewsStatus: string\n reviewHistogram: Array<{ stars: number; count: string }>\n reviewTopics: Array<{ label: string; count: string }>\n aboutAttributes: Array<{ section: string; attribute: string }>\n reviews: Array<{ stars: string | null; text: string | null; ownerResponse: string | null }>\n}\n\nasync function mapLimit<T, R>(items: T[], limit: number, fn: (item: T, index: number) => Promise<R>): Promise<R[]> {\n const out: R[] = new Array(items.length)\n let next = 0\n async function worker(): Promise<void> {\n while (next < items.length) {\n const index = next\n next += 1\n out[index] = await fn(items[index], index)\n }\n }\n await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => worker()))\n return out\n}\n\nfunction numberFrom(value: unknown): number | null {\n if (value === null || value === undefined || value === '') return null\n const parsed = Number(String(value).replace(/[^\\d.]/g, ''))\n return Number.isFinite(parsed) ? parsed : null\n}\n\nfunction median(values: Array<number | null>): number | null {\n const nums = values.filter((v): v is number => v !== null).sort((a, b) => a - b)\n if (!nums.length) return null\n return nums[Math.floor(nums.length / 2)] ?? null\n}\n\nfunction termsFrom(texts: string[]): string {\n const stop = new Set(['the', 'and', 'for', 'with', 'that', 'this', 'was', 'were', 'are', 'you', 'our', 'they', 'had', 'have', 'not', 'but', 'from', 'very', 'great', 'good'])\n const counts = new Map<string, number>()\n for (const text of texts) {\n for (const token of text.toLowerCase().replace(/[^a-z0-9\\s]/g, ' ').split(/\\s+/)) {\n if (token.length < 4 || stop.has(token)) continue\n counts.set(token, (counts.get(token) ?? 0) + 1)\n }\n }\n return [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 8).map(([term, count]) => `${term} (${count})`).join('; ')\n}\n\nexport const localCompetitiveAuditWorkflowDefinition: WorkflowDefinition<LocalCompetitiveAuditInput> = {\n id: 'local-competitive-audit',\n title: 'Local Competitive Audit',\n description: 'Audit local Maps competitors, categories, review counts, and review themes across city markets.',\n inputSchema: LocalCompetitiveAuditInputSchema,\n async run(input: LocalCompetitiveAuditInput, ctx: WorkflowRunContext): Promise<WorkflowRunSummary> {\n await ctx.artifacts.writeManifest('running', {}, [], [])\n const warnings: string[] = []\n const errors: string[] = []\n const directory = await ctx.client.post<DirectoryWorkflowApiResult>('/directory/run', {\n query: input.query,\n state: input.state,\n minPopulation: input.minPopulation,\n maxCities: input.maxCities,\n maxResultsPerCity: input.maxResultsPerCity,\n concurrency: input.concurrency,\n proxyMode: input.proxyMode,\n saveCsv: true,\n }, 900_000)\n\n await ctx.artifacts.writeJson('Directory raw JSON', 'raw/directory-workflow.json', directory)\n const baseRows = directoryRows(directory)\n await ctx.artifacts.writeCsv('Base directory CSV', 'exports/directory.csv', DIRECTORY_CSV_HEADERS, baseRows)\n\n const selected = directory.cities.flatMap(city =>\n city.results.slice(0, input.hydrateTop).map(result => ({ city, result })),\n )\n const seen = new Set<string>()\n const deduped = selected.filter(({ city, result }) => {\n const key = result.cid ?? result.placeUrl ?? `${city.location}:${result.name.toLowerCase()}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n\n const hydrated = await mapLimit(deduped, 3, async ({ city, result }, index) => {\n try {\n const detail = await ctx.client.post<MapsPlaceIntelResult>('/maps/place', {\n businessName: result.name,\n location: city.location,\n includeReviews: input.maxReviews > 0,\n maxReviews: Math.max(1, input.maxReviews),\n }, 180_000)\n await ctx.artifacts.writeJson(`${result.name} profile`, `raw/maps-place-intel/${index + 1}-${result.name.toLowerCase().replace(/[^a-z0-9]+/g, '-')}.json`, detail)\n return { city, result, detail, error: null as string | null }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n warnings.push(`Profile hydration failed for ${result.name} (${city.location}): ${message}`)\n return { city, result, detail: null, error: message }\n }\n })\n\n const competitorRows = hydrated.map(({ city, result, detail, error }) => {\n const reviews = detail?.reviews ?? []\n const ownerResponses = reviews.filter(r => r.ownerResponse).length\n return {\n city: city.city,\n state: city.state,\n source_location: city.location,\n result_position: result.position,\n business_name: result.name,\n category: detail?.category ?? result.category,\n review_stars: detail?.rating ?? result.rating,\n review_count: detail?.reviewCount ?? result.reviewCount,\n phone: result.phone,\n website_url: detail?.website ?? result.websiteUrl,\n place_url: result.placeUrl,\n cid: result.cid,\n cid_decimal: result.cidDecimal,\n hydrated: detail ? 'true' : 'false',\n reviews_status: detail?.reviewsStatus ?? '',\n review_topics: (detail?.reviewTopics ?? []).map(t => `${t.label} (${t.count})`).join('; '),\n owner_response_rate: reviews.length ? (ownerResponses / reviews.length).toFixed(2) : '',\n error: error ?? '',\n }\n })\n\n const reviewInsightRows = hydrated.map(({ city, result, detail }) => {\n const reviews = detail?.reviews ?? []\n const positive = reviews.filter(r => Number(r.stars) >= 5 && r.text).map(r => r.text!)\n const negative = reviews.filter(r => Number(r.stars) > 0 && Number(r.stars) <= 3 && r.text).map(r => r.text!)\n return {\n city: city.city,\n business_name: result.name,\n cid: result.cid,\n review_count: detail?.reviewCount ?? result.reviewCount,\n average_rating: detail?.rating ?? result.rating,\n topics: (detail?.reviewTopics ?? []).map(t => `${t.label} (${t.count})`).join('; '),\n praise_terms: termsFrom(positive),\n complaint_terms: termsFrom(negative),\n positive_sample: positive[0]?.slice(0, 280) ?? '',\n negative_sample: negative[0]?.slice(0, 280) ?? '',\n }\n })\n\n const citySummaryRows = directory.cities.map(city => {\n const resultReviewCounts = city.results.map(r => numberFrom(r.reviewCount))\n const resultRatings = city.results.map(r => numberFrom(r.rating))\n const topThreeReviews = city.results.slice(0, 3).map(r => numberFrom(r.reviewCount)).filter((v): v is number => v !== null)\n const categories = new Map<string, number>()\n for (const result of city.results) {\n if (!result.category) continue\n categories.set(result.category, (categories.get(result.category) ?? 0) + 1)\n }\n const medReviews = median(resultReviewCounts)\n const medRating = median(resultRatings)\n const topThreeAvg = topThreeReviews.length ? Math.round(topThreeReviews.reduce((a, b) => a + b, 0) / topThreeReviews.length) : null\n const difficulty = Math.min(100, Math.round((topThreeAvg ?? 0) / 20 + (medRating ?? 0) * 10 + city.results.filter(r => r.websiteUrl).length))\n const opportunity = Math.max(0, 100 - difficulty)\n return {\n city: city.city,\n state: city.state,\n population: city.population,\n result_count: city.resultCount,\n median_review_count: medReviews ?? '',\n median_rating: medRating ?? '',\n top_three_average_review_count: topThreeAvg ?? '',\n top_categories: [...categories.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([cat, count]) => `${cat} (${count})`).join('; '),\n opportunity_score: opportunity,\n difficulty_score: difficulty,\n }\n })\n\n await ctx.artifacts.writeCsv('Competitors CSV', 'competitors.csv', ['city', 'state', 'source_location', 'result_position', 'business_name', 'category', 'review_stars', 'review_count', 'phone', 'website_url', 'place_url', 'cid', 'cid_decimal', 'hydrated', 'reviews_status', 'review_topics', 'owner_response_rate', 'error'], competitorRows)\n await ctx.artifacts.writeCsv('Review insights CSV', 'review-insights.csv', ['city', 'business_name', 'cid', 'review_count', 'average_rating', 'topics', 'praise_terms', 'complaint_terms', 'positive_sample', 'negative_sample'], reviewInsightRows)\n await ctx.artifacts.writeCsv('City summary CSV', 'city-summary.csv', ['city', 'state', 'population', 'result_count', 'median_review_count', 'median_rating', 'top_three_average_review_count', 'top_categories', 'opportunity_score', 'difficulty_score'], citySummaryRows)\n await ctx.artifacts.writeJson('Audit evidence', 'evidence.json', { input, directory, hydrated, citySummaryRows, competitorRows, reviewInsightRows })\n await ctx.artifacts.writeText('Agent tasks', 'tasks.md', [\n '# Local Competitive Audit Tasks',\n '',\n '- [ ] Review city opportunity and difficulty scores as heuristics, not absolute truth.',\n '- [ ] Use review topics and samples as customer-language evidence.',\n '- [ ] Compare target GBP category, review count, and website quality against top competitors.',\n '- [ ] Identify cities with low review-count leaders and weak website coverage.',\n ].join('\\n'))\n\n const summary = `${directory.selectedCityCount} cities, ${directory.totalResultCount} Maps results, ${hydrated.filter(h => h.detail).length} hydrated profiles.`\n await ctx.artifacts.writeText('Summary', 'summary.md', `# Local Competitive Audit\\n\\n${summary}\\n`)\n const reportPath = await ctx.artifacts.writeHtml('HTML report', 'report.html', renderWorkflowReport({\n title: 'Local Competitive Audit',\n subtitle: `${input.query} · ${input.state}`,\n summary,\n warnings,\n tables: [\n { title: 'City Opportunity', columns: ['city', 'state', 'population', 'result_count', 'median_review_count', 'median_rating', 'top_three_average_review_count', 'top_categories', 'opportunity_score', 'difficulty_score'], rows: citySummaryRows },\n { title: 'Hydrated Competitors', columns: ['city', 'result_position', 'business_name', 'category', 'review_stars', 'review_count', 'hydrated', 'review_topics'], rows: competitorRows.slice(0, 100) },\n { title: 'Review Insights', columns: ['city', 'business_name', 'topics', 'praise_terms', 'complaint_terms'], rows: reviewInsightRows.slice(0, 100) },\n ],\n }))\n\n const status = warnings.length || directory.cities.some(city => city.status === 'failed') ? 'partial' : 'succeeded'\n const counts = { cities: directory.selectedCityCount, mapsResults: directory.totalResultCount, hydratedProfiles: hydrated.filter(h => h.detail).length }\n await ctx.artifacts.writeManifest(status, counts, warnings, errors)\n return { title: 'Local Competitive Audit', summary, status, counts, warnings, errors, reportPath }\n },\n}\n\n","import { z } from 'zod'\nimport { renderWorkflowReport } from '../report-renderer.js'\nimport type { WorkflowDefinition, WorkflowRunContext, WorkflowRunSummary } from '../types.js'\nimport { DIRECTORY_CSV_HEADERS, directoryRows, type DirectoryWorkflowApiResult } from './directory.js'\nimport {\n classifySentence,\n domainFromUrl,\n mapLimit,\n median,\n normalizeDomain,\n numberFrom,\n pageSummaryRow,\n questionRows,\n sourceDomainRows,\n splitSentences,\n textTerms,\n type ExtractUrlResult,\n type HarvestLike,\n type MapsSearchBusinessLike,\n type MapsSearchResultLike,\n type OrganicResult,\n} from './seo-workflow-utils.js'\n\nconst ProxyModeSchema = z.enum(['location', 'configured', 'none'])\n\nconst MapComparisonInputSchema = z.object({\n query: z.string().min(1),\n location: z.string().optional(),\n state: z.string().optional(),\n minPopulation: z.number().int().min(0).default(100_000),\n maxCities: z.number().int().min(1).max(100).default(5),\n maxResultsPerCity: z.number().int().min(1).max(50).default(20),\n hydrateTop: z.number().int().min(0).max(10).default(5),\n maxReviews: z.number().int().min(0).max(500).default(25),\n concurrency: z.number().int().min(1).max(5).default(5),\n proxyMode: ProxyModeSchema.default('location'),\n returnPartial: z.boolean().default(true),\n}).refine(input => input.location || input.state, {\n message: 'Either location or state is required for map-comparison',\n})\n\nconst SerpComparisonInputSchema = z.object({\n keyword: z.string().min(1),\n domain: z.string().optional(),\n url: z.string().url().optional(),\n location: z.string().optional(),\n maxResults: z.number().int().min(1).max(20).default(10),\n maxQuestions: z.number().int().min(1).max(200).default(40),\n extractTop: z.number().int().min(0).max(10).default(5),\n includePaa: z.boolean().default(true),\n includeAiOverview: z.boolean().default(true),\n returnPartial: z.boolean().default(true),\n})\n\nconst PaaExpansionBriefInputSchema = z.object({\n keyword: z.string().min(1),\n location: z.string().optional(),\n maxQuestions: z.number().int().min(1).max(300).default(80),\n depth: z.number().int().min(1).max(6).default(3),\n returnPartial: z.boolean().default(true),\n})\n\nconst AiOverviewLanguageInputSchema = z.object({\n keyword: z.string().min(1),\n domain: z.string().optional(),\n url: z.string().url().optional(),\n location: z.string().optional(),\n maxQuestions: z.number().int().min(1).max(200).default(40),\n extractTop: z.number().int().min(0).max(8).default(3),\n returnPartial: z.boolean().default(true),\n})\n\ntype MapComparisonInput = z.infer<typeof MapComparisonInputSchema>\ntype SerpComparisonInput = z.infer<typeof SerpComparisonInputSchema>\ntype PaaExpansionBriefInput = z.infer<typeof PaaExpansionBriefInputSchema>\ntype AiOverviewLanguageInput = z.infer<typeof AiOverviewLanguageInputSchema>\n\ninterface MapsPlaceIntelResult {\n name?: string | null\n rating?: string | null\n reviewCount?: string | null\n category?: string | null\n website?: string | null\n reviewsStatus?: string\n reviewTopics?: Array<{ label: string; count: string }>\n aboutAttributes?: Array<{ section: string; attribute: string }>\n reviews?: Array<{ stars: string | null; text: string | null; ownerResponse: string | null }>\n}\n\nfunction businessRowsFromMaps(location: string, query: string, results: MapsSearchBusinessLike[]): Array<Record<string, unknown>> {\n return results.map(result => ({\n source_query: query,\n source_location: location,\n city: location.split(',')[0]?.trim() ?? location,\n state: location.split(',')[1]?.trim() ?? '',\n population: '',\n result_position: result.position,\n business_name: result.name,\n review_stars: result.rating ?? '',\n review_count: result.reviewCount ?? '',\n category: result.category ?? '',\n address: result.address ?? '',\n phone: result.phone ?? '',\n website_url: result.websiteUrl ?? '',\n place_url: result.placeUrl ?? '',\n cid: result.cid ?? '',\n cid_decimal: result.cidDecimal ?? '',\n result_status: 'ok',\n error: '',\n }))\n}\n\nfunction marketRows(rows: Array<Record<string, unknown>>): Array<Record<string, unknown>> {\n const byLocation = new Map<string, Array<Record<string, unknown>>>()\n for (const row of rows) {\n const key = String(row.source_location ?? row.location ?? '')\n if (!key) continue\n const list = byLocation.get(key) ?? []\n list.push(row)\n byLocation.set(key, list)\n }\n return [...byLocation.entries()].map(([location, list]) => {\n const counts = list.map(row => numberFrom(row.review_count))\n const ratings = list.map(row => numberFrom(row.review_stars))\n const topThree = list.slice(0, 3).map(row => numberFrom(row.review_count)).filter((v): v is number => v !== null)\n const categories = new Map<string, number>()\n for (const row of list) {\n const category = String(row.category ?? '')\n if (category) categories.set(category, (categories.get(category) ?? 0) + 1)\n }\n return {\n source_location: location,\n result_count: list.filter(row => row.business_name).length,\n median_review_count: median(counts) ?? '',\n median_rating: median(ratings) ?? '',\n top_three_average_review_count: topThree.length ? Math.round(topThree.reduce((a, b) => a + b, 0) / topThree.length) : '',\n top_categories: [...categories.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([cat, count]) => `${cat} (${count})`).join('; '),\n websites_present: list.filter(row => row.website_url).length,\n }\n })\n}\n\nfunction comparisonRows(rows: Array<Record<string, unknown>>): Array<Record<string, unknown>> {\n const benchmarkByLocation = new Map<string, number>()\n for (const market of marketRows(rows)) {\n benchmarkByLocation.set(String(market.source_location), numberFrom(market.top_three_average_review_count) ?? 0)\n }\n return rows\n .filter(row => row.business_name)\n .map(row => {\n const reviews = numberFrom(row.review_count) ?? 0\n const benchmark = benchmarkByLocation.get(String(row.source_location)) ?? 0\n const websiteMissing = !row.website_url\n const rank = numberFrom(row.result_position) ?? 999\n return {\n source_location: row.source_location,\n result_position: row.result_position,\n business_name: row.business_name,\n category: row.category,\n review_stars: row.review_stars,\n review_count: row.review_count,\n review_gap_to_top3_average: benchmark ? Math.max(0, benchmark - reviews) : '',\n website_url: row.website_url,\n place_url: row.place_url,\n comparison_note: rank <= 3 ? 'visible leader' : websiteMissing ? 'ranking without website' : reviews < benchmark ? 'review-light competitor' : 'visible competitor',\n }\n })\n}\n\nfunction organicRows(serp: HarvestLike | null, targetDomain: string | null): Array<Record<string, unknown>> {\n return (serp?.organicResults ?? []).map(result => {\n const url = result.url ?? ''\n const domain = normalizeDomain(result.domain ?? '') ?? domainFromUrl(url)\n return {\n position: result.position ?? '',\n title: result.title ?? '',\n url,\n domain,\n snippet: result.snippet ?? '',\n is_target: targetDomain ? domain === targetDomain : false,\n }\n })\n}\n\nfunction pageGapRows(targetPage: ExtractUrlResult | null, competitorPages: Array<{ source: OrganicResult; page: ExtractUrlResult }>): Array<Record<string, unknown>> {\n const targetHeadingText = new Set((targetPage?.headings ?? []).map(h => h.text.toLowerCase().replace(/[^a-z0-9\\s]/g, ' ').trim()))\n const targetTerms = new Set((targetPage?.headings ?? []).flatMap(h => h.text.toLowerCase().replace(/[^a-z0-9\\s]/g, ' ').split(/\\s+/).filter(Boolean)))\n const rows: Array<Record<string, unknown>> = []\n for (const { source, page } of competitorPages) {\n for (const heading of page.headings ?? []) {\n if (heading.level > 3 || !heading.text) continue\n const normalized = heading.text.toLowerCase().replace(/[^a-z0-9\\s]/g, ' ').trim()\n const terms = normalized.split(/\\s+/).filter(term => term.length > 3)\n const overlap = terms.filter(term => targetTerms.has(term)).length\n const covered = targetHeadingText.has(normalized) || overlap >= Math.max(2, Math.ceil(terms.length / 2))\n if (covered && targetPage) continue\n rows.push({\n source_position: source.position ?? '',\n source_domain: normalizeDomain(source.domain ?? '') ?? domainFromUrl(source.url),\n source_url: source.url ?? '',\n heading_level: heading.level,\n competitor_heading: heading.text,\n target_coverage: targetPage ? 'not found in target headings' : 'no target page extracted',\n terms: textTerms(heading.text, 6),\n })\n }\n }\n return rows.slice(0, 150)\n}\n\nasync function extractPages(ctx: WorkflowRunContext, sources: OrganicResult[], warnings: string[], labelPrefix: string): Promise<Array<{ source: OrganicResult; page: ExtractUrlResult }>> {\n return mapLimit(sources.filter(source => source.url), 2, async (source, index) => {\n try {\n const page = await ctx.client.post<ExtractUrlResult>('/extract-url', { url: source.url }, 180_000)\n await ctx.artifacts.writeJson(`${labelPrefix} ${index + 1}`, `raw/extract-url/${labelPrefix.toLowerCase()}-${index + 1}.json`, page)\n return { source, page }\n } catch (err) {\n warnings.push(`Page extraction failed for ${source.url}: ${err instanceof Error ? err.message : String(err)}`)\n return null\n }\n }).then(items => items.filter((item): item is { source: OrganicResult; page: ExtractUrlResult } => item !== null))\n}\n\nexport const mapComparisonWorkflowDefinition: WorkflowDefinition<MapComparisonInput> = {\n id: 'map-comparison',\n title: 'Maps Comparison',\n description: 'Compare Google Maps competitors by rank, reviews, stars, categories, websites, and profile/review signals.',\n inputSchema: MapComparisonInputSchema,\n async run(input: MapComparisonInput, ctx: WorkflowRunContext): Promise<WorkflowRunSummary> {\n await ctx.artifacts.writeManifest('running', {}, [], [])\n const warnings: string[] = []\n let rows: Array<Record<string, unknown>>\n let directory: DirectoryWorkflowApiResult | null = null\n let mapsSearch: MapsSearchResultLike | null = null\n\n if (input.location) {\n mapsSearch = await ctx.client.post<MapsSearchResultLike>('/maps/search', {\n query: input.query,\n location: input.location,\n maxResults: input.maxResultsPerCity,\n proxyMode: input.proxyMode,\n }, 240_000)\n rows = businessRowsFromMaps(input.location, input.query, mapsSearch.results)\n await ctx.artifacts.writeJson('Maps search raw JSON', 'raw/maps-search.json', mapsSearch)\n } else {\n directory = await ctx.client.post<DirectoryWorkflowApiResult>('/directory/run', {\n query: input.query,\n state: input.state,\n minPopulation: input.minPopulation,\n maxCities: input.maxCities,\n maxResultsPerCity: input.maxResultsPerCity,\n concurrency: input.concurrency,\n proxyMode: input.proxyMode,\n saveCsv: true,\n }, 900_000)\n rows = directoryRows(directory)\n await ctx.artifacts.writeJson('Directory raw JSON', 'raw/directory-workflow.json', directory)\n await ctx.artifacts.writeCsv('Directory CSV', 'exports/directory.csv', DIRECTORY_CSV_HEADERS, rows)\n warnings.push(...directory.warnings)\n }\n\n const compareRows = comparisonRows(rows)\n const selected = compareRows.slice(0, input.hydrateTop * Math.max(1, input.location ? 1 : input.maxCities))\n const hydrated = await mapLimit(selected, 3, async (row, index) => {\n try {\n const detail = await ctx.client.post<MapsPlaceIntelResult>('/maps/place', {\n businessName: row.business_name,\n location: row.source_location,\n includeReviews: input.maxReviews > 0,\n maxReviews: Math.max(1, input.maxReviews),\n }, 180_000)\n await ctx.artifacts.writeJson(`${row.business_name} profile`, `raw/maps-place-intel/${index + 1}-${String(row.business_name).toLowerCase().replace(/[^a-z0-9]+/g, '-')}.json`, detail)\n return { row, detail, error: '' }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n warnings.push(`Profile hydration failed for ${row.business_name}: ${message}`)\n return { row, detail: null, error: message }\n }\n })\n\n const profileRows = hydrated.map(({ row, detail, error }) => ({\n source_location: row.source_location,\n result_position: row.result_position,\n business_name: row.business_name,\n category: detail?.category ?? row.category,\n review_stars: detail?.rating ?? row.review_stars,\n review_count: detail?.reviewCount ?? row.review_count,\n website_url: detail?.website ?? row.website_url,\n review_topics: (detail?.reviewTopics ?? []).map(t => `${t.label} (${t.count})`).join('; '),\n about_attributes: (detail?.aboutAttributes ?? []).map(a => `${a.section}: ${a.attribute}`).join('; '),\n reviews_status: detail?.reviewsStatus ?? '',\n error,\n }))\n const markets = marketRows(rows)\n await ctx.artifacts.writeCsv('Maps results CSV', 'maps-results.csv', ['source_query', 'source_location', 'city', 'state', 'population', 'result_position', 'business_name', 'review_stars', 'review_count', 'category', 'address', 'phone', 'website_url', 'place_url', 'cid', 'cid_decimal', 'result_status', 'error'], rows)\n await ctx.artifacts.writeCsv('Comparison CSV', 'map-comparison.csv', ['source_location', 'result_position', 'business_name', 'category', 'review_stars', 'review_count', 'review_gap_to_top3_average', 'website_url', 'place_url', 'comparison_note'], compareRows)\n await ctx.artifacts.writeCsv('Profile insights CSV', 'profile-insights.csv', ['source_location', 'result_position', 'business_name', 'category', 'review_stars', 'review_count', 'website_url', 'review_topics', 'about_attributes', 'reviews_status', 'error'], profileRows)\n await ctx.artifacts.writeJson('Maps comparison evidence', 'evidence.json', { input, directory, mapsSearch, rows, compareRows, profileRows, markets, warnings })\n await ctx.artifacts.writeText('Brief', 'brief.md', [\n `# Maps Comparison: ${input.query}`,\n '',\n `Markets: ${markets.map(row => row.source_location).join(', ')}`,\n '',\n '## How to Use',\n '- Compare rank position against review count and category patterns.',\n '- Treat review gaps and missing websites as opportunity signals, not guarantees.',\n '- Use profile topics and attributes as evidence for local content and GBP improvements.',\n ].join('\\n'))\n\n const summary = `${compareRows.length} Maps competitors compared across ${markets.length} market(s); ${profileRows.filter(row => !row.error).length} profiles hydrated.`\n const reportPath = await ctx.artifacts.writeHtml('HTML report', 'report.html', renderWorkflowReport({\n title: 'Maps Comparison',\n subtitle: `${input.query}${input.location ? ` · ${input.location}` : input.state ? ` · ${input.state}` : ''}`,\n summary,\n warnings,\n tables: [\n { title: 'Market Benchmarks', columns: ['source_location', 'result_count', 'median_review_count', 'median_rating', 'top_three_average_review_count', 'top_categories', 'websites_present'], rows: markets },\n { title: 'Competitor Comparison', columns: ['source_location', 'result_position', 'business_name', 'category', 'review_stars', 'review_count', 'review_gap_to_top3_average', 'comparison_note'], rows: compareRows.slice(0, 120) },\n { title: 'Profile Insights', columns: ['source_location', 'business_name', 'review_topics', 'about_attributes', 'error'], rows: profileRows },\n ],\n }))\n const status = warnings.length ? 'partial' : 'succeeded'\n const counts = { markets: markets.length, competitors: compareRows.length, hydratedProfiles: profileRows.filter(row => !row.error).length }\n await ctx.artifacts.writeManifest(status, counts, warnings, [])\n return { title: 'Maps Comparison', summary, status, counts, warnings, errors: [], reportPath }\n },\n}\n\nexport const serpComparisonWorkflowDefinition: WorkflowDefinition<SerpComparisonInput> = {\n id: 'serp-comparison',\n title: 'SERP Comparison',\n description: 'Compare ranking pages, SERP features, PAA evidence, AI Overview citations, and page-level content gaps.',\n inputSchema: SerpComparisonInputSchema,\n async run(input: SerpComparisonInput, ctx: WorkflowRunContext): Promise<WorkflowRunSummary> {\n await ctx.artifacts.writeManifest('running', {}, [], [])\n const warnings: string[] = []\n const targetDomain = normalizeDomain(input.domain ?? input.url ?? null)\n const serp = await ctx.client.post<HarvestLike>('/harvest/sync', {\n query: input.keyword,\n location: input.location,\n serpOnly: true,\n maxQuestions: 1,\n format: 'json',\n }, 180_000)\n await ctx.artifacts.writeJson('SERP raw JSON', 'raw/serp.json', serp)\n\n let paa: HarvestLike | null = null\n if (input.includePaa) {\n try {\n paa = await ctx.client.post<HarvestLike>('/harvest/sync', {\n query: input.keyword,\n location: input.location,\n maxQuestions: input.maxQuestions,\n format: 'json',\n }, 280_000)\n await ctx.artifacts.writeJson('PAA raw JSON', 'raw/paa.json', paa)\n } catch (err) {\n warnings.push(`PAA evidence unavailable: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n\n const organic = organicRows(serp, targetDomain).slice(0, input.maxResults)\n const organicSources = (serp.organicResults ?? []).slice(0, input.maxResults)\n const targetSource = input.url\n ? { position: 0, title: 'Target page', url: input.url, domain: domainFromUrl(input.url) }\n : organicSources.find(result => targetDomain && (normalizeDomain(result.domain ?? '') ?? domainFromUrl(result.url)) === targetDomain)\n const competitorSources = organicSources\n .filter(result => result.url && result.url !== targetSource?.url)\n .filter(result => !targetDomain || (normalizeDomain(result.domain ?? '') ?? domainFromUrl(result.url)) !== targetDomain)\n .slice(0, input.extractTop)\n\n const targetPages = targetSource ? await extractPages(ctx, [targetSource], warnings, 'Target') : []\n const competitorPages = input.extractTop > 0 ? await extractPages(ctx, competitorSources, warnings, 'Competitor') : []\n const targetPage = targetPages[0]?.page ?? null\n const pageRows = [\n ...targetPages.map(({ source, page }) => pageSummaryRow(page, { url: source.url ?? '', domain: normalizeDomain(source.domain ?? '') ?? domainFromUrl(source.url), position: source.position, title: source.title })),\n ...competitorPages.map(({ source, page }) => pageSummaryRow(page, { url: source.url ?? '', domain: normalizeDomain(source.domain ?? '') ?? domainFromUrl(source.url), position: source.position, title: source.title })),\n ]\n const gaps = pageGapRows(targetPage, competitorPages)\n const questions = questionRows(paa)\n const aiRows = (serp.aiOverview?.citations ?? []).map((citation, index) => ({\n citation_position: index + 1,\n citation_text: citation.text ?? '',\n url: citation.href ?? '',\n domain: domainFromUrl(citation.href ?? ''),\n is_target: targetDomain ? domainFromUrl(citation.href ?? '') === targetDomain : false,\n }))\n await ctx.artifacts.writeCsv('Organic results CSV', 'organic-results.csv', ['position', 'title', 'url', 'domain', 'snippet', 'is_target'], organic)\n await ctx.artifacts.writeCsv('Page comparison CSV', 'page-comparison.csv', ['position', 'domain', 'url', 'serp_title', 'page_title', 'h1', 'meta_description', 'word_count', 'heading_count', 'schema_types'], pageRows)\n await ctx.artifacts.writeCsv('Content gaps CSV', 'content-gaps.csv', ['source_position', 'source_domain', 'source_url', 'heading_level', 'competitor_heading', 'target_coverage', 'terms'], gaps)\n await ctx.artifacts.writeCsv('PAA questions CSV', 'paa-questions.csv', ['position', 'intent', 'question', 'answer_excerpt', 'source_title', 'source_domain', 'source_url'], questions)\n await ctx.artifacts.writeCsv('AI Overview citations CSV', 'ai-overview-citations.csv', ['citation_position', 'citation_text', 'url', 'domain', 'is_target'], aiRows)\n await ctx.artifacts.writeJson('SERP comparison evidence', 'evidence.json', { input, serp, paa, organic, pageRows, gaps, questions, aiRows, warnings })\n await ctx.artifacts.writeText('Writer brief', 'brief.md', [\n `# SERP Comparison Brief: ${input.keyword}`,\n '',\n `Target: ${targetDomain ?? input.url ?? 'not specified'}`,\n `Location: ${input.location ?? 'not specified'}`,\n '',\n '## Recommended Actions',\n '- Use `content-gaps.csv` to decide which missing sections deserve coverage.',\n '- Use `paa-questions.csv` for FAQ and answer-block candidates.',\n '- Use `ai-overview-citations.csv` to see whether the target is cited in AI Overview evidence.',\n '- Treat extracted page headings as evidence, not a complete semantic analysis.',\n ].join('\\n'))\n const summary = `${organic.length} organic results, ${pageRows.length} extracted pages, ${gaps.length} heading gaps, ${questions.length} PAA questions.`\n const reportPath = await ctx.artifacts.writeHtml('HTML report', 'report.html', renderWorkflowReport({\n title: 'SERP Comparison',\n subtitle: `${input.keyword}${input.location ? ` · ${input.location}` : ''}`,\n summary,\n warnings,\n tables: [\n { title: 'Organic Results', columns: ['position', 'title', 'domain', 'is_target'], rows: organic },\n { title: 'Page Comparison', columns: ['position', 'domain', 'h1', 'word_count', 'heading_count', 'schema_types'], rows: pageRows },\n { title: 'Content Gaps', columns: ['source_position', 'source_domain', 'competitor_heading', 'target_coverage', 'terms'], rows: gaps.slice(0, 80) },\n { title: 'PAA Questions', columns: ['position', 'intent', 'question', 'source_domain'], rows: questions.slice(0, 80) },\n ],\n }))\n const status = warnings.length ? 'partial' : 'succeeded'\n const counts = { organic: organic.length, pages: pageRows.length, gaps: gaps.length, questions: questions.length, aiCitations: aiRows.length }\n await ctx.artifacts.writeManifest(status, counts, warnings, [])\n return { title: 'SERP Comparison', summary, status, counts, warnings, errors: [], reportPath }\n },\n}\n\nexport const paaExpansionBriefWorkflowDefinition: WorkflowDefinition<PaaExpansionBriefInput> = {\n id: 'paa-expansion-brief',\n title: 'PAA Expansion Brief',\n description: 'Expand People Also Ask questions into an evidence-backed writer brief, section map, and source table.',\n inputSchema: PaaExpansionBriefInputSchema,\n async run(input: PaaExpansionBriefInput, ctx: WorkflowRunContext): Promise<WorkflowRunSummary> {\n await ctx.artifacts.writeManifest('running', {}, [], [])\n const warnings: string[] = []\n const paa = await ctx.client.post<HarvestLike>('/harvest/sync', {\n query: input.keyword,\n location: input.location,\n maxQuestions: input.maxQuestions,\n depth: input.depth,\n format: 'json',\n }, 300_000)\n await ctx.artifacts.writeJson('PAA raw JSON', 'raw/paa.json', paa)\n const questions = questionRows(paa)\n const sourceRows = sourceDomainRows(questions)\n const byIntent = new Map<string, Array<Record<string, unknown>>>()\n for (const row of questions) {\n const list = byIntent.get(String(row.intent)) ?? []\n list.push(row)\n byIntent.set(String(row.intent), list)\n }\n const sectionRows = [...byIntent.entries()].map(([intent, rows]) => ({\n recommended_section: intent,\n question_count: rows.length,\n sample_questions: rows.slice(0, 5).map(row => row.question).join(' | '),\n source_domains: [...new Set(rows.map(row => row.source_domain).filter(Boolean))].slice(0, 5).join('; '),\n terms: textTerms(rows.map(row => `${row.question} ${row.answer_excerpt}`).join(' '), 10),\n })).sort((a, b) => Number(b.question_count) - Number(a.question_count))\n\n await ctx.artifacts.writeCsv('PAA questions CSV', 'paa-questions.csv', ['position', 'intent', 'question', 'answer_excerpt', 'source_title', 'source_domain', 'source_url'], questions)\n await ctx.artifacts.writeCsv('Source domains CSV', 'source-domains.csv', ['domain', 'question_mentions', 'source_url_count', 'top_intents'], sourceRows)\n await ctx.artifacts.writeCsv('Section map CSV', 'section-map.csv', ['recommended_section', 'question_count', 'sample_questions', 'source_domains', 'terms'], sectionRows)\n await ctx.artifacts.writeJson('PAA brief evidence', 'evidence.json', { input, paa, questions, sourceRows, sectionRows })\n await ctx.artifacts.writeText('Writer brief', 'writer-brief.md', [\n `# PAA Expansion Brief: ${input.keyword}`,\n '',\n `Location: ${input.location ?? 'not specified'}`,\n '',\n '## Suggested Page Structure',\n ...sectionRows.map(row => `- ${row.recommended_section}: answer ${row.question_count} related question(s). Sample: ${row.sample_questions}`),\n '',\n '## Writing Rules',\n '- Answer the highest-frequency question in the first 60 words of each section.',\n '- Use exact customer question language from `paa-questions.csv` for H2/H3 candidates.',\n '- Use `source-domains.csv` to identify which source types Google is already rewarding.',\n '- Do not invent citations; cite only rows that have a source URL.',\n ].join('\\n'))\n const summary = `${questions.length} PAA questions grouped into ${sectionRows.length} writing sections.`\n const reportPath = await ctx.artifacts.writeHtml('HTML report', 'report.html', renderWorkflowReport({\n title: 'PAA Expansion Brief',\n subtitle: `${input.keyword}${input.location ? ` · ${input.location}` : ''}`,\n summary,\n warnings,\n tables: [\n { title: 'Section Map', columns: ['recommended_section', 'question_count', 'sample_questions', 'source_domains', 'terms'], rows: sectionRows },\n { title: 'Questions', columns: ['position', 'intent', 'question', 'source_domain'], rows: questions.slice(0, 120) },\n { title: 'Source Domains', columns: ['domain', 'question_mentions', 'source_url_count', 'top_intents'], rows: sourceRows },\n ],\n }))\n const counts = { questions: questions.length, sections: sectionRows.length, sourceDomains: sourceRows.length }\n await ctx.artifacts.writeManifest('succeeded', counts, warnings, [])\n return { title: 'PAA Expansion Brief', summary, status: 'succeeded', counts, warnings, errors: [], reportPath }\n },\n}\n\nexport const aiOverviewLanguageWorkflowDefinition: WorkflowDefinition<AiOverviewLanguageInput> = {\n id: 'ai-overview-language',\n title: 'AI Overview Language Brief',\n description: 'Turn AI Overview, citation, PAA, and ranking-page evidence into answer-block and citation-hook guidance.',\n inputSchema: AiOverviewLanguageInputSchema,\n async run(input: AiOverviewLanguageInput, ctx: WorkflowRunContext): Promise<WorkflowRunSummary> {\n await ctx.artifacts.writeManifest('running', {}, [], [])\n const warnings: string[] = []\n const targetDomain = normalizeDomain(input.domain ?? input.url ?? null)\n const serp = await ctx.client.post<HarvestLike>('/harvest/sync', {\n query: input.keyword,\n location: input.location,\n serpOnly: true,\n maxQuestions: 1,\n format: 'json',\n }, 180_000)\n await ctx.artifacts.writeJson('SERP raw JSON', 'raw/serp.json', serp)\n let paa: HarvestLike | null = null\n try {\n paa = await ctx.client.post<HarvestLike>('/harvest/sync', {\n query: input.keyword,\n location: input.location,\n maxQuestions: input.maxQuestions,\n format: 'json',\n }, 280_000)\n await ctx.artifacts.writeJson('PAA raw JSON', 'raw/paa.json', paa)\n } catch (err) {\n warnings.push(`PAA evidence unavailable: ${err instanceof Error ? err.message : String(err)}`)\n }\n\n const citations = (serp.aiOverview?.citations ?? []).map((citation, index) => {\n const domain = domainFromUrl(citation.href ?? '')\n return {\n citation_position: index + 1,\n citation_text: citation.text ?? '',\n url: citation.href ?? '',\n domain,\n is_target: targetDomain ? domain === targetDomain : false,\n }\n })\n const aioSentences = splitSentences(serp.aiOverview?.text)\n const claimRows = aioSentences.map((sentence, index) => ({\n position: index + 1,\n claim_type: classifySentence(sentence),\n sentence,\n reusable_pattern: sentence.length > 140 ? `${sentence.slice(0, 140)}...` : sentence,\n }))\n const questions = questionRows(paa)\n const citationSources = (serp.aiOverview?.citations ?? [])\n .filter(citation => citation.href)\n .map((citation, index) => ({ position: index + 1, title: citation.text, url: citation.href, domain: domainFromUrl(citation.href) }))\n .slice(0, input.extractTop)\n const extractedCitations = input.extractTop > 0 ? await extractPages(ctx, citationSources, warnings, 'Citation') : []\n const extractedRows = extractedCitations.map(({ source, page }) => pageSummaryRow(page, { url: source.url ?? '', domain: normalizeDomain(source.domain ?? '') ?? domainFromUrl(source.url), position: source.position, title: source.title }))\n const languageRows = [\n {\n block: 'direct_answer',\n guidance: 'Open with a 40-70 word answer that directly resolves the query before adding context.',\n evidence_basis: questions[0]?.question ?? input.keyword,\n },\n {\n block: 'criteria_or_steps',\n guidance: 'List the criteria, steps, or decision factors Google is already compressing into AI Overview language.',\n evidence_basis: claimRows.filter(row => ['criteria', 'process'].includes(String(row.claim_type))).map(row => row.sentence).slice(0, 3).join(' | '),\n },\n {\n block: 'citation_hook',\n guidance: 'Add source-worthy details competitors can cite: definitions, numbers, examples, process details, and named entity relationships.',\n evidence_basis: citations.map(row => `${row.domain}: ${row.citation_text}`).slice(0, 5).join(' | '),\n },\n {\n block: 'faq_followups',\n guidance: 'Use PAA phrasing for follow-up sections so the page answers adjacent questions in Google language.',\n evidence_basis: questions.slice(0, 5).map(row => row.question).join(' | '),\n },\n ]\n await ctx.artifacts.writeCsv('AI Overview citations CSV', 'ai-overview-citations.csv', ['citation_position', 'citation_text', 'url', 'domain', 'is_target'], citations)\n await ctx.artifacts.writeCsv('AI Overview claim patterns CSV', 'claim-patterns.csv', ['position', 'claim_type', 'sentence', 'reusable_pattern'], claimRows)\n await ctx.artifacts.writeCsv('Language guidance CSV', 'language-guidance.csv', ['block', 'guidance', 'evidence_basis'], languageRows)\n await ctx.artifacts.writeCsv('PAA questions CSV', 'paa-questions.csv', ['position', 'intent', 'question', 'answer_excerpt', 'source_title', 'source_domain', 'source_url'], questions)\n await ctx.artifacts.writeCsv('Extracted citation pages CSV', 'citation-pages.csv', ['position', 'domain', 'url', 'serp_title', 'page_title', 'h1', 'meta_description', 'word_count', 'heading_count', 'schema_types'], extractedRows)\n await ctx.artifacts.writeJson('AI Overview language evidence', 'evidence.json', { input, serp, paa, citations, claimRows, languageRows, extractedRows, warnings })\n await ctx.artifacts.writeText('Answer block template', 'answer-block-template.md', [\n `# AI Overview Language Brief: ${input.keyword}`,\n '',\n `AI Overview detected: ${serp.aiOverview?.detected ? 'yes' : 'no'}`,\n `Target cited: ${targetDomain ? citations.some(row => row.is_target) ? 'yes' : 'no' : 'target not specified'}`,\n '',\n '## Direct Answer Block',\n 'Write one compact answer block that starts with the answer, not background. Keep it clear enough that Google could lift it as a standalone summary.',\n '',\n '## Suggested Follow-Up Blocks',\n ...languageRows.map(row => `- ${row.block}: ${row.guidance}`),\n '',\n '## Evidence to Mirror',\n ...claimRows.slice(0, 8).map(row => `- ${row.claim_type}: ${row.sentence}`),\n '',\n '## Citation Hooks',\n ...citations.slice(0, 8).map(row => `- ${row.domain}: ${row.citation_text}`),\n ].join('\\n'))\n const summary = `${citations.length} AI Overview citations, ${claimRows.length} claim patterns, ${questions.length} PAA questions, ${extractedRows.length} citation pages extracted.`\n const reportPath = await ctx.artifacts.writeHtml('HTML report', 'report.html', renderWorkflowReport({\n title: 'AI Overview Language Brief',\n subtitle: `${input.keyword}${input.location ? ` · ${input.location}` : ''}`,\n summary,\n warnings,\n tables: [\n { title: 'Language Guidance', columns: ['block', 'guidance', 'evidence_basis'], rows: languageRows },\n { title: 'AI Overview Citations', columns: ['citation_position', 'citation_text', 'domain', 'is_target'], rows: citations },\n { title: 'Claim Patterns', columns: ['position', 'claim_type', 'sentence'], rows: claimRows },\n { title: 'PAA Follow-Ups', columns: ['position', 'intent', 'question', 'source_domain'], rows: questions.slice(0, 60) },\n ],\n }))\n const status = warnings.length || !serp.aiOverview?.detected ? 'partial' : 'succeeded'\n const counts = { citations: citations.length, claimPatterns: claimRows.length, questions: questions.length, extractedCitationPages: extractedRows.length }\n await ctx.artifacts.writeManifest(status, counts, warnings, [])\n return { title: 'AI Overview Language Brief', summary, status, counts, warnings, errors: [], reportPath }\n },\n}\n","export interface OrganicResult {\n position?: number\n title?: string\n url?: string\n domain?: string\n snippet?: string | null\n}\n\nexport interface PaaFlatRow {\n question?: string\n answer?: string | null\n source_title?: string | null\n source_site?: string | null\n source_cite?: string | null\n}\n\nexport interface HarvestLike {\n organicResults?: OrganicResult[]\n localPack?: Array<{ position?: number; name?: string; rating?: string | null; reviewCount?: string | null; websiteUrl?: string | null }>\n flat?: PaaFlatRow[]\n aiOverview?: { detected?: boolean; text?: string | null; citations?: Array<{ text?: string; href?: string }> }\n forumResults?: Array<{ title?: string; source?: string; url?: string }>\n videoResults?: Array<{ title?: string; channel?: string; platform?: string; url?: string }>\n}\n\nexport interface ExtractUrlResult {\n url?: string\n canonicalUrl?: string | null\n title?: string | null\n metaDescription?: string | null\n h1?: string | null\n headings?: Array<{ level: number; text: string }>\n wordCount?: number\n schemaTypes?: string[]\n bodyMarkdown?: string\n}\n\nexport interface MapsSearchBusinessLike {\n position: number\n name: string\n rating?: string | null\n reviewCount?: string | null\n category?: string | null\n address?: string | null\n phone?: string | null\n websiteUrl?: string | null\n placeUrl?: string\n cid?: string | null\n cidDecimal?: string | null\n hoursStatus?: string | null\n}\n\nexport interface MapsSearchResultLike {\n query: string\n location?: string | null\n searchQuery?: string\n resultCount: number\n results: MapsSearchBusinessLike[]\n}\n\nconst STOP_WORDS = new Set([\n 'about', 'after', 'also', 'because', 'been', 'best', 'both', 'from', 'have', 'into',\n 'more', 'most', 'near', 'only', 'over', 'than', 'that', 'their', 'them', 'then',\n 'there', 'these', 'they', 'this', 'what', 'when', 'where', 'which', 'while', 'with',\n 'your', 'will', 'would', 'should', 'could', 'does', 'were', 'cost', 'costs',\n])\n\nexport function normalizeDomain(value?: string | null): string | null {\n if (!value) return null\n try {\n const url = new URL(value.includes('://') ? value : `https://${value}`)\n return url.hostname.replace(/^www\\./, '').toLowerCase()\n } catch {\n return value.replace(/^https?:\\/\\//, '').replace(/^www\\./, '').split('/')[0]?.toLowerCase() || null\n }\n}\n\nexport function domainFromUrl(url?: string | null): string {\n return normalizeDomain(url) ?? ''\n}\n\nexport function numberFrom(value: unknown): number | null {\n if (value === null || value === undefined || value === '') return null\n const parsed = Number(String(value).replace(/[^\\d.]/g, ''))\n return Number.isFinite(parsed) ? parsed : null\n}\n\nexport function median(values: Array<number | null>): number | null {\n const nums = values.filter((v): v is number => v !== null).sort((a, b) => a - b)\n if (!nums.length) return null\n return nums[Math.floor(nums.length / 2)] ?? null\n}\n\nexport function textTerms(text: string, limit = 12): string {\n const counts = new Map<string, number>()\n for (const token of text.toLowerCase().replace(/[^a-z0-9\\s]/g, ' ').split(/\\s+/)) {\n if (token.length < 4 || STOP_WORDS.has(token)) continue\n counts.set(token, (counts.get(token) ?? 0) + 1)\n }\n return [...counts.entries()]\n .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))\n .slice(0, limit)\n .map(([term, count]) => `${term} (${count})`)\n .join('; ')\n}\n\nexport function classifyQuestion(question: string): string {\n const q = question.toLowerCase()\n if (/\\b(cost|price|pricing|charge|expensive|cheap)\\b/.test(q)) return 'cost'\n if (/\\b(best|top|recommended|reviews?|compare|versus|vs)\\b/.test(q)) return 'comparison'\n if (/\\b(how|steps?|process|way to)\\b/.test(q)) return 'process'\n if (/\\b(why|worth|important|benefit)\\b/.test(q)) return 'why'\n if (/\\b(near me|city|local|nearby)\\b/.test(q)) return 'local'\n if (/\\b(can|does|do|is|are|should|will)\\b/.test(q)) return 'decision'\n return 'definition'\n}\n\nexport function questionRows(paa: HarvestLike | null): Array<Record<string, unknown>> {\n return (paa?.flat ?? [])\n .filter(row => row.question)\n .map((row, index) => {\n const url = row.source_cite ?? ''\n const domain = normalizeDomain(row.source_site ?? '') ?? domainFromUrl(url)\n return {\n position: index + 1,\n intent: classifyQuestion(row.question ?? ''),\n question: row.question ?? '',\n answer_excerpt: (row.answer ?? '').slice(0, 320),\n source_title: row.source_title ?? '',\n source_domain: domain,\n source_url: url,\n }\n })\n}\n\nexport function sourceDomainRows(rows: Array<Record<string, unknown>>): Array<Record<string, unknown>> {\n const byDomain = new Map<string, { questions: number; urls: Set<string>; intents: Map<string, number> }>()\n for (const row of rows) {\n const domain = String(row.source_domain ?? row.domain ?? '')\n if (!domain) continue\n const entry = byDomain.get(domain) ?? { questions: 0, urls: new Set<string>(), intents: new Map<string, number>() }\n entry.questions += row.question ? 1 : 0\n if (row.source_url || row.url) entry.urls.add(String(row.source_url ?? row.url))\n if (row.intent) entry.intents.set(String(row.intent), (entry.intents.get(String(row.intent)) ?? 0) + 1)\n byDomain.set(domain, entry)\n }\n return [...byDomain.entries()]\n .map(([domain, entry]) => ({\n domain,\n question_mentions: entry.questions,\n source_url_count: entry.urls.size,\n top_intents: [...entry.intents.entries()].sort((a, b) => b[1] - a[1]).map(([intent, count]) => `${intent} (${count})`).join('; '),\n }))\n .sort((a, b) => Number(b.question_mentions) - Number(a.question_mentions) || String(a.domain).localeCompare(String(b.domain)))\n}\n\nexport function splitSentences(text?: string | null): string[] {\n return (text ?? '')\n .replace(/\\s+/g, ' ')\n .split(/(?<=[.!?])\\s+/)\n .map(sentence => sentence.trim())\n .filter(sentence => sentence.length > 20)\n .slice(0, 20)\n}\n\nexport function classifySentence(sentence: string): string {\n const s = sentence.toLowerCase()\n if (/\\bis\\b|\\bare\\b|\\bmeans\\b|\\brefers to\\b/.test(s)) return 'definition'\n if (/\\binclude\\b|\\bconsider\\b|\\bfactors?\\b|\\bcriteria\\b/.test(s)) return 'criteria'\n if (/\\bfirst\\b|\\bthen\\b|\\bsteps?\\b|\\bprocess\\b/.test(s)) return 'process'\n if (/\\bvs\\b|\\bthan\\b|\\bcompare\\b|\\bdifference\\b/.test(s)) return 'comparison'\n if (/\\bcost\\b|\\bprice\\b|\\baverage\\b|\\brange\\b/.test(s)) return 'cost'\n return 'claim'\n}\n\nexport function headingRows(page: ExtractUrlResult, source: { url: string; domain: string; position?: number | string }): Array<Record<string, unknown>> {\n return (page.headings ?? [])\n .filter(heading => heading.text)\n .map(heading => ({\n source_url: source.url,\n source_domain: source.domain,\n source_position: source.position ?? '',\n heading_level: heading.level,\n heading_text: heading.text,\n heading_terms: textTerms(heading.text, 6),\n }))\n}\n\nexport function pageSummaryRow(page: ExtractUrlResult, source: { url: string; domain: string; position?: number | string; title?: string }): Record<string, unknown> {\n return {\n position: source.position ?? '',\n domain: source.domain,\n url: source.url,\n serp_title: source.title ?? '',\n page_title: page.title ?? '',\n h1: page.h1 ?? '',\n meta_description: page.metaDescription ?? '',\n word_count: page.wordCount ?? '',\n heading_count: page.headings?.length ?? 0,\n schema_types: (page.schemaTypes ?? []).join('; '),\n }\n}\n\nexport async function mapLimit<T, R>(items: T[], limit: number, fn: (item: T, index: number) => Promise<R>): Promise<R[]> {\n const out: R[] = new Array(items.length)\n let next = 0\n async function worker(): Promise<void> {\n while (next < items.length) {\n const index = next\n next += 1\n out[index] = await fn(items[index], index)\n }\n }\n await Promise.all(Array.from({ length: Math.min(Math.max(1, limit), items.length) }, () => worker()))\n return out\n}\n\n"],"mappings":"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","names":["z","z","z","z","z","competitorRows","z","normalizeDomain","domainFromUrl","numberFrom","median","mapLimit","z","numberFrom","median","normalizeDomain","domainFromUrl","mapLimit","sourceRows"]}
@@ -1,7 +0,0 @@
1
- // src/version.ts
2
- var PACKAGE_VERSION = "0.2.18";
3
-
4
- export {
5
- PACKAGE_VERSION
6
- };
7
- //# sourceMappingURL=chunk-M5SAUO4K.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/version.ts"],"sourcesContent":["export const PACKAGE_VERSION = '0.2.18'\n"],"mappings":";AAAO,IAAM,kBAAkB;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/mcp/browser-agent-mcp-server.ts","../src/mcp/browser-agent-tool-schemas.ts","../src/mcp/replay-annotator.ts"],"sourcesContent":["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 { PACKAGE_VERSION } from '../version.js'\nimport {\n BrowserOpenInputSchema,\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} from './browser-agent-tool-schemas.js'\nimport { annotateReplayVideo } from './replay-annotator.js'\n\nexport interface BrowserAgentHttpOptions {\n baseUrl: string\n apiKey: string\n consoleBaseUrl?: string\n timeoutMs?: number\n}\n\nfunction textResult(value: unknown, isError = false): CallToolResult {\n return { content: [{ type: 'text', text: JSON.stringify(value) }], isError }\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 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(method: string, path: string, body?: Record<string, unknown>): 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(timeoutMs),\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 server.registerTool(\n 'browser_open',\n {\n title: 'Open Browser Session',\n description:\n 'Open a fresh cloud browser you can drive. Returns a session_id used by all other browser_* tools, and a watch_url where a human can watch live or take over. Anti-bot stealth and automatic CAPTCHA/Cloudflare solving are on by default: if a Cloudflare or CAPTCHA challenge appears, do NOT click it — wait a few seconds and call browser_screenshot again; it is solved automatically. Billing: metered per second of active browser work at ~4 credits per minute; idle and standby time are free. Call browser_close when done to stop the meter. After opening, call browser_screenshot to see the page.',\n inputSchema: BrowserOpenInputSchema,\n annotations: annotations('Open Browser Session'),\n },\n async input => {\n const open = await req('POST', '/agent/sessions', {\n label: input.label,\n profile: input.profile,\n timeout_seconds: input.timeout_seconds,\n })\n if (!open.ok) return textResult(open.data, true)\n const session = open.data\n if (input.url) {\n await req('POST', `/agent/sessions/${session.session_id}/goto`, { url: input.url })\n }\n return textResult({\n session_id: session.session_id,\n watch_url: `${consoleBase}/console/${session.session_id}`,\n live_view_url: session.live_view_url ?? null,\n hint: 'Call browser_screenshot to see the page. Click by the x,y of an element from the snapshot.',\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 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 textResult(res.data, true)\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 content.push({\n type: 'text',\n text: JSON.stringify({ url, title, elements, text }),\n })\n return { content }\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 annotations: annotations('Read Page', true),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/read`)\n return textResult(res.data, !res.ok)\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 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 return textResult(res.data, !res.ok)\n },\n )\n\n server.registerTool(\n 'browser_goto',\n {\n title: 'Navigate To URL',\n description: 'Navigate the browser to a URL. Follow with browser_screenshot to see the result.',\n inputSchema: BrowserGotoInputSchema,\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 textResult(res.data, !res.ok)\n },\n )\n\n server.registerTool(\n 'browser_click',\n {\n title: 'Click',\n description: 'Click at x,y (screenshot pixel coordinates). Use the x,y of a target element from the latest browser_screenshot or browser_read.',\n inputSchema: BrowserClickInputSchema,\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 textResult(res.data, !res.ok)\n },\n )\n\n server.registerTool(\n 'browser_type',\n {\n title: 'Type Text',\n description: 'Type text at the current focus. Click an input field first to focus it. Use browser_press with [\"Return\"] to submit.',\n inputSchema: BrowserTypeInputSchema,\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 textResult(res.data, !res.ok)\n },\n )\n\n server.registerTool(\n 'browser_scroll',\n {\n title: 'Scroll',\n description: 'Scroll the page. Positive delta_y scrolls down. Follow with browser_screenshot to see newly revealed content.',\n inputSchema: BrowserScrollInputSchema,\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 textResult(res.data, !res.ok)\n },\n )\n\n server.registerTool(\n 'browser_press',\n {\n title: 'Press Keys',\n description: 'Press keys or combinations, e.g. [\"Return\"] to submit, [\"Ctrl+a\"] to select all, [\"Ctrl+Shift+Tab\"] to switch tabs.',\n inputSchema: BrowserPressInputSchema,\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 textResult(res.data, !res.ok)\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 annotations: annotations('Start Recording'),\n },\n async input => {\n const res = await req('POST', `/agent/sessions/${input.session_id}/replay/start`)\n return textResult(res.data, !res.ok)\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 locally.',\n inputSchema: BrowserReplayStopInputSchema,\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 return textResult(res.data, !res.ok)\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 annotations: annotations('List Replay Videos', true),\n },\n async input => {\n const res = await req('GET', `/agent/sessions/${input.session_id}/replays`)\n return textResult(res.data, !res.ok)\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 locally under MCP_SCRAPER_OUTPUT_DIR/browser-replays. Use after browser_replay_stop or browser_list_replays.',\n inputSchema: BrowserReplayDownloadInputSchema,\n annotations: annotations('Download Replay MP4', true),\n },\n async input => {\n const res = await downloadReplay(input.session_id, input.replay_id, input.filename)\n return textResult(res.data, !res.ok)\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 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 textResult(res.data, true)\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 textResult({ error: target?.error ?? 'target not found in current viewport', target }, true)\n }\n if (!finiteNumber(elapsed)) {\n return textResult({ error: 'no active replay clock found; call browser_replay_start before browser_replay_mark' }, true)\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 textResult({\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 locally. 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 annotations: annotations('Annotate Replay MP4', true),\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 textResult(downloaded.data, true)\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 textResult({\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 textResult({ error: err instanceof Error ? err.message : String(err) }, true)\n }\n },\n )\n\n server.registerTool(\n 'browser_close',\n {\n title: 'Close Browser Session',\n description: 'Close and release the browser session when the task is done.',\n inputSchema: BrowserSessionInputSchema,\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 return textResult(res.data, !res.ok)\n },\n )\n\n server.registerTool(\n 'browser_list_sessions',\n {\n title: 'List Browser Sessions',\n description: 'List your browser sessions and their status, with a watch_url for each.',\n inputSchema: BrowserListInputSchema,\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 textResult(res.data, true)\n const sessions = (res.data.sessions ?? []).map((s: any) => ({ ...s, watch_url: `${consoleBase}/console/${s.session_id}` }))\n return textResult({ sessions })\n },\n )\n\n}\n","import { z } from 'zod'\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 profile name to load a logged-in session for a site.'),\n timeout_seconds: z.number().int().min(60).max(259200).optional().describe('How long the 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 BrowserSessionInputSchema = {\n session_id: z.string().describe('The session id returned by browser_open.'),\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.'),\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.'),\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.'),\n x: z.number().describe('X coordinate to click, in screenshot pixels. Use the x of an element from the latest screenshot.'),\n y: z.number().describe('Y coordinate to click, in screenshot pixels.'),\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.'),\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.'),\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.'),\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.'),\n replay_id: z.string().describe('The replay id returned by browser_replay_start.'),\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.'),\n replay_id: z.string().describe('The replay id returned by browser_replay_start or browser_list_replays.'),\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. 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.'),\n replay_id: z.string().describe('The replay id returned by browser_replay_start or browser_list_replays.'),\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","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"],"mappings":";;;;;AAAA,SAAS,iBAAiB;AAE1B,SAAS,WAAW,qBAAqB;AACzC,SAAS,eAAe;AACxB,SAAS,QAAAA,aAAY;;;ACJrB,SAAS,SAAS;AAEX,IAAM,yBAAyB;AAAA,EACpC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oEAAoE;AAAA,EAC1G,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,wDAAwD;AAAA,EAClG,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qEAAqE;AAAA,EAC7G,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,MAAM,EAAE,SAAS,EAAE,SAAS,mKAAmK;AAC/O;AAGO,IAAM,4BAA4B;AAAA,EACvC,YAAY,EAAE,OAAO,EAAE,SAAS,0CAA0C;AAC5E;AAGO,IAAM,4BAA4B,EAAE,OAAO;AAAA,EAChD,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uDAAuD;AAAA,EAC5F,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,+GAA+G;AAAA,EACxJ,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,4GAA4G;AAAA,EACjJ,OAAO,EAAE,KAAK,CAAC,YAAY,OAAO,CAAC,EAAE,QAAQ,UAAU,EAAE,SAAS,kDAAkD;AAAA,EACpH,OAAO,EAAE,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,EAAE,OAAO,EAAE,SAAS,0CAA0C;AAAA,EAC1E,SAAS,EAAE,MAAM,yBAAyB,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,mHAAmH;AACzL;AAGO,IAAM,yBAAyB;AAAA,EACpC,YAAY,EAAE,OAAO,EAAE,SAAS,0CAA0C;AAAA,EAC1E,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,iCAAiC;AAClE;AAGO,IAAM,0BAA0B;AAAA,EACrC,YAAY,EAAE,OAAO,EAAE,SAAS,0CAA0C;AAAA,EAC1E,GAAG,EAAE,OAAO,EAAE,SAAS,kGAAkG;AAAA,EACzH,GAAG,EAAE,OAAO,EAAE,SAAS,8CAA8C;AAAA,EACrE,QAAQ,EAAE,KAAK,CAAC,QAAQ,SAAS,QAAQ,CAAC,EAAE,QAAQ,MAAM,EAAE,SAAS,eAAe;AAAA,EACpF,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,4CAA4C;AAC7G;AAGO,IAAM,yBAAyB;AAAA,EACpC,YAAY,EAAE,OAAO,EAAE,SAAS,0CAA0C;AAAA,EAC1E,MAAM,EAAE,OAAO,EAAE,SAAS,qEAAqE;AAAA,EAC/F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,2DAA2D;AACzH;AAGO,IAAM,2BAA2B;AAAA,EACtC,YAAY,EAAE,OAAO,EAAE,SAAS,0CAA0C;AAAA,EAC1E,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,qEAAqE;AAAA,EAC7G,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,mCAAmC;AAAA,EAC3E,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qDAAqD;AAAA,EACvF,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qDAAqD;AACzF;AAGO,IAAM,0BAA0B;AAAA,EACrC,YAAY,EAAE,OAAO,EAAE,SAAS,0CAA0C;AAAA,EAC1E,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,iFAAiF;AAC7H;AAGO,IAAM,+BAA+B;AAAA,EAC1C,YAAY,EAAE,OAAO,EAAE,SAAS,0CAA0C;AAAA,EAC1E,WAAW,EAAE,OAAO,EAAE,SAAS,iDAAiD;AAClF;AAGO,IAAM,mCAAmC;AAAA,EAC9C,YAAY,EAAE,OAAO,EAAE,SAAS,0CAA0C;AAAA,EAC1E,WAAW,EAAE,OAAO,EAAE,SAAS,yEAAyE;AAAA,EACxG,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yEAAyE;AACpH;AAGO,IAAM,gCAAgC,EAAE,OAAO;AAAA,EACpD,MAAM,EAAE,KAAK,CAAC,OAAO,UAAU,aAAa,SAAS,OAAO,CAAC,EAAE,QAAQ,KAAK,EAAE,SAAS,2CAA2C;AAAA,EAClI,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,kDAAkD;AAAA,EACvG,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,oFAAoF;AAAA,EACvI,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uGAAuG;AAAA,EAC5I,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qGAAqG;AAAA,EACzI,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,oGAAoG;AAAA,EACrJ,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,sGAAsG;AAAA,EACxJ,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kFAAkF;AAAA,EACpH,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kFAAkF;AAAA,EACpH,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kFAAkF;AAAA,EACzH,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kFAAkF;AAAA,EACzH,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,4FAA4F;AAAA,EACjI,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,4FAA4F;AAAA,EACjI,OAAO,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,sDAAsD;AAAA,EACrG,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,EAAE,SAAS,EAAE,SAAS,+CAA+C;AAAA,EACjH,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,4CAA4C;AACvG,CAAC;AAEM,IAAM,+BAA+B;AAAA,EAC1C,YAAY,EAAE,OAAO,EAAE,SAAS,8EAA8E;AAAA,EAC9G,QAAQ,0BAA0B,SAAS,sEAAsE;AAAA,EACjH,MAAM,EAAE,KAAK,CAAC,OAAO,UAAU,aAAa,OAAO,CAAC,EAAE,QAAQ,KAAK,EAAE,SAAS,sGAAsG;AAAA,EACpL,OAAO,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,kDAAkD;AAAA,EACjG,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,EAAE,SAAS,EAAE,SAAS,+CAA+C;AAAA,EACjH,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,4CAA4C;AAAA,EACrG,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,gFAAgF;AAAA,EACvI,sBAAsB,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,QAAQ,KAAK,EAAE,SAAS,uHAAuH;AAAA,EAChM,kBAAkB,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,0DAA0D;AAC9H;AAGO,IAAM,mCAAmC;AAAA,EAC9C,YAAY,EAAE,OAAO,EAAE,SAAS,0CAA0C;AAAA,EAC1E,WAAW,EAAE,OAAO,EAAE,SAAS,yEAAyE;AAAA,EACxG,aAAa,EAAE,MAAM,6BAA6B,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,4LAA4L;AAAA,EACxQ,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oFAAoF;AAAA,EAC7H,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,oGAAoG;AAAA,EAC5J,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,oLAAoL;AAAA,EAC7O,oBAAoB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,sGAAsG;AAAA,EAChK,mBAAmB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,6LAA6L;AACxP;AAGO,IAAM,yBAAyB;AAAA,EACpC,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,sCAAsC;AAC5F;;;AC/HA,SAAS,gBAAgB;AACzB,SAAS,SAAS,IAAI,MAAM,iBAAiB;AAC7C,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAE1B,IAAM,gBAAgB,UAAU,QAAQ;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,QAAM,OAAO,KAAK,IAAI,GAAG,OAAO;AAChC,QAAM,QAAQ,KAAK,MAAM,OAAO,IAAI;AACpC,QAAM,UAAU,KAAK,MAAO,OAAO,OAAQ,EAAE;AAC7C,QAAM,eAAe,KAAK,MAAM,OAAO,EAAE;AACzC,QAAM,eAAe,KAAK,OAAO,OAAO,KAAK,MAAM,IAAI,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,MAAM,QAAQ,KAAK,OAAO,GAAG,kBAAkB,CAAC;AAC5D,QAAM,UAAU,KAAK,KAAK,iBAAiB;AAC3C,MAAI;AACF,UAAM,UAAU,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,MAAM,KAAK,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,UAAM,GAAG,KAAK,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EAChD;AACF;;;AFzUA,SAAS,WAAW,OAAgB,UAAU,OAAuB;AACnE,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,KAAK,EAAE,CAAC,GAAG,QAAQ;AAC7E;AAEA,SAAS,gBAAwB;AAC/B,SAAO,QAAQ,IAAI,wBAAwB,KAAK,KAAKC,MAAK,QAAQ,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,SAAOA,MAAK,cAAc,GAAG,mBAAmB,GAAG,IAAI,MAAM;AAC/D;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;AAEO,SAAS,2BAA2B,MAA0C;AACnF,QAAM,SAAS,IAAI,UAAU,EAAE,MAAM,iBAAiB,SAAS,gBAAgB,CAAC;AAChF,+BAA6B,QAAQ,IAAI;AACzC,SAAO;AACT;AAEO,SAAS,6BAA6B,QAAmB,MAAqC;AACnG,QAAM,UAAU,KAAK,QAAQ,QAAQ,OAAO,EAAE;AAC9C,QAAM,eAAe,KAAK,kBAAkB,KAAK,SAAS,QAAQ,OAAO,EAAE;AAC3E,QAAM,YAAY,KAAK,aAAa;AAEpC,iBAAe,IAAI,QAAgB,MAAc,MAAqE;AACpH,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,OAAO,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,SAAS;AAAA,MACvC,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,GAAG,OAAO,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,gBAAUD,MAAK,cAAc,GAAG,iBAAiB,GAAG,EAAE,WAAW,KAAK,CAAC;AACvE,oBAAc,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,GAAG,OAAO,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,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,aAAa,YAAY,sBAAsB;AAAA,IACjD;AAAA,IACA,OAAM,UAAS;AACb,YAAM,OAAO,MAAM,IAAI,QAAQ,mBAAmB;AAAA,QAChD,OAAO,MAAM;AAAA,QACb,SAAS,MAAM;AAAA,QACf,iBAAiB,MAAM;AAAA,MACzB,CAAC;AACD,UAAI,CAAC,KAAK,GAAI,QAAO,WAAW,KAAK,MAAM,IAAI;AAC/C,YAAM,UAAU,KAAK;AACrB,UAAI,MAAM,KAAK;AACb,cAAM,IAAI,QAAQ,mBAAmB,QAAQ,UAAU,SAAS,EAAE,KAAK,MAAM,IAAI,CAAC;AAAA,MACpF;AACA,aAAO,WAAW;AAAA,QAChB,YAAY,QAAQ;AAAA,QACpB,WAAW,GAAG,WAAW,YAAY,QAAQ,UAAU;AAAA,QACvD,eAAe,QAAQ,iBAAiB;AAAA,QACxC,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,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,WAAW,IAAI,MAAM,IAAI;AAC7C,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,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,MAAM,KAAK,UAAU,EAAE,KAAK,OAAO,UAAU,KAAK,CAAC;AAAA,MACrD,CAAC;AACD,aAAO,EAAE,QAAQ;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,aAAa,YAAY,aAAa,IAAI;AAAA,IAC5C;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,OAAO;AACxE,aAAO,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,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,aAAO,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,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,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,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,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,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,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,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,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,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,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,aAAa,YAAY,iBAAiB;AAAA,IAC5C;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,QAAQ,mBAAmB,MAAM,UAAU,eAAe;AAChF,aAAO,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,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,aAAO,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,aAAa,YAAY,sBAAsB,IAAI;AAAA,IACrD;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,IAAI,OAAO,mBAAmB,MAAM,UAAU,UAAU;AAC1E,aAAO,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,aAAa,YAAY,uBAAuB,IAAI;AAAA,IACtD;AAAA,IACA,OAAM,UAAS;AACb,YAAM,MAAM,MAAM,eAAe,MAAM,YAAY,MAAM,WAAW,MAAM,QAAQ;AAClF,aAAO,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,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,WAAW,IAAI,MAAM,IAAI;AAC7C,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,WAAW,EAAE,OAAO,QAAQ,SAAS,wCAAwC,OAAO,GAAG,IAAI;AAAA,MACpG;AACA,UAAI,CAACC,cAAa,OAAO,GAAG;AAC1B,eAAO,WAAW,EAAE,OAAO,qFAAqF,GAAG,IAAI;AAAA,MACzH;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,WAAW;AAAA,QAChB;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,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,aAAa,YAAY,uBAAuB,IAAI;AAAA,IACtD;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,WAAW,WAAW,MAAM,IAAI;AAC3D,UAAI;AACF,cAAM,aAAa,OAAO,WAAW,KAAK,SAAS;AACnD,cAAM,aAAa,wBAAwB,MAAM,YAAY,MAAM,WAAW,MAAM,QAAQ;AAC5F,kBAAUD,MAAK,cAAc,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,WAAW;AAAA,UAChB,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,WAAW,EAAE,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,GAAG,IAAI;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,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,aAAO,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,MACb,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,WAAW,IAAI,MAAM,IAAI;AAC7C,YAAM,YAAY,IAAI,KAAK,YAAY,CAAC,GAAG,IAAI,CAAC,OAAY,EAAE,GAAG,GAAG,WAAW,GAAG,WAAW,YAAY,EAAE,UAAU,GAAG,EAAE;AAC1H,aAAO,WAAW,EAAE,SAAS,CAAC;AAAA,IAChC;AAAA,EACF;AAEF;","names":["join","rect","join","finiteNumber"]}