mcp-scraper 0.35.1 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +9 -9
  2. package/dist/bin/api-server.cjs +25071 -19082
  3. package/dist/bin/api-server.cjs.map +1 -1
  4. package/dist/bin/api-server.js +3 -3
  5. package/dist/bin/mcp-scraper-cli.cjs +51 -7
  6. package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
  7. package/dist/bin/mcp-scraper-cli.js +48 -5
  8. package/dist/bin/mcp-scraper-cli.js.map +1 -1
  9. package/dist/bin/mcp-scraper-install.cjs +2 -2
  10. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  11. package/dist/bin/mcp-scraper-install.js +2 -2
  12. package/dist/bin/mcp-stdio-server.cjs +995 -222
  13. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  14. package/dist/bin/mcp-stdio-server.js +8 -8
  15. package/dist/bin/paa-harvest.cjs +125 -70
  16. package/dist/bin/paa-harvest.cjs.map +1 -1
  17. package/dist/bin/paa-harvest.js +4 -4
  18. package/dist/chunk-345BQXZH.js +712 -0
  19. package/dist/chunk-345BQXZH.js.map +1 -0
  20. package/dist/chunk-3LWYPAU5.js +7 -0
  21. package/dist/chunk-3LWYPAU5.js.map +1 -0
  22. package/dist/{chunk-M2S27J6Z.js → chunk-44HZLHDV.js} +10 -1
  23. package/dist/chunk-44HZLHDV.js.map +1 -0
  24. package/dist/{chunk-62DQAWPF.js → chunk-CSCD2HNS.js} +498 -43
  25. package/dist/chunk-CSCD2HNS.js.map +1 -0
  26. package/dist/{chunk-ZID3WQID.js → chunk-FQI5PFE7.js} +9 -71
  27. package/dist/chunk-FQI5PFE7.js.map +1 -0
  28. package/dist/{chunk-3HBPKR5G.js → chunk-FSAXLDB3.js} +3 -3
  29. package/dist/chunk-G3P3ZDB4.js +69 -0
  30. package/dist/chunk-G3P3ZDB4.js.map +1 -0
  31. package/dist/{chunk-YRGSEY5L.js → chunk-G7KAVJ3F.js} +2 -2
  32. package/dist/{chunk-YRGSEY5L.js.map → chunk-G7KAVJ3F.js.map} +1 -1
  33. package/dist/{chunk-NPMW5HUS.js → chunk-JK2FRDAP.js} +930 -244
  34. package/dist/chunk-JK2FRDAP.js.map +1 -0
  35. package/dist/{chunk-XVVNKASZ.js → chunk-LOPKN3YL.js} +118 -73
  36. package/dist/chunk-LOPKN3YL.js.map +1 -0
  37. package/dist/{chunk-4ZB3X6BQ.js → chunk-MA5JBAUZ.js} +16 -2
  38. package/dist/{chunk-4ZB3X6BQ.js.map → chunk-MA5JBAUZ.js.map} +1 -1
  39. package/dist/chunk-PUJFYJXB.js +684 -0
  40. package/dist/chunk-PUJFYJXB.js.map +1 -0
  41. package/dist/{chunk-BWXLTWF7.js → chunk-PWPUKR5U.js} +9 -5
  42. package/dist/chunk-PWPUKR5U.js.map +1 -0
  43. package/dist/chunk-Q35WZJJK.js +499 -0
  44. package/dist/chunk-Q35WZJJK.js.map +1 -0
  45. package/dist/chunk-QZXKQB7Y.js +414 -0
  46. package/dist/chunk-QZXKQB7Y.js.map +1 -0
  47. package/dist/{db-YAI5AQOI.js → db-N3YECFWR.js} +12 -2
  48. package/dist/{extract-bundle-ONWZVV55.js → extract-bundle-346R6MXD.js} +284 -98
  49. package/dist/extract-bundle-346R6MXD.js.map +1 -0
  50. package/dist/index.cjs +129 -70
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.cts +11 -0
  53. package/dist/index.d.ts +11 -0
  54. package/dist/index.js +4 -4
  55. package/dist/location-data-repository-O2VII3ON.js +35 -0
  56. package/dist/{server-GKUTC73B.js → server-QKDDEBVQ.js} +7325 -3762
  57. package/dist/server-QKDDEBVQ.js.map +1 -0
  58. package/dist/site-extract-repository-I3VM6WXN.js +62 -0
  59. package/dist/site-extract-repository-I3VM6WXN.js.map +1 -0
  60. package/dist/{worker-645BZPEK.js → worker-TTFXPPDK.js} +7 -7
  61. package/docs/hosted-location-data.md +108 -0
  62. package/docs/mcp-tool-craft-lint.generated.md +6 -3
  63. package/docs/mcp-tool-manifest.generated.json +1447 -240
  64. package/docs/mcp-tool-quality-spec.md +1 -1
  65. package/docs/specs/connected-services-control-plane-decoupling-spec.md +1044 -0
  66. package/docs/specs/kernel-stealth-captcha-test-matrix.md +278 -0
  67. package/docs/specs/multimodal-image-memory-architecture-spec.md +1022 -0
  68. package/docs/specs/unified-credit-and-scheduled-execution-billing-spec.md +36 -27
  69. package/package.json +7 -6
  70. package/dist/chunk-62DQAWPF.js.map +0 -1
  71. package/dist/chunk-BWXLTWF7.js.map +0 -1
  72. package/dist/chunk-M2S27J6Z.js.map +0 -1
  73. package/dist/chunk-NPMW5HUS.js.map +0 -1
  74. package/dist/chunk-R7EETU7Z.js +0 -419
  75. package/dist/chunk-R7EETU7Z.js.map +0 -1
  76. package/dist/chunk-U44TPRST.js +0 -130
  77. package/dist/chunk-U44TPRST.js.map +0 -1
  78. package/dist/chunk-XVVNKASZ.js.map +0 -1
  79. package/dist/chunk-YR4LJ6AQ.js +0 -7
  80. package/dist/chunk-YR4LJ6AQ.js.map +0 -1
  81. package/dist/chunk-YV2FUEBX.js +0 -851
  82. package/dist/chunk-YV2FUEBX.js.map +0 -1
  83. package/dist/chunk-ZID3WQID.js.map +0 -1
  84. package/dist/extract-bundle-ONWZVV55.js.map +0 -1
  85. package/dist/server-GKUTC73B.js.map +0 -1
  86. package/dist/site-extract-repository-L6BHWVDU.js +0 -30
  87. /package/dist/{chunk-3HBPKR5G.js.map → chunk-FSAXLDB3.js.map} +0 -0
  88. /package/dist/{db-YAI5AQOI.js.map → db-N3YECFWR.js.map} +0 -0
  89. /package/dist/{site-extract-repository-L6BHWVDU.js.map → location-data-repository-O2VII3ON.js.map} +0 -0
  90. /package/dist/{worker-645BZPEK.js.map → worker-TTFXPPDK.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api/location-data-repository.ts"],"sourcesContent":["import { createHash, randomUUID } from 'node:crypto'\nimport { getDb } from './db.js'\nimport { csvRecords } from '../directory/csv.js'\nimport type { DirectoryMarket, PopulationYear } from '../directory/location-db.js'\n\nexport const HOSTED_ZIP_DATASET_KIND = 'us_zip_groups' as const\nexport const HOSTED_CENSUS_DATASET_PREFIX = 'us_census_places' as const\nexport type HostedLocationDatasetKind = typeof HOSTED_ZIP_DATASET_KIND | `${typeof HOSTED_CENSUS_DATASET_PREFIX}:${string}`\nexport const MIN_NATIONWIDE_ZIP_COUNT = 25_000\n\nexport const REQUIRED_LOCATION_STATE_CODES = [\n 'AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'DC', 'FL', 'GA', 'HI', 'ID', 'IL', 'IN', 'IA',\n 'KS', 'KY', 'LA', 'ME', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ', 'NM',\n 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA',\n 'WV', 'WI', 'WY',\n] as const\n\nconst STATE_FIPS_BY_ABBR: Record<typeof REQUIRED_LOCATION_STATE_CODES[number], string> = {\n AL: '01', AK: '02', AZ: '04', AR: '05', CA: '06', CO: '08', CT: '09', DE: '10', DC: '11',\n FL: '12', GA: '13', HI: '15', ID: '16', IL: '17', IN: '18', IA: '19', KS: '20', KY: '21',\n LA: '22', ME: '23', MD: '24', MA: '25', MI: '26', MN: '27', MS: '28', MO: '29', MT: '30',\n NE: '31', NV: '32', NH: '33', NJ: '34', NM: '35', NY: '36', NC: '37', ND: '38', OH: '39',\n OK: '40', OR: '41', PA: '42', RI: '44', SC: '45', SD: '46', TN: '47', TX: '48', UT: '49',\n VT: '50', VA: '51', WA: '53', WV: '54', WI: '55', WY: '56',\n}\nconst REQUIRED_LOCATION_STATE_SET = new Set<string>(REQUIRED_LOCATION_STATE_CODES)\n\nexport interface HostedZipGroup {\n city: string\n cityKey: string\n state: string\n zips: string[]\n counties: string[]\n}\n\nexport interface HostedLocationDataset {\n id: string\n kind: HostedLocationDatasetKind\n sourceUrl: string | null\n sha256: string\n rowCount: number\n groupCount: number\n stateCount: number\n sourceRowCount: number\n rejectedRowCount: number\n zipCount: number\n coveredStates: string[]\n coverageComplete: boolean\n status: 'loading' | 'ready' | 'failed'\n createdAt: string\n completedAt: string | null\n error: string | null\n}\n\nexport interface HostedZipGroupLookup {\n dataset: HostedLocationDataset | null\n groups: Map<string, HostedZipGroup>\n}\n\nexport interface HostedZipImportResult {\n dataset: HostedLocationDataset\n duplicate: boolean\n}\n\nexport interface HostedLocationMarketQuery {\n state: string\n minPopulation: number\n populationYear: PopulationYear\n maxResults: number\n includeZipGroups: boolean\n cityQuery?: string\n zip?: string\n}\n\nexport interface HostedLocationMarketResult {\n markets: DirectoryMarket[]\n populationDataset: HostedLocationDataset | null\n zipDataset: HostedLocationDataset | null\n warnings: string[]\n}\n\ninterface HostedCensusPlace {\n city: string\n cityKey: string\n censusName: string\n estimatesBase2020: number | null\n populations: Record<PopulationYear, number | null>\n}\n\ninterface ParsedCensusDataset {\n sourceRowCount: number\n places: HostedCensusPlace[]\n}\n\ninterface ParsedZipDataset {\n sourceRowCount: number\n rowCount: number\n rejectedRowCount: number\n zipCount: number\n stateCount: number\n coveredStates: string[]\n groups: HostedZipGroup[]\n}\n\nconst IMPORT_BATCH_SIZE = 200\nconst MAX_SOURCE_URL_LENGTH = 2_000\n\nlet schemaDb: ReturnType<typeof getDb> | null = null\nlet schemaPromise: Promise<void> | null = null\n\nfunction normalizeHostedCityKey(value: string): string {\n return value.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim()\n}\n\nfunction stringArray(value: unknown): string[] {\n if (value == null) return []\n try {\n const parsed = JSON.parse(String(value)) as unknown\n return Array.isArray(parsed) ? parsed.map(String) : []\n } catch {\n return []\n }\n}\n\nfunction rowToDataset(row: Record<string, unknown>): HostedLocationDataset {\n return {\n id: String(row.id),\n kind: String(row.dataset_kind) as HostedLocationDatasetKind,\n sourceUrl: row.source_url == null ? null : String(row.source_url),\n sha256: String(row.sha256),\n rowCount: Number(row.row_count ?? 0),\n groupCount: Number(row.group_count ?? 0),\n stateCount: Number(row.state_count ?? 0),\n sourceRowCount: Number(row.source_row_count ?? row.row_count ?? 0),\n rejectedRowCount: Number(row.rejected_row_count ?? 0),\n zipCount: Number(row.zip_count ?? 0),\n coveredStates: stringArray(row.covered_states_json),\n coverageComplete: Number(row.coverage_complete ?? 0) === 1,\n status: String(row.status) as HostedLocationDataset['status'],\n createdAt: String(row.created_at),\n completedAt: row.completed_at == null ? null : String(row.completed_at),\n error: row.error == null ? null : String(row.error),\n }\n}\n\nfunction censusDatasetKind(state: string): `${typeof HOSTED_CENSUS_DATASET_PREFIX}:${string}` {\n return `${HOSTED_CENSUS_DATASET_PREFIX}:${state}`\n}\n\nfunction normalizedSourceUrl(value: string | null | undefined): string | null {\n const trimmed = value?.trim()\n if (!trimmed) return null\n if (trimmed.length > MAX_SOURCE_URL_LENGTH) throw new Error(`sourceUrl must be ${MAX_SOURCE_URL_LENGTH} characters or fewer`)\n let parsed: URL\n try {\n parsed = new URL(trimmed)\n } catch {\n throw new Error('sourceUrl must be a valid URL')\n }\n parsed.username = ''\n parsed.password = ''\n parsed.search = ''\n parsed.hash = ''\n return parsed.toString()\n}\n\nfunction normalizedZip(value: string): string | null {\n const digits = value.trim()\n if (!/^\\d{1,5}$/.test(digits)) return null\n return digits.padStart(5, '0')\n}\n\nfunction normalizedState(value: string): string | null {\n const state = value.trim().toUpperCase()\n return REQUIRED_LOCATION_STATE_SET.has(state) ? state : null\n}\n\nfunction csvColumn(record: Record<string, string>, names: string[]): string {\n for (const name of names) {\n const value = record[name]\n if (value !== undefined) return value\n }\n return ''\n}\n\nfunction numberOrNull(value: string | undefined): number | null {\n if (value === undefined || value.trim() === '') return null\n const parsed = Number(value)\n return Number.isFinite(parsed) && parsed >= 0 ? Math.trunc(parsed) : null\n}\n\nfunction displayCityFromCensus(name: string): string {\n if (/^Nashville-Davidson metropolitan government/i.test(name)) return 'Nashville'\n return name.replace(/\\s+(city|town|village|municipality|borough)$/i, '').trim()\n}\n\nexport function parseHostedCensusPlacesCsv(csv: string, expectedStateFips?: string): ParsedCensusDataset {\n const records = csvRecords(csv.replace(/^\\uFEFF/, ''))\n if (records.length === 0) throw new Error('Census place CSV contains no data rows.')\n const headers = new Set(Object.keys(records[0] ?? {}).map(header => header.trim()))\n const required = ['SUMLEV', 'STATE', 'NAME', 'POPESTIMATE2020', 'POPESTIMATE2021', 'POPESTIMATE2022', 'POPESTIMATE2023', 'POPESTIMATE2024', 'POPESTIMATE2025']\n const missing = required.filter(header => !headers.has(header))\n if (missing.length > 0) throw new Error(`Census place CSV is missing required columns: ${missing.join(', ')}.`)\n\n const placeRecords = records.filter(record => record.SUMLEV?.trim() === '162')\n if (expectedStateFips) {\n const expected = expectedStateFips.padStart(2, '0')\n const mismatched = placeRecords.filter(record => record.STATE?.trim().padStart(2, '0') !== expected)\n if (mismatched.length > 0) {\n const received = [...new Set(mismatched.map(record => record.STATE?.trim() || '(blank)'))].slice(0, 5)\n throw new Error(`Census place CSV STATE does not match requested FIPS ${expected}; received ${received.join(', ')}.`)\n }\n }\n\n const candidates = placeRecords\n .map((record): HostedCensusPlace | null => {\n const censusName = record.NAME?.trim() ?? ''\n if (!censusName) return null\n const city = displayCityFromCensus(censusName)\n const cityKey = normalizeHostedCityKey(city)\n if (!cityKey) return null\n const populations = {\n 2020: numberOrNull(record.POPESTIMATE2020),\n 2021: numberOrNull(record.POPESTIMATE2021),\n 2022: numberOrNull(record.POPESTIMATE2022),\n 2023: numberOrNull(record.POPESTIMATE2023),\n 2024: numberOrNull(record.POPESTIMATE2024),\n 2025: numberOrNull(record.POPESTIMATE2025),\n } satisfies Record<PopulationYear, number | null>\n if (Object.values(populations).every(value => value === null)) return null\n return {\n city,\n cityKey,\n censusName,\n estimatesBase2020: numberOrNull(record.ESTIMATESBASE2020),\n populations,\n }\n })\n .filter((place): place is HostedCensusPlace => place !== null)\n\n // Census can contain separate legal entities with the same normalized place\n // name in one state (for example, both a small \"Wilmington village\" and a\n // much larger \"Wilmington city\" in Illinois). The hosted table and the ZIP\n // join intentionally use one row per state/city key, so retain the largest\n // current place deterministically instead of failing the whole state import.\n const placesByCityKey = new Map<string, HostedCensusPlace>()\n const populationRank = (place: HostedCensusPlace): number => (\n place.populations[2025]\n ?? place.populations[2024]\n ?? place.populations[2023]\n ?? place.populations[2022]\n ?? place.populations[2021]\n ?? place.populations[2020]\n ?? place.estimatesBase2020\n ?? -1\n )\n for (const candidate of candidates) {\n const current = placesByCityKey.get(candidate.cityKey)\n if (!current\n || populationRank(candidate) > populationRank(current)\n || (populationRank(candidate) === populationRank(current)\n && candidate.censusName.localeCompare(current.censusName) < 0)) {\n placesByCityKey.set(candidate.cityKey, candidate)\n }\n }\n const places = [...placesByCityKey.values()]\n .sort((a, b) => a.city.localeCompare(b.city))\n\n if (places.length === 0) throw new Error('Census place CSV did not contain any valid place population rows.')\n return { sourceRowCount: records.length, places }\n}\n\nexport function parseHostedZipGroupsCsv(csv: string): ParsedZipDataset {\n const records = csvRecords(csv.replace(/^\\uFEFF/, ''))\n if (records.length === 0) throw new Error('Location ZIP CSV contains no data rows.')\n\n const first = records[0] ?? {}\n const headers = new Set(Object.keys(first).map(header => header.trim().toLowerCase()))\n const hasState = ['state_abbr', 'state', 'state_id'].some(header => headers.has(header))\n const hasCity = ['city', 'primary_city'].some(header => headers.has(header))\n const hasZip = ['zipcode', 'zip', 'zip_code'].some(header => headers.has(header))\n if (!hasState || !hasCity || !hasZip) {\n throw new Error('Location ZIP CSV must include state_abbr/state, city, and zipcode/zip columns.')\n }\n\n const grouped = new Map<string, { city: string; cityKey: string; state: string; zips: Set<string>; counties: Set<string> }>()\n let rowCount = 0\n let rejectedRowCount = 0\n const states = new Set<string>()\n const uniqueZips = new Set<string>()\n\n for (const rawRecord of records) {\n const record = Object.fromEntries(Object.entries(rawRecord).map(([key, value]) => [key.trim().toLowerCase(), value]))\n const state = normalizedState(csvColumn(record, ['state_abbr', 'state', 'state_id']))\n const city = csvColumn(record, ['city', 'primary_city']).trim()\n const zip = normalizedZip(csvColumn(record, ['zipcode', 'zip', 'zip_code']))\n const county = csvColumn(record, ['county', 'county_name']).trim()\n if (!state || !REQUIRED_LOCATION_STATE_SET.has(state) || !city || !zip) {\n rejectedRowCount += 1\n continue\n }\n\n const cityKey = normalizeHostedCityKey(city)\n if (!cityKey) {\n rejectedRowCount += 1\n continue\n }\n const key = `${state}\\0${cityKey}`\n let group = grouped.get(key)\n if (!group) {\n group = { city, cityKey, state, zips: new Set(), counties: new Set() }\n grouped.set(key, group)\n }\n group.zips.add(zip)\n if (county) group.counties.add(county)\n states.add(state)\n uniqueZips.add(zip)\n rowCount += 1\n }\n\n if (grouped.size === 0) throw new Error('Location ZIP CSV did not contain any valid US city/ZIP rows.')\n return {\n sourceRowCount: records.length,\n rowCount,\n rejectedRowCount,\n zipCount: uniqueZips.size,\n stateCount: states.size,\n coveredStates: [...states].sort(),\n groups: [...grouped.values()]\n .map(group => ({\n city: group.city,\n cityKey: group.cityKey,\n state: group.state,\n zips: [...group.zips].sort(),\n counties: [...group.counties].sort(),\n }))\n .sort((a, b) => a.state.localeCompare(b.state) || a.city.localeCompare(b.city)),\n }\n}\n\nfunction assertNationwideZipCoverage(parsed: ParsedZipDataset): void {\n const covered = new Set(parsed.coveredStates)\n const missingStates = REQUIRED_LOCATION_STATE_CODES.filter(state => !covered.has(state))\n const errors: string[] = []\n if (missingStates.length > 0) errors.push(`missing required states: ${missingStates.join(', ')}`)\n if (parsed.zipCount < MIN_NATIONWIDE_ZIP_COUNT) {\n errors.push(`only ${parsed.zipCount} unique ZIPs; at least ${MIN_NATIONWIDE_ZIP_COUNT} are required`)\n }\n if (errors.length > 0) {\n throw new Error(`Location ZIP snapshot is not nationwide and was not activated (${errors.join('; ')}; ${parsed.rejectedRowCount} rejected rows).`)\n }\n}\n\nexport async function ensureHostedLocationDataSchema(): Promise<void> {\n const db = getDb()\n if (schemaDb !== db) {\n schemaDb = db\n schemaPromise = null\n }\n if (!schemaPromise) {\n schemaPromise = (async () => {\n await db.execute(`\n CREATE TABLE IF NOT EXISTS location_data_imports (\n id TEXT PRIMARY KEY,\n dataset_kind TEXT NOT NULL,\n source_url TEXT,\n sha256 TEXT NOT NULL,\n row_count INTEGER NOT NULL DEFAULT 0,\n group_count INTEGER NOT NULL DEFAULT 0,\n state_count INTEGER NOT NULL DEFAULT 0,\n source_row_count INTEGER NOT NULL DEFAULT 0,\n rejected_row_count INTEGER NOT NULL DEFAULT 0,\n zip_count INTEGER NOT NULL DEFAULT 0,\n covered_states_json TEXT NOT NULL DEFAULT '[]',\n coverage_complete INTEGER NOT NULL DEFAULT 0,\n status TEXT NOT NULL,\n error TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n completed_at TEXT\n )\n `)\n const importColumns = new Set((await db.execute(`PRAGMA table_info(location_data_imports)`)).rows.map(row => String(row.name)))\n const missingImportColumns = [\n ['source_row_count', `INTEGER NOT NULL DEFAULT 0`],\n ['rejected_row_count', `INTEGER NOT NULL DEFAULT 0`],\n ['zip_count', `INTEGER NOT NULL DEFAULT 0`],\n ['covered_states_json', `TEXT NOT NULL DEFAULT '[]'`],\n ['coverage_complete', `INTEGER NOT NULL DEFAULT 0`],\n ] as const\n for (const [column, definition] of missingImportColumns) {\n if (!importColumns.has(column)) await db.execute(`ALTER TABLE location_data_imports ADD COLUMN ${column} ${definition}`)\n }\n await db.execute(`CREATE INDEX IF NOT EXISTS location_data_imports_kind_created ON location_data_imports(dataset_kind, created_at DESC)`)\n await db.execute(`\n CREATE TABLE IF NOT EXISTS location_zip_groups (\n import_id TEXT NOT NULL REFERENCES location_data_imports(id) ON DELETE CASCADE,\n state_abbr TEXT NOT NULL,\n city_key TEXT NOT NULL,\n city TEXT NOT NULL,\n zips_json TEXT NOT NULL,\n counties_json TEXT NOT NULL,\n PRIMARY KEY(import_id, state_abbr, city_key)\n )\n `)\n await db.execute(`CREATE INDEX IF NOT EXISTS location_zip_groups_state ON location_zip_groups(import_id, state_abbr, city_key)`)\n await db.execute(`\n CREATE TABLE IF NOT EXISTS location_census_places (\n import_id TEXT NOT NULL REFERENCES location_data_imports(id) ON DELETE CASCADE,\n state_abbr TEXT NOT NULL,\n city_key TEXT NOT NULL,\n city TEXT NOT NULL,\n census_name TEXT NOT NULL,\n estimates_base_2020 INTEGER,\n population_2020 INTEGER,\n population_2021 INTEGER,\n population_2022 INTEGER,\n population_2023 INTEGER,\n population_2024 INTEGER,\n population_2025 INTEGER,\n PRIMARY KEY(import_id, state_abbr, city_key)\n )\n `)\n await db.execute(`CREATE INDEX IF NOT EXISTS location_census_places_state ON location_census_places(import_id, state_abbr, city_key)`)\n await db.execute(`\n CREATE TABLE IF NOT EXISTS location_data_active (\n dataset_kind TEXT PRIMARY KEY,\n import_id TEXT NOT NULL REFERENCES location_data_imports(id),\n activated_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `)\n })().catch(error => {\n schemaPromise = null\n throw error\n })\n }\n await schemaPromise\n}\n\nexport async function getActiveHostedDataset(kind: HostedLocationDatasetKind): Promise<HostedLocationDataset | null> {\n await ensureHostedLocationDataSchema()\n const result = await getDb().execute({\n sql: `\n SELECT i.*\n FROM location_data_active a\n JOIN location_data_imports i ON i.id = a.import_id\n WHERE a.dataset_kind = ? AND i.status = 'ready'\n LIMIT 1\n `,\n args: [kind],\n })\n const row = result.rows[0]\n return row ? rowToDataset(row as unknown as Record<string, unknown>) : null\n}\n\nexport async function getActiveHostedLocationDataset(): Promise<HostedLocationDataset | null> {\n return getActiveHostedDataset(HOSTED_ZIP_DATASET_KIND)\n}\n\nexport async function listActiveHostedLocationDatasets(): Promise<HostedLocationDataset[]> {\n await ensureHostedLocationDataSchema()\n const result = await getDb().execute(`\n SELECT i.*\n FROM location_data_active a\n JOIN location_data_imports i ON i.id = a.import_id\n WHERE i.status = 'ready'\n ORDER BY i.dataset_kind ASC\n `)\n return result.rows.map(row => rowToDataset(row as unknown as Record<string, unknown>))\n}\n\nexport async function getHostedZipGroups(stateInput: string): Promise<HostedZipGroupLookup> {\n const state = normalizedState(stateInput)\n if (!state) throw new Error('state must be a two-letter US state abbreviation')\n const dataset = await getActiveHostedLocationDataset()\n if (!dataset) return { dataset: null, groups: new Map() }\n\n const result = await getDb().execute({\n sql: `\n SELECT city, city_key, state_abbr, zips_json, counties_json\n FROM location_zip_groups\n WHERE import_id = ? AND state_abbr = ?\n ORDER BY city COLLATE NOCASE ASC\n `,\n args: [dataset.id, state],\n })\n const groups = new Map<string, HostedZipGroup>()\n for (const row of result.rows) {\n const cityKey = String(row.city_key)\n groups.set(cityKey, {\n city: String(row.city),\n cityKey,\n state: String(row.state_abbr),\n zips: JSON.parse(String(row.zips_json)) as string[],\n counties: JSON.parse(String(row.counties_json)) as string[],\n })\n }\n return { dataset, groups }\n}\n\nexport async function importHostedZipGroupsCsv(input: {\n csv: string\n sourceUrl?: string | null\n}): Promise<HostedZipImportResult> {\n await ensureHostedLocationDataSchema()\n const sourceUrl = normalizedSourceUrl(input.sourceUrl)\n const sha256 = createHash('sha256').update(input.csv).digest('hex')\n const active = await getActiveHostedLocationDataset()\n if (active?.sha256 === sha256) return { dataset: active, duplicate: true }\n\n const parsed = parseHostedZipGroupsCsv(input.csv)\n assertNationwideZipCoverage(parsed)\n const id = `loc_${randomUUID().replaceAll('-', '')}`\n const db = getDb()\n await db.execute({\n sql: `\n INSERT INTO location_data_imports (\n id, dataset_kind, source_url, sha256, row_count, group_count, state_count,\n source_row_count, rejected_row_count, zip_count, covered_states_json, coverage_complete, status\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 'loading')\n `,\n args: [\n id, HOSTED_ZIP_DATASET_KIND, sourceUrl, sha256, parsed.rowCount, parsed.groups.length, parsed.stateCount,\n parsed.sourceRowCount, parsed.rejectedRowCount, parsed.zipCount, JSON.stringify(parsed.coveredStates),\n ],\n })\n\n try {\n for (let offset = 0; offset < parsed.groups.length; offset += IMPORT_BATCH_SIZE) {\n const batch = parsed.groups.slice(offset, offset + IMPORT_BATCH_SIZE).map(group => ({\n sql: `\n INSERT INTO location_zip_groups (\n import_id, state_abbr, city_key, city, zips_json, counties_json\n ) VALUES (?, ?, ?, ?, ?, ?)\n `,\n args: [id, group.state, group.cityKey, group.city, JSON.stringify(group.zips), JSON.stringify(group.counties)],\n }))\n await db.batch(batch, 'write')\n }\n\n await db.batch([\n {\n sql: `UPDATE location_data_imports SET status = 'ready', completed_at = datetime('now'), error = NULL WHERE id = ? AND status = 'loading'`,\n args: [id],\n },\n {\n sql: `\n INSERT INTO location_data_active (dataset_kind, import_id, activated_at)\n VALUES (?, ?, datetime('now'))\n ON CONFLICT(dataset_kind) DO UPDATE SET import_id = excluded.import_id, activated_at = excluded.activated_at\n `,\n args: [HOSTED_ZIP_DATASET_KIND, id],\n },\n ], 'write')\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n await db.execute({\n sql: `UPDATE location_data_imports SET status = 'failed', error = ?, completed_at = datetime('now') WHERE id = ?`,\n args: [message.slice(0, 1_000), id],\n }).catch(() => undefined)\n throw error\n }\n\n const result = await db.execute({ sql: 'SELECT * FROM location_data_imports WHERE id = ? LIMIT 1', args: [id] })\n const row = result.rows[0]\n if (!row) throw new Error('Hosted location import completed without a durable metadata row.')\n return { dataset: rowToDataset(row as unknown as Record<string, unknown>), duplicate: false }\n}\n\nexport async function importHostedCensusPlacesCsv(input: {\n state: string\n csv: string\n sourceUrl?: string | null\n}): Promise<HostedZipImportResult> {\n await ensureHostedLocationDataSchema()\n const state = normalizedState(input.state)\n if (!state) throw new Error('state must be a two-letter US state abbreviation')\n const kind = censusDatasetKind(state)\n const sourceUrl = normalizedSourceUrl(input.sourceUrl)\n const sha256 = createHash('sha256').update(input.csv).digest('hex')\n const active = await getActiveHostedDataset(kind)\n if (active?.sha256 === sha256) return { dataset: active, duplicate: true }\n\n const stateFips = STATE_FIPS_BY_ABBR[state as keyof typeof STATE_FIPS_BY_ABBR]\n const parsed = parseHostedCensusPlacesCsv(input.csv, stateFips)\n const id = `loc_${randomUUID().replaceAll('-', '')}`\n const db = getDb()\n await db.execute({\n sql: `\n INSERT INTO location_data_imports (\n id, dataset_kind, source_url, sha256, row_count, group_count, state_count,\n source_row_count, rejected_row_count, zip_count, covered_states_json, coverage_complete, status\n ) VALUES (?, ?, ?, ?, ?, ?, 1, ?, 0, 0, ?, 1, 'loading')\n `,\n args: [id, kind, sourceUrl, sha256, parsed.places.length, parsed.places.length, parsed.sourceRowCount, JSON.stringify([state])],\n })\n\n try {\n for (let offset = 0; offset < parsed.places.length; offset += IMPORT_BATCH_SIZE) {\n const batch = parsed.places.slice(offset, offset + IMPORT_BATCH_SIZE).map(place => ({\n sql: `\n INSERT INTO location_census_places (\n import_id, state_abbr, city_key, city, census_name, estimates_base_2020,\n population_2020, population_2021, population_2022, population_2023,\n population_2024, population_2025\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `,\n args: [\n id,\n state,\n place.cityKey,\n place.city,\n place.censusName,\n place.estimatesBase2020,\n place.populations[2020],\n place.populations[2021],\n place.populations[2022],\n place.populations[2023],\n place.populations[2024],\n place.populations[2025],\n ],\n }))\n await db.batch(batch, 'write')\n }\n\n await db.batch([\n {\n sql: `UPDATE location_data_imports SET status = 'ready', completed_at = datetime('now'), error = NULL WHERE id = ? AND status = 'loading'`,\n args: [id],\n },\n {\n sql: `\n INSERT INTO location_data_active (dataset_kind, import_id, activated_at)\n VALUES (?, ?, datetime('now'))\n ON CONFLICT(dataset_kind) DO UPDATE SET import_id = excluded.import_id, activated_at = excluded.activated_at\n `,\n args: [kind, id],\n },\n ], 'write')\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n await db.execute({\n sql: `UPDATE location_data_imports SET status = 'failed', error = ?, completed_at = datetime('now') WHERE id = ?`,\n args: [message.slice(0, 1_000), id],\n }).catch(() => undefined)\n throw error\n }\n\n const result = await db.execute({ sql: 'SELECT * FROM location_data_imports WHERE id = ? LIMIT 1', args: [id] })\n const row = result.rows[0]\n if (!row) throw new Error('Hosted Census import completed without a durable metadata row.')\n return { dataset: rowToDataset(row as unknown as Record<string, unknown>), duplicate: false }\n}\n\nexport async function queryHostedLocationMarkets(input: HostedLocationMarketQuery): Promise<HostedLocationMarketResult> {\n const state = normalizedState(input.state)\n if (!state) throw new Error('state must be a two-letter US state abbreviation')\n if (!Number.isSafeInteger(input.minPopulation) || input.minPopulation < 0) throw new Error('minPopulation must be a non-negative integer')\n if (!Number.isSafeInteger(input.maxResults) || input.maxResults < 1 || input.maxResults > 100) throw new Error('maxResults must be between 1 and 100')\n\n const populationDataset = await getActiveHostedDataset(censusDatasetKind(state))\n const needsZipDataset = input.includeZipGroups || Boolean(input.zip)\n const zipLookup = needsZipDataset\n ? await getHostedZipGroups(state)\n : { dataset: null, groups: new Map<string, HostedZipGroup>() }\n if (!populationDataset) {\n return { markets: [], populationDataset: null, zipDataset: zipLookup.dataset, warnings: [] }\n }\n\n const result = await getDb().execute({\n sql: `\n SELECT *\n FROM location_census_places\n WHERE import_id = ? AND state_abbr = ?\n ORDER BY city COLLATE NOCASE ASC\n `,\n args: [populationDataset.id, state],\n })\n const cityQuery = normalizeHostedCityKey(input.cityQuery ?? '')\n const zip = input.zip?.trim()\n const populationColumn = `population_${input.populationYear}`\n const markets = result.rows\n .map((row): DirectoryMarket | null => {\n const populationValue = row[populationColumn]\n if (populationValue == null) return null\n const population = Number(populationValue)\n if (!Number.isSafeInteger(population) || population < input.minPopulation) return null\n const city = String(row.city)\n const normalizedKey = String(row.city_key)\n if (cityQuery && !normalizedKey.includes(cityQuery)) return null\n const zipGroup = zipLookup.groups.get(normalizedKey)\n const zips = zipGroup?.zips ?? []\n if (zip && !zips.includes(zip)) return null\n return {\n city,\n state,\n location: `${city}, ${state}`,\n cityKey: `${city}|${state}`,\n censusName: String(row.census_name),\n population,\n populationYear: input.populationYear,\n estimatesBase2020: row.estimates_base_2020 == null ? null : Number(row.estimates_base_2020),\n zips: input.includeZipGroups ? zips : [],\n counties: input.includeZipGroups ? zipGroup?.counties ?? [] : [],\n }\n })\n .filter((market): market is DirectoryMarket => market !== null)\n .sort((a, b) => b.population - a.population || a.city.localeCompare(b.city))\n .slice(0, input.maxResults)\n\n const warnings: string[] = []\n if (input.includeZipGroups && zipLookup.dataset && markets.some(market => market.zips.length === 0)) {\n warnings.push('Some hosted Census places did not match the hosted ZIP city groups.')\n }\n return {\n markets,\n populationDataset,\n zipDataset: zipLookup.dataset,\n warnings,\n }\n}\n"],"mappings":";;;;;;;;AAAA,SAAS,YAAY,kBAAkB;AAKhC,IAAM,0BAA0B;AAChC,IAAM,+BAA+B;AAErC,IAAM,2BAA2B;AAEjC,IAAM,gCAAgC;AAAA,EAC3C;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AACd;AAEA,IAAM,qBAAmF;AAAA,EACvF,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EACpF,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EACpF,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EACpF,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EACpF,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EACpF,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AAAA,EAAM,IAAI;AACxD;AACA,IAAM,8BAA8B,IAAI,IAAY,6BAA6B;AA+EjF,IAAM,oBAAoB;AAC1B,IAAM,wBAAwB;AAE9B,IAAI,WAA4C;AAChD,IAAI,gBAAsC;AAE1C,SAAS,uBAAuB,OAAuB;AACrD,SAAO,MAAM,YAAY,EAAE,QAAQ,eAAe,GAAG,EAAE,KAAK;AAC9D;AAEA,SAAS,YAAY,OAA0B;AAC7C,MAAI,SAAS,KAAM,QAAO,CAAC;AAC3B,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,OAAO,KAAK,CAAC;AACvC,WAAO,MAAM,QAAQ,MAAM,IAAI,OAAO,IAAI,MAAM,IAAI,CAAC;AAAA,EACvD,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,SAAS,aAAa,KAAqD;AACzE,SAAO;AAAA,IACL,IAAI,OAAO,IAAI,EAAE;AAAA,IACjB,MAAM,OAAO,IAAI,YAAY;AAAA,IAC7B,WAAW,IAAI,cAAc,OAAO,OAAO,OAAO,IAAI,UAAU;AAAA,IAChE,QAAQ,OAAO,IAAI,MAAM;AAAA,IACzB,UAAU,OAAO,IAAI,aAAa,CAAC;AAAA,IACnC,YAAY,OAAO,IAAI,eAAe,CAAC;AAAA,IACvC,YAAY,OAAO,IAAI,eAAe,CAAC;AAAA,IACvC,gBAAgB,OAAO,IAAI,oBAAoB,IAAI,aAAa,CAAC;AAAA,IACjE,kBAAkB,OAAO,IAAI,sBAAsB,CAAC;AAAA,IACpD,UAAU,OAAO,IAAI,aAAa,CAAC;AAAA,IACnC,eAAe,YAAY,IAAI,mBAAmB;AAAA,IAClD,kBAAkB,OAAO,IAAI,qBAAqB,CAAC,MAAM;AAAA,IACzD,QAAQ,OAAO,IAAI,MAAM;AAAA,IACzB,WAAW,OAAO,IAAI,UAAU;AAAA,IAChC,aAAa,IAAI,gBAAgB,OAAO,OAAO,OAAO,IAAI,YAAY;AAAA,IACtE,OAAO,IAAI,SAAS,OAAO,OAAO,OAAO,IAAI,KAAK;AAAA,EACpD;AACF;AAEA,SAAS,kBAAkB,OAAmE;AAC5F,SAAO,GAAG,4BAA4B,IAAI,KAAK;AACjD;AAEA,SAAS,oBAAoB,OAAiD;AAC5E,QAAM,UAAU,OAAO,KAAK;AAC5B,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,QAAQ,SAAS,sBAAuB,OAAM,IAAI,MAAM,qBAAqB,qBAAqB,sBAAsB;AAC5H,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,OAAO;AAAA,EAC1B,QAAQ;AACN,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AACA,SAAO,WAAW;AAClB,SAAO,WAAW;AAClB,SAAO,SAAS;AAChB,SAAO,OAAO;AACd,SAAO,OAAO,SAAS;AACzB;AAEA,SAAS,cAAc,OAA8B;AACnD,QAAM,SAAS,MAAM,KAAK;AAC1B,MAAI,CAAC,YAAY,KAAK,MAAM,EAAG,QAAO;AACtC,SAAO,OAAO,SAAS,GAAG,GAAG;AAC/B;AAEA,SAAS,gBAAgB,OAA8B;AACrD,QAAM,QAAQ,MAAM,KAAK,EAAE,YAAY;AACvC,SAAO,4BAA4B,IAAI,KAAK,IAAI,QAAQ;AAC1D;AAEA,SAAS,UAAU,QAAgC,OAAyB;AAC1E,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,OAAO,IAAI;AACzB,QAAI,UAAU,OAAW,QAAO;AAAA,EAClC;AACA,SAAO;AACT;AAEA,SAAS,aAAa,OAA0C;AAC9D,MAAI,UAAU,UAAa,MAAM,KAAK,MAAM,GAAI,QAAO;AACvD,QAAM,SAAS,OAAO,KAAK;AAC3B,SAAO,OAAO,SAAS,MAAM,KAAK,UAAU,IAAI,KAAK,MAAM,MAAM,IAAI;AACvE;AAEA,SAAS,sBAAsB,MAAsB;AACnD,MAAI,+CAA+C,KAAK,IAAI,EAAG,QAAO;AACtE,SAAO,KAAK,QAAQ,iDAAiD,EAAE,EAAE,KAAK;AAChF;AAEO,SAAS,2BAA2B,KAAa,mBAAiD;AACvG,QAAM,UAAU,WAAW,IAAI,QAAQ,WAAW,EAAE,CAAC;AACrD,MAAI,QAAQ,WAAW,EAAG,OAAM,IAAI,MAAM,yCAAyC;AACnF,QAAM,UAAU,IAAI,IAAI,OAAO,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,YAAU,OAAO,KAAK,CAAC,CAAC;AAClF,QAAM,WAAW,CAAC,UAAU,SAAS,QAAQ,mBAAmB,mBAAmB,mBAAmB,mBAAmB,mBAAmB,iBAAiB;AAC7J,QAAM,UAAU,SAAS,OAAO,YAAU,CAAC,QAAQ,IAAI,MAAM,CAAC;AAC9D,MAAI,QAAQ,SAAS,EAAG,OAAM,IAAI,MAAM,iDAAiD,QAAQ,KAAK,IAAI,CAAC,GAAG;AAE9G,QAAM,eAAe,QAAQ,OAAO,YAAU,OAAO,QAAQ,KAAK,MAAM,KAAK;AAC7E,MAAI,mBAAmB;AACrB,UAAM,WAAW,kBAAkB,SAAS,GAAG,GAAG;AAClD,UAAM,aAAa,aAAa,OAAO,YAAU,OAAO,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG,MAAM,QAAQ;AACnG,QAAI,WAAW,SAAS,GAAG;AACzB,YAAM,WAAW,CAAC,GAAG,IAAI,IAAI,WAAW,IAAI,YAAU,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC;AACrG,YAAM,IAAI,MAAM,wDAAwD,QAAQ,cAAc,SAAS,KAAK,IAAI,CAAC,GAAG;AAAA,IACtH;AAAA,EACF;AAEA,QAAM,aAAa,aAChB,IAAI,CAAC,WAAqC;AACzC,UAAM,aAAa,OAAO,MAAM,KAAK,KAAK;AAC1C,QAAI,CAAC,WAAY,QAAO;AACxB,UAAM,OAAO,sBAAsB,UAAU;AAC7C,UAAM,UAAU,uBAAuB,IAAI;AAC3C,QAAI,CAAC,QAAS,QAAO;AACrB,UAAM,cAAc;AAAA,MAClB,MAAM,aAAa,OAAO,eAAe;AAAA,MACzC,MAAM,aAAa,OAAO,eAAe;AAAA,MACzC,MAAM,aAAa,OAAO,eAAe;AAAA,MACzC,MAAM,aAAa,OAAO,eAAe;AAAA,MACzC,MAAM,aAAa,OAAO,eAAe;AAAA,MACzC,MAAM,aAAa,OAAO,eAAe;AAAA,IAC3C;AACA,QAAI,OAAO,OAAO,WAAW,EAAE,MAAM,WAAS,UAAU,IAAI,EAAG,QAAO;AACtE,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,mBAAmB,aAAa,OAAO,iBAAiB;AAAA,MACxD;AAAA,IACF;AAAA,EACF,CAAC,EACA,OAAO,CAAC,UAAsC,UAAU,IAAI;AAO/D,QAAM,kBAAkB,oBAAI,IAA+B;AAC3D,QAAM,iBAAiB,CAAC,UACtB,MAAM,YAAY,IAAI,KACjB,MAAM,YAAY,IAAI,KACtB,MAAM,YAAY,IAAI,KACtB,MAAM,YAAY,IAAI,KACtB,MAAM,YAAY,IAAI,KACtB,MAAM,YAAY,IAAI,KACtB,MAAM,qBACN;AAEP,aAAW,aAAa,YAAY;AAClC,UAAM,UAAU,gBAAgB,IAAI,UAAU,OAAO;AACrD,QAAI,CAAC,WACA,eAAe,SAAS,IAAI,eAAe,OAAO,KACjD,eAAe,SAAS,MAAM,eAAe,OAAO,KACnD,UAAU,WAAW,cAAc,QAAQ,UAAU,IAAI,GAAI;AAClE,sBAAgB,IAAI,UAAU,SAAS,SAAS;AAAA,IAClD;AAAA,EACF;AACA,QAAM,SAAS,CAAC,GAAG,gBAAgB,OAAO,CAAC,EACxC,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAE9C,MAAI,OAAO,WAAW,EAAG,OAAM,IAAI,MAAM,mEAAmE;AAC5G,SAAO,EAAE,gBAAgB,QAAQ,QAAQ,OAAO;AAClD;AAEO,SAAS,wBAAwB,KAA+B;AACrE,QAAM,UAAU,WAAW,IAAI,QAAQ,WAAW,EAAE,CAAC;AACrD,MAAI,QAAQ,WAAW,EAAG,OAAM,IAAI,MAAM,yCAAyC;AAEnF,QAAM,QAAQ,QAAQ,CAAC,KAAK,CAAC;AAC7B,QAAM,UAAU,IAAI,IAAI,OAAO,KAAK,KAAK,EAAE,IAAI,YAAU,OAAO,KAAK,EAAE,YAAY,CAAC,CAAC;AACrF,QAAM,WAAW,CAAC,cAAc,SAAS,UAAU,EAAE,KAAK,YAAU,QAAQ,IAAI,MAAM,CAAC;AACvF,QAAM,UAAU,CAAC,QAAQ,cAAc,EAAE,KAAK,YAAU,QAAQ,IAAI,MAAM,CAAC;AAC3E,QAAM,SAAS,CAAC,WAAW,OAAO,UAAU,EAAE,KAAK,YAAU,QAAQ,IAAI,MAAM,CAAC;AAChF,MAAI,CAAC,YAAY,CAAC,WAAW,CAAC,QAAQ;AACpC,UAAM,IAAI,MAAM,gFAAgF;AAAA,EAClG;AAEA,QAAM,UAAU,oBAAI,IAAwG;AAC5H,MAAI,WAAW;AACf,MAAI,mBAAmB;AACvB,QAAM,SAAS,oBAAI,IAAY;AAC/B,QAAM,aAAa,oBAAI,IAAY;AAEnC,aAAW,aAAa,SAAS;AAC/B,UAAM,SAAS,OAAO,YAAY,OAAO,QAAQ,SAAS,EAAE,IAAI,CAAC,CAACA,MAAK,KAAK,MAAM,CAACA,KAAI,KAAK,EAAE,YAAY,GAAG,KAAK,CAAC,CAAC;AACpH,UAAM,QAAQ,gBAAgB,UAAU,QAAQ,CAAC,cAAc,SAAS,UAAU,CAAC,CAAC;AACpF,UAAM,OAAO,UAAU,QAAQ,CAAC,QAAQ,cAAc,CAAC,EAAE,KAAK;AAC9D,UAAM,MAAM,cAAc,UAAU,QAAQ,CAAC,WAAW,OAAO,UAAU,CAAC,CAAC;AAC3E,UAAM,SAAS,UAAU,QAAQ,CAAC,UAAU,aAAa,CAAC,EAAE,KAAK;AACjE,QAAI,CAAC,SAAS,CAAC,4BAA4B,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK;AACtE,0BAAoB;AACpB;AAAA,IACF;AAEA,UAAM,UAAU,uBAAuB,IAAI;AAC3C,QAAI,CAAC,SAAS;AACZ,0BAAoB;AACpB;AAAA,IACF;AACA,UAAM,MAAM,GAAG,KAAK,KAAK,OAAO;AAChC,QAAI,QAAQ,QAAQ,IAAI,GAAG;AAC3B,QAAI,CAAC,OAAO;AACV,cAAQ,EAAE,MAAM,SAAS,OAAO,MAAM,oBAAI,IAAI,GAAG,UAAU,oBAAI,IAAI,EAAE;AACrE,cAAQ,IAAI,KAAK,KAAK;AAAA,IACxB;AACA,UAAM,KAAK,IAAI,GAAG;AAClB,QAAI,OAAQ,OAAM,SAAS,IAAI,MAAM;AACrC,WAAO,IAAI,KAAK;AAChB,eAAW,IAAI,GAAG;AAClB,gBAAY;AAAA,EACd;AAEA,MAAI,QAAQ,SAAS,EAAG,OAAM,IAAI,MAAM,8DAA8D;AACtG,SAAO;AAAA,IACL,gBAAgB,QAAQ;AAAA,IACxB;AAAA,IACA;AAAA,IACA,UAAU,WAAW;AAAA,IACrB,YAAY,OAAO;AAAA,IACnB,eAAe,CAAC,GAAG,MAAM,EAAE,KAAK;AAAA,IAChC,QAAQ,CAAC,GAAG,QAAQ,OAAO,CAAC,EACzB,IAAI,YAAU;AAAA,MACb,MAAM,MAAM;AAAA,MACZ,SAAS,MAAM;AAAA,MACf,OAAO,MAAM;AAAA,MACb,MAAM,CAAC,GAAG,MAAM,IAAI,EAAE,KAAK;AAAA,MAC3B,UAAU,CAAC,GAAG,MAAM,QAAQ,EAAE,KAAK;AAAA,IACrC,EAAE,EACD,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,cAAc,EAAE,KAAK,KAAK,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAAA,EAClF;AACF;AAEA,SAAS,4BAA4B,QAAgC;AACnE,QAAM,UAAU,IAAI,IAAI,OAAO,aAAa;AAC5C,QAAM,gBAAgB,8BAA8B,OAAO,WAAS,CAAC,QAAQ,IAAI,KAAK,CAAC;AACvF,QAAM,SAAmB,CAAC;AAC1B,MAAI,cAAc,SAAS,EAAG,QAAO,KAAK,4BAA4B,cAAc,KAAK,IAAI,CAAC,EAAE;AAChG,MAAI,OAAO,WAAW,0BAA0B;AAC9C,WAAO,KAAK,QAAQ,OAAO,QAAQ,0BAA0B,wBAAwB,eAAe;AAAA,EACtG;AACA,MAAI,OAAO,SAAS,GAAG;AACrB,UAAM,IAAI,MAAM,kEAAkE,OAAO,KAAK,IAAI,CAAC,KAAK,OAAO,gBAAgB,kBAAkB;AAAA,EACnJ;AACF;AAEA,eAAsB,iCAAgD;AACpE,QAAM,KAAK,MAAM;AACjB,MAAI,aAAa,IAAI;AACnB,eAAW;AACX,oBAAgB;AAAA,EAClB;AACA,MAAI,CAAC,eAAe;AAClB,qBAAiB,YAAY;AAC3B,YAAM,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAmBhB;AACD,YAAM,gBAAgB,IAAI,KAAK,MAAM,GAAG,QAAQ,0CAA0C,GAAG,KAAK,IAAI,SAAO,OAAO,IAAI,IAAI,CAAC,CAAC;AAC9H,YAAM,uBAAuB;AAAA,QAC3B,CAAC,oBAAoB,4BAA4B;AAAA,QACjD,CAAC,sBAAsB,4BAA4B;AAAA,QACnD,CAAC,aAAa,4BAA4B;AAAA,QAC1C,CAAC,uBAAuB,4BAA4B;AAAA,QACpD,CAAC,qBAAqB,4BAA4B;AAAA,MACpD;AACA,iBAAW,CAAC,QAAQ,UAAU,KAAK,sBAAsB;AACvD,YAAI,CAAC,cAAc,IAAI,MAAM,EAAG,OAAM,GAAG,QAAQ,gDAAgD,MAAM,IAAI,UAAU,EAAE;AAAA,MACzH;AACA,YAAM,GAAG,QAAQ,uHAAuH;AACxI,YAAM,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAUhB;AACD,YAAM,GAAG,QAAQ,8GAA8G;AAC/H,YAAM,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAgBhB;AACD,YAAM,GAAG,QAAQ,oHAAoH;AACrI,YAAM,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAMhB;AAAA,IACH,GAAG,EAAE,MAAM,WAAS;AAClB,sBAAgB;AAChB,YAAM;AAAA,IACR,CAAC;AAAA,EACH;AACA,QAAM;AACR;AAEA,eAAsB,uBAAuB,MAAwE;AACnH,QAAM,+BAA+B;AACrC,QAAM,SAAS,MAAM,MAAM,EAAE,QAAQ;AAAA,IACnC,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOL,MAAM,CAAC,IAAI;AAAA,EACb,CAAC;AACD,QAAM,MAAM,OAAO,KAAK,CAAC;AACzB,SAAO,MAAM,aAAa,GAAyC,IAAI;AACzE;AAEA,eAAsB,iCAAwE;AAC5F,SAAO,uBAAuB,uBAAuB;AACvD;AAEA,eAAsB,mCAAqE;AACzF,QAAM,+BAA+B;AACrC,QAAM,SAAS,MAAM,MAAM,EAAE,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAMpC;AACD,SAAO,OAAO,KAAK,IAAI,SAAO,aAAa,GAAyC,CAAC;AACvF;AAEA,eAAsB,mBAAmB,YAAmD;AAC1F,QAAM,QAAQ,gBAAgB,UAAU;AACxC,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,kDAAkD;AAC9E,QAAM,UAAU,MAAM,+BAA+B;AACrD,MAAI,CAAC,QAAS,QAAO,EAAE,SAAS,MAAM,QAAQ,oBAAI,IAAI,EAAE;AAExD,QAAM,SAAS,MAAM,MAAM,EAAE,QAAQ;AAAA,IACnC,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAML,MAAM,CAAC,QAAQ,IAAI,KAAK;AAAA,EAC1B,CAAC;AACD,QAAM,SAAS,oBAAI,IAA4B;AAC/C,aAAW,OAAO,OAAO,MAAM;AAC7B,UAAM,UAAU,OAAO,IAAI,QAAQ;AACnC,WAAO,IAAI,SAAS;AAAA,MAClB,MAAM,OAAO,IAAI,IAAI;AAAA,MACrB;AAAA,MACA,OAAO,OAAO,IAAI,UAAU;AAAA,MAC5B,MAAM,KAAK,MAAM,OAAO,IAAI,SAAS,CAAC;AAAA,MACtC,UAAU,KAAK,MAAM,OAAO,IAAI,aAAa,CAAC;AAAA,IAChD,CAAC;AAAA,EACH;AACA,SAAO,EAAE,SAAS,OAAO;AAC3B;AAEA,eAAsB,yBAAyB,OAGZ;AACjC,QAAM,+BAA+B;AACrC,QAAM,YAAY,oBAAoB,MAAM,SAAS;AACrD,QAAM,SAAS,WAAW,QAAQ,EAAE,OAAO,MAAM,GAAG,EAAE,OAAO,KAAK;AAClE,QAAM,SAAS,MAAM,+BAA+B;AACpD,MAAI,QAAQ,WAAW,OAAQ,QAAO,EAAE,SAAS,QAAQ,WAAW,KAAK;AAEzE,QAAM,SAAS,wBAAwB,MAAM,GAAG;AAChD,8BAA4B,MAAM;AAClC,QAAM,KAAK,OAAO,WAAW,EAAE,WAAW,KAAK,EAAE,CAAC;AAClD,QAAM,KAAK,MAAM;AACjB,QAAM,GAAG,QAAQ;AAAA,IACf,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAML,MAAM;AAAA,MACJ;AAAA,MAAI;AAAA,MAAyB;AAAA,MAAW;AAAA,MAAQ,OAAO;AAAA,MAAU,OAAO,OAAO;AAAA,MAAQ,OAAO;AAAA,MAC9F,OAAO;AAAA,MAAgB,OAAO;AAAA,MAAkB,OAAO;AAAA,MAAU,KAAK,UAAU,OAAO,aAAa;AAAA,IACtG;AAAA,EACF,CAAC;AAED,MAAI;AACF,aAAS,SAAS,GAAG,SAAS,OAAO,OAAO,QAAQ,UAAU,mBAAmB;AAC/E,YAAM,QAAQ,OAAO,OAAO,MAAM,QAAQ,SAAS,iBAAiB,EAAE,IAAI,YAAU;AAAA,QAClF,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,QAKL,MAAM,CAAC,IAAI,MAAM,OAAO,MAAM,SAAS,MAAM,MAAM,KAAK,UAAU,MAAM,IAAI,GAAG,KAAK,UAAU,MAAM,QAAQ,CAAC;AAAA,MAC/G,EAAE;AACF,YAAM,GAAG,MAAM,OAAO,OAAO;AAAA,IAC/B;AAEA,UAAM,GAAG,MAAM;AAAA,MACb;AAAA,QACE,KAAK;AAAA,QACL,MAAM,CAAC,EAAE;AAAA,MACX;AAAA,MACA;AAAA,QACE,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,QAKL,MAAM,CAAC,yBAAyB,EAAE;AAAA,MACpC;AAAA,IACF,GAAG,OAAO;AAAA,EACZ,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,GAAG,QAAQ;AAAA,MACf,KAAK;AAAA,MACL,MAAM,CAAC,QAAQ,MAAM,GAAG,GAAK,GAAG,EAAE;AAAA,IACpC,CAAC,EAAE,MAAM,MAAM,MAAS;AACxB,UAAM;AAAA,EACR;AAEA,QAAM,SAAS,MAAM,GAAG,QAAQ,EAAE,KAAK,4DAA4D,MAAM,CAAC,EAAE,EAAE,CAAC;AAC/G,QAAM,MAAM,OAAO,KAAK,CAAC;AACzB,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,kEAAkE;AAC5F,SAAO,EAAE,SAAS,aAAa,GAAyC,GAAG,WAAW,MAAM;AAC9F;AAEA,eAAsB,4BAA4B,OAIf;AACjC,QAAM,+BAA+B;AACrC,QAAM,QAAQ,gBAAgB,MAAM,KAAK;AACzC,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,kDAAkD;AAC9E,QAAM,OAAO,kBAAkB,KAAK;AACpC,QAAM,YAAY,oBAAoB,MAAM,SAAS;AACrD,QAAM,SAAS,WAAW,QAAQ,EAAE,OAAO,MAAM,GAAG,EAAE,OAAO,KAAK;AAClE,QAAM,SAAS,MAAM,uBAAuB,IAAI;AAChD,MAAI,QAAQ,WAAW,OAAQ,QAAO,EAAE,SAAS,QAAQ,WAAW,KAAK;AAEzE,QAAM,YAAY,mBAAmB,KAAwC;AAC7E,QAAM,SAAS,2BAA2B,MAAM,KAAK,SAAS;AAC9D,QAAM,KAAK,OAAO,WAAW,EAAE,WAAW,KAAK,EAAE,CAAC;AAClD,QAAM,KAAK,MAAM;AACjB,QAAM,GAAG,QAAQ;AAAA,IACf,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAML,MAAM,CAAC,IAAI,MAAM,WAAW,QAAQ,OAAO,OAAO,QAAQ,OAAO,OAAO,QAAQ,OAAO,gBAAgB,KAAK,UAAU,CAAC,KAAK,CAAC,CAAC;AAAA,EAChI,CAAC;AAED,MAAI;AACF,aAAS,SAAS,GAAG,SAAS,OAAO,OAAO,QAAQ,UAAU,mBAAmB;AAC/E,YAAM,QAAQ,OAAO,OAAO,MAAM,QAAQ,SAAS,iBAAiB,EAAE,IAAI,YAAU;AAAA,QAClF,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOL,MAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM,YAAY,IAAI;AAAA,UACtB,MAAM,YAAY,IAAI;AAAA,UACtB,MAAM,YAAY,IAAI;AAAA,UACtB,MAAM,YAAY,IAAI;AAAA,UACtB,MAAM,YAAY,IAAI;AAAA,UACtB,MAAM,YAAY,IAAI;AAAA,QACxB;AAAA,MACF,EAAE;AACF,YAAM,GAAG,MAAM,OAAO,OAAO;AAAA,IAC/B;AAEA,UAAM,GAAG,MAAM;AAAA,MACb;AAAA,QACE,KAAK;AAAA,QACL,MAAM,CAAC,EAAE;AAAA,MACX;AAAA,MACA;AAAA,QACE,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,QAKL,MAAM,CAAC,MAAM,EAAE;AAAA,MACjB;AAAA,IACF,GAAG,OAAO;AAAA,EACZ,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,GAAG,QAAQ;AAAA,MACf,KAAK;AAAA,MACL,MAAM,CAAC,QAAQ,MAAM,GAAG,GAAK,GAAG,EAAE;AAAA,IACpC,CAAC,EAAE,MAAM,MAAM,MAAS;AACxB,UAAM;AAAA,EACR;AAEA,QAAM,SAAS,MAAM,GAAG,QAAQ,EAAE,KAAK,4DAA4D,MAAM,CAAC,EAAE,EAAE,CAAC;AAC/G,QAAM,MAAM,OAAO,KAAK,CAAC;AACzB,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,gEAAgE;AAC1F,SAAO,EAAE,SAAS,aAAa,GAAyC,GAAG,WAAW,MAAM;AAC9F;AAEA,eAAsB,2BAA2B,OAAuE;AACtH,QAAM,QAAQ,gBAAgB,MAAM,KAAK;AACzC,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,kDAAkD;AAC9E,MAAI,CAAC,OAAO,cAAc,MAAM,aAAa,KAAK,MAAM,gBAAgB,EAAG,OAAM,IAAI,MAAM,8CAA8C;AACzI,MAAI,CAAC,OAAO,cAAc,MAAM,UAAU,KAAK,MAAM,aAAa,KAAK,MAAM,aAAa,IAAK,OAAM,IAAI,MAAM,sCAAsC;AAErJ,QAAM,oBAAoB,MAAM,uBAAuB,kBAAkB,KAAK,CAAC;AAC/E,QAAM,kBAAkB,MAAM,oBAAoB,QAAQ,MAAM,GAAG;AACnE,QAAM,YAAY,kBACd,MAAM,mBAAmB,KAAK,IAC9B,EAAE,SAAS,MAAM,QAAQ,oBAAI,IAA4B,EAAE;AAC/D,MAAI,CAAC,mBAAmB;AACtB,WAAO,EAAE,SAAS,CAAC,GAAG,mBAAmB,MAAM,YAAY,UAAU,SAAS,UAAU,CAAC,EAAE;AAAA,EAC7F;AAEA,QAAM,SAAS,MAAM,MAAM,EAAE,QAAQ;AAAA,IACnC,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAML,MAAM,CAAC,kBAAkB,IAAI,KAAK;AAAA,EACpC,CAAC;AACD,QAAM,YAAY,uBAAuB,MAAM,aAAa,EAAE;AAC9D,QAAM,MAAM,MAAM,KAAK,KAAK;AAC5B,QAAM,mBAAmB,cAAc,MAAM,cAAc;AAC3D,QAAM,UAAU,OAAO,KACpB,IAAI,CAAC,QAAgC;AACpC,UAAM,kBAAkB,IAAI,gBAAgB;AAC5C,QAAI,mBAAmB,KAAM,QAAO;AACpC,UAAM,aAAa,OAAO,eAAe;AACzC,QAAI,CAAC,OAAO,cAAc,UAAU,KAAK,aAAa,MAAM,cAAe,QAAO;AAClF,UAAM,OAAO,OAAO,IAAI,IAAI;AAC5B,UAAM,gBAAgB,OAAO,IAAI,QAAQ;AACzC,QAAI,aAAa,CAAC,cAAc,SAAS,SAAS,EAAG,QAAO;AAC5D,UAAM,WAAW,UAAU,OAAO,IAAI,aAAa;AACnD,UAAM,OAAO,UAAU,QAAQ,CAAC;AAChC,QAAI,OAAO,CAAC,KAAK,SAAS,GAAG,EAAG,QAAO;AACvC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU,GAAG,IAAI,KAAK,KAAK;AAAA,MAC3B,SAAS,GAAG,IAAI,IAAI,KAAK;AAAA,MACzB,YAAY,OAAO,IAAI,WAAW;AAAA,MAClC;AAAA,MACA,gBAAgB,MAAM;AAAA,MACtB,mBAAmB,IAAI,uBAAuB,OAAO,OAAO,OAAO,IAAI,mBAAmB;AAAA,MAC1F,MAAM,MAAM,mBAAmB,OAAO,CAAC;AAAA,MACvC,UAAU,MAAM,mBAAmB,UAAU,YAAY,CAAC,IAAI,CAAC;AAAA,IACjE;AAAA,EACF,CAAC,EACA,OAAO,CAAC,WAAsC,WAAW,IAAI,EAC7D,KAAK,CAAC,GAAG,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC,EAC1E,MAAM,GAAG,MAAM,UAAU;AAE5B,QAAM,WAAqB,CAAC;AAC5B,MAAI,MAAM,oBAAoB,UAAU,WAAW,QAAQ,KAAK,YAAU,OAAO,KAAK,WAAW,CAAC,GAAG;AACnG,aAAS,KAAK,qEAAqE;AAAA,EACrF;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,YAAY,UAAU;AAAA,IACtB;AAAA,EACF;AACF;","names":["key"]}
@@ -52,9 +52,9 @@ var SCHEDULED_RUN_DEFAULT_MAX_CREDITS = 5e3;
52
52
  var CONNECTED_USAGE_RATE_POLICY_VERSION = "2026-07-23.connected-usage-v2";
53
53
  var CONNECTED_ACTIVE_CONNECTION_MONTHLY_CREDITS = 15e3;
54
54
  var CONNECTED_ACTIVE_CONNECTION_MONTHLY_MC = CONNECTED_ACTIVE_CONNECTION_MONTHLY_CREDITS * MC_PER_CREDIT;
55
- var CONNECTED_FUNCTION_RUN_CREDITS = 2;
56
- var CONNECTED_PROXY_REQUEST_CREDITS = 2;
57
- var CONNECTED_COMPUTE_CREDITS_PER_SECOND = 5;
55
+ var CONNECTED_FUNCTION_RUN_CREDITS = 1.5;
56
+ var CONNECTED_PROXY_REQUEST_CREDITS = 1.5;
57
+ var CONNECTED_COMPUTE_CREDITS_PER_SECOND = 3;
58
58
  var CONNECTED_FUNCTION_RUN_MC = CONNECTED_FUNCTION_RUN_CREDITS * MC_PER_CREDIT;
59
59
  var CONNECTED_PROXY_REQUEST_MC = CONNECTED_PROXY_REQUEST_CREDITS * MC_PER_CREDIT;
60
60
  var CONNECTED_COMPUTE_MC_PER_SECOND = CONNECTED_COMPUTE_CREDITS_PER_SECOND * MC_PER_CREDIT;
@@ -491,6 +491,8 @@ var LedgerOperation = {
491
491
  YT_CHANNEL: "yt_channel",
492
492
  FB_AD: "fb_ad",
493
493
  MAPS_SEARCH: "maps_search",
494
+ DIRECTORY_WORKFLOW_HOLD: "directory_workflow_hold",
495
+ DIRECTORY_WORKFLOW_REFUND: "directory_workflow_refund",
494
496
  MAPS_PLACE: "maps_place",
495
497
  MAPS_REVIEW: "maps_review",
496
498
  MAPS_REVIEW_REFUND: "maps_review_refund",
@@ -542,7 +544,9 @@ var LedgerOperation = {
542
544
  SITE_AUDIT_LLM: "site_audit_llm",
543
545
  SCHEDULED_RUN: "scheduled_run",
544
546
  CONNECTED_USAGE: "connected_usage",
545
- CONNECTED_ACCOUNT_FEE: "connected_account_fee"
547
+ CONNECTED_ACCOUNT_FEE: "connected_account_fee",
548
+ ADMIN_GRANT: "admin_grant",
549
+ ADMIN_REVOKE: "admin_revoke"
546
550
  };
547
551
  var MEMORY_AI_MARGIN_MULTIPLE = 3;
548
552
  var SITE_AUDIT_LLM_MARGIN_MULTIPLE = 1.5;
@@ -601,4 +605,4 @@ export {
601
605
  MEDIA_TRANSCRIBE_HOLD_MC,
602
606
  MC_PER_USD
603
607
  };
604
- //# sourceMappingURL=chunk-BWXLTWF7.js.map
608
+ //# sourceMappingURL=chunk-PWPUKR5U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api/rates.ts"],"sourcesContent":["export const MC_COSTS = {\n serp: 400,\n serp_headless: 400,\n serp_headful: 1_400,\n paa: 300,\n paa_base: 5_500,\n page_scrape: 100,\n url_map: 500,\n yt_channel: 200,\n yt_transcription: 200,\n fb_ad: 200,\n maps_search: 500,\n maps_place: 6_000,\n maps_review: 100,\n fb_search: 600,\n fb_transcribe: 33_300,\n google_ads_search: 600,\n google_ads_intel: 200,\n google_ads_transcribe: 33_300,\n instagram_profile: 400,\n instagram_media: 400,\n instagram_transcribe: 33_300,\n browser_minute: 12_000,\n reddit_thread: 3_000,\n reddit_comment: 200,\n video_analysis: 666_700,\n trustpilot_reviews: 500,\n trustpilot_review: 100,\n g2_reviews: 500,\n g2_review: 200,\n diff_page: 100,\n} as const\n\nexport type McCostKey = keyof typeof MC_COSTS\n\n/**\n * Kernel omits the `headless` field for a headful session, so the runtime\n * records headless as `true` and headful/unknown as `null`. Unknown is billed\n * at the conservative headful rate because no cheaper mode was proven.\n */\nexport function serpActualCostMc(headlessSent: boolean | null | undefined): number {\n return headlessSent === true ? MC_COSTS.serp_headless : MC_COSTS.serp_headful\n}\n\nexport const MC_PER_BROWSER_MS = MC_COSTS.browser_minute / 60_000\n\nexport function browserActiveCostMc(activeMs: number): number {\n return Math.round(activeMs * MC_PER_BROWSER_MS)\n}\n\nexport const BROWSER_OPEN_MIN_BALANCE_MC = 1_000\n\nexport const MC_PER_CREDIT = 100\n\n// Billing conversion is intentionally explicit rather than derived from a\n// Stripe plan. Plan grant changes must not silently reprice vendor-backed work.\nexport const BILLING_MC_PER_USD_NUMERATOR = 2_000_000\nexport const BILLING_MC_PER_USD_DENOMINATOR = 3\nexport const BILLING_BASIS_POINTS = 10_000\nexport const USD_NANOS = 1_000_000_000\n\nexport const SCHEDULED_RUN_BASE_CREDITS = 75\nexport const SCHEDULED_RUN_BASE_MC = SCHEDULED_RUN_BASE_CREDITS * MC_PER_CREDIT\nexport const SCHEDULED_AGENT_LLM_MARKUP_BPS = 15_000\nexport const SCHEDULED_AGENT_LLM_MARKUP = SCHEDULED_AGENT_LLM_MARKUP_BPS / BILLING_BASIS_POINTS\nexport const SCHEDULED_RUN_DEFAULT_MAX_CREDITS = 5_000\n\nexport const CONNECTED_USAGE_RATE_POLICY_VERSION = '2026-07-23.connected-usage-v2'\nexport const CONNECTED_ACTIVE_CONNECTION_MONTHLY_CREDITS = 15_000\nexport const CONNECTED_ACTIVE_CONNECTION_MONTHLY_MC = CONNECTED_ACTIVE_CONNECTION_MONTHLY_CREDITS * MC_PER_CREDIT\nexport const CONNECTED_FUNCTION_RUN_CREDITS = 1.5\nexport const CONNECTED_PROXY_REQUEST_CREDITS = 1.5\nexport const CONNECTED_COMPUTE_CREDITS_PER_SECOND = 3\nexport const CONNECTED_FUNCTION_RUN_MC = CONNECTED_FUNCTION_RUN_CREDITS * MC_PER_CREDIT\nexport const CONNECTED_PROXY_REQUEST_MC = CONNECTED_PROXY_REQUEST_CREDITS * MC_PER_CREDIT\nexport const CONNECTED_COMPUTE_MC_PER_SECOND = CONNECTED_COMPUTE_CREDITS_PER_SECOND * MC_PER_CREDIT\n\n/**\n * Versioned commercial contract for tenant-owned Nango connections.\n *\n * The recurring connection line item is denominated in USD and is deliberately\n * separate from usage debits in the Credit wallet. Usage receipts are reported\n * in aggregate milliseconds and rounded once to the smallest ledger unit (mc),\n * never up to a whole compute second.\n */\nexport const CONNECTED_USAGE_RATE_POLICY = {\n schemaVersion: 2,\n ratePolicyVersion: CONNECTED_USAGE_RATE_POLICY_VERSION,\n effectiveAt: '2026-07-23T00:00:00.000Z',\n provider: 'nango',\n entitlement: 'paid_plan_add_on',\n connection: {\n billingMode: 'flat_recurring_credits',\n amountCredits: CONNECTED_ACTIVE_CONNECTION_MONTHLY_CREDITS,\n interval: 'month',\n unit: 'active_connection',\n proration: 'none',\n },\n usage: {\n billingMode: 'credits',\n settlementMode: 'authoritative_receipt',\n rounding: 'aggregate_then_ceil_to_mc',\n functionRun: {\n credits: CONNECTED_FUNCTION_RUN_CREDITS,\n mc: CONNECTED_FUNCTION_RUN_MC,\n unit: 'per_function_run',\n },\n proxyRequest: {\n credits: CONNECTED_PROXY_REQUEST_CREDITS,\n mc: CONNECTED_PROXY_REQUEST_MC,\n unit: 'per_proxy_request',\n },\n compute: {\n creditsPerSecond: CONNECTED_COMPUTE_CREDITS_PER_SECOND,\n mcPerSecond: CONNECTED_COMPUTE_MC_PER_SECOND,\n sourceUnit: 'millisecond',\n unit: 'per_compute_second',\n formula: 'ceil(computeMilliseconds * mcPerSecond / 1000)',\n },\n },\n} as const\n\nexport interface ConnectedUsageQuantities {\n functionRuns: number\n proxyRequests: number\n computeMilliseconds: number\n}\n\nexport interface ConnectedUsageCharge {\n functionRunMc: number\n proxyRequestMc: number\n computeMc: number\n amountMc: number\n credits: number\n}\n\nfunction nonNegativeSafeInteger(value: number, field: string): bigint {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new Error(`${field} must be a non-negative safe integer`)\n }\n return BigInt(value)\n}\n\nfunction safeMc(value: bigint): number {\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) throw new Error('connected usage charge exceeds the safe integer range')\n return Number(value)\n}\n\n/** Calculate one receipt after aggregating its raw Nango usage counters. */\nexport function calculateConnectedUsageCharge(usage: ConnectedUsageQuantities): ConnectedUsageCharge {\n const functionRuns = nonNegativeSafeInteger(usage.functionRuns, 'functionRuns')\n const proxyRequests = nonNegativeSafeInteger(usage.proxyRequests, 'proxyRequests')\n const computeMilliseconds = nonNegativeSafeInteger(usage.computeMilliseconds, 'computeMilliseconds')\n const functionRunMc = functionRuns * BigInt(CONNECTED_FUNCTION_RUN_MC)\n const proxyRequestMc = proxyRequests * BigInt(CONNECTED_PROXY_REQUEST_MC)\n const computeNumerator = computeMilliseconds * BigInt(CONNECTED_COMPUTE_MC_PER_SECOND)\n const computeMc = computeNumerator === 0n ? 0n : (computeNumerator + 999n) / 1_000n\n const amountMc = functionRunMc + proxyRequestMc + computeMc\n\n return {\n functionRunMc: safeMc(functionRunMc),\n proxyRequestMc: safeMc(proxyRequestMc),\n computeMc: safeMc(computeMc),\n amountMc: safeMc(amountMc),\n credits: safeMc(amountMc) / MC_PER_CREDIT,\n }\n}\n\n/**\n * Public, machine-readable Scheduled Actions billing contract.\n *\n * Keep every API/UI surface on this object instead of restating the policy.\n * The primitive constants above remain the execution-time source of truth;\n * this object gives clients stable semantic fields for displaying and applying\n * those rates without having to infer behavior from prose.\n */\nexport const SCHEDULED_ACTIONS_RATE_POLICY = {\n billingMode: 'credits',\n entitlement: 'paid_plan_included',\n separateSubscriptionRequired: false,\n chargeEvent: 'started_occurrence',\n runBaseCredits: SCHEDULED_RUN_BASE_CREDITS,\n runBaseMc: SCHEDULED_RUN_BASE_MC,\n llmCostMultiplier: SCHEDULED_AGENT_LLM_MARKUP,\n llmCostMultiplierBps: SCHEDULED_AGENT_LLM_MARKUP_BPS,\n modes: {\n connection_sync: {\n runBaseCredits: SCHEDULED_RUN_BASE_CREDITS,\n modelCostBilling: 'none',\n modelCostMultiplier: 0,\n },\n agent: {\n runBaseCredits: SCHEDULED_RUN_BASE_CREDITS,\n modelCostBilling: 'actual_reported_cost',\n modelCostProvider: 'openrouter',\n modelCostMultiplier: SCHEDULED_AGENT_LLM_MARKUP,\n modelCostMultiplierBps: SCHEDULED_AGENT_LLM_MARKUP_BPS,\n },\n },\n} as const\n\nexport function vendorCostUsdToMc(costUsd: number, markupBps: number): number {\n if (!Number.isFinite(costUsd) || costUsd < 0) throw new Error('costUsd must be a finite non-negative number')\n if (!Number.isInteger(markupBps) || markupBps < 0) throw new Error('markupBps must be a non-negative integer')\n\n const rawCostNanos = BigInt(Math.round(costUsd * USD_NANOS))\n const numerator =\n rawCostNanos *\n BigInt(markupBps) *\n BigInt(BILLING_MC_PER_USD_NUMERATOR)\n const denominator =\n BigInt(USD_NANOS) *\n BigInt(BILLING_BASIS_POINTS) *\n BigInt(BILLING_MC_PER_USD_DENOMINATOR)\n const mc = numerator === 0n ? 0n : (numerator + denominator - 1n) / denominator\n if (mc > BigInt(Number.MAX_SAFE_INTEGER)) throw new Error('calculated mc exceeds the safe integer range')\n return Number(mc)\n}\n\nexport const CREDIT_COST_CATALOG: Array<{\n key: McCostKey\n label: string\n aliases: string[]\n credits: number\n unit: string\n notes?: string\n}> = [\n {\n key: 'serp',\n label: 'SERP search',\n aliases: ['search_serp', 'serp', 'google search', 'organic results'],\n credits: mcToCredits(MC_COSTS.serp_headless),\n unit: 'per search (headless); escalates to headful only when needed',\n notes: `Returns AI Overview, PAA snippet, videos, forums, and local pack. Billed ${mcToCredits(MC_COSTS.serp_headless)} credits when served headless (the common case), ${mcToCredits(MC_COSTS.serp_headful)} credits if an anti-bot escalation forces headful mode (overestimate refunded). Optional SERP Intelligence page snapshots add ${mcToCredits(MC_COSTS.page_scrape)} credit per attempted URL.`,\n },\n {\n key: 'paa',\n label: 'PAA harvest',\n aliases: ['harvest_paa', 'paa', 'people also ask', 'questions'],\n credits: mcToCredits(MC_COSTS.paa),\n unit: `per question (+${mcToCredits(MC_COSTS.paa_base)} credit base)`,\n notes: `Full SERP feature extraction. Billed ${mcToCredits(MC_COSTS.paa_base)} credit base + ${mcToCredits(MC_COSTS.paa)} per question actually returned (unused estimate refunded).`,\n },\n {\n key: 'page_scrape',\n label: 'Page crawl / extract',\n aliases: ['extract_url', 'extract_site', 'page scrape', 'url scrape', 'single page', 'site crawl'],\n credits: mcToCredits(MC_COSTS.page_scrape),\n unit: 'per page',\n notes: 'Applies to both single-URL extraction and per-page site crawls.',\n },\n {\n key: 'url_map',\n label: 'Site URL mapping',\n aliases: ['map_site_urls', 'url map', 'site map', 'crawl urls'],\n credits: mcToCredits(MC_COSTS.url_map),\n unit: 'per mapping operation',\n notes: 'Flat rate for the full /map-urls call regardless of URL count discovered.',\n },\n {\n key: 'yt_channel',\n label: 'YouTube search / channel harvest',\n aliases: ['youtube_harvest', 'youtube search', 'youtube channel', 'yt_channel'],\n credits: mcToCredits(MC_COSTS.yt_channel),\n unit: 'per call',\n },\n {\n key: 'yt_transcription',\n label: 'YouTube transcription',\n aliases: ['youtube_transcribe', 'youtube transcript', 'transcription', 'yt_transcription'],\n credits: mcToCredits(20_000),\n unit: 'base + 2/min of video',\n notes: 'Flat 200-credit base plus 2 credits per minute of video, reconciled to the real video length after transcription (e.g. a 10-minute video is about 220 credits).',\n },\n {\n key: 'fb_ad',\n label: 'Facebook search / ad lookup',\n aliases: ['facebook_page_intel', 'facebook_ad_search', 'facebook_ad', 'facebook ads', 'fb ads'],\n credits: mcToCredits(MC_COSTS.fb_ad),\n unit: 'per call',\n },\n {\n key: 'maps_search',\n label: 'Maps business search',\n aliases: ['maps_search', 'google maps search', 'gmb search', 'gbp search', 'business profiles'],\n credits: mcToCredits(MC_COSTS.maps_search),\n unit: 'per search',\n notes: 'Returns up to 50 Google Maps business/profile candidates. Use maps_place_intel to hydrate selected businesses.',\n },\n {\n key: 'maps_place',\n label: 'Maps business lookup',\n aliases: ['maps_place_intel', 'google maps', 'maps place', 'place intel'],\n credits: mcToCredits(MC_COSTS.maps_place),\n unit: 'per business',\n notes: 'Base lookup. Reviews billed separately per card at maps_review rate.',\n },\n {\n key: 'maps_review',\n label: 'Maps review',\n aliases: ['maps_reviews', 'google reviews', 'review cards', 'reviews'],\n credits: mcToCredits(MC_COSTS.maps_review),\n unit: 'per review card',\n notes: 'Charged after extraction when includeReviews is true.',\n },\n {\n key: 'fb_search',\n label: 'Facebook ad library search',\n aliases: ['facebook_search', 'fb_search', 'fb ad search'],\n credits: mcToCredits(MC_COSTS.fb_search),\n unit: 'per search',\n notes: 'Browser automation to search Facebook Ads Library by keyword.',\n },\n {\n key: 'google_ads_search',\n label: 'Google Ads Transparency search',\n aliases: ['google_ads_search', 'google ads search', 'ads transparency search'],\n credits: mcToCredits(MC_COSTS.google_ads_search),\n unit: 'per search',\n notes: 'Browser automation to find advertisers in Google Ads Transparency Center by domain or name.',\n },\n {\n key: 'google_ads_intel',\n label: 'Google Ads Transparency advertiser intel',\n aliases: ['google_ads_page_intel', 'google ads intel', 'ads transparency intel'],\n credits: mcToCredits(MC_COSTS.google_ads_intel),\n unit: 'per call',\n notes: 'Lists and hydrates an advertiser\\'s creatives with image URLs and video references.',\n },\n {\n key: 'google_ads_transcribe',\n label: 'Google ad video transcription',\n aliases: ['google_ads_transcribe', 'google ad transcript'],\n credits: mcToCredits(20_000),\n unit: 'base + 2/min of video',\n notes: 'Flat 200-credit base plus 2 credits per minute of video, reconciled to the real video length after transcription (e.g. a 10-minute video is about 220 credits).',\n },\n {\n key: 'fb_transcribe',\n label: 'Facebook video / ad transcription',\n aliases: ['facebook_transcribe', 'facebook_video_transcribe', 'fb_transcribe', 'fb ad transcript'],\n credits: mcToCredits(20_000),\n unit: 'base + 2/min of video',\n notes: 'Flat 200-credit base plus 2 credits per minute of video, reconciled to the real video length after transcription (e.g. a 10-minute video is about 220 credits).',\n },\n {\n key: 'instagram_profile',\n label: 'Instagram profile content discovery',\n aliases: ['instagram_profile_content', 'instagram profile', 'instagram content list', 'ig profile'],\n credits: mcToCredits(MC_COSTS.instagram_profile),\n unit: 'per profile scan',\n notes: 'Browser extraction of public Instagram profile grid links. Complete history may require a logged-in profile.',\n },\n {\n key: 'instagram_media',\n label: 'Instagram media download',\n aliases: ['instagram_media_download', 'instagram reel download', 'instagram post download', 'ig media'],\n credits: mcToCredits(MC_COSTS.instagram_media),\n unit: 'per post or reel',\n notes: 'Extracts post text, image URLs, and reel audio/video tracks, with local downloads when the server can write files.',\n },\n {\n key: 'instagram_transcribe',\n label: 'Instagram media transcription',\n aliases: ['instagram transcript', 'instagram reel transcript', 'ig transcribe'],\n credits: mcToCredits(20_000),\n unit: 'base + 2/min of video',\n notes: 'Whisper transcription of selected Instagram audio/video media. Flat 200-credit base plus 2 credits per minute of video, reconciled to the real video length after transcription (e.g. a 10-minute video is about 220 credits).',\n },\n {\n key: 'browser_minute',\n label: 'Interactive browser session',\n aliases: ['browser_open', 'browser agent', 'browser_agent', 'live browser', 'browse', 'browser control', 'interactive browser'],\n credits: mcToCredits(MC_COSTS.browser_minute),\n unit: 'per minute of use',\n notes: 'Metered per minute of use for the whole time the browser session is open. Close the session to stop the meter; abandoned sessions are auto-closed after a short idle window.',\n },\n {\n key: 'reddit_thread',\n label: 'Reddit thread base lookup',\n aliases: ['reddit', 'reddit_thread', 'reddit comments', 'subreddit', 'reddit post'],\n credits: mcToCredits(MC_COSTS.reddit_thread),\n unit: 'per thread',\n notes: 'Base lookup for the post itself. Comments billed separately per comment at reddit_comment rate. Refunded if the thread cannot be retrieved.',\n },\n {\n key: 'reddit_comment',\n label: 'Reddit comment',\n aliases: ['reddit_comment', 'reddit comments'],\n credits: mcToCredits(MC_COSTS.reddit_comment),\n unit: 'per comment',\n notes: 'Charged per comment actually extracted, billed down automatically if the balance runs out mid-thread.',\n },\n {\n key: 'video_analysis',\n label: 'Video breakdown (frame-by-frame + transcript)',\n aliases: ['video_frame_analysis', 'video breakdown', 'video analysis', 'analyze video'],\n credits: mcToCredits(MC_COSTS.video_analysis),\n unit: 'per 120 frames (max 480)',\n notes: 'Full multi-lens video breakdown: samples frames across a video (up to 30 minutes), analyzes each with vision AI, transcribes the audio, then produces summary, pacing/energy, words-per-minute, topic outline, key points, hook analysis, visual style, and a how-to-replicate recipe with a quality-control pass. $1 per 120 frames requested (max 480 = $4); billed down automatically if the video cannot use the requested frames, and refunded fully if the run fails.',\n },\n {\n key: 'trustpilot_reviews',\n label: 'Trustpilot review harvest',\n aliases: ['trustpilot_reviews', 'trustpilot', 'trustpilot reviews'],\n credits: mcToCredits(MC_COSTS.trustpilot_reviews),\n unit: 'per call',\n notes: 'Base lookup. Reviews billed separately per card at trustpilot_review rate. Refunded if no reviews are found.',\n },\n {\n key: 'trustpilot_review',\n label: 'Trustpilot review card',\n aliases: ['trustpilot_review', 'trustpilot card'],\n credits: mcToCredits(MC_COSTS.trustpilot_review),\n unit: 'per review card',\n notes: 'Charged per review actually extracted, billed down automatically if the balance runs out mid-page.',\n },\n {\n key: 'g2_reviews',\n label: 'G2 review harvest',\n aliases: ['g2_reviews', 'g2', 'g2 reviews'],\n credits: mcToCredits(MC_COSTS.g2_reviews),\n unit: 'per call',\n notes: 'Base lookup. Reviews billed separately per card at g2_review rate. Refunded if no reviews are found.',\n },\n {\n key: 'g2_review',\n label: 'G2 review card',\n aliases: ['g2_review', 'g2 card'],\n credits: mcToCredits(MC_COSTS.g2_review),\n unit: 'per review card',\n notes: 'Charged per review actually extracted (each card carries up to 3 Q&A sections), billed down automatically if the balance runs out mid-page.',\n },\n {\n key: 'diff_page',\n label: 'Page change check',\n aliases: ['diff_page', 'page diff', 'change detection'],\n credits: mcToCredits(MC_COSTS.diff_page),\n unit: 'per check',\n notes: 'Same cost as a single page extract — one scrape is performed per check, then compared against your last stored snapshot for that URL.',\n },\n]\n\nexport const CONCURRENCY_PRICE_ID = 'price_1Ta1NRS8aAcsk3TGwsRnYbix'\n\nexport interface SubscriptionTier {\n tier: string\n label: string\n price_id: string\n monthly_usd: number\n billed_usd?: number\n credits_mc: number\n concurrency: number\n intro_coupon: string | null\n billing_interval?: 'month' | 'year'\n credits_never_expire?: boolean\n includes_memory?: boolean\n private_offer?: boolean\n}\n\nexport function tierBillingInterval(tier: SubscriptionTier): 'month' | 'year' {\n return tier.billing_interval ?? 'month'\n}\n\nexport function tierAmountChargedUsd(tier: SubscriptionTier): number {\n return tier.billed_usd ?? tier.monthly_usd\n}\n\nexport function tierCreditsPerInterval(tier: SubscriptionTier): number {\n return tier.credits_mc / MC_PER_CREDIT\n}\n\nexport const SUBSCRIPTION_TIERS: Record<string, SubscriptionTier> = {\n 'price_1TmiHRS8aAcsk3TGwmSNfNIa': { tier: 'starter', label: 'Starter', price_id: 'price_1TmiHRS8aAcsk3TGwmSNfNIa', monthly_usd: 12, credits_mc: 8_000_000, concurrency: 3, intro_coupon: 'mcp-starter-1dollar-intro-12' },\n 'price_1TrgihS8aAcsk3TG5cglrq4D': { tier: 'growth', label: 'Growth', price_id: 'price_1TrgihS8aAcsk3TG5cglrq4D', monthly_usd: 40, credits_mc: 26_666_700, concurrency: 10, intro_coupon: null },\n 'price_1TrgihS8aAcsk3TG4HnG4gbY': { tier: 'scale', label: 'Scale', price_id: 'price_1TrgihS8aAcsk3TG4HnG4gbY', monthly_usd: 100, credits_mc: 80_000_000, concurrency: 20, intro_coupon: null },\n 'price_1TwqIVS8aAcsk3TG0FE3ddDM': { tier: 'sonic', label: 'Sonic Annual', price_id: 'price_1TwqIVS8aAcsk3TG0FE3ddDM', monthly_usd: 25, billed_usd: 300, credits_mc: 250_000_000, concurrency: 3, intro_coupon: null, billing_interval: 'year', credits_never_expire: true, private_offer: true },\n 'price_1TwqIWS8aAcsk3TGbGbtlLak': { tier: 'sonic-memory', label: 'Sonic Annual + Memory Pro', price_id: 'price_1TwqIWS8aAcsk3TGbGbtlLak', monthly_usd: 34.5, billed_usd: 414, credits_mc: 250_000_000, concurrency: 3, intro_coupon: null, billing_interval: 'year', credits_never_expire: true, includes_memory: true, private_offer: true },\n}\n\nexport const SUBSCRIPTION_TIER_BY_KEY: Record<string, SubscriptionTier> = Object.fromEntries(\n Object.values(SUBSCRIPTION_TIERS).map(t => [t.tier, t]),\n)\n\nexport interface PrivateOffer {\n slug: string\n label: string\n headline: string\n tier_keys: string[]\n}\n\nexport const PRIVATE_OFFERS: Record<string, PrivateOffer> = {\n sonic: {\n slug: 'sonic',\n label: 'Sonic annual partner offer',\n headline: 'A full year of MCP Scraper, with Credits that never expire.',\n tier_keys: ['sonic', 'sonic-memory'],\n },\n}\n\nexport function offerClaimPathForTier(tierKey: string): string | null {\n const offer = Object.values(PRIVATE_OFFERS).find(o => o.tier_keys.includes(tierKey))\n return offer ? `/${offer.slug}/claim` : null\n}\n\nexport function getPrivateOfferPayload(slug: string) {\n const offer = PRIVATE_OFFERS[slug]\n if (!offer) return null\n const options = offer.tier_keys\n .map(key => SUBSCRIPTION_TIER_BY_KEY[key])\n .filter((t): t is SubscriptionTier => !!t)\n .map(t => ({\n tier: t.tier,\n label: t.label,\n amount_usd: tierAmountChargedUsd(t),\n interval: tierBillingInterval(t),\n monthly_equivalent_usd: t.monthly_usd,\n credits: tierCreditsPerInterval(t),\n credits_never_expire: !!t.credits_never_expire,\n includes_memory: !!t.includes_memory,\n concurrency: t.concurrency,\n }))\n if (!options.length) return null\n return { slug: offer.slug, label: offer.label, headline: offer.headline, options }\n}\n\nexport function getPublicRatesPayload() {\n const starter = SUBSCRIPTION_TIER_BY_KEY.starter\n const costs = CREDIT_COST_CATALOG.map(({ aliases, ...cost }) => ({\n ...cost,\n ...(cost.notes ? { notes: cost.notes.replace(/ via fal\\.ai/g, '') } : {}),\n }))\n\n return {\n creditsPerDollarStarter: Math.round(mcToCredits(starter.credits_mc) / starter.monthly_usd),\n costs,\n scheduling: SCHEDULED_ACTIONS_RATE_POLICY,\n connectedAccounts: CONNECTED_USAGE_RATE_POLICY,\n }\n}\n\nexport const CONCURRENCY_SLOT_PRICE_USD = 5\nexport const CONCURRENCY_SLOT_PRICE_CURRENCY = 'usd'\nexport const CONCURRENCY_SLOT_PRICE_INTERVAL = 'month'\nexport const CONCURRENCY_SLOT_PRICE_LABEL = '$5/month'\nexport const CONCURRENCY_SLOT_TERMINAL_COMMAND = 'npx -y -p mcp-scraper@latest mcp-scraper-cli billing concurrency checkout'\n\nexport function concurrencySlotBillingInfo() {\n const billingUrl = process.env.CONCURRENCY_BILLING_URL ?? 'https://mcpscraper.dev/billing'\n return {\n product: 'Extra concurrency slot',\n price_label: CONCURRENCY_SLOT_PRICE_LABEL,\n unit_amount_usd: CONCURRENCY_SLOT_PRICE_USD,\n currency: CONCURRENCY_SLOT_PRICE_CURRENCY,\n interval: CONCURRENCY_SLOT_PRICE_INTERVAL,\n billing_url: billingUrl,\n terminal_command: CONCURRENCY_SLOT_TERMINAL_COMMAND,\n terminal_command_with_api_key_env: `MCP_SCRAPER_API_KEY=sk_live_your_key ${CONCURRENCY_SLOT_TERMINAL_COMMAND}`,\n }\n}\n\n// The free tier is retired. Keep these exported compatibility constants at zero\n// so older consumers do not advertise or grant credits that no longer exist.\nexport const FREE_SIGNUP_MC = 0\nexport const FREE_MONTHLY_REFRESH_MC = 0\n\nexport const BALANCE_PRICE_IDS: Record<string, number> = {\n 'price_1TZx6rS8aAcsk3TGNMc1Vgpo': 11_000_000,\n 'price_1TZx6sS8aAcsk3TGxgqB7khO': 27_500_000,\n 'price_1TZx6tS8aAcsk3TG8PnJqHlG': 60_500_000,\n 'price_1TZx6tS8aAcsk3TGNgRMpy0e': 121_000_000,\n}\n\nexport const BALANCE_PACK_LABELS: Record<string, string> = {\n 'price_1TZx6rS8aAcsk3TGNMc1Vgpo': '$10',\n 'price_1TZx6sS8aAcsk3TGxgqB7khO': '$25',\n 'price_1TZx6tS8aAcsk3TG8PnJqHlG': '$50',\n 'price_1TZx6tS8aAcsk3TGNgRMpy0e': '$100',\n}\n\nexport function mcToCredits(mc: number): number {\n return mc / MC_PER_CREDIT\n}\n\nexport function insufficientBalanceResponse(balanceMc: number, requiredMc: number) {\n const topupUrl = process.env.TOPUP_URL ?? 'https://mcpscraper.dev/billing'\n const balanceCredits = mcToCredits(balanceMc)\n const requiredCredits = mcToCredits(requiredMc)\n return {\n error: 'insufficient_balance',\n error_code: 'insufficient_balance' as const,\n message: `Insufficient credits. Balance: ${balanceCredits} credits. This call requires ${requiredCredits} credits. Top up at ${topupUrl}`,\n balance_credits: balanceCredits,\n required_credits: requiredCredits,\n topup_url: topupUrl,\n }\n}\n\nexport interface MemoryPlan {\n plan: 'pro' | 'team'\n label: string\n price_id: string\n interval: 'month' | 'year'\n monthly_usd: number\n quota_bytes: number\n}\n\nexport const MEMORY_FREE_QUOTA_BYTES = 0.01e9 * 1\n\nexport const MEMORY_PLANS: Record<string, MemoryPlan> = {\n 'price_1TnMSTS8aAcsk3TGBgiwuvqL': { plan: 'pro', label: 'Pro', price_id: 'price_1TnMSTS8aAcsk3TGBgiwuvqL', interval: 'month', monthly_usd: 19, quota_bytes: 5e9 },\n 'price_1TnMSTS8aAcsk3TGWBVU2agY': { plan: 'pro', label: 'Pro', price_id: 'price_1TnMSTS8aAcsk3TGWBVU2agY', interval: 'year', monthly_usd: 19, quota_bytes: 5e9 },\n}\n\nexport const MEMORY_PLAN_QUOTA: Record<string, number> = { free: MEMORY_FREE_QUOTA_BYTES, pro: 5e9, team: 50e9 }\n\nexport const MEMORY_MARGIN_MULTIPLE = 3\nexport const MEMORY_FREE_COST_CAP_USD = 1.0\nexport const MEMORY_PRO_COST_BUDGET_USD = 19 / MEMORY_MARGIN_MULTIPLE\n\nexport const LedgerOperation = {\n TOPUP: 'topup',\n SUBSCRIPTION: 'subscription',\n SIGNUP_GRANT: 'signup_grant',\n MONTHLY_REFRESH: 'monthly_free_refresh',\n PAA: 'paa',\n PAA_REFUND: 'paa_refund',\n SERP: 'serp',\n SERP_REFUND: 'serp_refund',\n REFUND: 'refund',\n TRANSCRIPTION: 'transcription',\n TRANSCRIPTION_HOLD: 'transcription_hold',\n TRANSCRIPTION_REFUND: 'transcription_refund',\n YT_CHANNEL: 'yt_channel',\n FB_AD: 'fb_ad',\n MAPS_SEARCH: 'maps_search',\n DIRECTORY_WORKFLOW_HOLD: 'directory_workflow_hold',\n DIRECTORY_WORKFLOW_REFUND: 'directory_workflow_refund',\n MAPS_PLACE: 'maps_place',\n MAPS_REVIEW: 'maps_review',\n MAPS_REVIEW_REFUND: 'maps_review_refund',\n EXTRACT_SITE: 'extract_site',\n EXTRACT_SITE_REFUND: 'extract_site_refund',\n EXTRACT_URL: 'page_scrape',\n URL_MAP: 'url_map',\n EXTRACT_SITE_HOLD: 'extract_site_hold',\n YT_CHANNEL_REFUND: 'yt_channel_refund',\n FB_AD_REFUND: 'fb_ad_refund',\n URL_MAP_REFUND: 'url_map_refund',\n FB_SEARCH: 'fb_search',\n FB_TRANSCRIBE: 'fb_transcribe',\n FB_SEARCH_REFUND: 'fb_search_refund',\n FB_TRANSCRIBE_REFUND: 'fb_transcribe_refund',\n GOOGLE_ADS_SEARCH: 'google_ads_search',\n GOOGLE_ADS_SEARCH_REFUND: 'google_ads_search_refund',\n GOOGLE_ADS_INTEL: 'google_ads_intel',\n GOOGLE_ADS_INTEL_REFUND: 'google_ads_intel_refund',\n GOOGLE_ADS_TRANSCRIBE: 'google_ads_transcribe',\n GOOGLE_ADS_TRANSCRIBE_REFUND: 'google_ads_transcribe_refund',\n INSTAGRAM_PROFILE: 'instagram_profile',\n INSTAGRAM_PROFILE_REFUND: 'instagram_profile_refund',\n INSTAGRAM_MEDIA: 'instagram_media',\n INSTAGRAM_MEDIA_REFUND:'instagram_media_refund',\n INSTAGRAM_TRANSCRIBE: 'instagram_transcribe',\n INSTAGRAM_TRANSCRIBE_REFUND: 'instagram_transcribe_refund',\n BROWSER_SESSION: 'browser_session',\n REDDIT_THREAD: 'reddit_thread',\n REDDIT_THREAD_REFUND: 'reddit_thread_refund',\n REDDIT_COMMENT: 'reddit_comment',\n REDDIT_COMMENT_REFUND: 'reddit_comment_refund',\n VIDEO_ANALYSIS: 'video_analysis',\n VIDEO_ANALYSIS_REFUND: 'video_analysis_refund',\n VIDEO_ANALYSIS_ADJUST: 'video_analysis_adjust',\n VIDEO_ANALYSIS_LLM: 'video_analysis_llm',\n MEMORY_AI: 'memory_ai',\n MEMORY_AI_REFUND: 'memory_ai_refund',\n TRUSTPILOT_REVIEWS: 'trustpilot_reviews',\n TRUSTPILOT_REVIEWS_REFUND: 'trustpilot_reviews_refund',\n TRUSTPILOT_REVIEW: 'trustpilot_review',\n TRUSTPILOT_REVIEW_REFUND: 'trustpilot_review_refund',\n G2_REVIEWS: 'g2_reviews',\n G2_REVIEWS_REFUND: 'g2_reviews_refund',\n G2_REVIEW: 'g2_review',\n G2_REVIEW_REFUND: 'g2_review_refund',\n DIFF_PAGE: 'diff_page',\n DIFF_PAGE_REFUND: 'diff_page_refund',\n SITE_AUDIT_LLM: 'site_audit_llm',\n SCHEDULED_RUN: 'scheduled_run',\n CONNECTED_USAGE: 'connected_usage',\n CONNECTED_ACCOUNT_FEE: 'connected_account_fee',\n ADMIN_GRANT: 'admin_grant',\n ADMIN_REVOKE: 'admin_revoke',\n} as const\n\nexport type LedgerOperation = typeof LedgerOperation[keyof typeof LedgerOperation]\n\nexport const MEMORY_AI_MARGIN_MULTIPLE = 3\nexport const SITE_AUDIT_LLM_MARGIN_MULTIPLE = 1.5\nexport const VIDEO_ANALYSIS_LLM_MARGIN_MULTIPLE = 1.5\nexport const MEDIA_TRANSCRIBE_FLAT_MC = 20_000\nexport const MEDIA_TRANSCRIBE_PER_MIN_MC = 200\n\nexport function mediaTranscribeChargeMc(durationSecs: number): number {\n const mins = Math.max(1, Math.ceil((durationSecs || 60) / 60))\n return MEDIA_TRANSCRIBE_FLAT_MC + MEDIA_TRANSCRIBE_PER_MIN_MC * mins\n}\n\nexport const MEDIA_TRANSCRIBE_MARGIN_MULTIPLE = 3\nexport const MEDIA_TRANSCRIBE_HOLD_MC = MEDIA_TRANSCRIBE_FLAT_MC + MEDIA_TRANSCRIBE_PER_MIN_MC * 30\n\nexport const MC_PER_USD =\n SUBSCRIPTION_TIERS['price_1TmiHRS8aAcsk3TGwmSNfNIa'].credits_mc /\n SUBSCRIPTION_TIERS['price_1TmiHRS8aAcsk3TGwmSNfNIa'].monthly_usd\n"],"mappings":"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","names":[]}