mcp-scraper 0.90.4 → 0.90.5

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 (42) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +1 -1
  3. package/dist/{analytics-repository-UX6VU22H.js → analytics-repository-WNJESD4A.js} +1 -1
  4. package/dist/bin/api-server.js +1 -1
  5. package/dist/bin/mcp-scraper-cli.js +1 -1
  6. package/dist/bin/mcp-scraper-core.js +1 -1
  7. package/dist/bin/mcp-scraper-install.js +1 -1
  8. package/dist/bin/mcp-stdio-server.js +1 -1
  9. package/dist/bin/paa-harvest.js +1 -1
  10. package/dist/{chunk-HR2A2WTL.js → chunk-4OTWTGKC.js} +1 -1
  11. package/dist/{chunk-DKQZNSYM.js → chunk-56UT5M5Y.js} +4 -4
  12. package/dist/{chunk-LTT2B7NY.js → chunk-5JCPVCBT.js} +1 -1
  13. package/dist/{chunk-HJ7OGU2J.js → chunk-5RTZPHIY.js} +1 -1
  14. package/dist/{chunk-7AC66V3T.js → chunk-AAJG5OHF.js} +1 -1
  15. package/dist/chunk-ARKQYLKU.js +1 -0
  16. package/dist/{chunk-JSNFZPPB.js → chunk-BVSK6YHX.js} +1 -1
  17. package/dist/{chunk-LZTDANNZ.js → chunk-COIA4RW4.js} +1 -1
  18. package/dist/{chunk-3R5QLQT3.js → chunk-IRWULJS5.js} +1 -1
  19. package/dist/{chunk-7BEWBRMT.js → chunk-KKHTMYCD.js} +198 -87
  20. package/dist/{chunk-WTOKMWDS.js → chunk-NC32JCZT.js} +1 -1
  21. package/dist/{chunk-HR2ALIEH.js → chunk-PNDXAOZD.js} +1 -1
  22. package/dist/{chunk-2GRE4BAO.js → chunk-Q5SUDDSQ.js} +1 -1
  23. package/dist/{chunk-7QHYBK6U.js → chunk-W4QBJ7WW.js} +1 -1
  24. package/dist/chunk-X4YCWF4B.js +48 -0
  25. package/dist/{chunk-ZMLCK45S.js → chunk-XSYLDTMI.js} +1 -1
  26. package/dist/{chunk-JVU2THSY.js → chunk-XXK5PLRB.js} +1 -1
  27. package/dist/{chunk-GW6ITK76.js → chunk-ZJOD3YKH.js} +8 -8
  28. package/dist/{db-UKQ74OVT.js → db-XN7YPDGC.js} +1 -1
  29. package/dist/{extract-bundle-7BI2K26D.js → extract-bundle-MQM3P7VS.js} +1 -1
  30. package/dist/{gmail-service-Y2UZX3YW.js → gmail-service-DTUP6EWC.js} +1 -1
  31. package/dist/index.cjs +46 -46
  32. package/dist/index.js +1 -1
  33. package/dist/{lead-list-enrichment-repository-GPDHJVM3.js → lead-list-enrichment-repository-AIMOP7YM.js} +1 -1
  34. package/dist/{location-data-repository-MXUNVDHW.js → location-data-repository-25D3GHXE.js} +1 -1
  35. package/dist/{server-ZZVUT4N6.js → server-NTIME7TQ.js} +590 -587
  36. package/dist/{site-extract-repository-T23S2T7L.js → site-extract-repository-IZT3NTWY.js} +1 -1
  37. package/dist/{stripe-event-worker-HVCB6SF3.js → stripe-event-worker-5QNWGHVK.js} +1 -1
  38. package/dist/worker-Z27YG7TE.js +1 -0
  39. package/package.json +1 -1
  40. package/dist/chunk-KJA62B7P.js +0 -1
  41. package/dist/chunk-PHBU6X5B.js +0 -1
  42. package/dist/worker-KFILERH3.js +0 -1
@@ -1,4 +1,4 @@
1
- import{f as Z}from"./chunk-M5QHXNFZ.js";import{a as ve}from"./chunk-4FROKQJN.js";import{a as fe,b as Pe,c as Wt,d as be,g as We}from"./chunk-DKQZNSYM.js";import{a as ke,c as pe,d as gt,g as me,l as Ie}from"./chunk-2TZBO52D.js";import{a as Ne,i as Te,j as K,k as bt,m as q,n as yt,o as $t}from"./chunk-7BEWBRMT.js";import{chromium as Zt}from"playwright-extra";import An from"puppeteer-extra-plugin-stealth";import{chromium as Ln}from"playwright";var F={container:".eJH8qe.adDDi",dataInitq:"[data-initq]",item:".related-question-pair",itemDataQ:"data-q",itemDataInitQ:"data-initq",itemQuestionEl:".JlqpRe",answerContainer:".bCOlv, .hgKElc, .wDYxhc, .LGOjhe, .fo7IQd, .fmW3u",aiAnswerBody:".pWvJNd",aiCitation:"a.PMDqCb[href]",aiSourceCard:"a.vIWmYe[href], a.Zbfntb[href]",sourceTitle:"h3",sourceSite:".VuuXrf",sourceCite:"cite",clickTarget:".JlqpRe",expandedClass:"aoRk1c",captchaMarker:'#captcha-form, #recaptcha, form[action*="/sorry/"], .g-recaptcha, [data-sitekey]'},Ae={container:'div[jscontroller="HWk0Gf"]',sectionHeading:'.mgAbYb[role="heading"]',item:"a.rIRoqf"},It={udm:"39",item:"a.rIRoqf",durationPattern:/^\d+:\d+$/,platforms:["YouTube","TikTok","Instagram","Facebook","X"]},Le={section:".ULSxyf",item:"a.KYg7td.INpicf",title:".hyYc0c",source:".K4ETW"},Oe={sectionTag:"g-section-with-header",sectionHeadingText:"What people are saying",card:'.dRzkFf[role="listitem"]',cardLink:'a.WlydOe[jsname="YKoRaf"]',titleH1:"h1.WQWxe",titleDiv:".eAaXgc",popularCommentLabel:".qgdis",source:".sTl1Td",platformBadge:".appd0, .KrMNbf",ytChannel:".sjVJQd",ytDate:".PLq9Je",authorNote:".nDgy9d"},xe={root:"[data-lhcontainer][data-streaming-container][eid]",legacyRoot:'[data-hveid="CBMQAA"]',wrapper:".Fgyi2e",controller:'[jscontroller="AkrxPe"]',contentSubtree:'[data-subtree="mfc"]',header:".heWuVc",heading:".Fzsovc.cwYVJe.RJPOee",showMoreButton:'[aria-label="Show more AI Overview"]',sourcesPanel:".OZ9ddf.WAUd4",disclaimer:".DuQANe.MSJHRb"},Be={root:'[data-hveid="CAUQAA"]',wrapper:".Fgyi2e",citations:'.Fgyi2e [data-hveid] a[jsname="pxBnId"]'},He={result:".wHYlTd.tF2Cxc",title:"h3.LC20lb",siteName:".VuuXrf",cite:"cite.tjvcx",snippet:".VwiC3b",redditCite:"cite.qLRx3b",ratingWrap:".Y0A0hc",ratingValue:".yi40Hd",reviewCount:".RDApEe"},Fe={headingText:"Businesses",card:".w7Dbne",name:".OSrXXb",ratingValue:".yi40Hd",reviewCount:".RDApEe"};var ti={ratingAndCount:"div.F7nice",hoursTable:"table.eK4R0e",reviewScrollPane:'div.m6QErb[tabindex="-1"]',reviewScrollPaneFallback:'[role="main"] div[tabindex="-1"]',reviewCardAuthor:"div.d4r55, span.d4r55, span.RPZfBb",reviewCardDate:"span.rsqaWe",reviewCardText:"span.wiI7pd",reviewCardOwnerBlock:"div.CDe7pd",hoursTableAlt:'table[aria-label*="Hour"]',reviewCard:"[data-review-id]",reviewStars:'[role="img"][aria-label*="star"]',reviewTab:'button[role="tab"][aria-label*="Review"]',aboutTab:'button[role="tab"][aria-label*="About"]',expandReview:'[data-review-id] button[aria-label*="See more"], [data-review-id] button.w8nwRe'};async function At(e,t,n,a){let s,i=!1,d,l=()=>{},h=()=>a?.reason instanceof DOMException&&a.reason.name==="TimeoutError"?a.reason:new q,U=()=>l(h()),S=new Promise((r,u)=>{l=u}),o=async r=>{let u;try{await Promise.race([r.close().catch(()=>{}),new Promise(c=>{u=setTimeout(c,2e3)})])}finally{u&&clearTimeout(u)}};if(a?.aborted)throw h();a?.addEventListener("abort",U,{once:!0}),d=setTimeout(()=>l(new DOMException("Optional pagination timed out","TimeoutError")),3e4);try{return await Promise.race([(async()=>{let r=await e.newPage();if(i)throw await o(r),new q;if(s=r,await t(r),i)throw new q;return n(r)})(),S])}finally{i=!0,d&&clearTimeout(d),a?.removeEventListener("abort",U),s&&await o(s)}}var In=/\b(?:HeadlessChrome|Chrome|Chromium|Firefox)\/\d+|\bVersion\/\d+.*\bSafari\//;async function Lt(e){try{let t=await e.evaluate(()=>navigator.userAgent);return typeof t=="string"&&In.test(t)?t:null}catch{return null}}async function Ot(e){let t=null;try{let n=e.contexts().flatMap(a=>a.pages())[0];return n||(t=await e.newContext(),n=t.pages()[0]??await t.newPage()),await Lt(n)}catch{return null}finally{t&&await t.close().catch(()=>{})}}function ii(e,t){return t?{...e,userAgent:t}:e}Zt.use(An());var On=180,xn=3e3,Bn=5e3,Hn='#search, #rso, a[href] h3, [data-snhf], [role="main"]';function jt(e,t){return e?Math.max(1,Math.min(t,e-Date.now())):t}function Fn(e,t){let n=process.env[e];if(!n)return t;let a=Number(n);return Number.isInteger(a)&&a>0?a:t}function Qt(e){return e?e.slice(-6):null}function Re(e,t){let n=(t??process.env.SERP_REDIRECT_BASE)?.trim().replace(/\/+$/,"");return n?`${n}/g/${Buffer.from(e,"utf8").toString("base64url")}`:e}function Rn(e){return e?/united states|u\.?s\.?a?\.?|^us$/i.test(e.trim()):!1}function Ct(e){return e instanceof Error?e.message:String(e)}function Gn(e){return/\b409\b|conflict|already exists/i.test(Ct(e))}async function Dn(e,t){try{await e.profiles.create({name:t})}catch(n){if(!Gn(n))throw n}}function xt(e,t){return{viewport:e.viewport,locale:e.locale,...t?{userAgent:t}:{},...e.deviceScaleFactor?{deviceScaleFactor:e.deviceScaleFactor}:{},...e.isMobile!==void 0?{isMobile:e.isMobile}:{},...e.hasTouch!==void 0?{hasTouch:e.hasTouch}:{}}}async function St(e,t,n){let a;try{return await Promise.race([e,new Promise((s,i)=>{a=setTimeout(()=>i(new Error(`${n} timed out after ${t}ms`)),t)})])}finally{a&&clearTimeout(a)}}function Vn(e){let t=e.trim();if(!t)throw new Error("channelHandle is required");if(/^https?:\/\//i.test(t)||/^(www\.|m\.)?youtube\.com\//i.test(t)){let d=new URL(/^https?:\/\//i.test(t)?t:`https://${t}`);if(d.hostname.replace(/^www\./,"").replace(/^m\./,"").toLowerCase()!=="youtube.com")throw new Error("channel URL must be on youtube.com");let h=d.pathname.split("/").filter(Boolean),U=h[0]??"",S=h[1]??"";if(U.startsWith("@"))return`https://www.youtube.com/${U}/videos`;if(U==="channel"&&S)return`https://www.youtube.com/channel/${S}/videos`;if((U==="c"||U==="user")&&S)return`https://www.youtube.com/${U}/${S}/videos`;throw new Error("channel URL must be a YouTube handle, /channel/UC..., /c/..., or /user/... URL")}let s=t.replace(/^\/+/,"").replace(/\/+$/,"").replace(/\/videos$/i,"");if(/^UC[\w-]{20,}$/.test(s))return`https://www.youtube.com/channel/${s}/videos`;let i=s.startsWith("@")?s:`@${s}`;if(!/^@[\w.-]+$/.test(i))throw new Error("channelHandle must be an @handle, UC channel ID, or YouTube channel URL");return`https://www.youtube.com/${i}/videos`}var Bt=class{browser=null;context=null;page=null;\u006b\u0065\u0072\u006e\u0065\u006cClient=null;\u006b\u0065\u0072\u006e\u0065\u006cSessionId=null;\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=null;\u006b\u0065\u0072\u006e\u0065\u006cStealth=null;\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed=null;\u006b\u0065\u0072\u006e\u0065\u006cProxySource=null;\u006b\u0065\u0072\u006e\u0065\u006cProxyType=null;\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=null;debugEnabled=!1;debugSnapshot={\u006b\u0065\u0072\u006e\u0065\u006c:null,context:null,networkLocation:null,serpNavigation:null};async launch(t){this.debugEnabled=t.debug===!0;let n=t.proxyMode??(t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId?"configured":"none"),a=t.isMobile?"mobile":"desktop";if(this.debugSnapshot={\u006b\u0065\u0072\u006e\u0065\u006c:null,context:{viewport:t.viewport,locale:t.locale,device:a,userAgent:null,deviceScaleFactor:t.deviceScaleFactor??null,isMobile:t.isMobile===!0,hasTouch:t.hasTouch===!0},networkLocation:null,serpNavigation:null},t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey){this.\u006b\u0065\u0072\u006e\u0065\u006cClient=new Z({apiKey:t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey});let i=Number.isInteger(t.\u006b\u0065\u0072\u006e\u0065\u006cTimeoutSeconds)&&Number(t.\u006b\u0065\u0072\u006e\u0065\u006cTimeoutSeconds)>0?Number(t.\u006b\u0065\u0072\u006e\u0065\u006cTimeoutSeconds):Fn("\u004b\u0045\u0052\u004e\u0045\u004c_BROWSER_TIMEOUT_SECONDS",On),d=Math.min(i,600);t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName&&t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges===!0&&await Dn(this.\u006b\u0065\u0072\u006e\u0065\u006cClient,t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName);let l=Wt(),h;t.headlessMode==="headful"||l?.forceHeadful===!0?h=!1:t.headlessMode==="headless"?h=!0:h=l?.forceHeadless===!0||process.env.\u004b\u0045\u0052\u004e\u0045\u004c_HEADLESS_DISABLED!=="true"&&!!l?.op&&be.has(l.op),this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=h?!0:null,l?.headlessSentOut&&(l.headlessSentOut.value=this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent);let U=await this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.create({stealth:t.\u006b\u0065\u0072\u006e\u0065\u006cStealth===!0,timeout_seconds:d,...h?{headless:!0}:{},...t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId?{proxy_id:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId}:{},...t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName?{profile:{name:t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName,...typeof t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges=="boolean"?{save_changes:t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges}:{}}}:{}});this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId=U.session_id,this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=Date.now(),this.\u006b\u0065\u0072\u006e\u0065\u006cStealth=typeof U.stealth=="boolean"?U.stealth:null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed=typeof U.proxy_id=="string"?!!U.proxy_id:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource=t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution?.source??null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyType=t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution?.proxyType??null;let S=null,o=null;if(!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId&&!t.keepDefaultProxy)try{await St(this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.update(this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,{disable_default_proxy:!0}),5e3,`\u004b\u0065\u0072\u006e\u0065\u006c session ${this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId} disable default proxy`),S=!0}catch(u){S=!1,o=Ct(u)}let r={sessionId:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,proxyMode:n,requestedProxyIdPresent:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,requestedProxyIdSuffix:Qt(t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId),createdProxyIdPresent:typeof U.proxy_id=="string"?!!U.proxy_id:null,createdProxyIdSuffix:Qt(U.proxy_id),retrievedProxyIdPresent:null,retrievedProxyIdSuffix:null,retrievedProxyIdMatchesRequested:null,defaultProxyDisabled:S,defaultProxyDisableError:o,proxyResolution:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution??null,timeoutSeconds:d,stealth:typeof U.stealth=="boolean"?U.stealth:null,profilePresent:null,poolPresent:null,retrieveError:null};if(this.debugSnapshot.\u006b\u0065\u0072\u006e\u0065\u006c=r,console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_created",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,timeout_seconds:d,proxy_mode:n,proxy_id_present:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,profile_name_present:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName,proxy_resolution_source:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution?.source})),this.debugEnabled&&await this.populate\u004b\u0065\u0072\u006e\u0065\u006cRetrieveDebug(r,t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId),this.browser=await Ln.connectOverCDP(U.cdp_ws_url),t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName||t.preserve\u004b\u0065\u0072\u006e\u0065\u006cContext)this.context=this.browser.contexts()[0]??await this.browser.newContext(xt(t)),this.page=this.context.pages()[0]??await this.context.newPage(),this.debugSnapshot.context.userAgent=await Lt(this.page);else{let u=await Ot(this.browser);this.debugSnapshot.context.userAgent=u,this.context=await this.browser.newContext(xt(t,u)),this.page=await this.context.newPage()}if(await this.installEsbuildHelperShims(this.context),t.preserve\u004b\u0065\u0072\u006e\u0065\u006cContext||await this.page.setViewportSize(t.viewport),(this.debugEnabled||t.requireUsEgress)&&(this.debugSnapshot.networkLocation=await this.captureBrowserNetworkLocation()),t.requireUsEgress){let u=this.debugSnapshot.networkLocation?.country??null;if(!Rn(u))throw new K(`Non-US egress (${u??"unknown"}) \u2014 retrying with a fresh session`)}return}let s={headless:t.headless,proxy:t.proxy?{server:t.proxy}:void 0,...t.browserExecutablePath?{executablePath:t.browserExecutablePath}:{},...t.ignoreDefaultArgs?{ignoreDefaultArgs:t.ignoreDefaultArgs}:{}};if(t.profileDir)this.context=await Zt.launchPersistentContext(t.profileDir,{...s,...xt(t)}),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage(),this.debugSnapshot.context.userAgent=await Lt(this.page);else{this.browser=await Zt.launch(s);let i=await Ot(this.browser);this.debugSnapshot.context.userAgent=i,this.context=await this.browser.newContext(xt(t,i)),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage()}this.debugEnabled&&(this.debugSnapshot.networkLocation=await this.captureBrowserNetworkLocation())}async populate\u004b\u0065\u0072\u006e\u0065\u006cRetrieveDebug(t,n){if(!(!this.\u006b\u0065\u0072\u006e\u0065\u006cClient||!this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId))try{let a=await St(this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.retrieve(this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId),5e3,`\u004b\u0065\u0072\u006e\u0065\u006c session ${this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId} retrieve`);t.retrievedProxyIdPresent=typeof a.proxy_id=="string"?!!a.proxy_id:!1,t.retrievedProxyIdSuffix=Qt(a.proxy_id),t.retrievedProxyIdMatchesRequested=n?a.proxy_id===n:!a.proxy_id,t.timeoutSeconds=typeof a.timeout_seconds=="number"?a.timeout_seconds:t.timeoutSeconds,t.stealth=typeof a.stealth=="boolean"?a.stealth:t.stealth,t.profilePresent=!!a.profile,t.poolPresent=!!a.pool}catch(a){t.retrieveError=Ct(a)}}async captureBrowserNetworkLocation(){let t=(a,s="ipapi.co")=>({source:s,ip:null,city:null,region:null,country:null,org:null,timezone:null,error:a});if(!this.context)return t("browser context is not available");let n=null;try{n=await this.context.newPage();let a=await this.loadJsonInDebugPage(n,"https://ipwho.is/");if(a){let l=typeof a.connection=="object"&&a.connection!==null?a.connection:{};return{source:"ipwho.is",ip:typeof a.ip=="string"?a.ip:null,city:typeof a.city=="string"?a.city:null,region:typeof a.region=="string"?a.region:null,country:typeof a.country=="string"?a.country:null,org:typeof l.org=="string"?l.org:null,timezone:typeof a.timezone=="object"&&a.timezone!==null&&typeof a.timezone.id=="string"?a.timezone.id:null,error:null}}let s=await this.loadJsonInDebugPage(n,"https://api64.ipify.org?format=json");if(s)return{source:"api64.ipify.org",ip:typeof s.ip=="string"?s.ip:null,city:null,region:null,country:null,org:null,timezone:null,error:null};await St(n.goto("https://ipapi.co/json/",{waitUntil:"domcontentloaded",timeout:7e3}),8e3,"browser network location navigation");let i=await n.locator("body").innerText({timeout:2e3}),d=JSON.parse(i);return{source:"ipapi.co",ip:typeof d.ip=="string"?d.ip:null,city:typeof d.city=="string"?d.city:null,region:typeof d.region=="string"?d.region:null,country:typeof d.country_name=="string"?d.country_name:typeof d.country=="string"?d.country:null,org:typeof d.org=="string"?d.org:null,timezone:typeof d.timezone=="string"?d.timezone:null,error:null}}catch(a){return t(Ct(a))}finally{await n?.close().catch(()=>{})}}async loadJsonInDebugPage(t,n){try{await St(t.goto(n,{waitUntil:"domcontentloaded",timeout:7e3}),8e3,`browser network location navigation ${n}`);let a=await t.locator("body").innerText({timeout:2e3});return JSON.parse(a)}catch{return null}}async installEsbuildHelperShims(t){await t.addInitScript(()=>{let n=globalThis;typeof n.__name!="function"&&(n.__name=a=>a),typeof n.__publicField!="function"&&(n.__publicField=(a,s,i)=>(a[s]=i,i))})}async withTemporaryPage(t,n){if(!this.context)throw new Error("Browser context is not available");return At(this.context,async()=>{},t,n)}async navigateToSERP(t,n,a,s,i){let d=new URLSearchParams({q:t,gl:a,hl:s,pws:"0"});i?.tbs&&d.set("tbs",i.tbs),n&&d.set("uule",n);let l="https://www.google.com/search?"+d.toString(),h=Re(l),U=i?.debug?{requestedUrl:l,finalUrl:null,title:null,bodySnippet:null,hasPaa:null,captchaDetected:null,googleSorryUrl:null,redirected:null}:null;U&&(this.debugSnapshot.serpNavigation=U);try{await this.page.goto(h,{waitUntil:"domcontentloaded",timeout:jt(i?.deadlineMs,i?.purpose==="serp"?8e3:45e3)})}catch(o){await this.updateSerpNavigationDebug(U,l,{hasPaa:null,captchaDetected:null});let r=await this.captureDiagnostics(l);throw new bt(`page.goto failed: ${o.message} | ${r}`)}if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(U,l,{hasPaa:!1,captchaDetected:!0}),new K(this.captchaMessage());if(i?.purpose==="serp"){await this.page.waitForSelector(Hn,{timeout:jt(i.deadlineMs,1500)}).catch(()=>null);let o=await this.page.locator(F.item).count().catch(()=>0)>0;return await this.updateSerpNavigationDebug(U,l,{hasPaa:o,captchaDetected:!1}),{hasPaa:o}}if(await this.page.waitForSelector(F.item,{timeout:jt(i?.deadlineMs,4e3)}).catch(()=>null))return await this.updateSerpNavigationDebug(U,l,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(U,l,{hasPaa:!1,captchaDetected:!0}),new K(this.captchaMessage());for(let o=1;o<=6;o++)if(await this.page.evaluate(u=>{window.scrollTo(0,document.body.scrollHeight*u)},o/6),await this.page.waitForTimeout(600),await this.page.locator(F.item).count()>0)return await this.updateSerpNavigationDebug(U,l,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};return await this.updateSerpNavigationDebug(U,l,{hasPaa:!1,captchaDetected:!1}),{hasPaa:!1}}async isSerpChallengeVisible(){if(!this.page)return!1;if(await this.page.locator(F.captchaMarker).count().catch(()=>0)>0)return!0;let n=this.page.url();if(/google\.[^/]+\/sorry\//i.test(n))return!0;let a=await this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,1e3)).catch(()=>"");return/recaptcha|unusual traffic|are you a robot|about this page|detected unusual traffic/i.test(a)}async updateSerpNavigationDebug(t,n,a){if(!(!t||!this.page))try{let s=this.page.url(),i=await this.page.title().catch(()=>""),d=await this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,500)).catch(()=>""),l=/recaptcha|unusual traffic|are you a robot/i.test(d);t.finalUrl=s,t.title=i,t.bodySnippet=d,t.hasPaa=a.hasPaa,t.captchaDetected=a.captchaDetected??l,t.googleSorryUrl=/google\.[^/]+\/sorry\//i.test(s),t.redirected=s!==n}catch(s){t.bodySnippet=`debug capture failed: ${Ct(s)}`}}async captureDiagnostics(t){try{let n=this.page.url(),a=await this.page.title().catch(()=>""),s=await this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,400)).catch(()=>""),i=/consent\.google\./.test(n)||/before you continue/i.test(s),d=/recaptcha|unusual traffic|are you a robot/i.test(s),l=[i?"CONSENT_WALL":"",d?"BOT_CHALLENGE":"",n!==t?"REDIRECTED":""].filter(Boolean).join(",");return`intended=${t} | final=${n} | title="${a}" | flags=[${l}] | body="${s}"`}catch(n){return`diagnostics-failed: ${n.message}`}}captchaMessage(){return this.\u006b\u0065\u0072\u006e\u0065\u006cClient?"Google returned a CAPTCHA on this session \u2014 retrying with a fresh session.":Ne}async navigateTo(t){let n=process.env.ADS_ARRIVAL_REDIRECT_BASE?.trim(),a=n?Re(t,n):t;try{if(await this.page.goto(a,{waitUntil:"domcontentloaded",timeout:45e3}),/google\.[^/]+\/search\?/i.test(t)&&await this.isSerpChallengeVisible())throw new K(this.captchaMessage())}catch(s){if(s instanceof K)throw s;let i=await this.captureDiagnostics(t);throw new bt(`page.goto failed: ${s.message} | ${i}`)}}async navigateToChannel(t){let n=Vn(t);try{await this.page.goto(n,{waitUntil:"networkidle",timeout:3e4})}catch(a){let s=await this.captureDiagnostics(n);throw new bt(`navigateToChannel failed: ${a.message} | ${s}`)}}async evaluate(t,n){return this.page.evaluate(t,n)}getPage(){return this.page}get\u004b\u0065\u0072\u006e\u0065\u006cSessionId(){return this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId}getProviderSessionMetadata(){return{provider:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId?"\u006b\u0065\u0072\u006e\u0065\u006c":"local",providerSessionId:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,disconnectObservation:null}}getDebugSnapshot(){return this.debugSnapshot}async close(){if(this.browser){let t=this.browser,n=this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,a=this.\u006b\u0065\u0072\u006e\u0065\u006cClient,s=this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs,i=this.\u006b\u0065\u0072\u006e\u0065\u006cStealth,d=this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed,l=this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource,h=this.\u006b\u0065\u0072\u006e\u0065\u006cProxyType,U=this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent,S=this.getProviderSessionMetadata();if(this.browser=null,this.context=null,this.page=null,this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId=null,this.\u006b\u0065\u0072\u006e\u0065\u006cClient=null,this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=null,this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource=null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyType=null,a&&n&&s!=null&&We({\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,source:"browser_driver",stealth:i,headlessSent:U,proxyUsed:d,proxySource:l,proxyType:h,openedAtMs:s,closedAtMs:Date.now()}),a&&n){console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_started",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n}));let o=St(a.browsers.deleteByID(n),Bn,`\u004b\u0065\u0072\u006e\u0065\u006c session ${n} delete`),r=St(t.close(),xn,`\u004b\u0065\u0072\u006e\u0065\u006c browser ${n} close`),[u,c]=await Promise.allSettled([o,r]),g={\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!0,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:u.status==="fulfilled",\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:u.status==="rejected"?u.reason instanceof Error?u.reason.message:String(u.reason):null,browserCloseSucceeded:c.status==="fulfilled",browserCloseError:c.status==="rejected"?c.reason instanceof Error?c.reason.message:String(c.reason):null,provider:S.provider,providerSessionId:S.providerSessionId,providerDisconnectObserved:!1,providerDisconnectMessage:null};return u.status==="rejected"?(console.warn(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_failed",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n,message:g.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError})),console.warn(`\u004b\u0065\u0072\u006e\u0065\u006c session cleanup failed for ${n}:`,u.reason)):console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_succeeded",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n})),c.status==="rejected"&&(console.warn(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_close_failed",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n,message:g.browserCloseError})),console.warn(`\u004b\u0065\u0072\u006e\u0065\u006c browser close failed for ${n}:`,c.reason)),g}return await t.close(),{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:!0,browserCloseError:null,provider:S.provider,providerSessionId:S.providerSessionId,providerDisconnectObserved:!1,providerDisconnectMessage:null}}else if(this.context){let t=this.context;return this.context=null,this.page=null,await t.close(),{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:!0,browserCloseError:null,provider:"local",providerSessionId:null,providerDisconnectObserved:!1,providerDisconnectMessage:null}}return{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:null,browserCloseError:null,provider:"local",providerSessionId:null,providerDisconnectObserved:!1,providerDisconnectMessage:null}}};import{chromium as Kn}from"playwright";function Yn(e,t){if(typeof e!="string")return null;let n=e.replace(/[\u0000-\u001f\u007f]+/g," ").replace(/\s+/g," ").trim();return n?n.slice(0,t):null}function Ge(e){let t=Yn(e,320);return t?t.replace(/\b(?:wss?|https?):\/\/\S+/gi,"[redacted endpoint]").replace(/\b(?:authorization|proxy-authorization):\s*\S+/gi,"$1: [redacted]").replace(/\bBearer\s+\S+/gi,"Bearer [redacted]").slice(0,320):null}function De(e){return Ge(e)}function Ve(e){if(typeof e!="string"||e.length===0||e.length>512||e.trim()!==e||/[\s\u0000-\u001f\u007f]/.test(e)||/:\/\//.test(e))throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 did not return a valid browser session ID");return e}function Xt(e,t,n=new Date().toISOString()){let a=Ge(t);return{source:e,message:a??e.replaceAll("_"," "),observedAt:n}}function En(e){return{provider:e.provider,providerDisconnectObserved:e.disconnectObservation!==null,providerDisconnectMessage:e.disconnectObservation?.message??null}}function Ye(e){return{...En(e),providerSessionId:e.providerSessionId}}var Jn=new Set(["image","media","font","stylesheet","ping"]),_n=["doubleclick.net","googleadservices.com","googlesyndication.com","google-analytics.com"],zn='#search, #rso, a[href] h3, [data-snhf], [role="main"]',qn=3e4,Ee=1500;function Ht(e,t){return e?Math.max(1,Math.min(t,e-Date.now())):t}function Ke(){return process.env.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_BROWSER_WSS?.trim()||null}function Rt(){return process.env.SERP_BROWSER_PROVIDER?.trim().toLowerCase()==="\u006b\u0065\u0072\u006e\u0065\u006c"?!1:!!Ke()}async function te(e,t=!1){let n=e.request();try{let a=await n.allHeaders(),s=await fetch(n.url(),{method:n.method(),headers:{accept:a.accept??"*/*","accept-language":a["accept-language"]??"en-US,en;q=0.9","user-agent":a["user-agent"]??"Mozilla/5.0",...t?{cookie:a.cookie??"",referer:a.referer??"https://www.google.com/",...a["x-client-data"]?{"x-client-data":a["x-client-data"]}:{}}:{}},body:n.method()==="GET"||n.method()==="HEAD"?void 0:n.postData()});if(!s.ok)return!1;let i=Buffer.from(await s.arrayBuffer());return await e.fulfill({status:s.status,contentType:s.headers.get("content-type")??"application/octet-stream",headers:{"cache-control":"public, max-age=3600"},body:i}),!0}catch{return!1}}var Ft=class{browser=null;context=null;page=null;cdpSession=null;providerSessionId=null;disconnectObservation=null;closing=!1;observeDisconnect(t,n){this.closing||this.disconnectObservation||(this.disconnectObservation=Xt(t,n))}async launch(t){if(this.page)return;this.closing=!1,this.providerSessionId=null,this.disconnectObservation=null;let n=Ke();if(!n)throw new Error("SERP browser service is not configured");this.browser=await Kn.connectOverCDP(n,{timeout:Ht(t.operationDeadlineMs,qn)}),this.context=this.browser.contexts()[0]??await this.browser.newContext(),await this.context.addInitScript(()=>{let i=globalThis;typeof i.__name!="function"&&(i.__name=d=>d),typeof i.__publicField!="function"&&(i.__publicField=(d,l,h)=>(d[l]=h,h))}),this.page=this.context.pages()[0]??await this.context.newPage(),this.browser.on("disconnected",()=>this.observeDisconnect("browser_disconnected")),this.context.on("close",()=>this.observeDisconnect("context_closed")),this.page.on("close",()=>this.observeDisconnect("page_closed")),this.page.on("crash",()=>this.observeDisconnect("page_crashed")),this.cdpSession=await this.context.newCDPSession(this.page);let s=await this.cdpSession.send("Browser.getSessionId");this.providerSessionId=Ve(s?.sessionId),await this.setupPage(this.page)}async setupPage(t){await t.route("**/*",async n=>{let a=n.request(),s=a.resourceType(),i;try{i=new URL(a.url())}catch{await n.continue();return}let d=i.hostname.toLowerCase();if(!(i.pathname==="/sgasync"&&await te(n,!0))&&!(i.pathname.includes("/shared_dict/")&&await te(n))&&!(s==="script"&&(d==="www.google.com"||d==="www.gstatic.com")&&await te(n))){if(Jn.has(s)){await n.abort("blockedbyclient");return}if(_n.some(l=>d===l||d.endsWith(`.${l}`))){await n.abort("blockedbyclient");return}await n.continue()}})}async withTemporaryPage(t,n){if(!this.context||this.closing)throw new Error("Browser context is not available");return At(this.context,a=>this.setupPage(a),t,n)}async navigateToSERP(t,n,a,s,i){if(!this.page)throw new Error("Browser page is not available");let d=new URLSearchParams({q:t,gl:a,hl:s,pws:"0"});return i?.tbs&&d.set("tbs",i.tbs),n&&d.set("uule",n),await this.page.goto(`https://www.google.com/search?${d}`,{waitUntil:"domcontentloaded",timeout:Ht(i?.deadlineMs,i?.purpose==="serp"?8e3:45e3)}),i?.purpose==="serp"?(await this.page.waitForSelector(zn,{timeout:Ht(i.deadlineMs,1500)}).catch(()=>null),{hasPaa:await this.page.locator(F.item).count().catch(()=>0)>0}):{hasPaa:!!await this.page.waitForSelector(F.item,{timeout:Ht(i?.deadlineMs,8e3)}).catch(()=>null)}}async navigateTo(t){if(!this.page)throw new Error("Browser page is not available");await this.page.goto(t,{waitUntil:"load",timeout:45e3})}async navigateToChannel(){throw new Error("YouTube navigation is not supported by the SERP browser driver")}async evaluate(t,n){if(!this.page)throw new Error("Browser page is not available");return this.page.evaluate(t,n)}getPage(){if(!this.page)throw new Error("Browser page is not available");return this.page}get\u004b\u0065\u0072\u006e\u0065\u006cSessionId(){return null}getProviderSessionMetadata(){return{provider:"\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api",providerSessionId:this.providerSessionId,disconnectObservation:this.disconnectObservation}}getDebugSnapshot(){return{\u006b\u0065\u0072\u006e\u0065\u006c:null,context:null,networkLocation:null,serpNavigation:null}}async close(){this.closing=!0;let t=null,n;try{let s=this.browser?.close();s&&await Promise.race([s,new Promise((i,d)=>{n=setTimeout(()=>d(new Error(`Browser close acknowledgement exceeded ${Ee}ms`)),Ee)})])}catch(s){t=De(s instanceof Error?s.message:String(s))??"\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 browser close failed",this.disconnectObservation??=Xt("browser_close_error",t)}finally{n&&clearTimeout(n)}let a=Ye(this.getProviderSessionMetadata());return this.browser=null,this.context=null,this.page=null,this.cdpSession=null,{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:t===null,browserCloseError:t,...a}}};function Je(e,t){let n=!!(e?.serpIdentity||e?.\u006b\u0065\u0072\u006e\u0065\u006cProfileName);return!t?.force\u004b\u0065\u0072\u006e\u0065\u006c&&(t?.forceManaged===!0||Rt()&&!n)?new Ft:new Bt}var it={austin:"Austin,Texas,United States","new york":"New York,New York,United States","new york city":"New York,New York,United States",nyc:"New York,New York,United States","los angeles":"Los Angeles,California,United States",la:"Los Angeles,California,United States",chicago:"Chicago,Illinois,United States",houston:"Houston,Texas,United States",phoenix:"Phoenix,Arizona,United States",philadelphia:"Philadelphia,Pennsylvania,United States",philly:"Philadelphia,Pennsylvania,United States","san antonio":"San Antonio,Texas,United States",dallas:"Dallas,Texas,United States",miami:"Miami,Florida,United States",seattle:"Seattle,Washington,United States",denver:"Denver,Colorado,United States",loveland:"Loveland,Colorado,United States","loveland co":"Loveland,Colorado,United States","fort collins":"Fort Collins,Colorado,United States",boulder:"Boulder,Colorado,United States","colorado springs":"Colorado Springs,Colorado,United States",boston:"Boston,Massachusetts,United States",atlanta:"Atlanta,Georgia,United States","san francisco":"San Francisco,California,United States",sf:"San Francisco,California,United States",portland:"Portland,Oregon,United States","las vegas":"Las Vegas,Nevada,United States",minneapolis:"Minneapolis,Minnesota,United States",detroit:"Detroit,Michigan,United States",nashville:"Nashville,Tennessee,United States",charlotte:"Charlotte,North Carolina,United States",orlando:"Orlando,Florida,United States","san diego":"San Diego,California,United States",baltimore:"Baltimore,Maryland,United States",sacramento:"Sacramento,California,United States",columbus:"Columbus,Ohio,United States",indianapolis:"Indianapolis,Indiana,United States","san jose":"San Jose,California,United States","fort worth":"Fort Worth,Texas,United States",jacksonville:"Jacksonville,Florida,United States",memphis:"Memphis,Tennessee,United States",louisville:"Louisville,Kentucky,United States",raleigh:"Raleigh,North Carolina,United States",richmond:"Richmond,Virginia,United States","salt lake city":"Salt Lake City,Utah,United States",toronto:"Toronto,Ontario,Canada",vancouver:"Vancouver,British Columbia,Canada",montreal:"Montreal,Quebec,Canada",calgary:"Calgary,Alberta,Canada",ottawa:"Ottawa,Ontario,Canada",london:"London,England,United Kingdom",manchester:"Manchester,England,United Kingdom",birmingham:"Birmingham,England,United Kingdom",edinburgh:"Edinburgh,Scotland,United Kingdom",glasgow:"Glasgow,Scotland,United Kingdom",leeds:"Leeds,England,United Kingdom",sydney:"Sydney,New South Wales,Australia",melbourne:"Melbourne,Victoria,Australia",brisbane:"Brisbane,Queensland,Australia",perth:"Perth,Western Australia,Australia",adelaide:"Adelaide,South Australia,Australia",dublin:"Dublin,Leinster,Ireland"};var _e=`3, Nanjemoy,Maryland,United States
1
+ import{f as X}from"./chunk-M5QHXNFZ.js";import{a as ve}from"./chunk-4FROKQJN.js";import{a as fe,b as Pe,c as Wt,e as be,j as We}from"./chunk-56UT5M5Y.js";import{a as pe,c as jt,d as gt,g as me,l as Ie}from"./chunk-2TZBO52D.js";import{a as Ne,i as Te,j as E,k as bt,m as $,n as yt,o as Qt}from"./chunk-KKHTMYCD.js";import{chromium as te}from"playwright-extra";import Ln from"puppeteer-extra-plugin-stealth";import{chromium as On}from"playwright";var H={container:".eJH8qe.adDDi",dataInitq:"[data-initq]",item:".related-question-pair",itemDataQ:"data-q",itemDataInitQ:"data-initq",itemQuestionEl:".JlqpRe",answerContainer:".bCOlv, .hgKElc, .wDYxhc, .LGOjhe, .fo7IQd, .fmW3u",aiAnswerBody:".pWvJNd",aiCitation:"a.PMDqCb[href]",aiSourceCard:"a.vIWmYe[href], a.Zbfntb[href]",sourceTitle:"h3",sourceSite:".VuuXrf",sourceCite:"cite",clickTarget:".JlqpRe",expandedClass:"aoRk1c",captchaMarker:'#captcha-form, #recaptcha, form[action*="/sorry/"], .g-recaptcha, [data-sitekey]'},Ae={container:'div[jscontroller="HWk0Gf"]',sectionHeading:'.mgAbYb[role="heading"]',item:"a.rIRoqf"},It={udm:"39",item:"a.rIRoqf",durationPattern:/^\d+:\d+$/,platforms:["YouTube","TikTok","Instagram","Facebook","X"]},Le={section:".ULSxyf",item:"a.KYg7td.INpicf",title:".hyYc0c",source:".K4ETW"},Oe={sectionTag:"g-section-with-header",sectionHeadingText:"What people are saying",card:'.dRzkFf[role="listitem"]',cardLink:'a.WlydOe[jsname="YKoRaf"]',titleH1:"h1.WQWxe",titleDiv:".eAaXgc",popularCommentLabel:".qgdis",source:".sTl1Td",platformBadge:".appd0, .KrMNbf",ytChannel:".sjVJQd",ytDate:".PLq9Je",authorNote:".nDgy9d"},xe={root:"[data-lhcontainer][data-streaming-container][eid]",legacyRoot:'[data-hveid="CBMQAA"]',wrapper:".Fgyi2e",controller:'[jscontroller="AkrxPe"]',contentSubtree:'[data-subtree="mfc"]',header:".heWuVc",heading:".Fzsovc.cwYVJe.RJPOee",showMoreButton:'[aria-label="Show more AI Overview"]',sourcesPanel:".OZ9ddf.WAUd4",disclaimer:".DuQANe.MSJHRb"},Be={root:'[data-hveid="CAUQAA"]',wrapper:".Fgyi2e",citations:'.Fgyi2e [data-hveid] a[jsname="pxBnId"]'},He={result:".wHYlTd.tF2Cxc",title:"h3.LC20lb",siteName:".VuuXrf",cite:"cite.tjvcx",snippet:".VwiC3b",redditCite:"cite.qLRx3b",ratingWrap:".Y0A0hc",ratingValue:".yi40Hd",reviewCount:".RDApEe"},Fe={headingText:"Businesses",card:".w7Dbne",name:".OSrXXb",ratingValue:".yi40Hd",reviewCount:".RDApEe"},Re="2026-05-07",ai={ratingAndCount:"div.F7nice",hoursTable:"table.eK4R0e",reviewScrollPane:'div.m6QErb[tabindex="-1"]',reviewScrollPaneFallback:'[role="main"] div[tabindex="-1"]',reviewCardAuthor:"div.d4r55, span.d4r55, span.RPZfBb",reviewCardDate:"span.rsqaWe",reviewCardText:"span.wiI7pd",reviewCardOwnerBlock:"div.CDe7pd",hoursTableAlt:'table[aria-label*="Hour"]',reviewCard:"[data-review-id]",reviewStars:'[role="img"][aria-label*="star"]',reviewTab:'button[role="tab"][aria-label*="Review"]',aboutTab:'button[role="tab"][aria-label*="About"]',expandReview:'[data-review-id] button[aria-label*="See more"], [data-review-id] button.w8nwRe'};async function At(e,t,n,a){let s,i=!1,d,S=()=>{},U=()=>a?.reason instanceof DOMException&&a.reason.name==="TimeoutError"?a.reason:new $,h=()=>S(U()),l=new Promise((r,u)=>{S=u}),o=async r=>{let u;try{await Promise.race([r.close().catch(()=>{}),new Promise(c=>{u=setTimeout(c,2e3)})])}finally{u&&clearTimeout(u)}};if(a?.aborted)throw U();a?.addEventListener("abort",h,{once:!0}),d=setTimeout(()=>S(new DOMException("Optional pagination timed out","TimeoutError")),3e4);try{return await Promise.race([(async()=>{let r=await e.newPage();if(i)throw await o(r),new $;if(s=r,await t(r),i)throw new $;return n(r)})(),l])}finally{i=!0,d&&clearTimeout(d),a?.removeEventListener("abort",h),s&&await o(s)}}var An=/\b(?:HeadlessChrome|Chrome|Chromium|Firefox)\/\d+|\bVersion\/\d+.*\bSafari\//;async function Lt(e){try{let t=await e.evaluate(()=>navigator.userAgent);return typeof t=="string"&&An.test(t)?t:null}catch{return null}}async function Ot(e){let t=null;try{let n=e.contexts().flatMap(a=>a.pages())[0];return n||(t=await e.newContext(),n=t.pages()[0]??await t.newPage()),await Lt(n)}catch{return null}finally{t&&await t.close().catch(()=>{})}}function di(e,t){return t?{...e,userAgent:t}:e}te.use(Ln());var xn=180,Bn=3e3,Hn=5e3,Fn='#search, #rso, a[href] h3, [data-snhf], [role="main"]';function Zt(e,t){return e?Math.max(1,Math.min(t,e-Date.now())):t}function Rn(e,t){let n=process.env[e];if(!n)return t;let a=Number(n);return Number.isInteger(a)&&a>0?a:t}function Xt(e){return e?e.slice(-6):null}function Ge(e,t){let n=(t??process.env.SERP_REDIRECT_BASE)?.trim().replace(/\/+$/,"");return n?`${n}/g/${Buffer.from(e,"utf8").toString("base64url")}`:e}function Gn(e){return e?/united states|u\.?s\.?a?\.?|^us$/i.test(e.trim()):!1}function Ct(e){return e instanceof Error?e.message:String(e)}function Dn(e){return/\b409\b|conflict|already exists/i.test(Ct(e))}async function Vn(e,t){try{await e.profiles.create({name:t})}catch(n){if(!Dn(n))throw n}}function xt(e,t){return{viewport:e.viewport,locale:e.locale,...t?{userAgent:t}:{},...e.deviceScaleFactor?{deviceScaleFactor:e.deviceScaleFactor}:{},...e.isMobile!==void 0?{isMobile:e.isMobile}:{},...e.hasTouch!==void 0?{hasTouch:e.hasTouch}:{}}}async function ht(e,t,n){let a;try{return await Promise.race([e,new Promise((s,i)=>{a=setTimeout(()=>i(new Error(`${n} timed out after ${t}ms`)),t)})])}finally{a&&clearTimeout(a)}}function Yn(e){let t=e.trim();if(!t)throw new Error("channelHandle is required");if(/^https?:\/\//i.test(t)||/^(www\.|m\.)?youtube\.com\//i.test(t)){let d=new URL(/^https?:\/\//i.test(t)?t:`https://${t}`);if(d.hostname.replace(/^www\./,"").replace(/^m\./,"").toLowerCase()!=="youtube.com")throw new Error("channel URL must be on youtube.com");let U=d.pathname.split("/").filter(Boolean),h=U[0]??"",l=U[1]??"";if(h.startsWith("@"))return`https://www.youtube.com/${h}/videos`;if(h==="channel"&&l)return`https://www.youtube.com/channel/${l}/videos`;if((h==="c"||h==="user")&&l)return`https://www.youtube.com/${h}/${l}/videos`;throw new Error("channel URL must be a YouTube handle, /channel/UC..., /c/..., or /user/... URL")}let s=t.replace(/^\/+/,"").replace(/\/+$/,"").replace(/\/videos$/i,"");if(/^UC[\w-]{20,}$/.test(s))return`https://www.youtube.com/channel/${s}/videos`;let i=s.startsWith("@")?s:`@${s}`;if(!/^@[\w.-]+$/.test(i))throw new Error("channelHandle must be an @handle, UC channel ID, or YouTube channel URL");return`https://www.youtube.com/${i}/videos`}var Bt=class{browser=null;context=null;page=null;\u006b\u0065\u0072\u006e\u0065\u006cClient=null;\u006b\u0065\u0072\u006e\u0065\u006cSessionId=null;\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=null;\u006b\u0065\u0072\u006e\u0065\u006cStealth=null;\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed=null;\u006b\u0065\u0072\u006e\u0065\u006cProxySource=null;\u006b\u0065\u0072\u006e\u0065\u006cProxyType=null;\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=null;debugEnabled=!1;debugSnapshot={\u006b\u0065\u0072\u006e\u0065\u006c:null,context:null,networkLocation:null,serpNavigation:null};async launch(t){this.debugEnabled=t.debug===!0;let n=t.proxyMode??(t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId?"configured":"none"),a=t.isMobile?"mobile":"desktop";if(this.debugSnapshot={\u006b\u0065\u0072\u006e\u0065\u006c:null,context:{viewport:t.viewport,locale:t.locale,device:a,userAgent:null,deviceScaleFactor:t.deviceScaleFactor??null,isMobile:t.isMobile===!0,hasTouch:t.hasTouch===!0},networkLocation:null,serpNavigation:null},t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey){this.\u006b\u0065\u0072\u006e\u0065\u006cClient=new X({apiKey:t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey});let i=Number.isInteger(t.\u006b\u0065\u0072\u006e\u0065\u006cTimeoutSeconds)&&Number(t.\u006b\u0065\u0072\u006e\u0065\u006cTimeoutSeconds)>0?Number(t.\u006b\u0065\u0072\u006e\u0065\u006cTimeoutSeconds):Rn("\u004b\u0045\u0052\u004e\u0045\u004c_BROWSER_TIMEOUT_SECONDS",xn),d=Math.min(i,600);t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName&&t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges===!0&&await Vn(this.\u006b\u0065\u0072\u006e\u0065\u006cClient,t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName);let S=Wt(),U;t.headlessMode==="headful"||S?.forceHeadful===!0?U=!1:t.headlessMode==="headless"?U=!0:U=S?.forceHeadless===!0||process.env.\u004b\u0045\u0052\u004e\u0045\u004c_HEADLESS_DISABLED!=="true"&&!!S?.op&&be.has(S.op),this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=U?!0:null,S?.headlessSentOut&&(S.headlessSentOut.value=this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent);let h=await this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.create({stealth:t.\u006b\u0065\u0072\u006e\u0065\u006cStealth===!0,timeout_seconds:d,...U?{headless:!0}:{},...t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId?{proxy_id:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId}:{},...t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName?{profile:{name:t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName,...typeof t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges=="boolean"?{save_changes:t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges}:{}}}:{}});this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId=h.session_id,this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=Date.now(),this.\u006b\u0065\u0072\u006e\u0065\u006cStealth=typeof h.stealth=="boolean"?h.stealth:null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed=typeof h.proxy_id=="string"?!!h.proxy_id:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource=t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution?.source??null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyType=t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution?.proxyType??null;let l=null,o=null;if(!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId&&!t.keepDefaultProxy)try{await ht(this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.update(this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,{disable_default_proxy:!0}),5e3,`\u004b\u0065\u0072\u006e\u0065\u006c session ${this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId} disable default proxy`),l=!0}catch(u){l=!1,o=Ct(u)}let r={sessionId:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,proxyMode:n,requestedProxyIdPresent:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,requestedProxyIdSuffix:Xt(t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId),createdProxyIdPresent:typeof h.proxy_id=="string"?!!h.proxy_id:null,createdProxyIdSuffix:Xt(h.proxy_id),retrievedProxyIdPresent:null,retrievedProxyIdSuffix:null,retrievedProxyIdMatchesRequested:null,defaultProxyDisabled:l,defaultProxyDisableError:o,proxyResolution:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution??null,timeoutSeconds:d,stealth:typeof h.stealth=="boolean"?h.stealth:null,profilePresent:null,poolPresent:null,retrieveError:null};if(this.debugSnapshot.\u006b\u0065\u0072\u006e\u0065\u006c=r,console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_created",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,timeout_seconds:d,proxy_mode:n,proxy_id_present:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,profile_name_present:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName,proxy_resolution_source:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution?.source})),this.debugEnabled&&await this.populate\u004b\u0065\u0072\u006e\u0065\u006cRetrieveDebug(r,t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId),this.browser=await On.connectOverCDP(h.cdp_ws_url),t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName||t.preserve\u004b\u0065\u0072\u006e\u0065\u006cContext)this.context=this.browser.contexts()[0]??await this.browser.newContext(xt(t)),this.page=this.context.pages()[0]??await this.context.newPage(),this.debugSnapshot.context.userAgent=await Lt(this.page);else{let u=await Ot(this.browser);this.debugSnapshot.context.userAgent=u,this.context=await this.browser.newContext(xt(t,u)),this.page=await this.context.newPage()}if(await this.installEsbuildHelperShims(this.context),t.preserve\u004b\u0065\u0072\u006e\u0065\u006cContext||await this.page.setViewportSize(t.viewport),(this.debugEnabled||t.requireUsEgress)&&(this.debugSnapshot.networkLocation=await this.captureBrowserNetworkLocation()),t.requireUsEgress){let u=this.debugSnapshot.networkLocation?.country??null;if(!Gn(u))throw new E(`Non-US egress (${u??"unknown"}) \u2014 retrying with a fresh session`)}return}let s={headless:t.headless,proxy:t.proxy?{server:t.proxy}:void 0,...t.browserExecutablePath?{executablePath:t.browserExecutablePath}:{},...t.ignoreDefaultArgs?{ignoreDefaultArgs:t.ignoreDefaultArgs}:{}};if(t.profileDir)this.context=await te.launchPersistentContext(t.profileDir,{...s,...xt(t)}),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage(),this.debugSnapshot.context.userAgent=await Lt(this.page);else{this.browser=await te.launch(s);let i=await Ot(this.browser);this.debugSnapshot.context.userAgent=i,this.context=await this.browser.newContext(xt(t,i)),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage()}this.debugEnabled&&(this.debugSnapshot.networkLocation=await this.captureBrowserNetworkLocation())}async populate\u004b\u0065\u0072\u006e\u0065\u006cRetrieveDebug(t,n){if(!(!this.\u006b\u0065\u0072\u006e\u0065\u006cClient||!this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId))try{let a=await ht(this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.retrieve(this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId),5e3,`\u004b\u0065\u0072\u006e\u0065\u006c session ${this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId} retrieve`);t.retrievedProxyIdPresent=typeof a.proxy_id=="string"?!!a.proxy_id:!1,t.retrievedProxyIdSuffix=Xt(a.proxy_id),t.retrievedProxyIdMatchesRequested=n?a.proxy_id===n:!a.proxy_id,t.timeoutSeconds=typeof a.timeout_seconds=="number"?a.timeout_seconds:t.timeoutSeconds,t.stealth=typeof a.stealth=="boolean"?a.stealth:t.stealth,t.profilePresent=!!a.profile,t.poolPresent=!!a.pool}catch(a){t.retrieveError=Ct(a)}}async captureBrowserNetworkLocation(){let t=(a,s="ipapi.co")=>({source:s,ip:null,city:null,region:null,country:null,org:null,timezone:null,error:a});if(!this.context)return t("browser context is not available");let n=null;try{n=await this.context.newPage();let a=await this.loadJsonInDebugPage(n,"https://ipwho.is/");if(a){let S=typeof a.connection=="object"&&a.connection!==null?a.connection:{};return{source:"ipwho.is",ip:typeof a.ip=="string"?a.ip:null,city:typeof a.city=="string"?a.city:null,region:typeof a.region=="string"?a.region:null,country:typeof a.country=="string"?a.country:null,org:typeof S.org=="string"?S.org:null,timezone:typeof a.timezone=="object"&&a.timezone!==null&&typeof a.timezone.id=="string"?a.timezone.id:null,error:null}}let s=await this.loadJsonInDebugPage(n,"https://api64.ipify.org?format=json");if(s)return{source:"api64.ipify.org",ip:typeof s.ip=="string"?s.ip:null,city:null,region:null,country:null,org:null,timezone:null,error:null};await ht(n.goto("https://ipapi.co/json/",{waitUntil:"domcontentloaded",timeout:7e3}),8e3,"browser network location navigation");let i=await n.locator("body").innerText({timeout:2e3}),d=JSON.parse(i);return{source:"ipapi.co",ip:typeof d.ip=="string"?d.ip:null,city:typeof d.city=="string"?d.city:null,region:typeof d.region=="string"?d.region:null,country:typeof d.country_name=="string"?d.country_name:typeof d.country=="string"?d.country:null,org:typeof d.org=="string"?d.org:null,timezone:typeof d.timezone=="string"?d.timezone:null,error:null}}catch(a){return t(Ct(a))}finally{await n?.close().catch(()=>{})}}async loadJsonInDebugPage(t,n){try{await ht(t.goto(n,{waitUntil:"domcontentloaded",timeout:7e3}),8e3,`browser network location navigation ${n}`);let a=await t.locator("body").innerText({timeout:2e3});return JSON.parse(a)}catch{return null}}async installEsbuildHelperShims(t){await t.addInitScript(()=>{let n=globalThis;typeof n.__name!="function"&&(n.__name=a=>a),typeof n.__publicField!="function"&&(n.__publicField=(a,s,i)=>(a[s]=i,i))})}async withTemporaryPage(t,n){if(!this.context)throw new Error("Browser context is not available");return At(this.context,async()=>{},t,n)}async navigateToSERP(t,n,a,s,i){let d=new URLSearchParams({q:t,gl:a,hl:s,pws:"0"});i?.tbs&&d.set("tbs",i.tbs),n&&d.set("uule",n);let S="https://www.google.com/search?"+d.toString(),U=Ge(S),h=i?.debug?{requestedUrl:S,finalUrl:null,title:null,bodySnippet:null,hasPaa:null,captchaDetected:null,googleSorryUrl:null,redirected:null}:null;h&&(this.debugSnapshot.serpNavigation=h);try{await this.page.goto(U,{waitUntil:"domcontentloaded",timeout:Zt(i?.deadlineMs,i?.purpose==="serp"?8e3:45e3)})}catch(o){await this.updateSerpNavigationDebug(h,S,{hasPaa:null,captchaDetected:null});let r=await this.captureDiagnostics(S);throw new bt(`page.goto failed: ${o.message} | ${r}`)}if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(h,S,{hasPaa:!1,captchaDetected:!0}),new E(this.captchaMessage());if(i?.purpose==="serp"){await this.page.waitForSelector(Fn,{timeout:Zt(i.deadlineMs,1500)}).catch(()=>null);let o=await this.page.locator(H.item).count().catch(()=>0)>0;return await this.updateSerpNavigationDebug(h,S,{hasPaa:o,captchaDetected:!1}),{hasPaa:o}}if(await this.page.waitForSelector(H.item,{timeout:Zt(i?.deadlineMs,4e3)}).catch(()=>null))return await this.updateSerpNavigationDebug(h,S,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(h,S,{hasPaa:!1,captchaDetected:!0}),new E(this.captchaMessage());for(let o=1;o<=6;o++)if(await this.page.evaluate(u=>{window.scrollTo(0,document.body.scrollHeight*u)},o/6),await this.page.waitForTimeout(600),await this.page.locator(H.item).count()>0)return await this.updateSerpNavigationDebug(h,S,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};return await this.updateSerpNavigationDebug(h,S,{hasPaa:!1,captchaDetected:!1}),{hasPaa:!1}}async isSerpChallengeVisible(){if(!this.page)return!1;if(await this.page.locator(H.captchaMarker).count().catch(()=>0)>0)return!0;let n=this.page.url();if(/google\.[^/]+\/sorry\//i.test(n))return!0;let a=await this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,1e3)).catch(()=>"");return/recaptcha|unusual traffic|are you a robot|about this page|detected unusual traffic/i.test(a)}async updateSerpNavigationDebug(t,n,a){if(!(!t||!this.page))try{let s=this.page.url(),i=await this.page.title().catch(()=>""),d=await this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,500)).catch(()=>""),S=/recaptcha|unusual traffic|are you a robot/i.test(d);t.finalUrl=s,t.title=i,t.bodySnippet=d,t.hasPaa=a.hasPaa,t.captchaDetected=a.captchaDetected??S,t.googleSorryUrl=/google\.[^/]+\/sorry\//i.test(s),t.redirected=s!==n}catch(s){t.bodySnippet=`debug capture failed: ${Ct(s)}`}}async captureDiagnostics(t){try{let n=this.page.url(),a=await this.page.title().catch(()=>""),s=await this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,400)).catch(()=>""),i=/consent\.google\./.test(n)||/before you continue/i.test(s),d=/recaptcha|unusual traffic|are you a robot/i.test(s),S=[i?"CONSENT_WALL":"",d?"BOT_CHALLENGE":"",n!==t?"REDIRECTED":""].filter(Boolean).join(",");return`intended=${t} | final=${n} | title="${a}" | flags=[${S}] | body="${s}"`}catch(n){return`diagnostics-failed: ${n.message}`}}captchaMessage(){return this.\u006b\u0065\u0072\u006e\u0065\u006cClient?"Google returned a CAPTCHA on this session \u2014 retrying with a fresh session.":Ne}async navigateTo(t){let n=process.env.ADS_ARRIVAL_REDIRECT_BASE?.trim(),a=n?Ge(t,n):t;try{if(await this.page.goto(a,{waitUntil:"domcontentloaded",timeout:45e3}),/google\.[^/]+\/search\?/i.test(t)&&await this.isSerpChallengeVisible())throw new E(this.captchaMessage())}catch(s){if(s instanceof E)throw s;let i=await this.captureDiagnostics(t);throw new bt(`page.goto failed: ${s.message} | ${i}`)}}async navigateToChannel(t){let n=Yn(t);try{await this.page.goto(n,{waitUntil:"networkidle",timeout:3e4})}catch(a){let s=await this.captureDiagnostics(n);throw new bt(`navigateToChannel failed: ${a.message} | ${s}`)}}async evaluate(t,n){return this.page.evaluate(t,n)}getPage(){return this.page}get\u004b\u0065\u0072\u006e\u0065\u006cSessionId(){return this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId}getProviderSessionMetadata(){return{provider:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId?"\u006b\u0065\u0072\u006e\u0065\u006c":"local",providerSessionId:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,disconnectObservation:null}}getDebugSnapshot(){return this.debugSnapshot}async close(){if(this.browser){let t=this.browser,n=this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,a=this.\u006b\u0065\u0072\u006e\u0065\u006cClient,s=this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs,i=this.\u006b\u0065\u0072\u006e\u0065\u006cStealth,d=this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed,S=this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource,U=this.\u006b\u0065\u0072\u006e\u0065\u006cProxyType,h=this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent,l=this.getProviderSessionMetadata();if(this.browser=null,this.context=null,this.page=null,this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId=null,this.\u006b\u0065\u0072\u006e\u0065\u006cClient=null,this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=null,this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource=null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyType=null,a&&n&&s!=null&&We({\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,source:"browser_driver",stealth:i,headlessSent:h,proxyUsed:d,proxySource:S,proxyType:U,openedAtMs:s,closedAtMs:Date.now()}),a&&n){console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_started",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n}));let o=ht(a.browsers.deleteByID(n),Hn,`\u004b\u0065\u0072\u006e\u0065\u006c session ${n} delete`),r=ht(t.close(),Bn,`\u004b\u0065\u0072\u006e\u0065\u006c browser ${n} close`),[u,c]=await Promise.allSettled([o,r]),y={\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!0,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:u.status==="fulfilled",\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:u.status==="rejected"?u.reason instanceof Error?u.reason.message:String(u.reason):null,browserCloseSucceeded:c.status==="fulfilled",browserCloseError:c.status==="rejected"?c.reason instanceof Error?c.reason.message:String(c.reason):null,provider:l.provider,providerSessionId:l.providerSessionId,providerDisconnectObserved:!1,providerDisconnectMessage:null};return u.status==="rejected"?(console.warn(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_failed",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n,message:y.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError})),console.warn(`\u004b\u0065\u0072\u006e\u0065\u006c session cleanup failed for ${n}:`,u.reason)):console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_succeeded",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n})),c.status==="rejected"&&(console.warn(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_close_failed",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n,message:y.browserCloseError})),console.warn(`\u004b\u0065\u0072\u006e\u0065\u006c browser close failed for ${n}:`,c.reason)),y}return await t.close(),{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:!0,browserCloseError:null,provider:l.provider,providerSessionId:l.providerSessionId,providerDisconnectObserved:!1,providerDisconnectMessage:null}}else if(this.context){let t=this.context;return this.context=null,this.page=null,await t.close(),{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:!0,browserCloseError:null,provider:"local",providerSessionId:null,providerDisconnectObserved:!1,providerDisconnectMessage:null}}return{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:null,browserCloseError:null,provider:"local",providerSessionId:null,providerDisconnectObserved:!1,providerDisconnectMessage:null}}};import{chromium as Jn}from"playwright";function En(e,t){if(typeof e!="string")return null;let n=e.replace(/[\u0000-\u001f\u007f]+/g," ").replace(/\s+/g," ").trim();return n?n.slice(0,t):null}function De(e){let t=En(e,320);return t?t.replace(/\b(?:wss?|https?):\/\/\S+/gi,"[redacted endpoint]").replace(/\b(?:authorization|proxy-authorization):\s*\S+/gi,"$1: [redacted]").replace(/\bBearer\s+\S+/gi,"Bearer [redacted]").slice(0,320):null}function Ve(e){return De(e)}function Ye(e){if(typeof e!="string"||e.length===0||e.length>512||e.trim()!==e||/[\s\u0000-\u001f\u007f]/.test(e)||/:\/\//.test(e))throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 did not return a valid browser session ID");return e}function ee(e,t,n=new Date().toISOString()){let a=De(t);return{source:e,message:a??e.replaceAll("_"," "),observedAt:n}}function Kn(e){return{provider:e.provider,providerDisconnectObserved:e.disconnectObservation!==null,providerDisconnectMessage:e.disconnectObservation?.message??null}}function Ee(e){return{...Kn(e),providerSessionId:e.providerSessionId}}var _n=new Set(["image","media","font","stylesheet","ping"]),zn=["doubleclick.net","googleadservices.com","googlesyndication.com","google-analytics.com"],qn='#search, #rso, a[href] h3, [data-snhf], [role="main"]',$n=3e4,Ke=1500;function Ht(e,t){return e?Math.max(1,Math.min(t,e-Date.now())):t}function Je(){return process.env.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_BROWSER_WSS?.trim()||null}function Rt(){return process.env.SERP_BROWSER_PROVIDER?.trim().toLowerCase()==="\u006b\u0065\u0072\u006e\u0065\u006c"?!1:!!Je()}async function ne(e,t=!1){let n=e.request();try{let a=await n.allHeaders(),s=await fetch(n.url(),{method:n.method(),headers:{accept:a.accept??"*/*","accept-language":a["accept-language"]??"en-US,en;q=0.9","user-agent":a["user-agent"]??"Mozilla/5.0",...t?{cookie:a.cookie??"",referer:a.referer??"https://www.google.com/",...a["x-client-data"]?{"x-client-data":a["x-client-data"]}:{}}:{}},body:n.method()==="GET"||n.method()==="HEAD"?void 0:n.postData()});if(!s.ok)return!1;let i=Buffer.from(await s.arrayBuffer());return await e.fulfill({status:s.status,contentType:s.headers.get("content-type")??"application/octet-stream",headers:{"cache-control":"public, max-age=3600"},body:i}),!0}catch{return!1}}var Ft=class{browser=null;context=null;page=null;cdpSession=null;providerSessionId=null;disconnectObservation=null;closing=!1;observeDisconnect(t,n){this.closing||this.disconnectObservation||(this.disconnectObservation=ee(t,n))}async launch(t){if(this.page)return;this.closing=!1,this.providerSessionId=null,this.disconnectObservation=null;let n=Je();if(!n)throw new Error("SERP browser service is not configured");this.browser=await Jn.connectOverCDP(n,{timeout:Ht(t.operationDeadlineMs,$n)}),this.context=this.browser.contexts()[0]??await this.browser.newContext(),await this.context.addInitScript(()=>{let i=globalThis;typeof i.__name!="function"&&(i.__name=d=>d),typeof i.__publicField!="function"&&(i.__publicField=(d,S,U)=>(d[S]=U,U))}),this.page=this.context.pages()[0]??await this.context.newPage(),this.browser.on("disconnected",()=>this.observeDisconnect("browser_disconnected")),this.context.on("close",()=>this.observeDisconnect("context_closed")),this.page.on("close",()=>this.observeDisconnect("page_closed")),this.page.on("crash",()=>this.observeDisconnect("page_crashed")),this.cdpSession=await this.context.newCDPSession(this.page);let s=await this.cdpSession.send("Browser.getSessionId");this.providerSessionId=Ye(s?.sessionId),await this.setupPage(this.page)}async setupPage(t){await t.route("**/*",async n=>{let a=n.request(),s=a.resourceType(),i;try{i=new URL(a.url())}catch{await n.continue();return}let d=i.hostname.toLowerCase();if(!(i.pathname==="/sgasync"&&await ne(n,!0))&&!(i.pathname.includes("/shared_dict/")&&await ne(n))&&!(s==="script"&&(d==="www.google.com"||d==="www.gstatic.com")&&await ne(n))){if(_n.has(s)){await n.abort("blockedbyclient");return}if(zn.some(S=>d===S||d.endsWith(`.${S}`))){await n.abort("blockedbyclient");return}await n.continue()}})}async withTemporaryPage(t,n){if(!this.context||this.closing)throw new Error("Browser context is not available");return At(this.context,a=>this.setupPage(a),t,n)}async navigateToSERP(t,n,a,s,i){if(!this.page)throw new Error("Browser page is not available");let d=new URLSearchParams({q:t,gl:a,hl:s,pws:"0"});return i?.tbs&&d.set("tbs",i.tbs),n&&d.set("uule",n),await this.page.goto(`https://www.google.com/search?${d}`,{waitUntil:"domcontentloaded",timeout:Ht(i?.deadlineMs,i?.purpose==="serp"?8e3:45e3)}),i?.purpose==="serp"?(await this.page.waitForSelector(qn,{timeout:Ht(i.deadlineMs,1500)}).catch(()=>null),{hasPaa:await this.page.locator(H.item).count().catch(()=>0)>0}):{hasPaa:!!await this.page.waitForSelector(H.item,{timeout:Ht(i?.deadlineMs,8e3)}).catch(()=>null)}}async navigateTo(t){if(!this.page)throw new Error("Browser page is not available");await this.page.goto(t,{waitUntil:"load",timeout:45e3})}async navigateToChannel(){throw new Error("YouTube navigation is not supported by the SERP browser driver")}async evaluate(t,n){if(!this.page)throw new Error("Browser page is not available");return this.page.evaluate(t,n)}getPage(){if(!this.page)throw new Error("Browser page is not available");return this.page}get\u004b\u0065\u0072\u006e\u0065\u006cSessionId(){return null}getProviderSessionMetadata(){return{provider:"\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api",providerSessionId:this.providerSessionId,disconnectObservation:this.disconnectObservation}}getDebugSnapshot(){return{\u006b\u0065\u0072\u006e\u0065\u006c:null,context:null,networkLocation:null,serpNavigation:null}}async close(){this.closing=!0;let t=null,n;try{let s=this.browser?.close();s&&await Promise.race([s,new Promise((i,d)=>{n=setTimeout(()=>d(new Error(`Browser close acknowledgement exceeded ${Ke}ms`)),Ke)})])}catch(s){t=Ve(s instanceof Error?s.message:String(s))??"\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 browser close failed",this.disconnectObservation??=ee("browser_close_error",t)}finally{n&&clearTimeout(n)}let a=Ee(this.getProviderSessionMetadata());return this.browser=null,this.context=null,this.page=null,this.cdpSession=null,{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:t===null,browserCloseError:t,...a}}};function _e(e,t){let n=!!(e?.serpIdentity||e?.\u006b\u0065\u0072\u006e\u0065\u006cProfileName);return!t?.force\u004b\u0065\u0072\u006e\u0065\u006c&&(t?.forceManaged===!0||Rt()&&!n)?new Ft:new Bt}var ot={austin:"Austin,Texas,United States","new york":"New York,New York,United States","new york city":"New York,New York,United States",nyc:"New York,New York,United States","los angeles":"Los Angeles,California,United States",la:"Los Angeles,California,United States",chicago:"Chicago,Illinois,United States",houston:"Houston,Texas,United States",phoenix:"Phoenix,Arizona,United States",philadelphia:"Philadelphia,Pennsylvania,United States",philly:"Philadelphia,Pennsylvania,United States","san antonio":"San Antonio,Texas,United States",dallas:"Dallas,Texas,United States",miami:"Miami,Florida,United States",seattle:"Seattle,Washington,United States",denver:"Denver,Colorado,United States",loveland:"Loveland,Colorado,United States","loveland co":"Loveland,Colorado,United States","fort collins":"Fort Collins,Colorado,United States",boulder:"Boulder,Colorado,United States","colorado springs":"Colorado Springs,Colorado,United States",boston:"Boston,Massachusetts,United States",atlanta:"Atlanta,Georgia,United States","san francisco":"San Francisco,California,United States",sf:"San Francisco,California,United States",portland:"Portland,Oregon,United States","las vegas":"Las Vegas,Nevada,United States",minneapolis:"Minneapolis,Minnesota,United States",detroit:"Detroit,Michigan,United States",nashville:"Nashville,Tennessee,United States",charlotte:"Charlotte,North Carolina,United States",orlando:"Orlando,Florida,United States","san diego":"San Diego,California,United States",baltimore:"Baltimore,Maryland,United States",sacramento:"Sacramento,California,United States",columbus:"Columbus,Ohio,United States",indianapolis:"Indianapolis,Indiana,United States","san jose":"San Jose,California,United States","fort worth":"Fort Worth,Texas,United States",jacksonville:"Jacksonville,Florida,United States",memphis:"Memphis,Tennessee,United States",louisville:"Louisville,Kentucky,United States",raleigh:"Raleigh,North Carolina,United States",richmond:"Richmond,Virginia,United States","salt lake city":"Salt Lake City,Utah,United States",toronto:"Toronto,Ontario,Canada",vancouver:"Vancouver,British Columbia,Canada",montreal:"Montreal,Quebec,Canada",calgary:"Calgary,Alberta,Canada",ottawa:"Ottawa,Ontario,Canada",london:"London,England,United Kingdom",manchester:"Manchester,England,United Kingdom",birmingham:"Birmingham,England,United Kingdom",edinburgh:"Edinburgh,Scotland,United Kingdom",glasgow:"Glasgow,Scotland,United Kingdom",leeds:"Leeds,England,United Kingdom",sydney:"Sydney,New South Wales,Australia",melbourne:"Melbourne,Victoria,Australia",brisbane:"Brisbane,Queensland,Australia",perth:"Perth,Western Australia,Australia",adelaide:"Adelaide,South Australia,Australia",dublin:"Dublin,Leinster,Ireland"};var ze=`3, Nanjemoy,Maryland,United States
2
2
  Aaronsburg,Pennsylvania,United States
3
3
  Abbeville,Alabama,United States
4
4
  Abbeville,Georgia,United States
@@ -21690,21 +21690,21 @@ Zortman,Montana,United States
21690
21690
  Zuehl,Texas,United States
21691
21691
  Zumbrota,Minnesota,United States
21692
21692
  Zuni,New Mexico,United States
21693
- Zwolle,Louisiana,United States`,ze={ad:"Andorra",ae:"United Arab Emirates",af:"Afghanistan",ag:"Antigua and Barbuda",al:"Albania",am:"Armenia",ao:"Angola",aq:"Antarctica",ar:"Argentina",as:"American Samoa",at:"Austria",au:"Australia",az:"Azerbaijan",ba:"Bosnia and Herzegovina",bb:"Barbados",bd:"Bangladesh",be:"Belgium",bf:"Burkina Faso",bg:"Bulgaria",bh:"Bahrain",bi:"Burundi",bj:"Benin",bl:"Saint Barthelemy",bn:"Brunei",bo:"Bolivia",bq:"Caribbean Netherlands",br:"Brazil",bs:"The Bahamas",bt:"Bhutan",bw:"Botswana",by:"Belarus",bz:"Belize",ca:"Canada",cc:"Cocos (Keeling) Islands",cd:"Democratic Republic of the Congo",cf:"Central African Republic",cg:"Republic of the Congo",ch:"Switzerland",ci:"Cote d'Ivoire",ck:"Cook Islands",cl:"Chile",cm:"Cameroon",cn:"China",co:"Colombia",cr:"Costa Rica",cv:"Cabo Verde",cw:"Curacao",cx:"Christmas Island",cy:"Cyprus",cz:"Czechia",de:"Germany",dj:"Djibouti",dk:"Denmark",dm:"Dominica",do:"Dominican Republic",dz:"Algeria",ec:"Ecuador",ee:"Estonia",eg:"Egypt",er:"Eritrea",es:"Spain",et:"Ethiopia",fi:"Finland",fj:"Fiji",fm:"Micronesia",fr:"France",ga:"Gabon",gb:"United Kingdom",gd:"Grenada",ge:"Georgia",gg:"Guernsey",gh:"Ghana",gm:"The Gambia",gn:"Guinea",gq:"Equatorial Guinea",gr:"Greece",gs:"South Georgia and the South Sandwich Islands",gt:"Guatemala",gu:"Guam",gw:"Guinea-Bissau",gy:"Guyana",hm:"Heard Island and McDonald Islands",hn:"Honduras",hr:"Croatia",ht:"Haiti",hu:"Hungary",id:"Indonesia",ie:"Ireland",il:"Israel",im:"Isle of Man",in:"India",iq:"Iraq",is:"Iceland",it:"Italy",je:"Jersey",jm:"Jamaica",jo:"Jordan",jp:"Japan",ke:"Kenya",kg:"Kyrgyzstan",kh:"Cambodia",ki:"Kiribati",km:"Comoros",kn:"Saint Kitts and Nevis",kr:"South Korea",kw:"Kuwait",kz:"Kazakhstan",la:"Laos",lb:"Lebanon",lc:"Saint Lucia",li:"Liechtenstein",lk:"Sri Lanka",lr:"Liberia",ls:"Lesotho",lt:"Lithuania",lu:"Luxembourg",lv:"Latvia",ly:"Libya",ma:"Morocco",mc:"Monaco",md:"Moldova",me:"Montenegro",mf:"Saint Martin",mg:"Madagascar",mh:"Marshall Islands",mk:"North Macedonia",ml:"Mali",mm:"Myanmar (Burma)",mn:"Mongolia",mp:"Northern Mariana Islands",mr:"Mauritania",mt:"Malta",mu:"Mauritius",mv:"Maldives",mw:"Malawi",mx:"Mexico",my:"Malaysia",mz:"Mozambique",na:"Namibia",nc:"New Caledonia",ne:"Niger",nf:"Norfolk Island",ng:"Nigeria",ni:"Nicaragua",nl:"Netherlands",no:"Norway",np:"Nepal",nr:"Nauru",nu:"Niue",nz:"New Zealand",om:"Oman",pa:"Panama",pe:"Peru",pf:"French Polynesia",pg:"Papua New Guinea",ph:"Philippines",pk:"Pakistan",pl:"Poland",pm:"Saint Pierre and Miquelon",pn:"Pitcairn Islands",pt:"Portugal",pw:"Palau",py:"Paraguay",qa:"Qatar",ro:"Romania",rs:"Serbia",ru:"Russia",rw:"Rwanda",sa:"Saudi Arabia",sb:"Solomon Islands",sc:"Seychelles",sd:"Sudan",se:"Sweden",sg:"Singapore",sh:"Saint Helena, Ascension and Tristan da Cunha",si:"Slovenia",sk:"Slovakia",sl:"Sierra Leone",sm:"San Marino",sn:"Senegal",so:"Somalia",sr:"Suriname",ss:"South Sudan",st:"Sao Tome and Principe",sv:"El Salvador",sx:"Sint Maarten",sy:"Syria",sz:"Eswatini",td:"Chad",tf:"French Southern and Antarctic Lands",tg:"Togo",th:"Thailand",tj:"Tajikistan",tk:"Tokelau",tl:"Timor-Leste",tm:"Turkmenistan",tn:"Tunisia",to:"Tonga",tr:"Turkiye",tt:"Trinidad and Tobago",tv:"Tuvalu",tz:"Tanzania",ua:"Ukraine",ug:"Uganda",um:"United States Minor Outlying Islands",us:"United States",uy:"Uruguay",uz:"Uzbekistan",va:"Vatican City",vc:"Saint Vincent and the Grenadines",ve:"Venezuela",vn:"Vietnam",vu:"Vanuatu",wf:"Wallis and Futuna",ws:"Samoa",ye:"Yemen",za:"South Africa",zm:"Zambia",zw:"Zimbabwe"};var ee={AL:"Alabama",AK:"Alaska",AZ:"Arizona",AR:"Arkansas",CA:"California",CO:"Colorado",CT:"Connecticut",DE:"Delaware",DC:"District of Columbia",FL:"Florida",GA:"Georgia",HI:"Hawaii",ID:"Idaho",IL:"Illinois",IN:"Indiana",IA:"Iowa",KS:"Kansas",KY:"Kentucky",LA:"Louisiana",ME:"Maine",MD:"Maryland",MA:"Massachusetts",MI:"Michigan",MN:"Minnesota",MS:"Mississippi",MO:"Missouri",MT:"Montana",NE:"Nebraska",NV:"Nevada",NH:"New Hampshire",NJ:"New Jersey",NM:"New Mexico",NY:"New York",NC:"North Carolina",ND:"North Dakota",OH:"Ohio",OK:"Oklahoma",OR:"Oregon",PA:"Pennsylvania",PR:"Puerto Rico",RI:"Rhode Island",SC:"South Carolina",SD:"South Dakota",TN:"Tennessee",TX:"Texas",UT:"Utah",VT:"Vermont",VA:"Virginia",WA:"Washington",WV:"West Virginia",WI:"Wisconsin",WY:"Wyoming"};var ne=null,$e=null;function $n(){if(ne)return;let e=new Map,t=new Map;for(let n of _e.split(`
21694
- `)){let a=n.trim();if(!a)continue;let s=a.toLowerCase();e.has(s)||e.set(s,a);let i=s.split(",",1)[0],d=t.get(i);d?d.push(a):t.set(i,[a])}for(let n of Object.values(ze)){let a=String(n).toLowerCase();e.has(a)||e.set(a,String(n))}ne=e,$e=t}function jn(e){let t=[],n=e;do{let a=n&127;n>>>=7,n>0&&(a|=128),t.push(a)}while(n>0);return t}function je(e){let t=Buffer.from(e,"utf8");return`w+${Buffer.concat([Buffer.from([8,2,16,32,34]),Buffer.from(jn(t.length)),t]).toString("base64")}`}function qe(){return{canonical:null,matched:!1,source:"unresolved",ambiguousCandidates:0}}function X(e,t){return{canonical:e,matched:!0,source:t,ambiguousCandidates:0}}function ae(e){let t=e.toLowerCase().trim();if(!t)return qe();if(it[t])return X(it[t],"alias");$n();let n=ne,a=$e,s=n.get(t);if(s)return X(s,"exact");let i=n.get(`${t},united states`);if(i)return X(i,"state-or-country");let d=t.split(",");if(d.length>=2){let o=d[0].trim(),r=d.slice(1).join(",").trim(),u=ee[r.toUpperCase()]??r,c=n.get(`${o},${u.toLowerCase()},united states`);if(c)return X(c,"city-state")}let l=t.match(/^(.*?)[\s,]+([a-z]{2})$/);if(l){let o=ee[l[2].toUpperCase()];if(o){let r=n.get(`${l[1].trim()},${o.toLowerCase()},united states`);if(r)return X(r,"city-state")}}let h=a.get(t);if(h?.length===1)return X(h[0],"city-unique");if(h&&h.length>1)return{canonical:null,matched:!1,source:"unresolved",ambiguousCandidates:h.length};let U=d[0].trim();if(U!==t&&it[U])return X(it[U],"alias-partial");let S=t.replace(/\s+[a-z]{2}$/,"").trim();return S!==t&&it[S]?X(it[S],"alias-partial"):qe()}function Qe(e){return ae(e).canonical??e}var ie={alabama:"AL",alaska:"AK",arizona:"AZ",arkansas:"AR",california:"CA",colorado:"CO",connecticut:"CT",delaware:"DE",florida:"FL",georgia:"GA",hawaii:"HI",idaho:"ID",illinois:"IL",indiana:"IN",iowa:"IA",kansas:"KS",kentucky:"KY",louisiana:"LA",maine:"ME",maryland:"MD",massachusetts:"MA",michigan:"MI",minnesota:"MN",mississippi:"MS",missouri:"MO",montana:"MT",nebraska:"NE",nevada:"NV","new hampshire":"NH","new jersey":"NJ","new mexico":"NM","new york":"NY","north carolina":"NC","north dakota":"ND",ohio:"OH",oklahoma:"OK",oregon:"OR",pennsylvania:"PA","rhode island":"RI","south carolina":"SC","south dakota":"SD",tennessee:"TN",texas:"TX",utah:"UT",vermont:"VT",virginia:"VA",washington:"WA","west virginia":"WV",wisconsin:"WI",wyoming:"WY","district of columbia":"DC"},Qn=[...Object.keys(ie).map(e=>e.replace(/\s+/g,"\\s+")),...Object.values(ie)].join("|"),Zn=new RegExp(`\\b([A-Z][A-Za-z]+(?:[\\s.-][A-Z][A-Za-z]+){0,4}),?\\s+(${Qn})\\b`,"gi");function Xe(e){if(!e)return null;let t=e.trim();return/^[A-Z]{2}$/i.test(t)?t.toUpperCase():ie[t.toLowerCase()]??null}function tn(e){return e.replace(/\s+/g," ").trim().replace(/^.*\b(?:in|near|around|serving)\s+/i,"").toLowerCase().replace(/\b[a-z]/g,n=>n.toUpperCase())}function Xn(e){if(!e)return null;let[t="",n=""]=e.split(",").map(a=>a.trim());return{city:tn(t),regionCode:Xe(n),canonicalLocation:e}}function ta(e,t,n,a){let s=tn(t),i=Xe(n);if(!s||!i)return;let d=`${s.toLowerCase()}|${i}`,l=e.get(d);if(l){l.count++,l.examples.length<3&&!l.examples.includes(a)&&l.examples.push(a);return}e.set(d,{city:s,regionCode:i,count:1,examples:[a]})}function ea(e){try{return decodeURIComponent(e)}catch{}try{return decodeURIComponent(e.replace(/%(?![0-9a-fA-F]{2})/g,"%25"))}catch{return e}}function Ze(e,t){let n=ea(t).replace(/[+/|_-]+/g," ");for(let a of n.matchAll(Zn))ta(e,a[1]??"",a[2]??"",n.slice(0,180))}function Mt(e,t,n){let a=Xn(e),s=new Map;for(let l of t)Ze(s,[l.title,l.snippet??"",l.cite??"",l.url].join(" "));for(let l of n)Ze(s,[l.name,...l.metadata,l.websiteUrl??"",l.directionsUrl??""].join(" "));let i=Array.from(s.values()).sort((l,h)=>h.count-l.count||l.city.localeCompare(h.city)).slice(0,8);return a?i.length===0?{status:"unknown",expected:a,candidates:[]}:{status:i.some(l=>l.city.toLowerCase()===a.city.toLowerCase()&&(a.regionCode==null||l.regionCode===a.regionCode))?"matched":"mismatch",expected:a,candidates:i}:{status:"not_requested",expected:null,candidates:i}}var na=[/An AI Overview is not available for this search/gi,/Can't generate an AI overview right now\.?\s*Try again later\.?/gi,/\bAI Overview\b/gi,/\bView all\b/gi],aa=[/\bRelated Links\b/i,/\bAsk anything in\s*AI Mode\b/i,/\bAI can make mistakes\b/i,/\bThis is for informational purposes only\b/i,/\bShow more\b/i,/\b\d+\s+sites\b/i,/\b\d{1,2}\s*[msh]\s*[A-Z][A-Za-z]/,/\b(?:YouTube|Reddit|Facebook|Instagram|TikTok)·/];function Gt(e){return e.replace(/\u00a0/g," ").replace(/([.!?])([A-Z])/g,"$1 $2").replace(/([:;])([A-Z])/g,"$1 $2").replace(/([a-z])([A-Z][a-z])/g,"$1 $2").replace(/(\d)([A-Z][a-z])/g,"$1 $2").replace(/([a-z])(\d)/g,"$1 $2").replace(/\s+/g," ").trim()}function ia(e){let t=-1;for(let n of aa){let a=n.exec(e);n.lastIndex=0,a&&(t===-1||a.index<t)&&(t=a.index)}return t===-1?e:e.slice(0,t)}function sa(e,t){let n=t?.trim();if(!n||n.length<8)return e;let a=e.toLowerCase().indexOf(n.toLowerCase());return a>40?e.slice(0,a):e}function oa(e){let t=e.match(/[•·]\s*(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\.?\s+\d{1,2},\s+\d{4}/i);if(t?.index&&t.index>40)return t.index;let n=Math.max(0,e.length-260),a=e.slice(n),s=[...a.matchAll(/[.!?]\s*(?=[A-Z][A-Za-z0-9"'$])/g)];for(let d of s){let l=a.slice(d.index+1).trim(),h=l.slice(0,160),U=/^(?:Best|Top|What|How|Why|When|Where|Which|Can|Should|Is|Are|Do|Does)\b/i.test(l);if(l.length>20&&U&&/(?:\s[-|]\s|Heating|Cooling|Company|Services|Blog|Guide|Review)/i.test(h))return n+d.index+1}let i=s.at(-1);return i?.index!==void 0?n+i.index+1:e.length}function da(e){let t=e.match(/https?:\/\/\S+/i);if(!t?.index)return e;let n=e.slice(0,t.index);return n.slice(0,oa(n))}function ra(e){if(e.length<=1200)return e;let t=e.slice(0,1200),n=Math.max(t.lastIndexOf("."),t.lastIndexOf("!"),t.lastIndexOf("?"));return(n>240?t.slice(0,n+1):t).trim()}function en(e,t,n){if(!e)return;let a=Gt(e),s=t?Gt(t):"";if(s&&a.toLowerCase().startsWith(s.toLowerCase())&&(a=a.slice(s.length).trim()),!/^An error has occurred\.?\s*Please try again later\.?/i.test(a)){for(let i of na)a=a.replace(i," ");if(a=a.replace(/\b[A-Z][A-Za-z&'\u2019 -]{2,60}\+\d+\b/g," ").replace(/\b(?:[a-z0-9-]+\.)+[a-z]{2,}\+\d+\b/gi," "),a=Gt(a),a=ia(a),a=sa(a,n),a=da(a),a=Gt(a),a=a.replace(/\s+(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\.?\s+\d{1,2},\s+\d{4}$/i,"").trim(),a=ra(a),!!a&&!/^An error has occurred\.?\s*Please try again later\.?$/i.test(a))return a}}async function nn(e){let t=e??{aio:{root:"[data-lhcontainer][data-streaming-container][eid]",legacyRoot:'[data-hveid="CBMQAA"]',wrapper:".Fgyi2e",controller:'[jscontroller="AkrxPe"]',contentSubtree:'[data-subtree="mfc"]',heading:".Fzsovc.cwYVJe.RJPOee",header:".heWuVc",showMoreButton:'[aria-label="Show more AI Overview"]',sourcesPanel:".OZ9ddf.WAUd4",disclaimer:".DuQANe.MSJHRb"},aim:{root:'[data-hveid="CAUQAA"]',wrapper:".Fgyi2e"},expandWaitMs:1500},n=window.google?.sn??"unknown",a=n==="aim"?"aim":n==="web"?"web":"unknown";function s(y){return y?(y.innerText??y.textContent??"").trim():""}function i(y){if(!y)return!1;let k=y.replace(/\s+/g," ").trim();return k.length>=16&&k.split(" ").filter(Boolean).length>=2}function d(y){let k=y.querySelector(t.aio.heading);if(s(k)==="AI Overview")return!0;let w=y.querySelector(t.aio.header);return!!s(w).split(/\n|\s{2,}/).some(p=>p.trim()==="AI Overview")}function l(){let k=Array.from(document.querySelectorAll(t.aio.root)).find(d);if(k)return k;if(t.aio.legacyRoot){let p=document.querySelector(t.aio.legacyRoot);if(p&&d(p))return p}let w=document.querySelectorAll(`${t.aio.heading}, h1, h2, h3, [role="heading"]`);for(let p of w){if(s(p)!=="AI Overview")continue;let m=p.parentElement;for(let P=0;P<8&&m;P++){if(m.matches(t.aio.root)||m.querySelector(t.aio.controller)||m.querySelector(t.aio.contentSubtree))return m;m=m.parentElement}return p.parentElement}return null}function h(y){if(!y)return null;let k=y.cloneNode(!0);k.querySelectorAll(["script","style","noscript","img","picture","video",t.aio.header,t.aio.showMoreButton,t.aio.sourcesPanel,t.aio.disclaimer,'[data-subtree="dfa"]',"[data-src-id]",'[role="dialog"]',".HWMcu",".bTFeG",".CyMdWb",".MFrAxb",".F0OfWd.hfWAgb",".x2qcTc.fZavHb",".SvjEff",".sR2MY",".lKuDef",".GSPQcc","a[href]","button",'[role="button"]'].join(",")).forEach(A=>A.remove());let w=document.createElement("div");w.style.position="fixed",w.style.left="-10000px",w.style.top="0",w.style.width=`${Math.max(320,Math.round(y.getBoundingClientRect?.().width||960))}px`,w.style.opacity="0",w.style.pointerEvents="none",w.append(k),document.body.append(w);let p=k.innerText||k.textContent||"";w.remove();let m=p.replace(/\r/g,"").replace(/[ \t]+\n/g,`
21693
+ Zwolle,Louisiana,United States`,qe={ad:"Andorra",ae:"United Arab Emirates",af:"Afghanistan",ag:"Antigua and Barbuda",al:"Albania",am:"Armenia",ao:"Angola",aq:"Antarctica",ar:"Argentina",as:"American Samoa",at:"Austria",au:"Australia",az:"Azerbaijan",ba:"Bosnia and Herzegovina",bb:"Barbados",bd:"Bangladesh",be:"Belgium",bf:"Burkina Faso",bg:"Bulgaria",bh:"Bahrain",bi:"Burundi",bj:"Benin",bl:"Saint Barthelemy",bn:"Brunei",bo:"Bolivia",bq:"Caribbean Netherlands",br:"Brazil",bs:"The Bahamas",bt:"Bhutan",bw:"Botswana",by:"Belarus",bz:"Belize",ca:"Canada",cc:"Cocos (Keeling) Islands",cd:"Democratic Republic of the Congo",cf:"Central African Republic",cg:"Republic of the Congo",ch:"Switzerland",ci:"Cote d'Ivoire",ck:"Cook Islands",cl:"Chile",cm:"Cameroon",cn:"China",co:"Colombia",cr:"Costa Rica",cv:"Cabo Verde",cw:"Curacao",cx:"Christmas Island",cy:"Cyprus",cz:"Czechia",de:"Germany",dj:"Djibouti",dk:"Denmark",dm:"Dominica",do:"Dominican Republic",dz:"Algeria",ec:"Ecuador",ee:"Estonia",eg:"Egypt",er:"Eritrea",es:"Spain",et:"Ethiopia",fi:"Finland",fj:"Fiji",fm:"Micronesia",fr:"France",ga:"Gabon",gb:"United Kingdom",gd:"Grenada",ge:"Georgia",gg:"Guernsey",gh:"Ghana",gm:"The Gambia",gn:"Guinea",gq:"Equatorial Guinea",gr:"Greece",gs:"South Georgia and the South Sandwich Islands",gt:"Guatemala",gu:"Guam",gw:"Guinea-Bissau",gy:"Guyana",hm:"Heard Island and McDonald Islands",hn:"Honduras",hr:"Croatia",ht:"Haiti",hu:"Hungary",id:"Indonesia",ie:"Ireland",il:"Israel",im:"Isle of Man",in:"India",iq:"Iraq",is:"Iceland",it:"Italy",je:"Jersey",jm:"Jamaica",jo:"Jordan",jp:"Japan",ke:"Kenya",kg:"Kyrgyzstan",kh:"Cambodia",ki:"Kiribati",km:"Comoros",kn:"Saint Kitts and Nevis",kr:"South Korea",kw:"Kuwait",kz:"Kazakhstan",la:"Laos",lb:"Lebanon",lc:"Saint Lucia",li:"Liechtenstein",lk:"Sri Lanka",lr:"Liberia",ls:"Lesotho",lt:"Lithuania",lu:"Luxembourg",lv:"Latvia",ly:"Libya",ma:"Morocco",mc:"Monaco",md:"Moldova",me:"Montenegro",mf:"Saint Martin",mg:"Madagascar",mh:"Marshall Islands",mk:"North Macedonia",ml:"Mali",mm:"Myanmar (Burma)",mn:"Mongolia",mp:"Northern Mariana Islands",mr:"Mauritania",mt:"Malta",mu:"Mauritius",mv:"Maldives",mw:"Malawi",mx:"Mexico",my:"Malaysia",mz:"Mozambique",na:"Namibia",nc:"New Caledonia",ne:"Niger",nf:"Norfolk Island",ng:"Nigeria",ni:"Nicaragua",nl:"Netherlands",no:"Norway",np:"Nepal",nr:"Nauru",nu:"Niue",nz:"New Zealand",om:"Oman",pa:"Panama",pe:"Peru",pf:"French Polynesia",pg:"Papua New Guinea",ph:"Philippines",pk:"Pakistan",pl:"Poland",pm:"Saint Pierre and Miquelon",pn:"Pitcairn Islands",pt:"Portugal",pw:"Palau",py:"Paraguay",qa:"Qatar",ro:"Romania",rs:"Serbia",ru:"Russia",rw:"Rwanda",sa:"Saudi Arabia",sb:"Solomon Islands",sc:"Seychelles",sd:"Sudan",se:"Sweden",sg:"Singapore",sh:"Saint Helena, Ascension and Tristan da Cunha",si:"Slovenia",sk:"Slovakia",sl:"Sierra Leone",sm:"San Marino",sn:"Senegal",so:"Somalia",sr:"Suriname",ss:"South Sudan",st:"Sao Tome and Principe",sv:"El Salvador",sx:"Sint Maarten",sy:"Syria",sz:"Eswatini",td:"Chad",tf:"French Southern and Antarctic Lands",tg:"Togo",th:"Thailand",tj:"Tajikistan",tk:"Tokelau",tl:"Timor-Leste",tm:"Turkmenistan",tn:"Tunisia",to:"Tonga",tr:"Turkiye",tt:"Trinidad and Tobago",tv:"Tuvalu",tz:"Tanzania",ua:"Ukraine",ug:"Uganda",um:"United States Minor Outlying Islands",us:"United States",uy:"Uruguay",uz:"Uzbekistan",va:"Vatican City",vc:"Saint Vincent and the Grenadines",ve:"Venezuela",vn:"Vietnam",vu:"Vanuatu",wf:"Wallis and Futuna",ws:"Samoa",ye:"Yemen",za:"South Africa",zm:"Zambia",zw:"Zimbabwe"};var ae={AL:"Alabama",AK:"Alaska",AZ:"Arizona",AR:"Arkansas",CA:"California",CO:"Colorado",CT:"Connecticut",DE:"Delaware",DC:"District of Columbia",FL:"Florida",GA:"Georgia",HI:"Hawaii",ID:"Idaho",IL:"Illinois",IN:"Indiana",IA:"Iowa",KS:"Kansas",KY:"Kentucky",LA:"Louisiana",ME:"Maine",MD:"Maryland",MA:"Massachusetts",MI:"Michigan",MN:"Minnesota",MS:"Mississippi",MO:"Missouri",MT:"Montana",NE:"Nebraska",NV:"Nevada",NH:"New Hampshire",NJ:"New Jersey",NM:"New Mexico",NY:"New York",NC:"North Carolina",ND:"North Dakota",OH:"Ohio",OK:"Oklahoma",OR:"Oregon",PA:"Pennsylvania",PR:"Puerto Rico",RI:"Rhode Island",SC:"South Carolina",SD:"South Dakota",TN:"Tennessee",TX:"Texas",UT:"Utah",VT:"Vermont",VA:"Virginia",WA:"Washington",WV:"West Virginia",WI:"Wisconsin",WY:"Wyoming"};var ie=null,je=null;function jn(){if(ie)return;let e=new Map,t=new Map;for(let n of ze.split(`
21694
+ `)){let a=n.trim();if(!a)continue;let s=a.toLowerCase();e.has(s)||e.set(s,a);let i=s.split(",",1)[0],d=t.get(i);d?d.push(a):t.set(i,[a])}for(let n of Object.values(qe)){let a=String(n).toLowerCase();e.has(a)||e.set(a,String(n))}ie=e,je=t}function Qn(e){let t=[],n=e;do{let a=n&127;n>>>=7,n>0&&(a|=128),t.push(a)}while(n>0);return t}function Qe(e){let t=Buffer.from(e,"utf8");return`w+${Buffer.concat([Buffer.from([8,2,16,32,34]),Buffer.from(Qn(t.length)),t]).toString("base64")}`}function $e(){return{canonical:null,matched:!1,source:"unresolved",ambiguousCandidates:0}}function tt(e,t){return{canonical:e,matched:!0,source:t,ambiguousCandidates:0}}function se(e){let t=e.toLowerCase().trim();if(!t)return $e();if(ot[t])return tt(ot[t],"alias");jn();let n=ie,a=je,s=n.get(t);if(s)return tt(s,"exact");let i=n.get(`${t},united states`);if(i)return tt(i,"state-or-country");let d=t.split(",");if(d.length>=2){let o=d[0].trim(),r=d.slice(1).join(",").trim(),u=ae[r.toUpperCase()]??r,c=n.get(`${o},${u.toLowerCase()},united states`);if(c)return tt(c,"city-state")}let S=t.match(/^(.*?)[\s,]+([a-z]{2})$/);if(S){let o=ae[S[2].toUpperCase()];if(o){let r=n.get(`${S[1].trim()},${o.toLowerCase()},united states`);if(r)return tt(r,"city-state")}}let U=a.get(t);if(U?.length===1)return tt(U[0],"city-unique");if(U&&U.length>1)return{canonical:null,matched:!1,source:"unresolved",ambiguousCandidates:U.length};let h=d[0].trim();if(h!==t&&ot[h])return tt(ot[h],"alias-partial");let l=t.replace(/\s+[a-z]{2}$/,"").trim();return l!==t&&ot[l]?tt(ot[l],"alias-partial"):$e()}function Ze(e){return se(e).canonical??e}var oe={alabama:"AL",alaska:"AK",arizona:"AZ",arkansas:"AR",california:"CA",colorado:"CO",connecticut:"CT",delaware:"DE",florida:"FL",georgia:"GA",hawaii:"HI",idaho:"ID",illinois:"IL",indiana:"IN",iowa:"IA",kansas:"KS",kentucky:"KY",louisiana:"LA",maine:"ME",maryland:"MD",massachusetts:"MA",michigan:"MI",minnesota:"MN",mississippi:"MS",missouri:"MO",montana:"MT",nebraska:"NE",nevada:"NV","new hampshire":"NH","new jersey":"NJ","new mexico":"NM","new york":"NY","north carolina":"NC","north dakota":"ND",ohio:"OH",oklahoma:"OK",oregon:"OR",pennsylvania:"PA","rhode island":"RI","south carolina":"SC","south dakota":"SD",tennessee:"TN",texas:"TX",utah:"UT",vermont:"VT",virginia:"VA",washington:"WA","west virginia":"WV",wisconsin:"WI",wyoming:"WY","district of columbia":"DC"},Zn=[...Object.keys(oe).map(e=>e.replace(/\s+/g,"\\s+")),...Object.values(oe)].join("|"),Xn=new RegExp(`\\b([A-Z][A-Za-z]+(?:[\\s.-][A-Z][A-Za-z]+){0,4}),?\\s+(${Zn})\\b`,"gi");function tn(e){if(!e)return null;let t=e.trim();return/^[A-Z]{2}$/i.test(t)?t.toUpperCase():oe[t.toLowerCase()]??null}function en(e){return e.replace(/\s+/g," ").trim().replace(/^.*\b(?:in|near|around|serving)\s+/i,"").toLowerCase().replace(/\b[a-z]/g,n=>n.toUpperCase())}function ta(e){if(!e)return null;let[t="",n=""]=e.split(",").map(a=>a.trim());return{city:en(t),regionCode:tn(n),canonicalLocation:e}}function ea(e,t,n,a){let s=en(t),i=tn(n);if(!s||!i)return;let d=`${s.toLowerCase()}|${i}`,S=e.get(d);if(S){S.count++,S.examples.length<3&&!S.examples.includes(a)&&S.examples.push(a);return}e.set(d,{city:s,regionCode:i,count:1,examples:[a]})}function na(e){try{return decodeURIComponent(e)}catch{}try{return decodeURIComponent(e.replace(/%(?![0-9a-fA-F]{2})/g,"%25"))}catch{return e}}function Xe(e,t){let n=na(t).replace(/[+/|_-]+/g," ");for(let a of n.matchAll(Xn))ea(e,a[1]??"",a[2]??"",n.slice(0,180))}function Mt(e,t,n){let a=ta(e),s=new Map;for(let S of t)Xe(s,[S.title,S.snippet??"",S.cite??"",S.url].join(" "));for(let S of n)Xe(s,[S.name,...S.metadata,S.websiteUrl??"",S.directionsUrl??""].join(" "));let i=Array.from(s.values()).sort((S,U)=>U.count-S.count||S.city.localeCompare(U.city)).slice(0,8);return a?i.length===0?{status:"unknown",expected:a,candidates:[]}:{status:i.some(S=>S.city.toLowerCase()===a.city.toLowerCase()&&(a.regionCode==null||S.regionCode===a.regionCode))?"matched":"mismatch",expected:a,candidates:i}:{status:"not_requested",expected:null,candidates:i}}var aa=[/An AI Overview is not available for this search/gi,/Can't generate an AI overview right now\.?\s*Try again later\.?/gi,/\bAI Overview\b/gi,/\bView all\b/gi],ia=[/\bRelated Links\b/i,/\bAsk anything in\s*AI Mode\b/i,/\bAI can make mistakes\b/i,/\bThis is for informational purposes only\b/i,/\bShow more\b/i,/\b\d+\s+sites\b/i,/\b\d{1,2}\s*[msh]\s*[A-Z][A-Za-z]/,/\b(?:YouTube|Reddit|Facebook|Instagram|TikTok)·/];function Gt(e){return e.replace(/\u00a0/g," ").replace(/([.!?])([A-Z])/g,"$1 $2").replace(/([:;])([A-Z])/g,"$1 $2").replace(/([a-z])([A-Z][a-z])/g,"$1 $2").replace(/(\d)([A-Z][a-z])/g,"$1 $2").replace(/([a-z])(\d)/g,"$1 $2").replace(/\s+/g," ").trim()}function sa(e){let t=-1;for(let n of ia){let a=n.exec(e);n.lastIndex=0,a&&(t===-1||a.index<t)&&(t=a.index)}return t===-1?e:e.slice(0,t)}function oa(e,t){let n=t?.trim();if(!n||n.length<8)return e;let a=e.toLowerCase().indexOf(n.toLowerCase());return a>40?e.slice(0,a):e}function da(e){let t=e.match(/[•·]\s*(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\.?\s+\d{1,2},\s+\d{4}/i);if(t?.index&&t.index>40)return t.index;let n=Math.max(0,e.length-260),a=e.slice(n),s=[...a.matchAll(/[.!?]\s*(?=[A-Z][A-Za-z0-9"'$])/g)];for(let d of s){let S=a.slice(d.index+1).trim(),U=S.slice(0,160),h=/^(?:Best|Top|What|How|Why|When|Where|Which|Can|Should|Is|Are|Do|Does)\b/i.test(S);if(S.length>20&&h&&/(?:\s[-|]\s|Heating|Cooling|Company|Services|Blog|Guide|Review)/i.test(U))return n+d.index+1}let i=s.at(-1);return i?.index!==void 0?n+i.index+1:e.length}function ra(e){let t=e.match(/https?:\/\/\S+/i);if(!t?.index)return e;let n=e.slice(0,t.index);return n.slice(0,da(n))}function la(e){if(e.length<=1200)return e;let t=e.slice(0,1200),n=Math.max(t.lastIndexOf("."),t.lastIndexOf("!"),t.lastIndexOf("?"));return(n>240?t.slice(0,n+1):t).trim()}function nn(e,t,n){if(!e)return;let a=Gt(e),s=t?Gt(t):"";if(s&&a.toLowerCase().startsWith(s.toLowerCase())&&(a=a.slice(s.length).trim()),!/^An error has occurred\.?\s*Please try again later\.?/i.test(a)){for(let i of aa)a=a.replace(i," ");if(a=a.replace(/\b[A-Z][A-Za-z&'\u2019 -]{2,60}\+\d+\b/g," ").replace(/\b(?:[a-z0-9-]+\.)+[a-z]{2,}\+\d+\b/gi," "),a=Gt(a),a=sa(a),a=oa(a,n),a=ra(a),a=Gt(a),a=a.replace(/\s+(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\.?\s+\d{1,2},\s+\d{4}$/i,"").trim(),a=la(a),!!a&&!/^An error has occurred\.?\s*Please try again later\.?$/i.test(a))return a}}async function an(e){let t=e??{aio:{root:"[data-lhcontainer][data-streaming-container][eid]",legacyRoot:'[data-hveid="CBMQAA"]',wrapper:".Fgyi2e",controller:'[jscontroller="AkrxPe"]',contentSubtree:'[data-subtree="mfc"]',heading:".Fzsovc.cwYVJe.RJPOee",header:".heWuVc",showMoreButton:'[aria-label="Show more AI Overview"]',sourcesPanel:".OZ9ddf.WAUd4",disclaimer:".DuQANe.MSJHRb"},aim:{root:'[data-hveid="CAUQAA"]',wrapper:".Fgyi2e"},expandWaitMs:1500},n=window.google?.sn??"unknown",a=n==="aim"?"aim":n==="web"?"web":"unknown";function s(g){return g?(g.innerText??g.textContent??"").trim():""}function i(g){if(!g)return!1;let P=g.replace(/\s+/g," ").trim();return P.length>=16&&P.split(" ").filter(Boolean).length>=2}function d(g){let P=g.querySelector(t.aio.heading);if(s(P)==="AI Overview")return!0;let w=g.querySelector(t.aio.header);return!!s(w).split(/\n|\s{2,}/).some(M=>M.trim()==="AI Overview")}function S(){let P=Array.from(document.querySelectorAll(t.aio.root)).find(d);if(P)return P;if(t.aio.legacyRoot){let M=document.querySelector(t.aio.legacyRoot);if(M&&d(M))return M}let w=document.querySelectorAll(`${t.aio.heading}, h1, h2, h3, [role="heading"]`);for(let M of w){if(s(M)!=="AI Overview")continue;let k=M.parentElement;for(let v=0;v<8&&k;v++){if(k.matches(t.aio.root)||k.querySelector(t.aio.controller)||k.querySelector(t.aio.contentSubtree))return k;k=k.parentElement}return M.parentElement}return null}function U(g){if(!g)return null;let P=g.cloneNode(!0);P.querySelectorAll(["script","style","noscript","img","picture","video",t.aio.header,t.aio.showMoreButton,t.aio.sourcesPanel,t.aio.disclaimer,'[data-subtree="dfa"]',"[data-src-id]",'[role="dialog"]',".HWMcu",".bTFeG",".CyMdWb",".MFrAxb",".F0OfWd.hfWAgb",".x2qcTc.fZavHb",".SvjEff",".sR2MY",".lKuDef",".GSPQcc","a[href]","button",'[role="button"]'].join(",")).forEach(b=>b.remove());let w=document.createElement("div");w.style.position="fixed",w.style.left="-10000px",w.style.top="0",w.style.width=`${Math.max(320,Math.round(g.getBoundingClientRect?.().width||960))}px`,w.style.opacity="0",w.style.pointerEvents="none",w.append(P),document.body.append(w);let M=P.innerText||P.textContent||"";w.remove();let k=M.replace(/\r/g,"").replace(/[ \t]+\n/g,`
21695
21695
  `).replace(/\n[ \t]+/g,`
21696
21696
  `).replace(/\n{3,}/g,`
21697
21697
 
21698
21698
  `).replace(/[ \t]{2,}/g," ").trim().split(`
21699
- `).map(A=>A.replace(/\u00a0/g," ").trim()).filter(Boolean),P=[];for(let A=0;A<m.length;A++){let f=m[A],G=m[A+1]??"";if(f!=="AI Overview"&&f!=="Show more"&&!/^AI can make mistakes/i.test(f)&&!/^Thank you\b/i.test(f)&&!/^Your feedback helps Google improve/i.test(f)&&!/^\+?\d+$/.test(f)){if(/^\+\d+$/.test(G)&&f.length<=80){A++;continue}P.push(f)}}let N=P.join(`
21699
+ `).map(b=>b.replace(/\u00a0/g," ").trim()).filter(Boolean),v=[];for(let b=0;b<k.length;b++){let W=k[b],V=k[b+1]??"";if(W!=="AI Overview"&&W!=="Show more"&&!/^AI can make mistakes/i.test(W)&&!/^Thank you\b/i.test(W)&&!/^Your feedback helps Google improve/i.test(W)&&!/^\+?\d+$/.test(W)){if(/^\+\d+$/.test(V)&&W.length<=80){b++;continue}v.push(W)}}let I=v.join(`
21700
21700
  `).replace(/\n{3,}/g,`
21701
21701
 
21702
- `).trim();return!N||/not available|try again|can't generate/i.test(N)?null:N}function U(y){if(!y||y.startsWith("javascript:"))return null;try{let k=new URL(y,window.location.href);return!["http:","https:"].includes(k.protocol)||k.username||k.password?null:{href:k.href,rawHref:k.href}}catch{return null}}function S(y){if(!y)return[];let k=new Set,w=[];for(let p of Array.from(y.querySelectorAll("a[href]"))){let m=U(p.getAttribute("href")??"");if(!m||k.has(m.rawHref))continue;k.add(m.rawHref);let P="";try{P=new URL(m.href).hostname.replace(/^www\./,"")}catch{}w.push({text:s(p)||P||m.href,href:m.href,rawHref:m.rawHref})}return w}async function o(y){let k=y.querySelector(t.aio.showMoreButton);if(!k||k.getAttribute("aria-expanded")!=="false")return!1;k.click();let w=t.expandWaitMs??1500;return w>0&&await new Promise(p=>setTimeout(p,w)),!0}let r=l(),u=null,c=[],g=!1,M=!1,T=[];if(r){g=await o(r);let y=r.querySelector(t.aio.controller),k=r.querySelector(t.aio.contentSubtree),w=r.querySelector(t.aio.showMoreButton);M=y?.getAttribute("data-trnct")==="false"||w?.getAttribute("aria-expanded")==="true"||!w,u=h(k??y??r),T=(u??"").split(`
21703
- `).map(p=>p.trim()).filter(p=>/^\d+\.\s+.+/.test(p)),c=S(r)}let b=document.querySelector(t.aim.root),L=a==="aim"&&!!b,O=b?.closest(t.aim.wrapper)??b,H=L?h(O):null,W=L&&i(H),C=W?H:null,v=W?S(O):[],I=!!r&&i(u);return{surface:a,aiOverview:{detected:I,text:I?u:null,citations:I?c:[],expanded:I?g:!1,fullyExpanded:I?M:!1,sections:I?T:[]},aiMode:{detected:W&&C!==null,text:C,citations:v}}}import{createHash as la}from"crypto";var sn=8e3,on=3e3,dn=1e4,Sa=8;function tt(e){return/(^|\.)google\.(?:com|[a-z]{2,3}(?:\.[a-z]{2})?)$/i.test(e)}function pt(e){if(!e||e.length>sn)return null;try{let t=new URL(e);return t.protocol!=="http:"&&t.protocol!=="https:"||t.username||t.password?null:t}catch{return null}}function Ua(e,t){if(!e||e.length>sn||/^javascript:/i.test(e))return null;try{let n=new URL(e,t);return pt(n.href)}catch{return null}}function kt(e){let t=pt(e);return!t||t.protocol!=="https:"||!tt(t.hostname)||t.pathname!=="/goto"?null:t.searchParams.get("url")?t:null}function se(e){if(e.linkType!=="google_goto_redirect"||e.resolutionStatus!=="resolved"||!kt(e.rawUrl)||!e.resolvedUrl)return!1;let t=pt(e.resolvedUrl);return!!(t&&!tt(t.hostname)&&t.href===e.resolvedUrl&&e.url===t.href)}function st(e){let t=e.normalize("NFKC").toLocaleLowerCase("en-US").replace(/[^\p{L}\p{N}\s]/gu,"").replace(/\s+/g," ").trim();return`paa_${la("sha256").update(t).digest("hex").slice(0,16)}`}function Dt(e,t){let n=Ua(e,t);if(!n)return null;let a=n.href;if(!tt(n.hostname))return{url:a,rawUrl:a,resolvedUrl:a,linkType:"plain",resolutionStatus:"not_needed"};if(n.pathname==="/url"){let s=pt(n.searchParams.get("q")??n.searchParams.get("url")??"");return!s||tt(s.hostname)?null:{url:s.href,rawUrl:a,resolvedUrl:s.href,linkType:"google_url_redirect",resolutionStatus:"resolved"}}return n.pathname==="/goto"&&n.searchParams.get("url")?{url:a,rawUrl:a,resolvedUrl:null,linkType:"google_goto_redirect",resolutionStatus:"unresolved"}:null}function oe(e){return kt(e)?.searchParams.get("url")??null}function rn(e,t){try{let n=new URL(e),a=pt(new URL(t,n).href);return!a||tt(a.hostname)?null:(!a.hash&&n.hash&&(a.hash=n.hash),a.href)}catch{return null}}async function ln(e,t={}){let n=[...new Set([...e].flatMap(o=>kt(o)?[o]:[]))],a=new Map(n.map(o=>[o,{rawUrl:o,resolvedUrl:null,resolutionStatus:"unresolved"}])),s=typeof globalThis.fetch=="function"?globalThis.fetch.bind(globalThis):null,i=t.fetchImpl??s;if(n.length===0||!i)return{resolutions:[...a.values()],nonGoogleRequestsObserved:0};let d=Math.max(1,t.timeoutMs??on),l=Date.now()+Math.max(1,t.totalBudgetMs??dn),h=Math.max(1,Math.min(16,Math.floor(t.concurrency??Sa))),U=0,S=async()=>{for(;U<n.length;){let o=n[U++],r=kt(o),u=r?.searchParams.get("url");if(!r||!u){a.set(o,{rawUrl:o,resolvedUrl:null,resolutionStatus:"rejected"});continue}r.hash="";let c=r.href;for(let g=0;g<2;g++){let M=l-Date.now();if(M<=0)return;let T=new AbortController,b=setTimeout(()=>T.abort(),Math.min(d,M)),L;try{L=await i(c,{method:"GET",redirect:"manual",headers:{accept:"*/*","user-agent":"Mozilla/5.0"},signal:T.signal})}catch{break}finally{clearTimeout(b)}if(L.status<300||L.status>=400)break;let O=L.headers.get("location");if(!O)break;let H=rn(o,O);if(H){a.set(o,{rawUrl:o,resolvedUrl:H,resolutionStatus:"resolved"});break}let W;try{W=new URL(O,c)}catch{a.set(o,{rawUrl:o,resolvedUrl:null,resolutionStatus:"rejected"});break}if(!tt(W.hostname)||oe(W.href)!==u){a.set(o,{rawUrl:o,resolvedUrl:null,resolutionStatus:"rejected"});break}c=W.href}}};return await Promise.all(Array.from({length:Math.min(h,n.length)},()=>S())),{resolutions:[...a.values()],nonGoogleRequestsObserved:0}}function an(e,t){try{return new URL(e.resolvedUrl??e.url).hostname.replace(/^www\./,"")}catch{return t}}async function Sn(e,t={}){let n=[],a=o=>{for(let r of o)n.push(r),a(r.children??[])};a(e.tree??[]);let s=[...e.flat.flatMap(o=>o.sources??[]),...n.flatMap(o=>o.sources),...e.organicResults??[],...(e.aiOverview?.citations??[]).map(({text:o,href:r,...u})=>({...u,url:r})),...(e.aiMode?.citations??[]).map(({text:o,href:r,...u})=>({...u,url:r}))],i=new Map(s.filter(o=>!!o?.rawUrl).map(o=>[o.rawUrl,o])),d=[...i.values()].filter(o=>o.linkType==="google_goto_redirect"&&o.resolutionStatus!=="resolved").map(o=>o.rawUrl);if(d.length>0){let o=await ln(d,t);for(let r of o.resolutions){let u=i.get(r.rawUrl);u&&i.set(r.rawUrl,r.resolutionStatus==="resolved"&&r.resolvedUrl?{...u,url:r.resolvedUrl,resolvedUrl:r.resolvedUrl,resolutionStatus:"resolved"}:{...u,resolutionStatus:r.resolutionStatus})}}let l=o=>({...o,...i.get(o.rawUrl)??o}),h=o=>o.map(r=>{let u=l(r);return{...u,site:an(u,r.site)}});for(let o of e.flat){o.sources=h(o.sources??[]);let r=o.sources[0];o.source_title=r?.title??o.source_title,o.source_site=r?.site??o.source_site,o.source_cite=r?.url??o.source_cite}for(let o of n){o.sources=h(o.sources??[]);let r=o.sources[0];o.sourceTitle=r?.title??o.sourceTitle,o.sourceSite=r?.site??o.sourceSite,o.sourceCite=r?.url??o.sourceCite}for(let o=0;o<(e.organicResults?.length??0);o++){let r=l(e.organicResults[o]);e.organicResults[o]={...r,domain:an(r,e.organicResults[o].domain)??""}}let U=o=>{let r=l({url:o.href,rawUrl:o.rawUrl,resolvedUrl:o.resolvedUrl,linkType:o.linkType,resolutionStatus:o.resolutionStatus}),{url:u,...c}=r;return{...o,...c,href:u}};e.aiOverview&&(e.aiOverview.citations=(e.aiOverview.citations??[]).map(U)),e.aiMode&&(e.aiMode.citations=(e.aiMode.citations??[]).map(U));let S=[...i.values()];return e.diagnostics.links={linkCandidatesObserved:i.size,plainLinksObserved:S.filter(o=>o.linkType==="plain").length,googleUrlRedirectsObserved:S.filter(o=>o.linkType==="google_url_redirect").length,googleGotoRedirectsObserved:S.filter(o=>o.linkType==="google_goto_redirect").length,redirectsResolved:S.filter(o=>o.linkType!=="plain"&&o.resolutionStatus==="resolved").length,redirectsUnresolved:S.filter(o=>o.resolutionStatus==="unresolved").length,redirectsRejected:S.filter(o=>o.resolutionStatus==="rejected").length,resolverNonGoogleRequestsObserved:0,paaSourcesPreserved:e.flat.reduce((o,r)=>o+r.sources.length,0),aiOverviewLabelValidated:e.aiOverview?.detected??!1},e}async function Un(e,t,n={}){let a=new Map;for(let r of t){let u=a.get(r.rawUrl);u&&se(u)||a.set(r.rawUrl,r.linkType==="google_goto_redirect"&&!se(r)?{...r,url:r.rawUrl,resolvedUrl:null,resolutionStatus:"unresolved"}:r)}let s=[...a.values()].filter(r=>r.linkType==="google_goto_redirect"&&!se(r));if(s.length===0)return a;let i=Date.now()+(n.totalBudgetMs??dn),d=await ln(s.map(r=>r.rawUrl),n);for(let r of d.resolutions){let u=a.get(r.rawUrl);u&&a.set(r.rawUrl,r.resolutionStatus==="resolved"&&r.resolvedUrl?{...u,url:r.resolvedUrl,resolvedUrl:r.resolvedUrl,resolutionStatus:"resolved"}:{...u,resolutionStatus:r.resolutionStatus})}let l=s.filter(r=>a.get(r.rawUrl)?.resolutionStatus==="unresolved");if(l.length===0||n.browserFallback===!1||Date.now()>=i)return n.onNetworkAudit?.({nonGoogleRequestsObserved:0}),a;let h=n.timeoutMs??on,U=await e.context().newPage().catch(()=>null);if(!U)return n.onNetworkAudit?.({nonGoogleRequestsObserved:0}),a;let S=null,o=0;try{await U.route("**/*",async r=>{let u=r.request().url();try{tt(new URL(u).hostname)||(o+=1)}catch{}let c=oe(u);if(!S||c!==S.token){await r.abort("blockedbyclient").catch(()=>{});return}let g=S;try{let M=await r.fetch({maxRedirects:0,timeout:g.timeoutMs});g.location=M.headers().location??null}finally{await r.abort("blockedbyclient").catch(()=>{}),g.finish()}});for(let r of l){let u=i-Date.now();if(u<=0)break;let c=kt(r.rawUrl),g=c?.searchParams.get("url");if(!c||!g){a.set(r.rawUrl,{...r,resolutionStatus:"rejected"});continue}let M=Math.min(h,u);c.hash="";let T=c.href,b=!1;for(let L=0;L<2;L++){let O,H=new Promise(y=>{O=y}),W=`mcp-goto-${Math.random().toString(36).slice(2)}`;S={token:g,timeoutMs:M,location:null,finish:O},await U.evaluate(({url:y,id:k})=>{let w=document.createElement("iframe");w.id=k,w.hidden=!0,w.src=y,document.body.append(w)},{url:T,id:W}).catch(()=>null),await Promise.race([H,new Promise(y=>setTimeout(y,M))]);let C=S.location;if(S=null,await U.evaluate(y=>document.getElementById(y)?.remove(),W).catch(()=>null),!C)break;let v=rn(r.rawUrl,C);if(v){a.set(r.rawUrl,{...r,url:v,resolvedUrl:v,resolutionStatus:"resolved"});break}let I;try{I=new URL(C,T)}catch{b=!0;break}if(!tt(I.hostname)||oe(I.href)!==g){b=!0;break}T=I.href}b&&a.get(r.rawUrl)?.resolutionStatus!=="resolved"&&a.set(r.rawUrl,{...r,resolutionStatus:"rejected"})}}finally{S=null,await U.close().catch(()=>{}),n.onNetworkAudit?.({nonGoogleRequestsObserved:o})}return a}var hn=String.raw`^(?:an error has occurred(?:[.!…]\s*)?(?:please try again later[.!…]?)?|loading|please wait|try again|something went wrong)[.!…\s]*$`,ha=700,ua=1e3,ca=1400,un=900,wa=3,cn=250,Vt=class{constructor(t,n,a,s){this.driver=t;this.reporter=n;this.onPaaProgress=a;this.onProviderSession=s}driver;reporter;onPaaProgress;onProviderSession;completeness={paaWithoutAnswer:0,paaWithoutSource:0,paaAnswersRecovered:0,aioShareCaptured:null};aioShareUrlEarly=null;linkDiagnostics=this.emptyLinkDiagnostics();collectedRows=[];partialContext=null;progressSequence=0;clickedQuestions=new Set;paaLifecycle=this.emptyPaaLifecycle(0);checkpointMaterial=null;interactionObservations=[];phaseTimings={};currentPhaseTimings(t){return{...this.phaseTimings,totalServerMs:Math.max(0,Date.now()-t)}}emptyPaaLifecycle(t){return{requestedQuestions:t,questionsFound:0,targetStatus:"not_met",discoveryStatus:"in_progress",materialStatus:"partial",completionReason:"PAA expansion is still running.",automaticRetries:0,retryBreakdown:{controlRetries:0,browserRetries:0,providerFallbacks:0,runtimeRecoveries:0,idempotentReplays:0},knownQuestions:0,processedQuestions:0,failedInteractions:0,noGrowthConfirmations:0,visibleControls:0,eligibleControls:0,dispatchedInteractions:0,confirmedInteractions:0,unconfirmedInteractions:0}}emptyLinkDiagnostics(){return{linkCandidatesObserved:0,plainLinksObserved:0,googleUrlRedirectsObserved:0,googleGotoRedirectsObserved:0,redirectsResolved:0,redirectsUnresolved:0,redirectsRejected:0,resolverNonGoogleRequestsObserved:0,paaSourcesPreserved:0,aiOverviewLabelValidated:!1}}mergePaaSources(t=[],n=[]){let a=new Map;for(let s of[...t,...n]){let i=a.get(s.rawUrl);if(!i){a.set(s.rawUrl,s);continue}let d=s.resolutionStatus==="resolved"&&i.resolutionStatus!=="resolved"?s:i;a.set(s.rawUrl,{...d,title:d.title??i.title??s.title,site:d.site??i.site??s.site})}return[...a.values()]}normalizeAICitations(t,n){let a=new Set;return n.flatMap(s=>{let i=Dt(s.rawHref??s.href,t);if(!i||a.has(i.rawUrl))return[];a.add(i.rawUrl);let{url:d,...l}=i;return[{...l,text:s.text,href:d}]})}async resolveMaterialLinks(t,n,a,s,i){let d=Date.now(),l=[...n.flatMap(c=>c.sources??[]),...a,...s.citations.map(({text:c,href:g,...M})=>({...M,url:g})),...i.citations.map(({text:c,href:g,...M})=>({...M,url:g}))],h=new Map(l.map(c=>[c.rawUrl,c])),U=0,S=await Un(t,l,{onNetworkAudit:c=>{U=c.nonGoogleRequestsObserved}}),o=c=>({...c,...S.get(c.rawUrl)??c});for(let c of n){c.sources=(c.sources??[]).map(o);let g=c.sources[0];c.source_title=g?.title??c.source_title,c.source_site=g?.site??c.source_site,c.source_cite=g?.url??c.source_cite}for(let c=0;c<a.length;c++){let g=o(a[c]);if(g.resolvedUrl)try{g.domain=new URL(g.resolvedUrl).hostname.replace(/^www\./,"")}catch{}a[c]=g}let r=c=>{let g=o({url:c.href,rawUrl:c.rawUrl,resolvedUrl:c.resolvedUrl,linkType:c.linkType,resolutionStatus:c.resolutionStatus}),{url:M,...T}=g;return{...T,text:c.text,href:M}};s.citations=s.citations.map(r),i.citations=i.citations.map(r);let u=[...S.values()];this.linkDiagnostics={linkCandidatesObserved:h.size,plainLinksObserved:u.filter(c=>c.linkType==="plain").length,googleUrlRedirectsObserved:u.filter(c=>c.linkType==="google_url_redirect").length,googleGotoRedirectsObserved:u.filter(c=>c.linkType==="google_goto_redirect").length,redirectsResolved:u.filter(c=>c.linkType!=="plain"&&c.resolutionStatus==="resolved").length,redirectsUnresolved:u.filter(c=>c.resolutionStatus==="unresolved").length,redirectsRejected:u.filter(c=>c.resolutionStatus==="rejected").length,resolverNonGoogleRequestsObserved:U,paaSourcesPreserved:n.reduce((c,g)=>c+(g.sources??[]).length,0),aiOverviewLabelValidated:s.detected},this.phaseTimings.linkResolutionMs=(this.phaseTimings.linkResolutionMs??0)+(Date.now()-d)}normalizeQuestion(t){return t.toLowerCase().replace(/[^\w\s]/g,"").replace(/\s+/g," ").trim()}throwIfAborted(t){if(t?.aborted)throw t.reason instanceof DOMException&&t.reason.name==="TimeoutError"?t.reason:new q}async throwIfCaptcha(t,n){if(await t.locator(F.captchaMarker).count().catch(()=>0)>0)throw new K(`${n} returned a CAPTCHA \u2014 retrying with a fresh session.`)}async extractVisibleItems(t,n){let a=F,s=await t.evaluate(({selectors:d,onlyQuestion:l,answerPlaceholderPattern:h})=>{function U(o){if(!o)return"";let r=[];for(let u of o.childNodes)if(u.nodeType===Node.TEXT_NODE){let c=u.textContent?.trim();c&&r.push(c)}else{if(u.tagName==="STYLE"||u.tagName==="SCRIPT")continue;{let c=U(u);c&&r.push(c)}}return r.join(" ").replace(/\s+/g," ").trim()}function S(o){return(o??"").replace(/\s*\(\+\d+\)\s*-\s*View related links.*$/i,"").replace(/\s*-\s*Opens in new tab.*$/i,"").trim()}return Array.from(document.querySelectorAll(d.item)).filter(o=>!l||(o.getAttribute(d.itemDataQ)||o.getAttribute(d.itemDataInitQ)||o.querySelector(d.itemQuestionEl)?.innerText?.trim()||"")===l).map(o=>{let r=o.querySelector(d.clickTarget),u=o.classList.contains(d.expandedClass)||r?.getAttribute("aria-expanded")==="true",c=o.querySelector(d.answerContainer),M=c?.querySelector(d.aiAnswerBody)??c,T=U(M),b=new RegExp(h,"i").test(T),L=[...Array.from((M??o).querySelectorAll("a[href]")),...Array.from(o.querySelectorAll(d.aiCitation)),...Array.from(o.querySelectorAll(d.aiSourceCard))],O=!b&&(u&&T.length>=10||T.length>30&&L.some(v=>/^https?:\/\//.test(v.href))),H=O&&o.querySelector(d.sourceTitle)?.innerText?.trim()||void 0,W=O&&o.querySelector(d.sourceSite)?.innerText?.trim()||void 0,C=[];if(O){let v=new Set;for(let y of L)!/^https?:\/\//.test(y.href)||v.has(y.href)||(v.add(y.href),C.push({title:S(y.getAttribute("aria-label"))||(y.textContent||"").trim(),rawHref:y.href}));let I=C.find(y=>y.title.length>2)??C[0];I&&(H=H||I.title||void 0)}return{googleLinkId:o.getAttribute("data-lk")||o.querySelector("[data-lk]")?.getAttribute("data-lk")||null,googleEvidenceId:o.getAttribute("data-ved")||o.querySelector("[data-ved]")?.getAttribute("data-ved")||null,question:o.getAttribute(d.itemDataQ)||o.getAttribute(d.itemDataInitQ)||o.querySelector(d.itemQuestionEl)?.innerText?.trim()||"",answer:O&&T||void 0,sourceTitle:H,sourceSite:W,sources:C}})},{selectors:a,onlyQuestion:n,answerPlaceholderPattern:hn}),i=typeof t.url=="function"?t.url():"https://www.google.com/";return s.flatMap(d=>{let l=[],h=new Set;for(let r of d.sources){let u=Dt(r.rawHref,i);if(!u||h.has(u.rawUrl))continue;h.add(u.rawUrl);let c=d.sourceSite??null;try{c||=new URL(u.resolvedUrl??u.rawUrl).hostname.replace(/^www\./,"")}catch{}l.push({...u,title:r.title||d.sourceTitle||null,site:c})}let U=l[0],S={questionId:st(d.question),googleLinkId:d.googleLinkId,googleEvidenceId:d.googleEvidenceId,question:d.question,answer:en(d.answer,d.question,d.sourceTitle),sourceTitle:U?.title??d.sourceTitle,sourceSite:U?.site??d.sourceSite,sourceCite:U?.url,sources:l},o=me.safeParse(S);return o.success?[o.data]:(console.warn("[PAAExtractor] item parse failed:",d.question,o.error.issues[0]?.message),[])})}jitteredDelayMs(t,n){return t+Math.floor(Math.random()*(n-t+1))}async clickItem(t,n){try{await t.locator(`${F.item}[data-q="${n}"], ${F.item}[data-initq="${n}"]`).first().click()}catch{}}toFlatRow(t,n,a,s){return{seed_query:s,question_id:t.questionId??st(t.question),google_link_id:t.googleLinkId??"",google_evidence_id:t.googleEvidenceId??"",question:t.question,answer:t.answer??"",source_title:t.sourceTitle??"",source_site:t.sourceSite??"",source_cite:t.sourceCite??"",sources:t.sources??[],depth:n,parent_question:a??"",extracted_at:new Date().toISOString()}}upsertCollectedRow(t){let n=this.normalizeQuestion(t.question),a=this.collectedRows.findIndex(l=>this.normalizeQuestion(l.question)===n);if(a<0)return this.collectedRows.push({...t}),!0;let s=this.collectedRows[a],i={...s,...t,answer:t.answer||s.answer,source_title:t.source_title||s.source_title,source_site:t.source_site||s.source_site,source_cite:t.source_cite||s.source_cite,sources:this.mergePaaSources(s.sources,t.sources),extracted_at:t.extracted_at||s.extracted_at},d=i.answer!==s.answer||i.source_title!==s.source_title||i.source_site!==s.source_site||i.source_cite!==s.source_cite||JSON.stringify(i.sources)!==JSON.stringify(s.sources);return d&&(this.collectedRows[a]=i),d}async emitProgress(t){if(!this.onPaaProgress||this.collectedRows.length===0&&!this.checkpointMaterial)return;let n={sequence:++this.progressSequence,observedAt:new Date().toISOString(),clickedQuestions:[...this.clickedQuestions],phase:t,records:this.collectedRows.map(a=>({...a})),lifecycle:{...this.paaLifecycle},...this.checkpointMaterial?{material:structuredClone(this.checkpointMaterial)}:{},interactions:this.interactionObservations.map(a=>({...a,confirmationSignals:[...a.confirmationSignals]}))};try{await this.onPaaProgress(n)}catch(a){console.warn(JSON.stringify({event:"paa_progress_sink_failed",sequence:n.sequence,phase:n.phase,message:a instanceof Error?a.message:String(a)}))}}getPartialResult(){let t=this.partialContext;if(!t||this.collectedRows.length===0&&!this.checkpointMaterial)return null;let n=this.collectedRows.map(l=>({...l})),a=this.checkpointMaterial,s=t.questionsOnly?0:n.filter(l=>!l.answer?.trim()).length,i=t.questionsOnly?0:n.filter(l=>(l.sources??[]).length===0).length,d={seed:t.seed,totalQuestions:n.length,maxDepthReached:n.reduce((l,h)=>Math.max(l,h.depth),0),durationMs:Date.now()-t.startMs,errorCount:0};return{seed:t.seed,location:t.location,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(t.startMs),completionStatus:"paa_found",problem:null,...a?.pagination?{pagination:{...a.pagination}}:{},resultQuality:"partial",degradedResult:!1,retryRecommended:!0,paaLifecycle:{...this.paaLifecycle,questionsFound:n.length,targetStatus:n.length>=(t.maxQuestions??0)?"met":"not_met",discoveryStatus:"interrupted",materialStatus:s>0||i>0?"partial":"complete",completionReason:"The browser attempt ended before frontier exhaustion could be proven."},completeness:{...this.completeness,paaWithoutAnswer:s,paaWithoutSource:i,paaRequested:t.maxQuestions,paaReturned:n.length,paaUnique:n.length},warnings:[{code:"paa_partial",surface:"paa",message:`Harvest stopped before finishing; returning the ${n.length} question(s) collected up to that point.`,retryable:!0}]},totalQuestions:n.length,surface:a?.surface??"web",aiOverview:a?.aiOverview??{detected:!1,text:null,citations:[]},aiMode:a?.aiMode??{detected:!1,text:null,citations:[]},whatPeopleSaying:a?.whatPeopleSaying??[],tree:this.buildTree(n,t.seed),flat:n,videos:a?.videos??[],forums:a?.forums??[],organicResults:a?.organicResults??[],localPack:a?.localPack??[],entityIds:a?.entityIds??{entities:[],kgIds:[],cids:[],gcids:[]},stats:d}}async runBFS(t,n,a){await t.waitForTimeout(700);let s=new Set,i=new Set,d=[];this.clickedQuestions=new Set,this.interactionObservations=[],this.phaseTimings={};let l=new Set,h=new Map,U=new Set,S=new Set,o=new Map,r=2,u=3,c=0,g={sel:F.item,dataQ:F.itemDataQ,dataInitQ:F.itemDataInitQ,questionEl:F.itemQuestionEl,answerSel:F.answerContainer,expandedClass:F.expandedClass,clickTarget:F.clickTarget,answerPlaceholderPattern:hn,questionsOnly:n.questionsOnly,sourceSel:"a[href]"},M=()=>t.evaluate(({sel:W,dataQ:C,dataInitQ:v,questionEl:I,expandedClass:y,clickTarget:k,answerSel:w,answerPlaceholderPattern:p,questionsOnly:m})=>{let P=N=>{if(!N)return"";let A=[];for(let f of N.childNodes){if(f.nodeType===Node.TEXT_NODE){let D=f.textContent?.trim();D&&A.push(D);continue}if(f.nodeType!==Node.ELEMENT_NODE)continue;let G=f;if(G.tagName==="STYLE"||G.tagName==="SCRIPT"||G.getAttribute("aria-hidden")==="true")continue;let x=P(G);x&&A.push(x)}return A.join(" ").replace(/\s+/g," ").trim()};return Array.from(document.querySelectorAll(W)).map((N,A)=>{let f=P(N.querySelector(w)).replace(/An AI Overview is not available for this search/gi," ").replace(/Can't generate an AI overview right now\.?\s*Try again later\.?/gi," ").replace(/\bAI Overview\b/gi," ").replace(/\s+/g," ").trim(),G=N.classList.contains(y)||N.querySelector(k)?.getAttribute("aria-expanded")==="true",x=f.length>=10&&!new RegExp(p,"i").test(f);return{q:N.getAttribute(C)||N.getAttribute(v)||N.querySelector(I)?.innerText?.trim()||"",done:G&&(m||x),expanded:G,index:A}}).filter(N=>N.q)},g),T=async(W,C,v,I,y,k)=>{let w=Date.now(),p={id:`${k}:${st(W)}:${y}`,questionId:st(W),question:W,batchNumber:k,controlAttempt:y,observedAt:new Date(w).toISOString(),beforeQuestionCount:C,expandedBefore:I},m=v>=0?t.locator(g.sel).nth(v).locator(g.clickTarget):null,P=null,N=m?await(async()=>(I&&(await m.click({timeout:un,force:!0}),await t.waitForTimeout(120)),await m.click({timeout:un,force:!0}),!0))().catch(R=>(P=R instanceof Error&&(R.name==="TimeoutError"||/timeout/i.test(R.message))?"click_ack_timeout":"click_failed",!1)):!1,A=Date.now()-w;if(!N&&P!=="click_ack_timeout")return{dispatched:!1,confirmed:!1,observation:{...p,dispatched:!1,outcome:"dispatch_failed",confirmationSignals:[],confirmationCheckpointMs:null,confirmedAtMs:null,dispatchDurationMs:A,totalDurationMs:A,afterQuestionCount:C,newQuestionCount:0,expandedAfter:I,answerObserved:!1,sourceCount:0,errorCode:v<0?"control_missing":P??"click_failed"}};let f={exists:!0,expanded:I,answerReady:!1,sourceCount:0,questionCount:C},G=[],x=null,D=null,_=!1;for(let R of[ha,ua,ca]){let z=w+R-Date.now();if(z>0&&await t.waitForTimeout(z),f=await t.evaluate(({sel:B,dataQ:E,dataInitQ:$,questionEl:ut,expandedClass:ct,clickTarget:at,answerSel:mt,answerPlaceholderPattern:dt,sourceSel:vt,target:wt})=>{let Nt=lt=>{if(!lt)return"";let qt=[];for(let ft of lt.childNodes){if(ft.nodeType===Node.TEXT_NODE){let Me=ft.textContent?.trim();Me&&qt.push(Me);continue}if(ft.nodeType!==Node.ELEMENT_NODE)continue;let Pt=ft;if(Pt.tagName==="STYLE"||Pt.tagName==="SCRIPT"||Pt.getAttribute("aria-hidden")==="true")continue;let Ce=Nt(Pt);Ce&&qt.push(Ce)}return qt.join(" ").replace(/\s+/g," ").trim()},rt=Array.from(document.querySelectorAll(B)),Tt=rt.find(lt=>(lt.getAttribute(E)||lt.getAttribute($)||lt.querySelector(ut)?.innerText?.trim())===wt);if(!Tt)return{exists:!1,expanded:!1,answerReady:!1,sourceCount:0,questionCount:rt.length};let Wn=Tt.classList.contains(ct)||Tt.querySelector(at)?.getAttribute("aria-expanded")==="true",we=Tt.querySelector(mt),ge=Nt(we).replace(/An AI Overview is not available for this search/gi," ").replace(/Can't generate an AI overview right now\.?\s*Try again later\.?/gi," ").replace(/\bAI Overview\b/gi," ").replace(/\s+/g," ").trim(),ye=ge.length>=10&&!new RegExp(dt,"i").test(ge);return{exists:!0,expanded:Wn,answerReady:ye,sourceCount:ye?we?.querySelectorAll(vt).length??0:0,questionCount:rt.length}},{...g,target:W}).catch(()=>f),G=[...f.expanded?["expanded"]:[],...f.answerReady?["answer"]:[],...f.sourceCount>0?["source"]:[],...f.questionCount>C?["question_growth"]:[]],f.answerReady||f.sourceCount>0||f.questionCount>C){_=!0,x=R,D=Date.now()-w;break}}let Q=Date.now()-w,V={...p,dispatched:N,outcome:_?"confirmed":N?"unconfirmed":"dispatch_failed",confirmationSignals:G,confirmationCheckpointMs:x,confirmedAtMs:D,dispatchDurationMs:A,totalDurationMs:Q,afterQuestionCount:f.questionCount,newQuestionCount:Math.max(0,f.questionCount-C),expandedAfter:f.expanded,answerObserved:f.answerReady,sourceCount:f.sourceCount,errorCode:N?_?null:f.exists?"confirmation_timeout":"control_missing":P};return{dispatched:N,confirmed:_,observation:V}},b=0;t:for(;;){if(n.softDeadlineMs&&Date.now()>=n.softDeadlineMs)throw this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"interrupted",completionReason:"The execution deadline arrived before frontier exhaustion could be proven."},new yt(this.paaLifecycle.completionReason);this.throwIfAborted(a);let W=await M(),C=!1;for(let w of W)i.has(w.q)||(i.add(w.q),d.push(w.q),d.length<=n.maxQuestions&&(C=this.upsertCollectedRow(this.toFlatRow({questionId:st(w.q),googleLinkId:null,googleEvidenceId:null,question:w.q,sources:[]},1,null,n.query))||C)),w.done&&U.add(w.q);if(this.paaLifecycle={...this.paaLifecycle,questionsFound:Math.min(d.length,n.maxQuestions),targetStatus:d.length>=n.maxQuestions?"met":"not_met",knownQuestions:d.length,processedQuestions:U.size,failedInteractions:S.size,visibleControls:W.length},C&&await this.emitProgress("discovered"),n.questionsOnly&&i.size>=n.maxQuestions){this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"target_reached",targetStatus:"met",completionReason:"The requested unique-question count was observed."};break}if(!n.questionsOnly&&i.size>=n.maxQuestions){let w=!1,p=new Set(d.slice(0,n.maxQuestions));for(let m of await this.extractVisibleItems(t)){if(!p.has(m.question))continue;let P=o.get(m.question),N={...m,answer:m.answer??P?.answer,sourceTitle:m.sourceTitle??P?.sourceTitle,sourceSite:m.sourceSite??P?.sourceSite,sourceCite:m.sourceCite??P?.sourceCite,sources:this.mergePaaSources(P?.sources,m.sources)};o.set(m.question,N),w=this.upsertCollectedRow(this.toFlatRow(N,1,null,n.query))||w}if(w&&await this.emitProgress("answer_captured"),[...p].every(m=>{let P=o.get(m);return!!(P?.answer?.trim()&&P.sources.length>0)})){S.clear(),this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"target_reached",targetStatus:"met",failedInteractions:0,completionReason:"The requested unique-question count and its answer/source material were observed."};break}}let v=new Set(d.slice(0,n.maxQuestions)),I=W.filter(w=>v.has(w.q)&&!w.done&&(h.get(w.q)??0)<r&&!l.has(w.q)),y=I.slice(-wa);if(this.paaLifecycle={...this.paaLifecycle,eligibleControls:I.length},y.length===0){if(i.size>=n.maxQuestions){this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"target_reached",targetStatus:"met",completionReason:"The requested unique-question count was observed."};break}let w=new Set(W.map(m=>m.q)),p=d.slice(0,n.maxQuestions).filter(m=>!U.has(m)&&(S.has(m)||!w.has(m)));if(p.length>0)throw this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"interrupted",failedInteractions:new Set([...S,...p]).size,completionReason:"At least one known PAA control failed or disappeared before it could be confirmed."},await this.emitProgress("expansion_finished"),new yt(this.paaLifecycle.completionReason);for(let m=1;m<=u;m++){this.throwIfAborted(a),await this.throwIfCaptcha(t,"Google PAA exhaustion confirmation"),await t.mouse.wheel(0,320);let P=await t.waitForFunction(({sel:A,min:f})=>document.querySelectorAll(A).length>f,{sel:F.item,min:W.length},{timeout:1500,polling:100}).catch(()=>null);if(this.paaLifecycle={...this.paaLifecycle,noGrowthConfirmations:m},P||(await M()).some(A=>!i.has(A.q)))continue t}this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"frontier_exhausted",targetStatus:"not_met",failedInteractions:0,noGrowthConfirmations:u,completionReason:"Every known eligible PAA control was processed and three healthy no-growth confirmations found no additional questions."};break}await this.throwIfCaptcha(t,"Google PAA expansion"),c+=1;for(let w of y){if(this.reporter.onDepth(++b),(h.get(w.q)??0)>0){let p=this.paaLifecycle.retryBreakdown.controlRetries+1;this.paaLifecycle={...this.paaLifecycle,automaticRetries:p+this.paaLifecycle.retryBreakdown.browserRetries+this.paaLifecycle.retryBreakdown.runtimeRecoveries,retryBreakdown:{...this.paaLifecycle.retryBreakdown,controlRetries:p}}}h.set(w.q,(h.get(w.q)??0)+1)}let k=await Promise.all(y.map(async w=>({target:w,result:await T(w.q,W.length,w.index,w.expanded,h.get(w.q)??1,c)})));for(let{target:w,result:p}of k)(p.dispatched||p.confirmed)&&this.clickedQuestions.add(w.q),this.interactionObservations.push(p.observation);if(this.interactionObservations.length>cn&&this.interactionObservations.splice(0,this.interactionObservations.length-cn),!n.questionsOnly){let w=new Set(y.map(p=>p.q));for(let p of await this.extractVisibleItems(t))w.has(p.question)&&(o.set(p.question,p),this.upsertCollectedRow(this.toFlatRow(p,1,null,n.query))&&await this.emitProgress("answer_captured"))}for(let{target:w,result:p}of k){let m=o.get(w.q);p.confirmed||m?.answer?.trim()?(U.add(w.q),S.delete(w.q)):(h.get(w.q)??0)>=r&&(S.add(w.q),l.add(w.q))}this.paaLifecycle={...this.paaLifecycle,processedQuestions:U.size,failedInteractions:S.size,noGrowthConfirmations:0,dispatchedInteractions:this.interactionObservations.filter(w=>w.dispatched).length,confirmedInteractions:this.interactionObservations.filter(w=>w.outcome==="confirmed").length,unconfirmedInteractions:this.interactionObservations.filter(w=>w.outcome!=="confirmed").length},await this.emitProgress("click_observed")}let L=n.questionsOnly?new Map:new Map(o);n.questionsOnly||await this.fillIncompleteItems(t,d,L,n,l);let O=[];for(let W of d){if(O.length>=n.maxQuestions)break;let C=this.normalizeQuestion(W);if(s.has(C))continue;s.add(C);let v=L.get(W);if(v){let I=this.toFlatRow(v,1,null,n.query);this.upsertCollectedRow(I),O.push(I),this.reporter.onQuestion({questionId:v.questionId,googleLinkId:v.googleLinkId,googleEvidenceId:v.googleEvidenceId,question:v.question,answer:v.answer??null,sourceTitle:v.sourceTitle??null,sourceSite:v.sourceSite??null,sourceCite:v.sourceCite??null,sources:v.sources,depth:1,parentQuestion:null,children:[]})}else{let I=this.toFlatRow({questionId:st(W),googleLinkId:null,googleEvidenceId:null,question:W,answer:void 0,sourceTitle:void 0,sourceSite:void 0,sourceCite:void 0,sources:[]},1,null,n.query);this.upsertCollectedRow(I),O.push(I)}}this.completeness.paaWithoutAnswer=n.questionsOnly?0:O.filter(W=>!W.answer).length,this.completeness.paaWithoutSource=n.questionsOnly?0:O.filter(W=>(W.sources??[]).length===0).length,this.completeness.paaRequested=n.maxQuestions,this.completeness.paaReturned=O.length,this.completeness.paaUnique=s.size;let H=!n.questionsOnly&&(this.completeness.paaWithoutAnswer>0||this.completeness.paaWithoutSource>0);return this.paaLifecycle={...this.paaLifecycle,questionsFound:O.length,targetStatus:O.length>=n.maxQuestions?"met":"not_met",materialStatus:H?"partial":"complete",processedQuestions:U.size,failedInteractions:S.size},await this.emitProgress("fill_incomplete"),await this.emitProgress("expansion_finished"),O}async fillIncompleteItems(t,n,a,s,i){let d=new Set(n.slice(0,s.maxQuestions)),l=S=>!S?.answer||(S.sources??[]).length===0,h=new Set([...d].filter(S=>l(a.get(S)))),U=new Set([...h].filter(S=>!a.get(S)?.answer));if(h.size!==0){for(let S of h){if(s.softDeadlineMs&&Date.now()>=s.softDeadlineMs)break;let o=(await this.extractVisibleItems(t,S))[0];if(!o)continue;let r=a.get(S);a.set(S,{...o,answer:o.answer??r?.answer,sourceTitle:o.sourceTitle??r?.sourceTitle,sourceSite:o.sourceSite??r?.sourceSite,sourceCite:o.sourceCite??r?.sourceCite,sources:this.mergePaaSources(r?.sources,o.sources)});let u=a.get(S);u&&this.upsertCollectedRow(this.toFlatRow(u,1,null,s.query))&&await this.emitProgress("fill_incomplete")}this.completeness.paaAnswersRecovered=[...U].filter(S=>a.get(S)?.answer).length}}async reExpandCollapsedItems(t){let n=`${F.item}:not(.${F.expandedClass}) ${F.clickTarget}`,a=await t.locator(n).count().catch(()=>0);if(a===0)return!1;for(let s=0;s<a;s++)try{let i=t.locator(n).first();await i.scrollIntoViewIfNeeded(),await i.click({force:!0}),await t.waitForTimeout(this.jitteredDelayMs(300,500))}catch{}return!0}async extractVideos(t){let n=Ae;return t.evaluate(a=>{let s=[],i=Array.from(document.querySelectorAll(a.container));for(let d of i){let U=(d.querySelector(a.sectionHeading)?.textContent?.trim()??"").toLowerCase().includes("short")?"short_video":"video",S=Array.from(d.querySelectorAll(a.item));for(let o of S){let r=o.href;if(!r||!r.includes("youtube")&&!r.includes("youtu.be"))continue;let u=o.textContent?.trim()??"",c=u.indexOf("YouTube");if(c===-1)continue;let g=u.slice(0,c).trim(),T=u.slice(c+7).replace(/^[·\s·]+/,"").match(/^([^·\n]+)/),b=T?T[1].trim():"";g&&s.push({type:U,title:g,channel:b,platform:"YouTube",duration:"",url:r})}}return s},n)}async extractForums(t){let n=Le;return t.evaluate(a=>{let s=[],d=Array.from(document.querySelectorAll(a.section)).find(h=>h.textContent?.includes("Discussions"));if(!d)return s;let l=Array.from(d.querySelectorAll(a.item));for(let h of l){let U=h.href;if(!U)continue;let S=h.querySelector(a.title),o=h.querySelector(a.source),r=S?.textContent?.trim()??"",u=o?.textContent?.trim()??"";r&&s.push({title:r,source:u,url:U})}return s},n)}async extractShortVideos(t,n){try{await t.goto(n,{waitUntil:"domcontentloaded"}),await t.waitForTimeout(1500)}catch{return[]}await this.throwIfCaptcha(t,"Google short video search");let a={item:It.item,platforms:[...It.platforms]};return(await t.evaluate(i=>{let d=new Set,l=[],h=Array.from(document.querySelectorAll(i.item)),U=["youtube.com","youtu.be","tiktok.com","instagram.com","facebook.com","fb.watch"],S=new Map;for(let o of h){let r=o.href;if(!r||!U.some(c=>r.includes(c)))continue;let u=o.textContent?.trim()??"";S.has(r)||S.set(r,[]),S.get(r).push(u)}for(let[o,r]of S.entries()){if(d.has(o))continue;d.add(o);let u=r.find(b=>/^\d+:\d+$/.test(b))??"",c=r.find(b=>!/^\d+:\d+$/.test(b)&&b.length>5)??"";if(!c)continue;let g=c,M="",T="";for(let b of i.platforms){let L=-1,O=0;for(;;){let I=c.indexOf(b,O);if(I===-1)break;L=I,O=I+1}if(L===-1)continue;let H=c.slice(L+b.length);if(!(/^[\s·]/.test(H)||H.trim()===""))continue;g=c.slice(0,L).trim(),M=b;let C=H.replace(/^[\s·]+/,""),v=C.indexOf("\xB7");T=(v===-1?C:C.slice(0,v)).trim();break}g&&l.push({title:g,channel:T,platform:M,duration:u,url:o})}return l},a)).map(i=>({type:"short_video",...i}))}async extractWhatPeopleSaying(t){let n=Oe;return t.evaluate(a=>{let s=Array.from(document.querySelectorAll(a.sectionTag)).find(i=>i.textContent?.includes(a.sectionHeadingText))??document.querySelector(".yG4QQe.TBC9ub.NbhJ1c");return s?Array.from(s.querySelectorAll(a.card)).map(i=>{let l=i.querySelector(a.cardLink)?.href??"",h=i.querySelector(a.titleH1)?.textContent?.trim(),U=i.querySelector(a.titleDiv)?.textContent?.trim(),S=h??U??"",o=i.querySelector(a.source)?.textContent?.trim()??"",u=i.querySelector(a.platformBadge)?.textContent?.trim()??"",c=i.querySelector(a.ytChannel)?.textContent?.trim()??"",g=i.querySelector(a.ytDate)?.textContent?.trim()??"",M=i.querySelector(a.authorNote)?.textContent?.trim()??null,T=i.querySelector(a.popularCommentLabel),b=null;if(T){let P=T.nextSibling;for(;P;){let N=P.textContent?.trim();if(N){b=N;break}P=P.nextSibling}}let L=Array.from(i.querySelectorAll("span")),O=L.find(P=>/^\d+:\d+$/.test(P.textContent?.trim()??""))?.textContent?.trim()??null,W=L.map(P=>P.textContent?.trim()??"").filter(P=>/\d/.test(P)&&(P.includes("comment")||P.includes("reaction")||P.includes("view")||P.includes("like")||P.includes("share")))[0]??"",C=L.map(P=>P.textContent?.trim()??"").filter(P=>/\d+ (day|week|month|year|hour)s? ago|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/.test(P)),v=g||(C[0]??""),I=u||(c?"YouTube":""),y=c||o,k="unknown",w=I.toLowerCase(),p=y.toLowerCase(),m=o.toLowerCase();return w.includes("reddit")||p.startsWith("r/")?k="reddit":w.includes("facebook")||m.includes("facebook")?k="facebook":w.includes("instagram")||m.includes("instagram")?k="instagram":w.includes("tiktok")||m.includes("tiktok")?k="tiktok":w.includes("youtube")||c?k="youtube":k="news",{type:k,title:S,url:l,source:y,platform:I,popularComment:b,engagement:W,date:v,duration:O,authorNote:M}}):[]},n)}async extractOrganicResults(t){let n=He,a=await t.evaluate(i=>{let d=[],l=0;return document.querySelectorAll(i.result).forEach(h=>{let U=h.querySelector(i.title);if(!U)return;let S=U.textContent?.trim()??"",r=U.closest("a")?.href??"";if(!S||!r)return;l++;let u=h.querySelector(i.cite)?.textContent?.trim()??null,c=h.querySelector(i.snippet)?.textContent?.trim()??null,g=!!h.querySelector(i.redditCite),M=h.querySelector(i.ratingWrap),T=M?{value:M.querySelector(i.ratingValue)?.textContent?.trim()??"",count:M.querySelector(i.reviewCount)?.textContent?.trim()??""}:null,b="";try{b=new URL(r).hostname.replace(/^www\./,"")}catch{b=h.querySelector(i.siteName)?.textContent?.trim()??""}d.push({position:l,title:S,url:r,domain:b,cite:u,snippet:c,isRedditStyle:g,inlineRating:T})}),d},n),s=typeof t.url=="function"?t.url():"https://www.google.com/";return a.flatMap(i=>{let d=Dt(i.url,s);if(!d)return[];let l=i.domain;try{l=new URL(d.resolvedUrl??d.rawUrl).hostname.replace(/^www\./,"")}catch{}return[{...i,...d,domain:l}]})}async extractLocalPack(t){let n=Fe;return t.evaluate(a=>{let s=[],i=null;return document.querySelectorAll('[role="heading"]').forEach(d=>{!i&&d.textContent?.includes(a.headingText)&&(i=d.closest("[data-hveid]"))}),i&&i.querySelectorAll(a.card).forEach((d,l)=>{let h=d.querySelector(a.name)?.textContent?.trim()??"";if(!h)return;let U=d.querySelector(a.ratingValue)?.textContent?.trim()??null,S=d.querySelector(a.reviewCount)?.textContent?.trim()??null,o=S?S.replace(/[()]/g,"").trim():null,r=d.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;if(!r)for(let T of Array.from(d.querySelectorAll("a[href]"))){let b=T.href.match(/[?&]cid=(\d+)/);if(b){r=b[1];break}let L=T.href.match(/!1s0x[0-9a-f]+:0x([0-9a-f]+)/i);if(L){try{r=BigInt("0x"+L[1]).toString()}catch{}if(r)break}}let u=[];d.querySelectorAll("div, span").forEach(T=>{let b=Array.from(T.childNodes).filter(L=>L.nodeType===3).map(L=>L.textContent?.trim()??"").filter(L=>L.length>1&&L.length<120).join(" ");b&&!u.includes(b)&&u.push(b)});let c=Array.from(d.querySelectorAll("a[href]")),g=c.find(T=>T.href.includes("google.com/maps"))?.href??null,M=c.find(T=>!T.href.includes("google.com")&&T.href.startsWith("http"))?.href??null;s.push({position:l+1,name:h,cid:r,rating:U,reviewCount:o,metadata:u,websiteUrl:M,directionsUrl:g})}),s},n)}async extractEntityIds(t){return t.evaluate(()=>{let n=new Set,a=new Set,s=new Set,i=new Map;function d(h){let U=[".OSrXXb",".dbg0pd",".tzt0oe",'[role="heading"]',"h3"];for(let S of U){let o=h.querySelector(S);if(o?.textContent?.trim())return o.textContent.trim()}return""}document.querySelectorAll('[id^="pv-/g/"]').forEach(h=>{let U=h.getAttribute("id");if(!U)return;let S=U.replace("pv-","");n.add(S);let o=d(h),u=h.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;u&&a.add(u),o&&i.set(S,{name:o,kgId:S,cid:u,gcid:null})}),document.querySelectorAll("[data-mid]").forEach(h=>{let U=h.getAttribute("data-mid");if(U?.startsWith("/g/")&&(n.add(U),!i.has(U))){let S=d(h);S&&i.set(U,{name:S,kgId:U,cid:null,gcid:null})}}),document.querySelectorAll(".w7Dbne").forEach(h=>{let S=h.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;if(!S)return;a.add(S);let o=h.querySelector(".OSrXXb")?.textContent?.trim()??"";if(!o)return;let r=h.querySelector('[id^="pv-/g/"]'),u=r?r.getAttribute("id").replace("pv-",""):null,c=u??`cid:${S}`;if(i.has(c)){let g=i.get(c);g.cid||i.set(c,{...g,cid:S})}else i.set(c,{name:o,kgId:u,cid:S,gcid:null})}),document.querySelectorAll("a[data-cid]").forEach(h=>{let U=h.getAttribute("data-cid");if(!U)return;if(a.add(U),![...i.values()].some(o=>o.cid===U)){let o=h.parentElement,r="";for(let u=0;u<8&&o;u++){let c=o.querySelector('.OSrXXb, .dbg0pd, [role="heading"], h3');if(c?.textContent?.trim()){r=c.textContent.trim();break}o=o.parentElement}r&&i.set(`cid:${U}`,{name:r,kgId:null,cid:U,gcid:null})}});let l=Array.from(document.querySelectorAll("script:not([src])")).map(h=>h.textContent??"").filter(h=>h.length>1e4).join(`
21704
- `);for(let h of l.matchAll(/\/g\/[a-zA-Z0-9_-]{5,20}/g))n.add(h[0]);for(let h of l.matchAll(/gcid:[a-zA-Z0-9_]+/g))s.add(h[0]);for(let h of l.matchAll(/0x[0-9a-f]+:0x([0-9a-f]+)/gi))try{a.add(BigInt("0x"+h[1]).toString())}catch{}return{entities:[...i.values()],kgIds:[...n],cids:[...a],gcids:[...s]}})}mergeLocalPackIntoEntities(t,n){let a=new Set(t.cids),s=t.entities.map(i=>({...i}));for(let i of n){if(!i.cid)continue;a.add(i.cid);let d=i.name.toLowerCase().trim(),l=s.find(h=>h.name.toLowerCase().trim()===d);l?l.cid||(l.cid=i.cid):s.find(h=>h.cid===i.cid)||s.push({name:i.name,kgId:null,cid:i.cid,gcid:null})}return{...t,entities:s,cids:[...a]}}async extractAISurfaces(t,n){let a=await t.evaluate(nn,{aio:xe,aim:Be,expandWaitMs:1500}),s=typeof t.url=="function"?t.url():"https://www.google.com/",i={surface:a.surface,aiOverview:{...a.aiOverview,citations:this.normalizeAICitations(s,a.aiOverview.citations)},aiMode:{...a.aiMode,citations:this.normalizeAICitations(s,a.aiMode.citations)}};if(!i.aiOverview.detected)return this.completeness.aioShareCaptured=null,i;let d=this.aioShareUrlEarly??await this.captureAIOverviewShareUrl(t,n).catch(()=>null);return this.completeness.aioShareCaptured=d!==null,{...i,aiOverview:{...i.aiOverview,shareUrl:d}}}async captureAIOverviewShareUrl(t,n){if(n?.softDeadlineMs&&Date.now()>=n.softDeadlineMs||!await t.evaluate(()=>{let i=Array.from(document.querySelectorAll('h1,h2,h3,[role="heading"],div')).filter(d=>(d.textContent||"").trim()==="AI Overview");for(let d of i){let l=d;for(let h=0;h<8&&l;h++){let U=l.querySelector('[aria-label="Share"]');if(U)return U.scrollIntoView({block:"center"}),U.click(),!0;l=l.parentElement}}return!1}).catch(()=>!1))return null;let s=null;try{s=await(await t.waitForFunction(()=>{let d=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT);for(;d.nextNode();){let l=(d.currentNode.textContent||"").match(/https:\/\/share\.google\/aimode\/\S+/);if(l)return l[0]}return!1},void 0,{timeout:4500,polling:250})).jsonValue()}catch{s=null}return await t.keyboard.press("Escape").catch(()=>{}),s}buildTree(t,n){let a=[],s=new Map;for(let i of t){let d={questionId:i.question_id,googleLinkId:i.google_link_id||null,googleEvidenceId:i.google_evidence_id||null,question:i.question,answer:i.answer||null,sourceTitle:i.source_title||null,sourceSite:i.source_site||null,sourceCite:i.source_cite||null,sources:i.sources??[],depth:i.depth,parentQuestion:i.parent_question||null,children:[]};s.set(i.question,d)}for(let i of s.values())i.parentQuestion&&s.has(i.parentQuestion)?s.get(i.parentQuestion).children.push(i):a.push(i);return a}getBrowserDebugSnapshot(){return this.driver.getDebugSnapshot()}buildHarvestDebugSnapshot(t,n,a,s,i){if(t.debug)return{enabled:!0,request:{query:t.query,locationInput:t.location??null,canonicalLocation:n,locationResolved:i?i.matched:null,locationMatchSource:i?i.source:null,locationAmbiguousCandidates:i?i.ambiguousCandidates:null,uule:a,gl:t.gl,hl:t.hl,device:t.device,proxyMode:t.proxyMode,proxyZip:t.proxyZip??null,serpIdentity:t.serpIdentity??null,serpOnly:t.serpOnly,pages:t.pages??1},browser:this.getBrowserDebugSnapshot(),...s?{locationEvidence:s}:{}}}async captureSecondOrganicPage(t,n,a){if(this.throwIfAborted(a),!this.driver.withTemporaryPage)return{organic:[],status:"failed",failureCode:"unsupported_driver"};let s;try{let i=new URL(t.url()),d=U=>{try{let S=new URL(U,i);return i.origin==="https://www.google.com"&&S.origin===i.origin&&!S.username&&!S.password&&S.pathname==="/search"&&S.searchParams.getAll("q").length===1&&S.searchParams.get("q")===n.query&&S.searchParams.getAll("start").length===1&&S.searchParams.get("start")==="10"&&(!S.searchParams.has("num")||S.searchParams.get("num")==="10")&&["gl","hl"].every(o=>!S.searchParams.has(o)||S.searchParams.getAll(o).length===1&&S.searchParams.get(o)===n[o])&&["uule","tbs","udm","tbm","pws"].every(o=>S.searchParams.getAll(o).length<=1&&S.searchParams.get(o)===i.searchParams.get(o))}catch{return!1}},l=await t.evaluate(()=>document.querySelector('a#pnnext, a[rel="next"]')?.getAttribute("href")??null);if(!l)return{organic:[],status:"unavailable",failureCode:"missing_next"};if(!d(l))return{organic:[],status:"unavailable",failureCode:"invalid_next"};let h=await this.driver.withTemporaryPage(async U=>{if(await U.route("**/*",async S=>{let o=S.request();o.isNavigationRequest()&&o.frame()===U.mainFrame()&&!d(o.url())?(s=/^https:\/\/www\.google\.com\/sorry(?:\/|\?)/.test(o.url())?"captcha":"invalid_next",await S.abort("blockedbyclient")):await S.fallback()}),await U.goto(new URL(l,i).href,{waitUntil:"domcontentloaded",timeout:2e4}),this.throwIfAborted(a),await this.throwIfCaptcha(U,"Google SERP page 2"),!d(U.url()))throw s="invalid_next",new Error("Invalid pagination landing");return this.extractOrganicResults(U)},a);return this.throwIfAborted(a),h.length>0?{organic:h.map(U=>({...U,position:U.position+10})),status:"captured"}:{organic:[],status:"unavailable",failureCode:"empty_page"}}catch(i){if(this.throwIfAborted(a),i instanceof q)throw i;return{organic:[],status:"failed",failureCode:s??(i instanceof K?"captcha":i instanceof Error&&(i.name==="TimeoutError"||/timed? ?out/i.test(i.message))?"timeout":"navigation_error")}}}async extract(t,n){let a=Date.now();this.completeness={paaWithoutAnswer:0,paaWithoutSource:0,paaAnswersRecovered:0,aioShareCaptured:null},this.linkDiagnostics=this.emptyLinkDiagnostics(),this.aioShareUrlEarly=null,this.collectedRows=[],this.progressSequence=0,this.checkpointMaterial=null,this.clickedQuestions=new Set,this.paaLifecycle=this.emptyPaaLifecycle(t.maxQuestions),this.partialContext={seed:t.query,location:t.location??null,startMs:a,maxQuestions:t.maxQuestions,questionsOnly:t.questionsOnly};let s=t.device==="mobile",i={headless:t.headless,profileDir:t.profileDir,proxy:t.proxy,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,\u006b\u0065\u0072\u006e\u0065\u006cProxyId:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,\u006b\u0065\u0072\u006e\u0065\u006cProfileName:t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName,\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges:t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges,\u006b\u0065\u0072\u006e\u0065\u006cStealth:t.\u006b\u0065\u0072\u006e\u0065\u006cStealth,\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution,proxyMode:t.proxyMode,keepDefaultProxy:t.keepDefaultProxy,requireUsEgress:t.requireUsEgress,viewport:s?{width:390,height:844}:{width:1280,height:800},locale:`${t.hl}-${t.gl.toUpperCase()}`,deviceScaleFactor:s?3:1,isMobile:s,hasTouch:s,debug:t.debug,operationDeadlineMs:t.softDeadlineMs},d=0,l=[];try{this.throwIfAborted(n);let h=Date.now();await this.driver.launch(i),this.phaseTimings.providerConnectMs=Date.now()-h;let U=this.driver.getProviderSessionMetadata?.();if(U?.providerSessionId&&this.onProviderSession)try{await this.onProviderSession(U)}catch(B){console.warn(JSON.stringify({event:"paa_provider_session_sink_failed",provider:U.provider,message:B instanceof Error?B.message:String(B)}))}this.throwIfAborted(n);let S=t.location?ae(t.location):null,o=t.location?S?.canonical??t.location:null,r=o?je(o):null,u=t,c=t.includeAllSerpFeatures,g=c||t.includeLocalPack,M=c||t.includeForums,T=c||t.includeVideos,b=c||t.includeAiOverview,L=c||t.includeWhatPeopleSaying,O={surface:"web",aiOverview:{detected:!1,text:null,citations:[]},aiMode:{detected:!1,text:null,citations:[]}},H=Date.now(),{hasPaa:W}=await this.driver.navigateToSERP(u.query,r,t.gl,t.hl,{...gt(t.recency)?{tbs:gt(t.recency)}:{},debug:t.debug,purpose:t.serpOnly?"serp":"paa",...t.softDeadlineMs?{deadlineMs:t.softDeadlineMs}:{}});this.phaseTimings.navigationMs=Date.now()-H,this.throwIfAborted(n);let C=this.driver.getPage();if(await this.throwIfCaptcha(C,"Google SERP"),W||(this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"no_paa_observed",materialStatus:"complete",completionReason:"A readable Google SERP was observed without a People Also Ask block."}),t.questionsOnly){let B=Date.now(),E=W?await this.runBFS(C,u,n):[];this.phaseTimings.paaExpansionMs=Date.now()-B,await this.resolveMaterialLinks(C,E,[],O.aiOverview,O.aiMode);let $={seed:u.query,totalQuestions:E.length,maxDepthReached:E.reduce((ut,ct)=>Math.max(ut,ct.depth),0),durationMs:Date.now()-a,errorCount:d};return this.reporter.onComplete($),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:W?"paa_found":"no_paa",...W?{}:{noPaaObserved:!0},problem:null,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,o,r,void 0,S)}:{}},totalQuestions:E.length,surface:"web",aiOverview:{detected:!1,text:null,citations:[]},aiMode:{detected:!1,text:null,citations:[]},whatPeopleSaying:[],tree:this.buildTree(E,u.query),flat:E,videos:[],forums:[],organicResults:[],localPack:[],entityIds:{entities:[],kgIds:[],cids:[],gcids:[]},stats:$}}if(b&&(this.aioShareUrlEarly=await this.captureAIOverviewShareUrl(C,t).catch(()=>null)),t.serpOnly){let B=Date.now(),[E,$,ut]=await Promise.all([this.extractOrganicResults(C),g?this.extractLocalPack(C):Promise.resolve([]),this.extractEntityIds(C)]),ct=this.mergeLocalPackIntoEntities(ut,$),at=b?await this.extractAISurfaces(C,t):O;this.phaseTimings.serpParseMs=Date.now()-B;let mt=t.debug?Mt(o,E,$):void 0,dt=E;if((t.pages??1)>=2){let wt=new URLSearchParams({q:u.query,gl:t.gl,hl:t.hl,pws:"0",start:"10"});gt(t.recency)&&wt.set("tbs",gt(t.recency)),r&&wt.set("uule",r),await this.driver.navigateTo("https://www.google.com/search?"+wt.toString()),await this.throwIfCaptcha(C,"Google SERP page 2");let Nt=await this.extractOrganicResults(C);dt=[...E,...Nt.map(rt=>({...rt,position:rt.position+10}))],t.debug&&(mt=Mt(o,dt,$))}await this.resolveMaterialLinks(C,[],dt,at.aiOverview,at.aiMode);let vt={seed:u.query,totalQuestions:0,maxDepthReached:0,durationMs:Date.now()-a,errorCount:d};return this.reporter.onComplete(vt),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"serp_only",problem:null,completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,o,r,mt,S)}:{}},totalQuestions:0,surface:at.surface,aiOverview:at.aiOverview,aiMode:at.aiMode,whatPeopleSaying:[],tree:[],flat:[],videos:[],forums:[],organicResults:dt,localPack:$,entityIds:ct,stats:vt}}let[v,I,y,k,w,p]=await Promise.all([T?this.extractVideos(C):Promise.resolve([]),M?this.extractForums(C):Promise.resolve([]),L?this.extractWhatPeopleSaying(C):Promise.resolve([]),this.extractEntityIds(C),this.extractOrganicResults(C),g?this.extractLocalPack(C):Promise.resolve([])]),m=this.mergeLocalPackIntoEntities(k,p),P=t.debug?Mt(o,w,p):void 0;this.reporter.onVideos(v),this.reporter.onForums(I);let N=b?await this.extractAISurfaces(C,t):O,A={requestedPages:(t.pages??1)>=2?2:1,capturedPages:1,page2Status:(t.pages??1)>=2?"not_attempted":"not_requested",page1OrganicCount:w.length,page2OrganicCount:0},f=w;if(this.checkpointMaterial={surface:N.surface,aiOverview:N.aiOverview,aiMode:N.aiMode,whatPeopleSaying:y,videos:v,forums:I,organicResults:f,localPack:p,entityIds:m,pagination:A},await this.emitProgress("serp_captured"),A.requestedPages===2){let B=await this.captureSecondOrganicPage(C,u,n);f=[...w,...B.organic],A={...A,capturedPages:B.status==="captured"?2:1,page2Status:B.status,page2OrganicCount:B.organic.length,...B.failureCode?{failureCode:B.failureCode}:{}},this.checkpointMaterial={...this.checkpointMaterial,organicResults:f,pagination:A},await this.emitProgress("serp_captured"),await this.resolveMaterialLinks(C,[],f,N.aiOverview,N.aiMode),this.checkpointMaterial={...this.checkpointMaterial,organicResults:f},await this.emitProgress("serp_captured")}let G=t.debug?Mt(o,f,p):P;if(!W){await this.resolveMaterialLinks(C,[],f,N.aiOverview,N.aiMode),this.checkpointMaterial={...this.checkpointMaterial,organicResults:f},await this.emitProgress("serp_captured");let B={seed:u.query,totalQuestions:0,maxDepthReached:0,durationMs:Date.now()-a,errorCount:d};return this.reporter.onComplete(B),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"no_paa",noPaaObserved:!0,problem:null,pagination:A,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,o,r,G,S)}:{}},totalQuestions:0,surface:N.surface,aiOverview:N.aiOverview,aiMode:N.aiMode,whatPeopleSaying:y,tree:[],flat:[],videos:v,forums:I,organicResults:f,localPack:p,entityIds:m,stats:B}}let x=Date.now(),D=await this.runBFS(C,u,n);this.phaseTimings.paaExpansionMs=Date.now()-x,this.throwIfAborted(n);let _=new URLSearchParams({q:u.query,gl:t.gl,hl:t.hl,pws:"0",udm:It.udm});r&&_.set("uule",r);let Q=[];if(t.includeShortVideos!==!1)try{Q=await this.extractShortVideos(C,"https://www.google.com/search?"+_.toString())}catch(B){if(!(B instanceof K))throw B;d++,l.push({code:"short_videos_captcha_skipped",surface:"short_videos",message:B.message,retryable:!0})}this.reporter.onVideos(Q),await this.resolveMaterialLinks(C,D,f,N.aiOverview,N.aiMode),this.checkpointMaterial={...this.checkpointMaterial,surface:N.surface,aiOverview:N.aiOverview,aiMode:N.aiMode,videos:[...v,...Q],organicResults:f},await this.emitProgress("expansion_finished");let V=[...v,...Q],R=this.buildTree(D,u.query),z={seed:u.query,totalQuestions:D.length,maxDepthReached:D.reduce((B,E)=>Math.max(B,E.depth),0),durationMs:Date.now()-a,errorCount:d};return this.reporter.onComplete(z),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"paa_found",problem:null,pagination:A,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...l.length>0?{warnings:l}:{},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,o,r,G,S)}:{}},totalQuestions:D.length,surface:N.surface,aiOverview:N.aiOverview,aiMode:N.aiMode,whatPeopleSaying:y,tree:R,flat:D,videos:V,forums:I,organicResults:f,localPack:p,entityIds:m,stats:z}}catch(h){throw d++,this.paaLifecycle.discoveryStatus==="in_progress"&&(this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"interrupted",completionReason:"The browser attempt ended before frontier exhaustion could be proven."}),await this.emitProgress("attempt_ending").catch(()=>{}),this.reporter.onError(h instanceof Error?h:new Error(String(h))),h}}};import{promises as J}from"fs";import ot from"path";import Ut from"papaparse";var Yt=class{async writeJSON(t,n){await J.mkdir(n,{recursive:!0});let s=`${t.seed.toLowerCase().replace(/\W+/g,"-").slice(0,40)}-${Date.now()}.json`,i=ot.join(n,s);return await J.writeFile(i,JSON.stringify(t,null,2),"utf8"),await Ie({title:`${t.seed} scrape`,content:JSON.stringify(t),source:`mcp-scraper:${i}`}),i}async writeCSV(t,n){await J.mkdir(n,{recursive:!0});let s=(t[0]?.seed_query??"paa").toLowerCase().replace(/\W+/g,"-").slice(0,40),i=Ut.unparse(t.map(({sources:h,...U})=>({...U,sources_json:JSON.stringify(h)})),{header:!0}),d=`${s}-${Date.now()}.csv`,l=ot.join(n,d);return await J.writeFile(l,i,"utf8"),l}async writeVideoCSV(t,n,a){await J.mkdir(a,{recursive:!0});let s=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),i=Ut.unparse(t,{header:!0}),d=`${s}-videos-${Date.now()}.csv`,l=ot.join(a,d);return await J.writeFile(l,i,"utf8"),l}async writeForumCSV(t,n,a){await J.mkdir(a,{recursive:!0});let s=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),i=Ut.unparse(t,{header:!0}),d=`${s}-forums-${Date.now()}.csv`,l=ot.join(a,d);return await J.writeFile(l,i,"utf8"),l}async writeAIOverviewCSV(t,n,a,s){await J.mkdir(s,{recursive:!0});let i=a.toLowerCase().replace(/\W+/g,"-").slice(0,40),d=t.map((S,o)=>({seed_query:a,response_text:o===0?n??"":"",citation_text:S.text,citation_href:S.href})),l=Ut.unparse(d,{header:!0}),h=`${i}-ai-overview-${Date.now()}.csv`,U=ot.join(s,h);return await J.writeFile(U,l,"utf8"),U}async writeAIModeCSV(t,n,a,s){await J.mkdir(s,{recursive:!0});let i=a.toLowerCase().replace(/\W+/g,"-").slice(0,40),d=t.map((S,o)=>({seed_query:a,response_text:o===0?n??"":"",citation_text:S.text,citation_href:S.href})),l=Ut.unparse(d,{header:!0}),h=`${i}-ai-mode-${Date.now()}.csv`,U=ot.join(s,h);return await J.writeFile(U,l,"utf8"),U}async writeWhatPeopleSayingCSV(t,n,a){await J.mkdir(a,{recursive:!0});let s=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),i=t.map(U=>({seed_query:n,...U})),d=Ut.unparse(i,{header:!0}),l=`${s}-what-people-saying-${Date.now()}.csv`,h=ot.join(a,l);return await J.writeFile(h,d,"utf8"),h}};var Et=class{onQuestion(t){process.stdout.write(JSON.stringify({event:"question",depth:t.depth,question:t.question})+`
21702
+ `).trim();return!I||/not available|try again|can't generate/i.test(I)?null:I}function h(g){if(!g||g.startsWith("javascript:"))return null;try{let P=new URL(g,window.location.href);return!["http:","https:"].includes(P.protocol)||P.username||P.password?null:{href:P.href,rawHref:P.href}}catch{return null}}function l(g){if(!g)return[];let P=new Set,w=[];for(let M of Array.from(g.querySelectorAll("a[href]"))){let k=h(M.getAttribute("href")??"");if(!k||P.has(k.rawHref))continue;P.add(k.rawHref);let v="";try{v=new URL(k.href).hostname.replace(/^www\./,"")}catch{}w.push({text:s(M)||v||k.href,href:k.href,rawHref:k.rawHref})}return w}async function o(g){let P=g.querySelector(t.aio.showMoreButton);if(!P||P.getAttribute("aria-expanded")!=="false")return!1;P.click();let w=t.expandWaitMs??1500;return w>0&&await new Promise(M=>setTimeout(M,w)),!0}let r=S(),u=null,c=[],y=!1,m=!1,f=[];if(r){y=await o(r);let g=r.querySelector(t.aio.controller),P=r.querySelector(t.aio.contentSubtree),w=r.querySelector(t.aio.showMoreButton);m=g?.getAttribute("data-trnct")==="false"||w?.getAttribute("aria-expanded")==="true"||!w,u=U(P??g??r),f=(u??"").split(`
21703
+ `).map(M=>M.trim()).filter(M=>/^\d+\.\s+.+/.test(M)),c=l(r)}let C=document.querySelector(t.aim.root),O=a==="aim"&&!!C,L=C?.closest(t.aim.wrapper)??C,x=O?U(L):null,N=O&&i(x),p=N?x:null,A=N?l(L):[],T=!!r&&i(u);return{surface:a,aiOverview:{detected:T,text:T?u:null,citations:T?c:[],expanded:T?y:!1,fullyExpanded:T?m:!1,sections:T?f:[]},aiMode:{detected:N&&p!==null,text:p,citations:A}}}import{createHash as Sa}from"crypto";var on=8e3,dn=3e3,rn=1e4,Ua=8;function et(e){return/(^|\.)google\.(?:com|[a-z]{2,3}(?:\.[a-z]{2})?)$/i.test(e)}function pt(e){if(!e||e.length>on)return null;try{let t=new URL(e);return t.protocol!=="http:"&&t.protocol!=="https:"||t.username||t.password?null:t}catch{return null}}function ha(e,t){if(!e||e.length>on||/^javascript:/i.test(e))return null;try{let n=new URL(e,t);return pt(n.href)}catch{return null}}function kt(e){let t=pt(e);return!t||t.protocol!=="https:"||!et(t.hostname)||t.pathname!=="/goto"?null:t.searchParams.get("url")?t:null}function de(e){if(e.linkType!=="google_goto_redirect"||e.resolutionStatus!=="resolved"||!kt(e.rawUrl)||!e.resolvedUrl)return!1;let t=pt(e.resolvedUrl);return!!(t&&!et(t.hostname)&&t.href===e.resolvedUrl&&e.url===t.href)}function dt(e){let t=e.normalize("NFKC").toLocaleLowerCase("en-US").replace(/[^\p{L}\p{N}\s]/gu,"").replace(/\s+/g," ").trim();return`paa_${Sa("sha256").update(t).digest("hex").slice(0,16)}`}function Dt(e,t){let n=ha(e,t);if(!n)return null;let a=n.href;if(!et(n.hostname))return{url:a,rawUrl:a,resolvedUrl:a,linkType:"plain",resolutionStatus:"not_needed"};if(n.pathname==="/url"){let s=pt(n.searchParams.get("q")??n.searchParams.get("url")??"");return!s||et(s.hostname)?null:{url:s.href,rawUrl:a,resolvedUrl:s.href,linkType:"google_url_redirect",resolutionStatus:"resolved"}}return n.pathname==="/goto"&&n.searchParams.get("url")?{url:a,rawUrl:a,resolvedUrl:null,linkType:"google_goto_redirect",resolutionStatus:"unresolved"}:null}function re(e){return kt(e)?.searchParams.get("url")??null}function ln(e,t){try{let n=new URL(e),a=pt(new URL(t,n).href);return!a||et(a.hostname)?null:(!a.hash&&n.hash&&(a.hash=n.hash),a.href)}catch{return null}}async function Sn(e,t={}){let n=[...new Set([...e].flatMap(o=>kt(o)?[o]:[]))],a=new Map(n.map(o=>[o,{rawUrl:o,resolvedUrl:null,resolutionStatus:"unresolved"}])),s=typeof globalThis.fetch=="function"?globalThis.fetch.bind(globalThis):null,i=t.fetchImpl??s;if(n.length===0||!i)return{resolutions:[...a.values()],nonGoogleRequestsObserved:0};let d=Math.max(1,t.timeoutMs??dn),S=Date.now()+Math.max(1,t.totalBudgetMs??rn),U=Math.max(1,Math.min(16,Math.floor(t.concurrency??Ua))),h=0,l=async()=>{for(;h<n.length;){let o=n[h++],r=kt(o),u=r?.searchParams.get("url");if(!r||!u){a.set(o,{rawUrl:o,resolvedUrl:null,resolutionStatus:"rejected"});continue}r.hash="";let c=r.href;for(let y=0;y<2;y++){let m=S-Date.now();if(m<=0)return;let f=new AbortController,C=setTimeout(()=>f.abort(),Math.min(d,m)),O;try{O=await i(c,{method:"GET",redirect:"manual",headers:{accept:"*/*","user-agent":"Mozilla/5.0"},signal:f.signal})}catch{break}finally{clearTimeout(C)}if(O.status<300||O.status>=400)break;let L=O.headers.get("location");if(!L)break;let x=ln(o,L);if(x){a.set(o,{rawUrl:o,resolvedUrl:x,resolutionStatus:"resolved"});break}let N;try{N=new URL(L,c)}catch{a.set(o,{rawUrl:o,resolvedUrl:null,resolutionStatus:"rejected"});break}if(!et(N.hostname)||re(N.href)!==u){a.set(o,{rawUrl:o,resolvedUrl:null,resolutionStatus:"rejected"});break}c=N.href}}};return await Promise.all(Array.from({length:Math.min(U,n.length)},()=>l())),{resolutions:[...a.values()],nonGoogleRequestsObserved:0}}function sn(e,t){try{return new URL(e.resolvedUrl??e.url).hostname.replace(/^www\./,"")}catch{return t}}async function Un(e,t={}){let n=[],a=o=>{for(let r of o)n.push(r),a(r.children??[])};a(e.tree??[]);let s=[...e.flat.flatMap(o=>o.sources??[]),...n.flatMap(o=>o.sources),...e.organicResults??[],...(e.aiOverview?.citations??[]).map(({text:o,href:r,...u})=>({...u,url:r})),...(e.aiMode?.citations??[]).map(({text:o,href:r,...u})=>({...u,url:r}))],i=new Map(s.filter(o=>!!o?.rawUrl).map(o=>[o.rawUrl,o])),d=[...i.values()].filter(o=>o.linkType==="google_goto_redirect"&&o.resolutionStatus!=="resolved").map(o=>o.rawUrl);if(d.length>0){let o=await Sn(d,t);for(let r of o.resolutions){let u=i.get(r.rawUrl);u&&i.set(r.rawUrl,r.resolutionStatus==="resolved"&&r.resolvedUrl?{...u,url:r.resolvedUrl,resolvedUrl:r.resolvedUrl,resolutionStatus:"resolved"}:{...u,resolutionStatus:r.resolutionStatus})}}let S=o=>({...o,...i.get(o.rawUrl)??o}),U=o=>o.map(r=>{let u=S(r);return{...u,site:sn(u,r.site)}});for(let o of e.flat){o.sources=U(o.sources??[]);let r=o.sources[0];o.source_title=r?.title??o.source_title,o.source_site=r?.site??o.source_site,o.source_cite=r?.url??o.source_cite}for(let o of n){o.sources=U(o.sources??[]);let r=o.sources[0];o.sourceTitle=r?.title??o.sourceTitle,o.sourceSite=r?.site??o.sourceSite,o.sourceCite=r?.url??o.sourceCite}for(let o=0;o<(e.organicResults?.length??0);o++){let r=S(e.organicResults[o]);e.organicResults[o]={...r,domain:sn(r,e.organicResults[o].domain)??""}}let h=o=>{let r=S({url:o.href,rawUrl:o.rawUrl,resolvedUrl:o.resolvedUrl,linkType:o.linkType,resolutionStatus:o.resolutionStatus}),{url:u,...c}=r;return{...o,...c,href:u}};e.aiOverview&&(e.aiOverview.citations=(e.aiOverview.citations??[]).map(h)),e.aiMode&&(e.aiMode.citations=(e.aiMode.citations??[]).map(h));let l=[...i.values()];return e.diagnostics.links={linkCandidatesObserved:i.size,plainLinksObserved:l.filter(o=>o.linkType==="plain").length,googleUrlRedirectsObserved:l.filter(o=>o.linkType==="google_url_redirect").length,googleGotoRedirectsObserved:l.filter(o=>o.linkType==="google_goto_redirect").length,redirectsResolved:l.filter(o=>o.linkType!=="plain"&&o.resolutionStatus==="resolved").length,redirectsUnresolved:l.filter(o=>o.resolutionStatus==="unresolved").length,redirectsRejected:l.filter(o=>o.resolutionStatus==="rejected").length,resolverNonGoogleRequestsObserved:0,paaSourcesPreserved:e.flat.reduce((o,r)=>o+r.sources.length,0),aiOverviewLabelValidated:e.aiOverview?.detected??!1},e}async function hn(e,t,n={}){let a=new Map;for(let r of t){let u=a.get(r.rawUrl);u&&de(u)||a.set(r.rawUrl,r.linkType==="google_goto_redirect"&&!de(r)?{...r,url:r.rawUrl,resolvedUrl:null,resolutionStatus:"unresolved"}:r)}let s=[...a.values()].filter(r=>r.linkType==="google_goto_redirect"&&!de(r));if(s.length===0)return a;let i=Date.now()+(n.totalBudgetMs??rn),d=await Sn(s.map(r=>r.rawUrl),n);for(let r of d.resolutions){let u=a.get(r.rawUrl);u&&a.set(r.rawUrl,r.resolutionStatus==="resolved"&&r.resolvedUrl?{...u,url:r.resolvedUrl,resolvedUrl:r.resolvedUrl,resolutionStatus:"resolved"}:{...u,resolutionStatus:r.resolutionStatus})}let S=s.filter(r=>a.get(r.rawUrl)?.resolutionStatus==="unresolved");if(S.length===0||n.browserFallback===!1||Date.now()>=i)return n.onNetworkAudit?.({nonGoogleRequestsObserved:0}),a;let U=n.timeoutMs??dn,h=await e.context().newPage().catch(()=>null);if(!h)return n.onNetworkAudit?.({nonGoogleRequestsObserved:0}),a;let l=null,o=0;try{await h.route("**/*",async r=>{let u=r.request().url();try{et(new URL(u).hostname)||(o+=1)}catch{}let c=re(u);if(!l||c!==l.token){await r.abort("blockedbyclient").catch(()=>{});return}let y=l;try{let m=await r.fetch({maxRedirects:0,timeout:y.timeoutMs});y.location=m.headers().location??null}finally{await r.abort("blockedbyclient").catch(()=>{}),y.finish()}});for(let r of S){let u=i-Date.now();if(u<=0)break;let c=kt(r.rawUrl),y=c?.searchParams.get("url");if(!c||!y){a.set(r.rawUrl,{...r,resolutionStatus:"rejected"});continue}let m=Math.min(U,u);c.hash="";let f=c.href,C=!1;for(let O=0;O<2;O++){let L,x=new Promise(g=>{L=g}),N=`mcp-goto-${Math.random().toString(36).slice(2)}`;l={token:y,timeoutMs:m,location:null,finish:L},await h.evaluate(({url:g,id:P})=>{let w=document.createElement("iframe");w.id=P,w.hidden=!0,w.src=g,document.body.append(w)},{url:f,id:N}).catch(()=>null),await Promise.race([x,new Promise(g=>setTimeout(g,m))]);let p=l.location;if(l=null,await h.evaluate(g=>document.getElementById(g)?.remove(),N).catch(()=>null),!p)break;let A=ln(r.rawUrl,p);if(A){a.set(r.rawUrl,{...r,url:A,resolvedUrl:A,resolutionStatus:"resolved"});break}let T;try{T=new URL(p,f)}catch{C=!0;break}if(!et(T.hostname)||re(T.href)!==y){C=!0;break}f=T.href}C&&a.get(r.rawUrl)?.resolutionStatus!=="resolved"&&a.set(r.rawUrl,{...r,resolutionStatus:"rejected"})}}finally{l=null,await h.close().catch(()=>{}),n.onNetworkAudit?.({nonGoogleRequestsObserved:o})}return a}var un=String.raw`^(?:an error has occurred(?:[.!…]\s*)?(?:please try again later[.!…]?)?|loading|please wait|try again|something went wrong)[.!…\s]*$`,ua=700,ca=1e3,wa=1400,cn=900,ga=3,wn=250,Vt=class{constructor(t,n,a,s){this.driver=t;this.reporter=n;this.onPaaProgress=a;this.onProviderSession=s}driver;reporter;onPaaProgress;onProviderSession;completeness={paaWithoutAnswer:0,paaWithoutSource:0,paaAnswersRecovered:0,aioShareCaptured:null};aioShareUrlEarly=null;linkDiagnostics=this.emptyLinkDiagnostics();collectedRows=[];partialContext=null;progressSequence=0;clickedQuestions=new Set;paaLifecycle=this.emptyPaaLifecycle(0);checkpointMaterial=null;interactionObservations=[];phaseTimings={};currentPhaseTimings(t){return{...this.phaseTimings,totalServerMs:Math.max(0,Date.now()-t)}}emptyPaaLifecycle(t){return{requestedQuestions:t,questionsFound:0,targetStatus:"not_met",discoveryStatus:"in_progress",materialStatus:"partial",completionReason:"PAA expansion is still running.",automaticRetries:0,retryBreakdown:{controlRetries:0,browserRetries:0,providerFallbacks:0,runtimeRecoveries:0,idempotentReplays:0},knownQuestions:0,processedQuestions:0,failedInteractions:0,noGrowthConfirmations:0,visibleControls:0,eligibleControls:0,dispatchedInteractions:0,confirmedInteractions:0,unconfirmedInteractions:0}}emptyLinkDiagnostics(){return{linkCandidatesObserved:0,plainLinksObserved:0,googleUrlRedirectsObserved:0,googleGotoRedirectsObserved:0,redirectsResolved:0,redirectsUnresolved:0,redirectsRejected:0,resolverNonGoogleRequestsObserved:0,paaSourcesPreserved:0,aiOverviewLabelValidated:!1}}mergePaaSources(t=[],n=[]){let a=new Map;for(let s of[...t,...n]){let i=a.get(s.rawUrl);if(!i){a.set(s.rawUrl,s);continue}let d=s.resolutionStatus==="resolved"&&i.resolutionStatus!=="resolved"?s:i;a.set(s.rawUrl,{...d,title:d.title??i.title??s.title,site:d.site??i.site??s.site})}return[...a.values()]}normalizeAICitations(t,n){let a=new Set;return n.flatMap(s=>{let i=Dt(s.rawHref??s.href,t);if(!i||a.has(i.rawUrl))return[];a.add(i.rawUrl);let{url:d,...S}=i;return[{...S,text:s.text,href:d}]})}async resolveMaterialLinks(t,n,a,s,i){let d=Date.now(),S=[...n.flatMap(c=>c.sources??[]),...a,...s.citations.map(({text:c,href:y,...m})=>({...m,url:y})),...i.citations.map(({text:c,href:y,...m})=>({...m,url:y}))],U=new Map(S.map(c=>[c.rawUrl,c])),h=0,l=await hn(t,S,{onNetworkAudit:c=>{h=c.nonGoogleRequestsObserved}}),o=c=>({...c,...l.get(c.rawUrl)??c});for(let c of n){c.sources=(c.sources??[]).map(o);let y=c.sources[0];c.source_title=y?.title??c.source_title,c.source_site=y?.site??c.source_site,c.source_cite=y?.url??c.source_cite}for(let c=0;c<a.length;c++){let y=o(a[c]);if(y.resolvedUrl)try{y.domain=new URL(y.resolvedUrl).hostname.replace(/^www\./,"")}catch{}a[c]=y}let r=c=>{let y=o({url:c.href,rawUrl:c.rawUrl,resolvedUrl:c.resolvedUrl,linkType:c.linkType,resolutionStatus:c.resolutionStatus}),{url:m,...f}=y;return{...f,text:c.text,href:m}};s.citations=s.citations.map(r),i.citations=i.citations.map(r);let u=[...l.values()];this.linkDiagnostics={linkCandidatesObserved:U.size,plainLinksObserved:u.filter(c=>c.linkType==="plain").length,googleUrlRedirectsObserved:u.filter(c=>c.linkType==="google_url_redirect").length,googleGotoRedirectsObserved:u.filter(c=>c.linkType==="google_goto_redirect").length,redirectsResolved:u.filter(c=>c.linkType!=="plain"&&c.resolutionStatus==="resolved").length,redirectsUnresolved:u.filter(c=>c.resolutionStatus==="unresolved").length,redirectsRejected:u.filter(c=>c.resolutionStatus==="rejected").length,resolverNonGoogleRequestsObserved:h,paaSourcesPreserved:n.reduce((c,y)=>c+(y.sources??[]).length,0),aiOverviewLabelValidated:s.detected},this.phaseTimings.linkResolutionMs=(this.phaseTimings.linkResolutionMs??0)+(Date.now()-d)}normalizeQuestion(t){return t.toLowerCase().replace(/[^\w\s]/g,"").replace(/\s+/g," ").trim()}throwIfAborted(t){if(t?.aborted)throw t.reason instanceof DOMException&&t.reason.name==="TimeoutError"?t.reason:new $}async throwIfCaptcha(t,n){if(await t.locator(H.captchaMarker).count().catch(()=>0)>0)throw new E(`${n} returned a CAPTCHA \u2014 retrying with a fresh session.`)}async extractVisibleItems(t,n){let a=H,s=await t.evaluate(({selectors:d,onlyQuestion:S,answerPlaceholderPattern:U})=>{function h(o){if(!o)return"";let r=[];for(let u of o.childNodes)if(u.nodeType===Node.TEXT_NODE){let c=u.textContent?.trim();c&&r.push(c)}else{if(u.tagName==="STYLE"||u.tagName==="SCRIPT")continue;{let c=h(u);c&&r.push(c)}}return r.join(" ").replace(/\s+/g," ").trim()}function l(o){return(o??"").replace(/\s*\(\+\d+\)\s*-\s*View related links.*$/i,"").replace(/\s*-\s*Opens in new tab.*$/i,"").trim()}return Array.from(document.querySelectorAll(d.item)).filter(o=>!S||(o.getAttribute(d.itemDataQ)||o.getAttribute(d.itemDataInitQ)||o.querySelector(d.itemQuestionEl)?.innerText?.trim()||"")===S).map(o=>{let r=o.querySelector(d.clickTarget),u=o.classList.contains(d.expandedClass)||r?.getAttribute("aria-expanded")==="true",c=o.querySelector(d.answerContainer),m=c?.querySelector(d.aiAnswerBody)??c,f=h(m),C=new RegExp(U,"i").test(f),O=[...Array.from((m??o).querySelectorAll("a[href]")),...Array.from(o.querySelectorAll(d.aiCitation)),...Array.from(o.querySelectorAll(d.aiSourceCard))],L=!C&&(u&&f.length>=10||f.length>30&&O.some(A=>/^https?:\/\//.test(A.href))),x=L&&o.querySelector(d.sourceTitle)?.innerText?.trim()||void 0,N=L&&o.querySelector(d.sourceSite)?.innerText?.trim()||void 0,p=[];if(L){let A=new Set;for(let g of O)!/^https?:\/\//.test(g.href)||A.has(g.href)||(A.add(g.href),p.push({title:l(g.getAttribute("aria-label"))||(g.textContent||"").trim(),rawHref:g.href}));let T=p.find(g=>g.title.length>2)??p[0];T&&(x=x||T.title||void 0)}return{googleLinkId:o.getAttribute("data-lk")||o.querySelector("[data-lk]")?.getAttribute("data-lk")||null,googleEvidenceId:o.getAttribute("data-ved")||o.querySelector("[data-ved]")?.getAttribute("data-ved")||null,question:o.getAttribute(d.itemDataQ)||o.getAttribute(d.itemDataInitQ)||o.querySelector(d.itemQuestionEl)?.innerText?.trim()||"",answer:L&&f||void 0,sourceTitle:x,sourceSite:N,sources:p}})},{selectors:a,onlyQuestion:n,answerPlaceholderPattern:un}),i=typeof t.url=="function"?t.url():"https://www.google.com/";return s.flatMap(d=>{let S=[],U=new Set;for(let r of d.sources){let u=Dt(r.rawHref,i);if(!u||U.has(u.rawUrl))continue;U.add(u.rawUrl);let c=d.sourceSite??null;try{c||=new URL(u.resolvedUrl??u.rawUrl).hostname.replace(/^www\./,"")}catch{}S.push({...u,title:r.title||d.sourceTitle||null,site:c})}let h=S[0],l={questionId:dt(d.question),googleLinkId:d.googleLinkId,googleEvidenceId:d.googleEvidenceId,question:d.question,answer:nn(d.answer,d.question,d.sourceTitle),sourceTitle:h?.title??d.sourceTitle,sourceSite:h?.site??d.sourceSite,sourceCite:h?.url,sources:S},o=me.safeParse(l);return o.success?[o.data]:(console.warn("[PAAExtractor] item parse failed:",d.question,o.error.issues[0]?.message),[])})}jitteredDelayMs(t,n){return t+Math.floor(Math.random()*(n-t+1))}async clickItem(t,n){try{await t.locator(`${H.item}[data-q="${n}"], ${H.item}[data-initq="${n}"]`).first().click()}catch{}}toFlatRow(t,n,a,s){return{seed_query:s,question_id:t.questionId??dt(t.question),google_link_id:t.googleLinkId??"",google_evidence_id:t.googleEvidenceId??"",question:t.question,answer:t.answer??"",source_title:t.sourceTitle??"",source_site:t.sourceSite??"",source_cite:t.sourceCite??"",sources:t.sources??[],depth:n,parent_question:a??"",extracted_at:new Date().toISOString()}}upsertCollectedRow(t){let n=this.normalizeQuestion(t.question),a=this.collectedRows.findIndex(S=>this.normalizeQuestion(S.question)===n);if(a<0)return this.collectedRows.push({...t}),!0;let s=this.collectedRows[a],i={...s,...t,answer:t.answer||s.answer,source_title:t.source_title||s.source_title,source_site:t.source_site||s.source_site,source_cite:t.source_cite||s.source_cite,sources:this.mergePaaSources(s.sources,t.sources),extracted_at:t.extracted_at||s.extracted_at},d=i.answer!==s.answer||i.source_title!==s.source_title||i.source_site!==s.source_site||i.source_cite!==s.source_cite||JSON.stringify(i.sources)!==JSON.stringify(s.sources);return d&&(this.collectedRows[a]=i),d}async emitProgress(t){if(!this.onPaaProgress||this.collectedRows.length===0&&!this.checkpointMaterial)return;let n={sequence:++this.progressSequence,observedAt:new Date().toISOString(),clickedQuestions:[...this.clickedQuestions],phase:t,records:this.collectedRows.map(a=>({...a})),lifecycle:{...this.paaLifecycle},...this.checkpointMaterial?{material:structuredClone(this.checkpointMaterial)}:{},interactions:this.interactionObservations.map(a=>({...a,confirmationSignals:[...a.confirmationSignals]}))};try{await this.onPaaProgress(n)}catch(a){console.warn(JSON.stringify({event:"paa_progress_sink_failed",sequence:n.sequence,phase:n.phase,message:a instanceof Error?a.message:String(a)}))}}getPartialResult(){let t=this.partialContext;if(!t||this.collectedRows.length===0&&!this.checkpointMaterial)return null;let n=this.collectedRows.map(S=>({...S})),a=this.checkpointMaterial,s=t.questionsOnly?0:n.filter(S=>!S.answer?.trim()).length,i=t.questionsOnly?0:n.filter(S=>(S.sources??[]).length===0).length,d={seed:t.seed,totalQuestions:n.length,maxDepthReached:n.reduce((S,U)=>Math.max(S,U.depth),0),durationMs:Date.now()-t.startMs,errorCount:0};return{seed:t.seed,location:t.location,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(t.startMs),completionStatus:"paa_found",problem:null,...a?.pagination?{pagination:{...a.pagination}}:{},resultQuality:"partial",degradedResult:!1,retryRecommended:!0,paaLifecycle:{...this.paaLifecycle,questionsFound:n.length,targetStatus:n.length>=(t.maxQuestions??0)?"met":"not_met",discoveryStatus:"interrupted",materialStatus:s>0||i>0?"partial":"complete",completionReason:"The browser attempt ended before frontier exhaustion could be proven."},completeness:{...this.completeness,paaWithoutAnswer:s,paaWithoutSource:i,paaRequested:t.maxQuestions,paaReturned:n.length,paaUnique:n.length},warnings:[{code:"paa_partial",surface:"paa",message:`Harvest stopped before finishing; returning the ${n.length} question(s) collected up to that point.`,retryable:!0}]},totalQuestions:n.length,surface:a?.surface??"web",aiOverview:a?.aiOverview??{detected:!1,text:null,citations:[]},aiMode:a?.aiMode??{detected:!1,text:null,citations:[]},whatPeopleSaying:a?.whatPeopleSaying??[],tree:this.buildTree(n,t.seed),flat:n,videos:a?.videos??[],forums:a?.forums??[],organicResults:a?.organicResults??[],localPack:a?.localPack??[],entityIds:a?.entityIds??{entities:[],kgIds:[],cids:[],gcids:[]},stats:d}}async runBFS(t,n,a){await t.waitForTimeout(700);let s=new Set,i=new Set,d=[];this.clickedQuestions=new Set,this.interactionObservations=[],this.phaseTimings={};let S=new Set,U=new Map,h=new Set,l=new Set,o=new Map,r=2,u=3,c=0,y={sel:H.item,dataQ:H.itemDataQ,dataInitQ:H.itemDataInitQ,questionEl:H.itemQuestionEl,answerSel:H.answerContainer,expandedClass:H.expandedClass,clickTarget:H.clickTarget,answerPlaceholderPattern:un,questionsOnly:n.questionsOnly,sourceSel:"a[href]"},m=()=>t.evaluate(({sel:N,dataQ:p,dataInitQ:A,questionEl:T,expandedClass:g,clickTarget:P,answerSel:w,answerPlaceholderPattern:M,questionsOnly:k})=>{let v=I=>{if(!I)return"";let b=[];for(let W of I.childNodes){if(W.nodeType===Node.TEXT_NODE){let B=W.textContent?.trim();B&&b.push(B);continue}if(W.nodeType!==Node.ELEMENT_NODE)continue;let V=W;if(V.tagName==="STYLE"||V.tagName==="SCRIPT"||V.getAttribute("aria-hidden")==="true")continue;let z=v(V);z&&b.push(z)}return b.join(" ").replace(/\s+/g," ").trim()};return Array.from(document.querySelectorAll(N)).map((I,b)=>{let W=v(I.querySelector(w)).replace(/An AI Overview is not available for this search/gi," ").replace(/Can't generate an AI overview right now\.?\s*Try again later\.?/gi," ").replace(/\bAI Overview\b/gi," ").replace(/\s+/g," ").trim(),V=I.classList.contains(g)||I.querySelector(P)?.getAttribute("aria-expanded")==="true",z=W.length>=10&&!new RegExp(M,"i").test(W);return{q:I.getAttribute(p)||I.getAttribute(A)||I.querySelector(T)?.innerText?.trim()||"",done:V&&(k||z),expanded:V,index:b}}).filter(I=>I.q)},y),f=async(N,p,A,T,g,P)=>{let w=Date.now(),M={id:`${P}:${dt(N)}:${g}`,questionId:dt(N),question:N,batchNumber:P,controlAttempt:g,observedAt:new Date(w).toISOString(),beforeQuestionCount:p,expandedBefore:T},k=A>=0?t.locator(y.sel).nth(A).locator(y.clickTarget):null,v=null,I=k?await(async()=>(T&&(await k.click({timeout:cn,force:!0}),await t.waitForTimeout(120)),await k.click({timeout:cn,force:!0}),!0))().catch(_=>(v=_ instanceof Error&&(_.name==="TimeoutError"||/timeout/i.test(_.message))?"click_ack_timeout":"click_failed",!1)):!1,b=Date.now()-w;if(!I&&v!=="click_ack_timeout")return{dispatched:!1,confirmed:!1,observation:{...M,dispatched:!1,outcome:"dispatch_failed",confirmationSignals:[],confirmationCheckpointMs:null,confirmedAtMs:null,dispatchDurationMs:b,totalDurationMs:b,afterQuestionCount:p,newQuestionCount:0,expandedAfter:T,answerObserved:!1,sourceCount:0,errorCode:A<0?"control_missing":v??"click_failed"}};let W={exists:!0,expanded:T,answerReady:!1,sourceCount:0,questionCount:p},V=[],z=null,B=null,J=!1;for(let _ of[ua,ca,wa]){let Q=w+_-Date.now();if(Q>0&&await t.waitForTimeout(Q),W=await t.evaluate(({sel:R,dataQ:G,dataInitQ:D,questionEl:q,expandedClass:it,clickTarget:st,answerSel:mt,answerPlaceholderPattern:lt,sourceSel:vt,target:wt})=>{let Nt=Ut=>{if(!Ut)return"";let $t=[];for(let ft of Ut.childNodes){if(ft.nodeType===Node.TEXT_NODE){let ke=ft.textContent?.trim();ke&&$t.push(ke);continue}if(ft.nodeType!==Node.ELEMENT_NODE)continue;let Pt=ft;if(Pt.tagName==="STYLE"||Pt.tagName==="SCRIPT"||Pt.getAttribute("aria-hidden")==="true")continue;let Me=Nt(Pt);Me&&$t.push(Me)}return $t.join(" ").replace(/\s+/g," ").trim()},St=Array.from(document.querySelectorAll(R)),Tt=St.find(Ut=>(Ut.getAttribute(G)||Ut.getAttribute(D)||Ut.querySelector(q)?.innerText?.trim())===wt);if(!Tt)return{exists:!1,expanded:!1,answerReady:!1,sourceCount:0,questionCount:St.length};let In=Tt.classList.contains(it)||Tt.querySelector(st)?.getAttribute("aria-expanded")==="true",ge=Tt.querySelector(mt),ye=Nt(ge).replace(/An AI Overview is not available for this search/gi," ").replace(/Can't generate an AI overview right now\.?\s*Try again later\.?/gi," ").replace(/\bAI Overview\b/gi," ").replace(/\s+/g," ").trim(),Ce=ye.length>=10&&!new RegExp(lt,"i").test(ye);return{exists:!0,expanded:In,answerReady:Ce,sourceCount:Ce?ge?.querySelectorAll(vt).length??0:0,questionCount:St.length}},{...y,target:N}).catch(()=>W),V=[...W.expanded?["expanded"]:[],...W.answerReady?["answer"]:[],...W.sourceCount>0?["source"]:[],...W.questionCount>p?["question_growth"]:[]],W.answerReady||W.sourceCount>0||W.questionCount>p){J=!0,z=_,B=Date.now()-w;break}}let Z=Date.now()-w,F={...M,dispatched:I,outcome:J?"confirmed":I?"unconfirmed":"dispatch_failed",confirmationSignals:V,confirmationCheckpointMs:z,confirmedAtMs:B,dispatchDurationMs:b,totalDurationMs:Z,afterQuestionCount:W.questionCount,newQuestionCount:Math.max(0,W.questionCount-p),expandedAfter:W.expanded,answerObserved:W.answerReady,sourceCount:W.sourceCount,errorCode:I?J?null:W.exists?"confirmation_timeout":"control_missing":v};return{dispatched:I,confirmed:J,observation:F}},C=0;t:for(;;){if(n.softDeadlineMs&&Date.now()>=n.softDeadlineMs)throw this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"interrupted",completionReason:"The execution deadline arrived before frontier exhaustion could be proven."},new yt(this.paaLifecycle.completionReason);this.throwIfAborted(a);let N=await m(),p=!1;for(let w of N)i.has(w.q)||(i.add(w.q),d.push(w.q),d.length<=n.maxQuestions&&(p=this.upsertCollectedRow(this.toFlatRow({questionId:dt(w.q),googleLinkId:null,googleEvidenceId:null,question:w.q,sources:[]},1,null,n.query))||p)),w.done&&h.add(w.q);if(this.paaLifecycle={...this.paaLifecycle,questionsFound:Math.min(d.length,n.maxQuestions),targetStatus:d.length>=n.maxQuestions?"met":"not_met",knownQuestions:d.length,processedQuestions:h.size,failedInteractions:l.size,visibleControls:N.length},p&&await this.emitProgress("discovered"),n.questionsOnly&&i.size>=n.maxQuestions){this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"target_reached",targetStatus:"met",completionReason:"The requested unique-question count was observed."};break}if(!n.questionsOnly&&i.size>=n.maxQuestions){let w=!1,M=new Set(d.slice(0,n.maxQuestions));for(let k of await this.extractVisibleItems(t)){if(!M.has(k.question))continue;let v=o.get(k.question),I={...k,answer:k.answer??v?.answer,sourceTitle:k.sourceTitle??v?.sourceTitle,sourceSite:k.sourceSite??v?.sourceSite,sourceCite:k.sourceCite??v?.sourceCite,sources:this.mergePaaSources(v?.sources,k.sources)};o.set(k.question,I),w=this.upsertCollectedRow(this.toFlatRow(I,1,null,n.query))||w}if(w&&await this.emitProgress("answer_captured"),[...M].every(k=>{let v=o.get(k);return!!(v?.answer?.trim()&&v.sources.length>0)})){l.clear(),this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"target_reached",targetStatus:"met",failedInteractions:0,completionReason:"The requested unique-question count and its answer/source material were observed."};break}}let A=new Set(d.slice(0,n.maxQuestions)),T=N.filter(w=>A.has(w.q)&&!w.done&&(U.get(w.q)??0)<r&&!S.has(w.q)),g=T.slice(-ga);if(this.paaLifecycle={...this.paaLifecycle,eligibleControls:T.length},g.length===0){if(i.size>=n.maxQuestions){this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"target_reached",targetStatus:"met",completionReason:"The requested unique-question count was observed."};break}let w=new Set(N.map(k=>k.q)),M=d.slice(0,n.maxQuestions).filter(k=>!h.has(k)&&(l.has(k)||!w.has(k)));if(M.length>0)throw this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"interrupted",failedInteractions:new Set([...l,...M]).size,completionReason:"At least one known PAA control failed or disappeared before it could be confirmed."},await this.emitProgress("expansion_finished"),new yt(this.paaLifecycle.completionReason);for(let k=1;k<=u;k++){this.throwIfAborted(a),await this.throwIfCaptcha(t,"Google PAA exhaustion confirmation"),await t.mouse.wheel(0,320);let v=await t.waitForFunction(({sel:b,min:W})=>document.querySelectorAll(b).length>W,{sel:H.item,min:N.length},{timeout:1500,polling:100}).catch(()=>null);if(this.paaLifecycle={...this.paaLifecycle,noGrowthConfirmations:k},v||(await m()).some(b=>!i.has(b.q)))continue t}this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"frontier_exhausted",targetStatus:"not_met",failedInteractions:0,noGrowthConfirmations:u,completionReason:"Every known eligible PAA control was processed and three healthy no-growth confirmations found no additional questions."};break}await this.throwIfCaptcha(t,"Google PAA expansion"),c+=1;for(let w of g){if(this.reporter.onDepth(++C),(U.get(w.q)??0)>0){let M=this.paaLifecycle.retryBreakdown.controlRetries+1;this.paaLifecycle={...this.paaLifecycle,automaticRetries:M+this.paaLifecycle.retryBreakdown.browserRetries+this.paaLifecycle.retryBreakdown.runtimeRecoveries,retryBreakdown:{...this.paaLifecycle.retryBreakdown,controlRetries:M}}}U.set(w.q,(U.get(w.q)??0)+1)}let P=await Promise.all(g.map(async w=>({target:w,result:await f(w.q,N.length,w.index,w.expanded,U.get(w.q)??1,c)})));for(let{target:w,result:M}of P)(M.dispatched||M.confirmed)&&this.clickedQuestions.add(w.q),this.interactionObservations.push(M.observation);if(this.interactionObservations.length>wn&&this.interactionObservations.splice(0,this.interactionObservations.length-wn),!n.questionsOnly){let w=new Set(g.map(M=>M.q));for(let M of await this.extractVisibleItems(t))w.has(M.question)&&(o.set(M.question,M),this.upsertCollectedRow(this.toFlatRow(M,1,null,n.query))&&await this.emitProgress("answer_captured"))}for(let{target:w,result:M}of P){let k=o.get(w.q);M.confirmed||k?.answer?.trim()?(h.add(w.q),l.delete(w.q)):(U.get(w.q)??0)>=r&&(l.add(w.q),S.add(w.q))}this.paaLifecycle={...this.paaLifecycle,processedQuestions:h.size,failedInteractions:l.size,noGrowthConfirmations:0,dispatchedInteractions:this.interactionObservations.filter(w=>w.dispatched).length,confirmedInteractions:this.interactionObservations.filter(w=>w.outcome==="confirmed").length,unconfirmedInteractions:this.interactionObservations.filter(w=>w.outcome!=="confirmed").length},await this.emitProgress("click_observed")}let O=n.questionsOnly?new Map:new Map(o);n.questionsOnly||await this.fillIncompleteItems(t,d,O,n,S);let L=[];for(let N of d){if(L.length>=n.maxQuestions)break;let p=this.normalizeQuestion(N);if(s.has(p))continue;s.add(p);let A=O.get(N);if(A){let T=this.toFlatRow(A,1,null,n.query);this.upsertCollectedRow(T),L.push(T),this.reporter.onQuestion({questionId:A.questionId,googleLinkId:A.googleLinkId,googleEvidenceId:A.googleEvidenceId,question:A.question,answer:A.answer??null,sourceTitle:A.sourceTitle??null,sourceSite:A.sourceSite??null,sourceCite:A.sourceCite??null,sources:A.sources,depth:1,parentQuestion:null,children:[]})}else{let T=this.toFlatRow({questionId:dt(N),googleLinkId:null,googleEvidenceId:null,question:N,answer:void 0,sourceTitle:void 0,sourceSite:void 0,sourceCite:void 0,sources:[]},1,null,n.query);this.upsertCollectedRow(T),L.push(T)}}this.completeness.paaWithoutAnswer=n.questionsOnly?0:L.filter(N=>!N.answer).length,this.completeness.paaWithoutSource=n.questionsOnly?0:L.filter(N=>(N.sources??[]).length===0).length,this.completeness.paaRequested=n.maxQuestions,this.completeness.paaReturned=L.length,this.completeness.paaUnique=s.size;let x=!n.questionsOnly&&(this.completeness.paaWithoutAnswer>0||this.completeness.paaWithoutSource>0);return this.paaLifecycle={...this.paaLifecycle,questionsFound:L.length,targetStatus:L.length>=n.maxQuestions?"met":"not_met",materialStatus:x?"partial":"complete",processedQuestions:h.size,failedInteractions:l.size},await this.emitProgress("fill_incomplete"),await this.emitProgress("expansion_finished"),L}async fillIncompleteItems(t,n,a,s,i){let d=new Set(n.slice(0,s.maxQuestions)),S=l=>!l?.answer||(l.sources??[]).length===0,U=new Set([...d].filter(l=>S(a.get(l)))),h=new Set([...U].filter(l=>!a.get(l)?.answer));if(U.size!==0){for(let l of U){if(s.softDeadlineMs&&Date.now()>=s.softDeadlineMs)break;let o=(await this.extractVisibleItems(t,l))[0];if(!o)continue;let r=a.get(l);a.set(l,{...o,answer:o.answer??r?.answer,sourceTitle:o.sourceTitle??r?.sourceTitle,sourceSite:o.sourceSite??r?.sourceSite,sourceCite:o.sourceCite??r?.sourceCite,sources:this.mergePaaSources(r?.sources,o.sources)});let u=a.get(l);u&&this.upsertCollectedRow(this.toFlatRow(u,1,null,s.query))&&await this.emitProgress("fill_incomplete")}this.completeness.paaAnswersRecovered=[...h].filter(l=>a.get(l)?.answer).length}}async reExpandCollapsedItems(t){let n=`${H.item}:not(.${H.expandedClass}) ${H.clickTarget}`,a=await t.locator(n).count().catch(()=>0);if(a===0)return!1;for(let s=0;s<a;s++)try{let i=t.locator(n).first();await i.scrollIntoViewIfNeeded(),await i.click({force:!0}),await t.waitForTimeout(this.jitteredDelayMs(300,500))}catch{}return!0}async extractVideos(t){let n=Ae;return t.evaluate(a=>{let s=[],i=Array.from(document.querySelectorAll(a.container));for(let d of i){let h=(d.querySelector(a.sectionHeading)?.textContent?.trim()??"").toLowerCase().includes("short")?"short_video":"video",l=Array.from(d.querySelectorAll(a.item));for(let o of l){let r=o.href;if(!r||!r.includes("youtube")&&!r.includes("youtu.be"))continue;let u=o.textContent?.trim()??"",c=u.indexOf("YouTube");if(c===-1)continue;let y=u.slice(0,c).trim(),f=u.slice(c+7).replace(/^[·\s·]+/,"").match(/^([^·\n]+)/),C=f?f[1].trim():"";y&&s.push({type:h,title:y,channel:C,platform:"YouTube",duration:"",url:r})}}return s},n)}async extractForums(t){let n=Le;return t.evaluate(a=>{let s=[],d=Array.from(document.querySelectorAll(a.section)).find(U=>U.textContent?.includes("Discussions"));if(!d)return s;let S=Array.from(d.querySelectorAll(a.item));for(let U of S){let h=U.href;if(!h)continue;let l=U.querySelector(a.title),o=U.querySelector(a.source),r=l?.textContent?.trim()??"",u=o?.textContent?.trim()??"";r&&s.push({title:r,source:u,url:h})}return s},n)}async extractShortVideos(t,n){try{await t.goto(n,{waitUntil:"domcontentloaded"}),await t.waitForTimeout(1500)}catch{return[]}await this.throwIfCaptcha(t,"Google short video search");let a={item:It.item,platforms:[...It.platforms]};return(await t.evaluate(i=>{let d=new Set,S=[],U=Array.from(document.querySelectorAll(i.item)),h=["youtube.com","youtu.be","tiktok.com","instagram.com","facebook.com","fb.watch"],l=new Map;for(let o of U){let r=o.href;if(!r||!h.some(c=>r.includes(c)))continue;let u=o.textContent?.trim()??"";l.has(r)||l.set(r,[]),l.get(r).push(u)}for(let[o,r]of l.entries()){if(d.has(o))continue;d.add(o);let u=r.find(C=>/^\d+:\d+$/.test(C))??"",c=r.find(C=>!/^\d+:\d+$/.test(C)&&C.length>5)??"";if(!c)continue;let y=c,m="",f="";for(let C of i.platforms){let O=-1,L=0;for(;;){let T=c.indexOf(C,L);if(T===-1)break;O=T,L=T+1}if(O===-1)continue;let x=c.slice(O+C.length);if(!(/^[\s·]/.test(x)||x.trim()===""))continue;y=c.slice(0,O).trim(),m=C;let p=x.replace(/^[\s·]+/,""),A=p.indexOf("\xB7");f=(A===-1?p:p.slice(0,A)).trim();break}y&&S.push({title:y,channel:f,platform:m,duration:u,url:o})}return S},a)).map(i=>({type:"short_video",...i}))}async extractWhatPeopleSaying(t){let n=Oe;return t.evaluate(a=>{let s=Array.from(document.querySelectorAll(a.sectionTag)).find(i=>i.textContent?.includes(a.sectionHeadingText))??document.querySelector(".yG4QQe.TBC9ub.NbhJ1c");return s?Array.from(s.querySelectorAll(a.card)).map(i=>{let S=i.querySelector(a.cardLink)?.href??"",U=i.querySelector(a.titleH1)?.textContent?.trim(),h=i.querySelector(a.titleDiv)?.textContent?.trim(),l=U??h??"",o=i.querySelector(a.source)?.textContent?.trim()??"",u=i.querySelector(a.platformBadge)?.textContent?.trim()??"",c=i.querySelector(a.ytChannel)?.textContent?.trim()??"",y=i.querySelector(a.ytDate)?.textContent?.trim()??"",m=i.querySelector(a.authorNote)?.textContent?.trim()??null,f=i.querySelector(a.popularCommentLabel),C=null;if(f){let v=f.nextSibling;for(;v;){let I=v.textContent?.trim();if(I){C=I;break}v=v.nextSibling}}let O=Array.from(i.querySelectorAll("span")),L=O.find(v=>/^\d+:\d+$/.test(v.textContent?.trim()??""))?.textContent?.trim()??null,N=O.map(v=>v.textContent?.trim()??"").filter(v=>/\d/.test(v)&&(v.includes("comment")||v.includes("reaction")||v.includes("view")||v.includes("like")||v.includes("share")))[0]??"",p=O.map(v=>v.textContent?.trim()??"").filter(v=>/\d+ (day|week|month|year|hour)s? ago|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/.test(v)),A=y||(p[0]??""),T=u||(c?"YouTube":""),g=c||o,P="unknown",w=T.toLowerCase(),M=g.toLowerCase(),k=o.toLowerCase();return w.includes("reddit")||M.startsWith("r/")?P="reddit":w.includes("facebook")||k.includes("facebook")?P="facebook":w.includes("instagram")||k.includes("instagram")?P="instagram":w.includes("tiktok")||k.includes("tiktok")?P="tiktok":w.includes("youtube")||c?P="youtube":P="news",{type:P,title:l,url:S,source:g,platform:T,popularComment:C,engagement:N,date:A,duration:L,authorNote:m}}):[]},n)}async extractOrganicResults(t){let n=He,a=await t.evaluate(i=>{let d=[],S=0;return document.querySelectorAll(i.result).forEach(U=>{let h=U.querySelector(i.title);if(!h)return;let l=h.textContent?.trim()??"",r=h.closest("a")?.href??"";if(!l||!r)return;S++;let u=U.querySelector(i.cite)?.textContent?.trim()??null,c=U.querySelector(i.snippet)?.textContent?.trim()??null,y=!!U.querySelector(i.redditCite),m=U.querySelector(i.ratingWrap),f=m?{value:m.querySelector(i.ratingValue)?.textContent?.trim()??"",count:m.querySelector(i.reviewCount)?.textContent?.trim()??""}:null,C="";try{C=new URL(r).hostname.replace(/^www\./,"")}catch{C=U.querySelector(i.siteName)?.textContent?.trim()??""}d.push({position:S,title:l,url:r,domain:C,cite:u,snippet:c,isRedditStyle:y,inlineRating:f})}),d},n),s=typeof t.url=="function"?t.url():"https://www.google.com/";return a.flatMap(i=>{let d=Dt(i.url,s);if(!d)return[];let S=i.domain;try{S=new URL(d.resolvedUrl??d.rawUrl).hostname.replace(/^www\./,"")}catch{}return[{...i,...d,domain:S}]})}async extractLocalPack(t){let n=Fe;return t.evaluate(a=>{let s=[],i=null;return document.querySelectorAll('[role="heading"]').forEach(d=>{!i&&d.textContent?.includes(a.headingText)&&(i=d.closest("[data-hveid]"))}),i&&i.querySelectorAll(a.card).forEach((d,S)=>{let U=d.querySelector(a.name)?.textContent?.trim()??"";if(!U)return;let h=d.querySelector(a.ratingValue)?.textContent?.trim()??null,l=d.querySelector(a.reviewCount)?.textContent?.trim()??null,o=l?l.replace(/[()]/g,"").trim():null,r=d.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;if(!r)for(let f of Array.from(d.querySelectorAll("a[href]"))){let C=f.href.match(/[?&]cid=(\d+)/);if(C){r=C[1];break}let O=f.href.match(/!1s0x[0-9a-f]+:0x([0-9a-f]+)/i);if(O){try{r=BigInt("0x"+O[1]).toString()}catch{}if(r)break}}let u=[];d.querySelectorAll("div, span").forEach(f=>{let C=Array.from(f.childNodes).filter(O=>O.nodeType===3).map(O=>O.textContent?.trim()??"").filter(O=>O.length>1&&O.length<120).join(" ");C&&!u.includes(C)&&u.push(C)});let c=Array.from(d.querySelectorAll("a[href]")),y=c.find(f=>f.href.includes("google.com/maps"))?.href??null,m=c.find(f=>!f.href.includes("google.com")&&f.href.startsWith("http"))?.href??null;s.push({position:S+1,name:U,cid:r,rating:h,reviewCount:o,metadata:u,websiteUrl:m,directionsUrl:y})}),s},n)}async extractEntityIds(t){return t.evaluate(()=>{let n=new Set,a=new Set,s=new Set,i=new Map;function d(U){let h=[".OSrXXb",".dbg0pd",".tzt0oe",'[role="heading"]',"h3"];for(let l of h){let o=U.querySelector(l);if(o?.textContent?.trim())return o.textContent.trim()}return""}document.querySelectorAll('[id^="pv-/g/"]').forEach(U=>{let h=U.getAttribute("id");if(!h)return;let l=h.replace("pv-","");n.add(l);let o=d(U),u=U.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;u&&a.add(u),o&&i.set(l,{name:o,kgId:l,cid:u,gcid:null})}),document.querySelectorAll("[data-mid]").forEach(U=>{let h=U.getAttribute("data-mid");if(h?.startsWith("/g/")&&(n.add(h),!i.has(h))){let l=d(U);l&&i.set(h,{name:l,kgId:h,cid:null,gcid:null})}}),document.querySelectorAll(".w7Dbne").forEach(U=>{let l=U.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;if(!l)return;a.add(l);let o=U.querySelector(".OSrXXb")?.textContent?.trim()??"";if(!o)return;let r=U.querySelector('[id^="pv-/g/"]'),u=r?r.getAttribute("id").replace("pv-",""):null,c=u??`cid:${l}`;if(i.has(c)){let y=i.get(c);y.cid||i.set(c,{...y,cid:l})}else i.set(c,{name:o,kgId:u,cid:l,gcid:null})}),document.querySelectorAll("a[data-cid]").forEach(U=>{let h=U.getAttribute("data-cid");if(!h)return;if(a.add(h),![...i.values()].some(o=>o.cid===h)){let o=U.parentElement,r="";for(let u=0;u<8&&o;u++){let c=o.querySelector('.OSrXXb, .dbg0pd, [role="heading"], h3');if(c?.textContent?.trim()){r=c.textContent.trim();break}o=o.parentElement}r&&i.set(`cid:${h}`,{name:r,kgId:null,cid:h,gcid:null})}});let S=Array.from(document.querySelectorAll("script:not([src])")).map(U=>U.textContent??"").filter(U=>U.length>1e4).join(`
21704
+ `);for(let U of S.matchAll(/\/g\/[a-zA-Z0-9_-]{5,20}/g))n.add(U[0]);for(let U of S.matchAll(/gcid:[a-zA-Z0-9_]+/g))s.add(U[0]);for(let U of S.matchAll(/0x[0-9a-f]+:0x([0-9a-f]+)/gi))try{a.add(BigInt("0x"+U[1]).toString())}catch{}return{entities:[...i.values()],kgIds:[...n],cids:[...a],gcids:[...s]}})}mergeLocalPackIntoEntities(t,n){let a=new Set(t.cids),s=t.entities.map(i=>({...i}));for(let i of n){if(!i.cid)continue;a.add(i.cid);let d=i.name.toLowerCase().trim(),S=s.find(U=>U.name.toLowerCase().trim()===d);S?S.cid||(S.cid=i.cid):s.find(U=>U.cid===i.cid)||s.push({name:i.name,kgId:null,cid:i.cid,gcid:null})}return{...t,entities:s,cids:[...a]}}async extractAISurfaces(t,n){let a=await t.evaluate(an,{aio:xe,aim:Be,expandWaitMs:1500}),s=typeof t.url=="function"?t.url():"https://www.google.com/",i={surface:a.surface,aiOverview:{...a.aiOverview,citations:this.normalizeAICitations(s,a.aiOverview.citations)},aiMode:{...a.aiMode,citations:this.normalizeAICitations(s,a.aiMode.citations)}};if(!i.aiOverview.detected)return this.completeness.aioShareCaptured=null,i;let d=this.aioShareUrlEarly??await this.captureAIOverviewShareUrl(t,n).catch(()=>null);return this.completeness.aioShareCaptured=d!==null,{...i,aiOverview:{...i.aiOverview,shareUrl:d}}}async captureAIOverviewShareUrl(t,n){if(n?.softDeadlineMs&&Date.now()>=n.softDeadlineMs||!await t.evaluate(()=>{let i=Array.from(document.querySelectorAll('h1,h2,h3,[role="heading"],div')).filter(d=>(d.textContent||"").trim()==="AI Overview");for(let d of i){let S=d;for(let U=0;U<8&&S;U++){let h=S.querySelector('[aria-label="Share"]');if(h)return h.scrollIntoView({block:"center"}),h.click(),!0;S=S.parentElement}}return!1}).catch(()=>!1))return null;let s=null;try{s=await(await t.waitForFunction(()=>{let d=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT);for(;d.nextNode();){let S=(d.currentNode.textContent||"").match(/https:\/\/share\.google\/aimode\/\S+/);if(S)return S[0]}return!1},void 0,{timeout:4500,polling:250})).jsonValue()}catch{s=null}return await t.keyboard.press("Escape").catch(()=>{}),s}buildTree(t,n){let a=[],s=new Map;for(let i of t){let d={questionId:i.question_id,googleLinkId:i.google_link_id||null,googleEvidenceId:i.google_evidence_id||null,question:i.question,answer:i.answer||null,sourceTitle:i.source_title||null,sourceSite:i.source_site||null,sourceCite:i.source_cite||null,sources:i.sources??[],depth:i.depth,parentQuestion:i.parent_question||null,children:[]};s.set(i.question,d)}for(let i of s.values())i.parentQuestion&&s.has(i.parentQuestion)?s.get(i.parentQuestion).children.push(i):a.push(i);return a}getBrowserDebugSnapshot(){return this.driver.getDebugSnapshot()}buildHarvestDebugSnapshot(t,n,a,s,i){if(t.debug)return{enabled:!0,request:{query:t.query,locationInput:t.location??null,canonicalLocation:n,locationResolved:i?i.matched:null,locationMatchSource:i?i.source:null,locationAmbiguousCandidates:i?i.ambiguousCandidates:null,uule:a,gl:t.gl,hl:t.hl,device:t.device,proxyMode:t.proxyMode,proxyZip:t.proxyZip??null,serpIdentity:t.serpIdentity??null,serpOnly:t.serpOnly,pages:t.pages??1},browser:this.getBrowserDebugSnapshot(),...s?{locationEvidence:s}:{}}}async captureSecondOrganicPage(t,n,a){if(this.throwIfAborted(a),!this.driver.withTemporaryPage)return{organic:[],status:"failed",failureCode:"unsupported_driver"};let s;try{let i=new URL(t.url()),d=h=>{try{let l=new URL(h,i);return i.origin==="https://www.google.com"&&l.origin===i.origin&&!l.username&&!l.password&&l.pathname==="/search"&&l.searchParams.getAll("q").length===1&&l.searchParams.get("q")===n.query&&l.searchParams.getAll("start").length===1&&l.searchParams.get("start")==="10"&&(!l.searchParams.has("num")||l.searchParams.get("num")==="10")&&["gl","hl"].every(o=>!l.searchParams.has(o)||l.searchParams.getAll(o).length===1&&l.searchParams.get(o)===n[o])&&["uule","tbs","udm","tbm","pws"].every(o=>l.searchParams.getAll(o).length<=1&&l.searchParams.get(o)===i.searchParams.get(o))}catch{return!1}},S=await t.evaluate(()=>document.querySelector('a#pnnext, a[rel="next"]')?.getAttribute("href")??null);if(!S)return{organic:[],status:"unavailable",failureCode:"missing_next"};if(!d(S))return{organic:[],status:"unavailable",failureCode:"invalid_next"};let U=await this.driver.withTemporaryPage(async h=>{if(await h.route("**/*",async l=>{let o=l.request();o.isNavigationRequest()&&o.frame()===h.mainFrame()&&!d(o.url())?(s=/^https:\/\/www\.google\.com\/sorry(?:\/|\?)/.test(o.url())?"captcha":"invalid_next",await l.abort("blockedbyclient")):await l.fallback()}),await h.goto(new URL(S,i).href,{waitUntil:"domcontentloaded",timeout:2e4}),this.throwIfAborted(a),await this.throwIfCaptcha(h,"Google SERP page 2"),!d(h.url()))throw s="invalid_next",new Error("Invalid pagination landing");return this.extractOrganicResults(h)},a);return this.throwIfAborted(a),U.length>0?{organic:U.map(h=>({...h,position:h.position+10})),status:"captured"}:{organic:[],status:"unavailable",failureCode:"empty_page"}}catch(i){if(this.throwIfAborted(a),i instanceof $)throw i;return{organic:[],status:"failed",failureCode:s??(i instanceof E?"captcha":i instanceof Error&&(i.name==="TimeoutError"||/timed? ?out/i.test(i.message))?"timeout":"navigation_error")}}}async extract(t,n){let a=Date.now();this.completeness={paaWithoutAnswer:0,paaWithoutSource:0,paaAnswersRecovered:0,aioShareCaptured:null},this.linkDiagnostics=this.emptyLinkDiagnostics(),this.aioShareUrlEarly=null,this.collectedRows=[],this.progressSequence=0,this.checkpointMaterial=null,this.clickedQuestions=new Set,this.paaLifecycle=this.emptyPaaLifecycle(t.maxQuestions),this.partialContext={seed:t.query,location:t.location??null,startMs:a,maxQuestions:t.maxQuestions,questionsOnly:t.questionsOnly};let s=t.device==="mobile",i={headless:t.headless,profileDir:t.profileDir,proxy:t.proxy,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,\u006b\u0065\u0072\u006e\u0065\u006cProxyId:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,\u006b\u0065\u0072\u006e\u0065\u006cProfileName:t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName,\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges:t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges,\u006b\u0065\u0072\u006e\u0065\u006cStealth:t.\u006b\u0065\u0072\u006e\u0065\u006cStealth,\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution,proxyMode:t.proxyMode,keepDefaultProxy:t.keepDefaultProxy,requireUsEgress:t.requireUsEgress,viewport:s?{width:390,height:844}:{width:1280,height:800},locale:`${t.hl}-${t.gl.toUpperCase()}`,deviceScaleFactor:s?3:1,isMobile:s,hasTouch:s,debug:t.debug,operationDeadlineMs:t.softDeadlineMs},d=0,S=[];try{this.throwIfAborted(n);let U=Date.now();await this.driver.launch(i),this.phaseTimings.providerConnectMs=Date.now()-U;let h=this.driver.getProviderSessionMetadata?.();if(h?.providerSessionId&&this.onProviderSession)try{await this.onProviderSession(h)}catch(R){console.warn(JSON.stringify({event:"paa_provider_session_sink_failed",provider:h.provider,message:R instanceof Error?R.message:String(R)}))}this.throwIfAborted(n);let l=t.location?se(t.location):null,o=t.location?l?.canonical??t.location:null,r=o?Qe(o):null,u=t,c=t.includeAllSerpFeatures,y=c||t.includeLocalPack,m=c||t.includeForums,f=c||t.includeVideos,C=c||t.includeAiOverview,O=c||t.includeWhatPeopleSaying,L={surface:"web",aiOverview:{detected:!1,text:null,citations:[]},aiMode:{detected:!1,text:null,citations:[]}},x=Date.now(),{hasPaa:N}=await this.driver.navigateToSERP(u.query,r,t.gl,t.hl,{...gt(t.recency)?{tbs:gt(t.recency)}:{},debug:t.debug,purpose:t.serpOnly?"serp":"paa",...t.softDeadlineMs?{deadlineMs:t.softDeadlineMs}:{}});this.phaseTimings.navigationMs=Date.now()-x,this.throwIfAborted(n);let p=this.driver.getPage();if(await this.throwIfCaptcha(p,"Google SERP"),N||(this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"no_paa_observed",materialStatus:"complete",completionReason:"A readable Google SERP was observed without a People Also Ask block."}),t.questionsOnly){let R=Date.now(),G=N?await this.runBFS(p,u,n):[];this.phaseTimings.paaExpansionMs=Date.now()-R,await this.resolveMaterialLinks(p,G,[],L.aiOverview,L.aiMode);let D={seed:u.query,totalQuestions:G.length,maxDepthReached:G.reduce((q,it)=>Math.max(q,it.depth),0),durationMs:Date.now()-a,errorCount:d};return this.reporter.onComplete(D),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:N?"paa_found":"no_paa",...N?{}:{noPaaObserved:!0},problem:null,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,o,r,void 0,l)}:{}},totalQuestions:G.length,surface:"web",aiOverview:{detected:!1,text:null,citations:[]},aiMode:{detected:!1,text:null,citations:[]},whatPeopleSaying:[],tree:this.buildTree(G,u.query),flat:G,videos:[],forums:[],organicResults:[],localPack:[],entityIds:{entities:[],kgIds:[],cids:[],gcids:[]},stats:D}}if(C&&(this.aioShareUrlEarly=await this.captureAIOverviewShareUrl(p,t).catch(()=>null)),t.serpOnly){let R=Date.now(),[G,D,q]=await Promise.all([this.extractOrganicResults(p),y?this.extractLocalPack(p):Promise.resolve([]),this.extractEntityIds(p)]),it=this.mergeLocalPackIntoEntities(q,D),st=C?await this.extractAISurfaces(p,t):L;this.phaseTimings.serpParseMs=Date.now()-R;let mt=t.debug?Mt(o,G,D):void 0,lt=G;if((t.pages??1)>=2){let wt=new URLSearchParams({q:u.query,gl:t.gl,hl:t.hl,pws:"0",start:"10"});gt(t.recency)&&wt.set("tbs",gt(t.recency)),r&&wt.set("uule",r),await this.driver.navigateTo("https://www.google.com/search?"+wt.toString()),await this.throwIfCaptcha(p,"Google SERP page 2");let Nt=await this.extractOrganicResults(p);lt=[...G,...Nt.map(St=>({...St,position:St.position+10}))],t.debug&&(mt=Mt(o,lt,D))}await this.resolveMaterialLinks(p,[],lt,st.aiOverview,st.aiMode);let vt={seed:u.query,totalQuestions:0,maxDepthReached:0,durationMs:Date.now()-a,errorCount:d};return this.reporter.onComplete(vt),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"serp_only",problem:null,completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,o,r,mt,l)}:{}},totalQuestions:0,surface:st.surface,aiOverview:st.aiOverview,aiMode:st.aiMode,whatPeopleSaying:[],tree:[],flat:[],videos:[],forums:[],organicResults:lt,localPack:D,entityIds:it,stats:vt}}let[A,T,g,P,w,M]=await Promise.all([f?this.extractVideos(p):Promise.resolve([]),m?this.extractForums(p):Promise.resolve([]),O?this.extractWhatPeopleSaying(p):Promise.resolve([]),this.extractEntityIds(p),this.extractOrganicResults(p),y?this.extractLocalPack(p):Promise.resolve([])]),k=this.mergeLocalPackIntoEntities(P,M),v=t.debug?Mt(o,w,M):void 0;this.reporter.onVideos(A),this.reporter.onForums(T);let I=C?await this.extractAISurfaces(p,t):L,b={requestedPages:(t.pages??1)>=2?2:1,capturedPages:1,page2Status:(t.pages??1)>=2?"not_attempted":"not_requested",page1OrganicCount:w.length,page2OrganicCount:0},W=w;if(this.checkpointMaterial={surface:I.surface,aiOverview:I.aiOverview,aiMode:I.aiMode,whatPeopleSaying:g,videos:A,forums:T,organicResults:W,localPack:M,entityIds:k,pagination:b},await this.emitProgress("serp_captured"),b.requestedPages===2){let R=await this.captureSecondOrganicPage(p,u,n);W=[...w,...R.organic],b={...b,capturedPages:R.status==="captured"?2:1,page2Status:R.status,page2OrganicCount:R.organic.length,...R.failureCode?{failureCode:R.failureCode}:{}},this.checkpointMaterial={...this.checkpointMaterial,organicResults:W,pagination:b},await this.emitProgress("serp_captured"),await this.resolveMaterialLinks(p,[],W,I.aiOverview,I.aiMode),this.checkpointMaterial={...this.checkpointMaterial,organicResults:W},await this.emitProgress("serp_captured")}let V=t.debug?Mt(o,W,M):v;if(!N){await this.resolveMaterialLinks(p,[],W,I.aiOverview,I.aiMode),this.checkpointMaterial={...this.checkpointMaterial,organicResults:W},await this.emitProgress("serp_captured");let R={seed:u.query,totalQuestions:0,maxDepthReached:0,durationMs:Date.now()-a,errorCount:d};return this.reporter.onComplete(R),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"no_paa",noPaaObserved:!0,problem:null,pagination:b,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,o,r,V,l)}:{}},totalQuestions:0,surface:I.surface,aiOverview:I.aiOverview,aiMode:I.aiMode,whatPeopleSaying:g,tree:[],flat:[],videos:A,forums:T,organicResults:W,localPack:M,entityIds:k,stats:R}}let z=Date.now(),B=await this.runBFS(p,u,n);this.phaseTimings.paaExpansionMs=Date.now()-z,this.throwIfAborted(n);let J=new URLSearchParams({q:u.query,gl:t.gl,hl:t.hl,pws:"0",udm:It.udm});r&&J.set("uule",r);let Z=[];if(t.includeShortVideos!==!1)try{Z=await this.extractShortVideos(p,"https://www.google.com/search?"+J.toString())}catch(R){if(!(R instanceof E))throw R;d++,S.push({code:"short_videos_captcha_skipped",surface:"short_videos",message:R.message,retryable:!0})}this.reporter.onVideos(Z),await this.resolveMaterialLinks(p,B,W,I.aiOverview,I.aiMode),this.checkpointMaterial={...this.checkpointMaterial,surface:I.surface,aiOverview:I.aiOverview,aiMode:I.aiMode,videos:[...A,...Z],organicResults:W},await this.emitProgress("expansion_finished");let F=[...A,...Z],_=this.buildTree(B,u.query),Q={seed:u.query,totalQuestions:B.length,maxDepthReached:B.reduce((R,G)=>Math.max(R,G.depth),0),durationMs:Date.now()-a,errorCount:d};return this.reporter.onComplete(Q),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"paa_found",problem:null,pagination:b,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...S.length>0?{warnings:S}:{},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,o,r,V,l)}:{}},totalQuestions:B.length,surface:I.surface,aiOverview:I.aiOverview,aiMode:I.aiMode,whatPeopleSaying:g,tree:_,flat:B,videos:F,forums:T,organicResults:W,localPack:M,entityIds:k,stats:Q}}catch(U){throw d++,this.paaLifecycle.discoveryStatus==="in_progress"&&(this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"interrupted",completionReason:"The browser attempt ended before frontier exhaustion could be proven."}),await this.emitProgress("attempt_ending").catch(()=>{}),this.reporter.onError(U instanceof Error?U:new Error(String(U))),U}}};import{promises as K}from"fs";import rt from"path";import ut from"papaparse";var Yt=class{async writeJSON(t,n){await K.mkdir(n,{recursive:!0});let s=`${t.seed.toLowerCase().replace(/\W+/g,"-").slice(0,40)}-${Date.now()}.json`,i=rt.join(n,s);return await K.writeFile(i,JSON.stringify(t,null,2),"utf8"),await Ie({title:`${t.seed} scrape`,content:JSON.stringify(t),source:`mcp-scraper:${i}`}),i}async writeCSV(t,n){await K.mkdir(n,{recursive:!0});let s=(t[0]?.seed_query??"paa").toLowerCase().replace(/\W+/g,"-").slice(0,40),i=ut.unparse(t.map(({sources:U,...h})=>({...h,sources_json:JSON.stringify(U)})),{header:!0}),d=`${s}-${Date.now()}.csv`,S=rt.join(n,d);return await K.writeFile(S,i,"utf8"),S}async writeVideoCSV(t,n,a){await K.mkdir(a,{recursive:!0});let s=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),i=ut.unparse(t,{header:!0}),d=`${s}-videos-${Date.now()}.csv`,S=rt.join(a,d);return await K.writeFile(S,i,"utf8"),S}async writeForumCSV(t,n,a){await K.mkdir(a,{recursive:!0});let s=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),i=ut.unparse(t,{header:!0}),d=`${s}-forums-${Date.now()}.csv`,S=rt.join(a,d);return await K.writeFile(S,i,"utf8"),S}async writeAIOverviewCSV(t,n,a,s){await K.mkdir(s,{recursive:!0});let i=a.toLowerCase().replace(/\W+/g,"-").slice(0,40),d=t.map((l,o)=>({seed_query:a,response_text:o===0?n??"":"",citation_text:l.text,citation_href:l.href})),S=ut.unparse(d,{header:!0}),U=`${i}-ai-overview-${Date.now()}.csv`,h=rt.join(s,U);return await K.writeFile(h,S,"utf8"),h}async writeAIModeCSV(t,n,a,s){await K.mkdir(s,{recursive:!0});let i=a.toLowerCase().replace(/\W+/g,"-").slice(0,40),d=t.map((l,o)=>({seed_query:a,response_text:o===0?n??"":"",citation_text:l.text,citation_href:l.href})),S=ut.unparse(d,{header:!0}),U=`${i}-ai-mode-${Date.now()}.csv`,h=rt.join(s,U);return await K.writeFile(h,S,"utf8"),h}async writeWhatPeopleSayingCSV(t,n,a){await K.mkdir(a,{recursive:!0});let s=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),i=t.map(h=>({seed_query:n,...h})),d=ut.unparse(i,{header:!0}),S=`${s}-what-people-saying-${Date.now()}.csv`,U=rt.join(a,S);return await K.writeFile(U,d,"utf8"),U}};var Et=class{onQuestion(t){process.stdout.write(JSON.stringify({event:"question",depth:t.depth,question:t.question})+`
21705
21705
  `)}onDepth(t){process.stdout.write(JSON.stringify({event:"depth",depth:t})+`
21706
21706
  `)}onVideos(t){for(let n of t)process.stdout.write(JSON.stringify({event:"video",type:n.type,platform:n.platform,duration:n.duration,title:n.title,channel:n.channel,url:n.url})+`
21707
21707
  `)}onForums(t){for(let n of t)process.stdout.write(JSON.stringify({event:"forum",title:n.title,source:n.source,url:n.url})+`
21708
21708
  `)}onComplete(t){process.stdout.write(JSON.stringify({event:"complete",...t})+`
21709
21709
  `)}onError(t){process.stderr.write(JSON.stringify({event:"error",type:t.constructor.name,message:t.message})+`
21710
- `)}};import{randomInt as ga}from"crypto";var ya="pr.oxylabs.io",Ca=7777,Ma=10,as=2;function wn(){return process.env.OXYLABS_USERNAME?.trim()||void 0}function gn(){return process.env.OXYLABS_PASSWORD?.trim()||void 0}function ka(){return(process.env.OXYLABS_COUNTRY?.trim()||"US").toUpperCase()}function Kt(){return!!(wn()&&gn())}function pa(){let e="";for(let t=0;t<10;t++)e+=String(ga(0,10));return e}function ma(e={}){let t=wn();if(!t)return;let n=t.startsWith("customer-")?t:`customer-${t}`,a=(e.country?.trim()||ka()).toUpperCase(),s=e.sticky?`-sessid-${pa()}-sesstime-${Ma}`:"";return`${n}-cc-${a}${s}`}function de(e){return e.replace(/pr\.oxylabs\.io(:\d+)?/gi,"backup proxy").replace(/oxylabs/gi,"backup proxy")}function va(e){return`mcp-backup-custom-${`${Date.now()}-${e??0}-${Math.random().toString(36).slice(2,8)}`}`}async function Jt(e,t={}){let n=ma({sticky:t.sticky}),a=gn();if(!n||!a)throw new Error("backup proxy pool is not configured");let s=new Z({apiKey:e});try{let i=await s.proxies.create({type:"custom",name:va(t.attemptIndex),protocol:"http",config:{host:ya,port:Ca,username:n,password:a}});if(!i.id)throw new Error("backup proxy creation did not return a proxy id");return i.id}catch(i){let d=i instanceof Error?i.message:String(i);throw new Error(de(d))}}async function is(e,t){if(!(!e||!Kt()))try{return await Jt(e,{attemptIndex:t})}catch{return}}async function ss(e,t){if(!(!e||!t))try{await new Z({apiKey:e}).proxies.delete(t)}catch{}}var Na={alabama:"AL",alaska:"AK",arizona:"AZ",arkansas:"AR",california:"CA",colorado:"CO",connecticut:"CT",delaware:"DE",florida:"FL",georgia:"GA",hawaii:"HI",idaho:"ID",illinois:"IL",indiana:"IN",iowa:"IA",kansas:"KS",kentucky:"KY",louisiana:"LA",maine:"ME",maryland:"MD",massachusetts:"MA",michigan:"MI",minnesota:"MN",mississippi:"MS",missouri:"MO",montana:"MT",nebraska:"NE",nevada:"NV","new hampshire":"NH","new jersey":"NJ","new mexico":"NM","new york":"NY","north carolina":"NC","north dakota":"ND",ohio:"OH",oklahoma:"OK",oregon:"OR",pennsylvania:"PA","rhode island":"RI","south carolina":"SC","south dakota":"SD",tennessee:"TN",texas:"TX",utah:"UT",vermont:"VT",virginia:"VA",washington:"WA","west virginia":"WV",wisconsin:"WI",wyoming:"WY"},Ta={"atlanta|GA":"30303","austin|TX":"78701","baltimore|MD":"21201","boston|MA":"02108","boulder|CO":"80302","charlotte|NC":"28202","chicago|IL":"60601","colorado_springs|CO":"80903","columbus|OH":"43215","dallas|TX":"75201","denver|CO":"80202","detroit|MI":"48226","fort_collins|CO":"80524","fort_worth|TX":"76102","houston|TX":"77002","indianapolis|IN":"46204","jacksonville|FL":"32202","las_vegas|NV":"89101","los_angeles|CA":"90012","louisville|KY":"40202","loveland|CO":"80537","memphis|TN":"38103","miami|FL":"33131","minneapolis|MN":"55401","nashville|TN":"37203","new_york|NY":"10001","orlando|FL":"32801","philadelphia|PA":"19103","phoenix|AZ":"85004","portland|OR":"97205","raleigh|NC":"27601","richmond|VA":"23219","sacramento|CA":"95814","salt_lake_city|UT":"84101","san_antonio|TX":"78205","san_diego|CA":"92101","san_francisco|CA":"94103","san_jose|CA":"95113","seattle|WA":"98101"};function fa(e){return e?e.slice(-6):null}function Y(e,t,n,a,s,i=!1){return{\u006b\u0065\u0072\u006e\u0065\u006cProxyId:n,...i&&n?{disposableProxyId:n}:{},resolution:{source:e,proxyType:e==="disabled"?"none":e==="configured_fallback"?"configured":e==="isp_created"?"isp":e==="backup_custom"?"custom":e==="location_created"||e==="location_reused"?"residential":"unknown",proxyMode:t,proxyIdPresent:!!n,proxyIdSuffix:fa(n),target:a,error:s,disposable:i}}}function Pa(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function ba(e){return e.trim().toLowerCase().replace(/\./g,"").replace(/\s+/g," ")}function Wa(e){if(!e)return!0;let t=ba(e);return t==="united states"||t==="united states of america"||t==="usa"||t==="us"}function yn(e){let t=e.trim();return/^[A-Za-z]{2}$/.test(t)?t.toUpperCase():Na[Pa(t)]??null}function Ia(e){let n=e.normalize("NFKD").replace(/[^\x00-\x7F]/g,"").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean),a=n.join("_"),s=n.join("");return Array.from(new Set([a,s].filter(Boolean)))}function nt(e,t,n){return n?`mcp-serp-residential-${e.toLowerCase()}-${t.toLowerCase()}-${n}`:`mcp-serp-residential-${e.toLowerCase()}-${t.toLowerCase()}`}function _t(e,t){let n=`${Date.now()}-${t??0}-${Math.random().toString(36).slice(2,8)}`;return`${e}-fresh-${n}`}function Aa(e){return`mcp-serp-residential-us-zip-${e}`}function La(e,t){if(!e||t.toLowerCase()!=="us")return null;let n=Qe(e),a=n.split(",").map(U=>U.trim()).filter(Boolean);if(a.length>1&&Wa(a[a.length-1])&&(a=a.slice(0,-1)),a.length===1){let U=yn(a[0]);return U?{canonicalLocation:n,level:"state",country:"US",state:U,city:"",cityCandidates:[],proxyName:nt("US",U),config:{country:"US",state:U}}:null}let[s="",i=""]=a;if(!s||!i)return null;let d=yn(i);if(!d)return null;let l=Ia(s),h=l[0];return h?{canonicalLocation:n,level:"city",country:"US",state:d,city:h,cityCandidates:l,proxyName:nt("US",d,h),config:{country:"US",state:d,city:h}}:null}function Oa(e){return`${e.city}|${e.state}`}function Cn(e,t){return t&&/^\d{5}$/.test(t)?t:Ta[Oa(e)]??null}function Mn(e,t){return{...e,level:"zip",zip:t,proxyName:Aa(t),config:{country:e.country,state:e.state,zip:t}}}function re(e,t){return{...e,proxyName:t}}function Se(e,t,n){return t.level==="zip"?e?.country?.toUpperCase()===t.country&&e?.zip===t.zip:e?.country?.toUpperCase()===t.country&&e?.state?.toUpperCase()===t.state&&(n?e?.city===n:!e?.city)}function xa(e,t){return e.find(n=>n.type==="residential"&&n.status!=="unavailable"&&!!n.id&&(n.name===t.proxyName||Se(n.config,t,t.level==="city"?t.city:void 0)))??null}function Ba(e,t){for(let n of t.cityCandidates){let a=nt(t.country,t.state,n),s=e.find(i=>i.type==="residential"&&i.status!=="unavailable"&&!!i.id&&(i.name===a||Se(i.config,t,n)));if(s)return s}return null}function zt(e){return{...e,level:"state",proxyName:nt(e.country,e.state),config:{country:e.country,state:e.state}}}function Ha(e,t){let n=nt(t.country,t.state);return e.find(a=>a.type==="residential"&&a.status!=="unavailable"&&!!a.id&&(a.name===n||Se(a.config,t)))??null}function Fa(e,t){return zt(e)}function et(e){return e instanceof Error?e.message:String(e)}function Ra(e,t,n){let a=[],s=Cn(e,t);if(s){let d=Mn(e,s);a.push(re(d,_t(d.proxyName,n)))}for(let d of e.cityCandidates){let l={...e,level:"city",city:d,proxyName:nt(e.country,e.state,d),config:{country:e.country,state:e.state,city:d}};a.push(re(l,_t(l.proxyName,n)))}let i=zt(e);return a.push(re(i,_t(i.proxyName,n))),a}async function le(e,t,n){if(e.backupOnExhaustion&&n.length>0&&e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey&&Kt())try{let a=await Jt(e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,{attemptIndex:e.attemptIndex});return Y("backup_custom",e.proxyMode,a,t,null,!0)}catch(a){n.push(`backup: ${de(et(a))}`)}return Y("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,t,n.join(" | "))}async function Ss(e){if(!e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey||!Kt())return null;try{let t=await Jt(e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,{attemptIndex:e.attemptIndex});return Y("backup_custom",e.proxyMode,t,null,null,!0)}catch{return null}}async function Ga(e,t,n){let a=[];for(let s of Ra(n,t.proxyZip,t.attemptIndex))try{let i=await e.proxies.create({type:"residential",name:s.proxyName,config:s.level==="zip"?{country:s.country,zip:s.zip}:s.config});if(i.id)return Y("location_created",t.proxyMode,i.id,s,null,!0);a.push(`${s.proxyName}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(i){a.push(`${s.proxyName}: ${et(i)}`)}if(process.env.\u004b\u0045\u0052\u004e\u0045\u004c_PROXY_TYPE!=="residential"){let s=zt(n);try{let i=await e.proxies.create({type:"isp",name:_t(`mcp-serp-isp-${s.country.toLowerCase()}-${(s.state??"").toLowerCase()}`,t.attemptIndex),config:{country:s.country,...s.state?{state:s.state}:{}}});if(i.id)return Y("isp_created",t.proxyMode,i.id,s,null,!0);a.push("isp: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id")}catch(i){a.push(`isp: ${et(i)}`)}}return le(t,n,a)}async function kn(e,t){if(!e||!t)return;await new Z({apiKey:e}).proxies.delete(t)}async function pn(e){if(e.proxyMode==="none")return Y("disabled",e.proxyMode,void 0,null,null);if(e.proxyMode==="configured")return Y("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,null,null);let t=La(e.location,e.gl);if(!t||!e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey)return Y("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,t,t?null:"location could not be normalized to a US city/state proxy target");let n=new Z({apiKey:e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey});try{let a=e.attemptIndex??0;if(e.fresh)return await Ga(n,e,t);if(a>=1){let S=Fa(t,a),o=[];try{let r=await n.proxies.create({type:"residential",name:S.proxyName,config:S.config});if(r.id)return Y("location_created",e.proxyMode,r.id,S,null);o.push(`${S.state}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(r){o.push(`${S.state}: ${et(r)}`)}return le(e,S,o)}let s=[];for await(let S of await n.proxies.list())s.push(S);let i=Cn(t,e.proxyZip),d=[];if(i){let S=Mn(t,i),o=xa(s,S);if(o?.id)return Y("location_reused",e.proxyMode,o.id,S,null);try{let r=await n.proxies.create({type:"residential",name:S.proxyName,config:{country:S.country,zip:i}});if(r.id)return Y("location_created",e.proxyMode,r.id,S,null);d.push(`${i}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(r){d.push(`${i}: ${et(r)}`)}}let l=Ba(s,t);if(l?.id)return Y("location_reused",e.proxyMode,l.id,t,d.join(" | ")||null);for(let S of t.cityCandidates)try{let o=await n.proxies.create({type:"residential",name:nt(t.country,t.state,S),config:{country:t.country,state:t.state,city:S}});if(o.id)return Y("location_created",e.proxyMode,o.id,{...t,level:"city",city:S,proxyName:nt(t.country,t.state,S),config:{country:t.country,state:t.state,city:S}},null);d.push(`${S}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(o){d.push(`${S}: ${et(o)}`)}let h=zt(t),U=Ha(s,h);if(U?.id)return Y("location_reused",e.proxyMode,U.id,h,d.join(" | "));try{let S=await n.proxies.create({type:"residential",name:h.proxyName,config:h.config});if(S.id)return Y("location_created",e.proxyMode,S.id,h,d.join(" | "));d.push(`${h.state}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(S){d.push(`${h.state}: ${et(S)}`)}return le(e,t,d)}catch(a){return Y("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,t,et(a))}}var he=2,Da=2,Va=3e3;function ue(e){return e.reason instanceof DOMException&&e.reason.name==="TimeoutError"?e.reason:new q}function Ya(e){if(!e||typeof e!="object")return;let t=e.signal;if(t instanceof AbortSignal)return t}function Ea(e){if(!e||typeof e!="object")return;let t=e.onAttemptEvent;return typeof t=="function"?t:void 0}function Ka(e){if(!e||typeof e!="object")return;let t=e.onPaaProgress;return typeof t=="function"?t:void 0}async function ht(e,t){if(e)try{await e(t)}catch(n){console.warn(JSON.stringify({event:"harvest_attempt_log_failed",attempt_number:t.attemptNumber,message:n instanceof Error?n.message:String(n)}))}}function ce(e){if(e instanceof K)return"captcha";if(e instanceof $t)return"location_mismatch";if(e instanceof q)return"request_aborted";if(e instanceof yt)return"browser_session_interrupted";if(e instanceof DOMException&&(e.name==="TimeoutError"||e.name==="AbortError"))return"timeout";let t=e instanceof Error?e.message:String(e);return/browser (?:has been )?closed|context (?:has been )?closed|target page, context or browser has been closed|session closed|page has been closed/i.test(t)?"browser_session_interrupted":$a(t)?"proxy_tunnel_failed":ja(t)?"proxy_unavailable":/timeout|timed out|Timeout \d+ms exceeded|deadline/i.test(t)?"timeout":"error"}function Ja(e){return e.diagnostics.degradedResult?"degraded_result":e.diagnostics?.completionStatus??(e.totalQuestions>0?"paa_found":"no_paa")}function _a(e){return e.flat.length>0||e.organicResults.length>0||e.localPack.length>0||e.videos.length>0||e.forums.length>0||e.whatPeopleSaying.length>0||e.aiOverview.detected||e.aiMode.detected}function mn(e,t,n){let a=_a(e),s=(e.diagnostics.warnings?.length??0)>0,i=new Set(e.flat.map(g=>g.question.toLowerCase().replace(/[^\w\s]/g,"").replace(/\s+/g," ").trim())).size,d=n?0:e.flat.filter(g=>!g.answer?.trim()).length,l=n?0:e.flat.filter(g=>!g.source_cite?.trim()).length,h=e.diagnostics.completionStatus==="no_paa"&&(e.diagnostics.noPaaObserved===!0||a),U=e.diagnostics.completionStatus==="paa_found",S=e.diagnostics.paaLifecycle?.discoveryStatus,o=S==="interrupted"||S==="recovery_exhausted",r=U&&(i<t&&S!=="frontier_exhausted"||d>0||l>0||!!e.diagnostics.interruption||o),u=h?"complete":U&&i>0?r||s?"partial":"complete":a?s?"partial":"complete":"degraded",c=u==="degraded";return e.diagnostics={...e.diagnostics,resultQuality:u,degradedResult:c,degradationReasons:c?["empty_primary_serp"]:[],retryRecommended:c||u==="partial"&&(r||e.diagnostics.warnings?.some(g=>g.retryable)===!0),completeness:{paaWithoutAnswer:d,paaWithoutSource:l,paaAnswersRecovered:e.diagnostics.completeness?.paaAnswersRecovered??0,aioShareCaptured:e.diagnostics.completeness?.aioShareCaptured??null,paaRequested:t,paaReturned:e.flat.length,paaUnique:i},...e.diagnostics.paaLifecycle?{paaLifecycle:{...e.diagnostics.paaLifecycle,questionsFound:i,targetStatus:i>=t?"met":"not_met",materialStatus:d>0||l>0?"partial":"complete"}}:{}},e}function vn(e,t,n){let a=e.diagnostics.paaLifecycle;if(!a)return e;let s={...a.retryBreakdown,browserRetries:t,providerFallbacks:n};return{...e,diagnostics:{...e.diagnostics,paaLifecycle:{...a,retryBreakdown:s,automaticRetries:s.controlRetries+s.browserRetries+s.runtimeRecoveries}}}}function za(e){return(e.diagnostics.degradationReasons??[]).includes("empty_primary_serp")?"No usable primary SERP surface was captured; the result may be incomplete.":"The harvest result was marked degraded."}function j(e){return e instanceof Error?e.message:String(e)}function qa(e){return e==="location"?Da:he}function $a(e){return/ERR_TUNNEL_CONNECTION_FAILED|ERR_PROXY_CONNECTION_FAILED|ERR_SOCKS_CONNECTION_FAILED|tunnel connection failed|proxy connection failed|transport error: proxy/i.test(e)}function ja(e){return/proxy unavailable|proxy_unavailable|connection_test_failed|did not return a proxy id|configured fallback/i.test(e)}function Nn(e){return e==="captcha"||e==="proxy_tunnel_failed"||e==="proxy_unavailable"}function Tn(e){return e==="browser_session_interrupted"}function Qa(e){let t=e.diagnostics.debug?.locationEvidence,n=t?.expected?.canonicalLocation??e.location??"requested location",a=t?.candidates.slice(0,3).map(s=>`${s.city}, ${s.regionCode}`).join("; ");return a?`Google returned results for ${a}, not ${n}`:`Google returned results for a different location than ${n}`}function Za(e,t){return t==="location"&&e.diagnostics.debug?.locationEvidence?.status==="mismatch"}function fn(e,t){if(t||!e.diagnostics.debug)return e;let n={...e.diagnostics};return delete n.debug,{...e,diagnostics:n}}async function Pn(e,t){let n=t==null?3e3:t-Date.now();if(n<=0)return e;try{return await Sn(e,{totalBudgetMs:Math.min(3e3,n)})}catch(a){return console.warn(JSON.stringify({event:"harvest_goto_resolution_failed",message:j(a)})),e}}async function Ue(e,t){if(!(!e||!t))try{await kn(e,t),console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_proxy_deleted",proxy_id_suffix:t.slice(-6)}))}catch(n){console.warn(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_proxy_delete_failed",proxy_id_suffix:t.slice(-6),message:j(n)}))}}async function bn(e,t,n=!1,a=!1,s,i){let d=Je(e,{forceManaged:n,force\u004b\u0065\u0072\u006e\u0065\u006c:a}),l=new Et,h=new Vt(d,l,s,i);if(t?.aborted)return{result:null,error:ue(t),cleanup:await d.close(),debug:null};let U,S=t?new Promise((g,M)=>{U=()=>M(ue(t)),t.addEventListener("abort",U,{once:!0})}):null,o=null,r=null,u,c=null;try{let g=h.extract(e,t);S&&g.catch(()=>{}),o=await(S?Promise.race([g,S]):g)}catch(g){r=g}finally{t&&U&&t.removeEventListener("abort",U),c=o?.diagnostics.debug??(e.debug?{enabled:!0,request:{query:e.query,locationInput:e.location??null,canonicalLocation:null,locationResolved:null,locationMatchSource:null,locationAmbiguousCandidates:null,uule:null,gl:e.gl,hl:e.hl,device:e.device,proxyMode:e.proxyMode,proxyZip:e.proxyZip??null,serpIdentity:e.serpIdentity??null,serpOnly:e.serpOnly,pages:e.pages??1},browser:d.getDebugSnapshot()}:null),u=await d.close()}if(r){let g=ce(r),M=g==="timeout"||g==="request_aborted"||g==="browser_session_interrupted"?g:null,T=null;if(M)try{T=typeof h.getPartialResult=="function"?h.getPartialResult():null}catch{T=null}return T&&M?(T.diagnostics={...T.diagnostics,interruption:{code:M,reasonSource:"client_runtime",message:j(r)}},{result:T,error:r,cleanup:u,debug:c,salvagedFrom:r}):{result:null,error:r,cleanup:u,debug:c}}return{result:o,error:null,cleanup:u,debug:c}}async function Ns(e){let t=typeof e=="object"&&e!==null?e:{},n=Ya(e),a=Ea(e),s=Ka(e),d=t.forceManagedSerp===!0||Rt()&&!t.serpIdentity,l=t.proxyMode,h=l==="location"||l==="none"||l==="configured"?l:ke,U=typeof t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey=="string"?t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey.trim():ve(),S=typeof t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId=="string"?t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId.trim():void 0,o={\u006b\u0065\u0072\u006e\u0065\u006cApiKey:U,proxyMode:h,configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId:S,location:typeof t.location=="string"?t.location:void 0,proxyZip:typeof t.proxyZip=="string"?t.proxyZip:void 0,gl:typeof t.gl=="string"?t.gl:"us"},r=typeof t.debug=="boolean"?t.debug:!1,u=h==="location"&&!!o.location,c=t.maxAttempts,g=typeof c=="number"&&Number.isInteger(c)&&c>=1?Math.min(he,c):qa(h),M=Math.min(he,g),T=typeof t.softDeadlineMs=="number"?t.softDeadlineMs:null,b=new Yt,L=null,O=h,H=0,W=()=>T==null||T-Date.now()>=Va;for(let C=0;C<M;C++){let v=C+1,I=Date.now();try{if(n?.aborted)throw ue(n);let y=await pn({...o,proxyMode:O,attemptIndex:C,fresh:O==="location"});if(!y)break;let k={...t,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:U,\u006b\u0065\u0072\u006e\u0065\u006cProxyId:y.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution:y.resolution,proxyMode:O,keepDefaultProxy:C>0,debug:r||u};O==="none"&&(k.\u006b\u0065\u0072\u006e\u0065\u006cProxyId=void 0);let w=pe.parse(k);await ht(a,{type:"started",attemptNumber:v,maxAttempts:M,query:w.query,location:w.location??null,maxQuestions:w.maxQuestions,startedAt:new Date(I).toISOString()}),console.info(JSON.stringify({event:"harvest_attempt_started",attempt_number:v,max_attempts:M,query:w.query,location:w.location??null,max_questions:w.maxQuestions}));let p=Wt(),m=V=>ht(a,{type:"provider_session_started",attemptNumber:v,maxAttempts:M,provider:V.provider,providerSessionId:V.providerSessionId,observedAt:new Date().toISOString()}),P=p?.harvestBrowserMode==="headless-test"&&process.env[fe]==="true",N=d&&C>0&&!!U,A=p?await Pe({...p,forceHeadless:P,forceHeadful:!P},()=>bn(w,n,d&&!N,N,s,m)):await bn(w,n,d&&!N,N,s,m);if(A.error){let V=A.error,R=ce(V);(R==="captcha"||R==="proxy_tunnel_failed")&&O==="location"&&(H++,H>=2&&(O="none"));let z=!A.result&&C<M-1&&W()&&(R==="captcha"||Tn(R)||h==="location"&&Nn(R));if(R==="captcha"?console.warn(JSON.stringify({event:"harvest_attempt_captcha",attempt_number:v,max_attempts:M,message:j(V),will_retry:z})):z&&console.warn(JSON.stringify({event:"harvest_attempt_proxy_retry",attempt_number:v,max_attempts:M,outcome:R,message:j(V),will_retry:z})),await ht(a,{type:"finished",attemptNumber:v,maxAttempts:M,outcome:R,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:A.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:A.result?.totalQuestions??0,durationMs:Date.now()-I,error:j(V),willRetry:z,cleanup:A.cleanup,debug:A.debug,completedAt:new Date().toISOString()}),await Ue(U,y.disposableProxyId),L=V,z)continue;if(A.result){let B=await Pn(A.result,T);return vn(mn(fn(B,r),w.maxQuestions,w.questionsOnly),C,N?1:0)}break}let f=A.result;if(!f)throw new Error("Harvest attempt completed without a result");if(Za(f,h)){let V=new $t(Qa(f)),R=C<M-1&&W();if(console.warn(JSON.stringify({event:"harvest_attempt_location_mismatch",attempt_number:v,max_attempts:M,message:V.message,will_retry:R})),await ht(a,{type:"finished",attemptNumber:v,maxAttempts:M,outcome:"location_mismatch",\u006b\u0065\u0072\u006e\u0065\u006cSessionId:A.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:f.totalQuestions,durationMs:Date.now()-I,error:V.message,willRetry:R,cleanup:A.cleanup,debug:A.debug,completedAt:new Date().toISOString()}),await Ue(U,y.disposableProxyId),L=V,R)continue;break}let G=await Pn(f,T),x=vn(mn(fn(G,r),w.maxQuestions,w.questionsOnly),C,N?1:0),D=Ja(x),_=D==="degraded_result"&&C<M-1&&W(),Q=D==="degraded_result"?za(x):null;if(_&&console.warn(JSON.stringify({event:"harvest_attempt_degraded_result",attempt_number:v,max_attempts:M,degradation_reasons:x.diagnostics.degradationReasons,will_retry:!0})),await ht(a,{type:"finished",attemptNumber:v,maxAttempts:M,outcome:D,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:A.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:x.totalQuestions,durationMs:Date.now()-I,error:Q,willRetry:_,cleanup:A.cleanup,debug:A.debug,completedAt:new Date().toISOString()}),await Ue(U,y.disposableProxyId),_)continue;return(w.format==="json"||w.format==="both")&&await b.writeJSON(x,w.outputDir),(w.format==="csv"||w.format==="both")&&await Promise.all([b.writeCSV(x.flat,w.outputDir),x.videos.length>0?b.writeVideoCSV(x.videos,x.seed,w.outputDir):Promise.resolve(""),x.forums.length>0?b.writeForumCSV(x.forums,x.seed,w.outputDir):Promise.resolve(""),x.aiOverview.detected?b.writeAIOverviewCSV(x.aiOverview.citations,x.aiOverview.text,x.seed,w.outputDir):Promise.resolve(""),x.aiMode.detected?b.writeAIModeCSV(x.aiMode.citations,x.aiMode.text,x.seed,w.outputDir):Promise.resolve(""),x.whatPeopleSaying.length>0?b.writeWhatPeopleSayingCSV(x.whatPeopleSaying,x.seed,w.outputDir):Promise.resolve("")]),x}catch(y){let k=ce(y);(k==="captcha"||k==="proxy_tunnel_failed")&&O==="location"&&(H++,H>=2&&(O="none"));let w=C<M-1&&W()&&(k==="captcha"||Tn(k)||h==="location"&&Nn(k));if(k==="captcha"?console.warn(JSON.stringify({event:"harvest_attempt_captcha",attempt_number:v,max_attempts:M,message:j(y),will_retry:w})):w&&console.warn(JSON.stringify({event:"harvest_attempt_proxy_retry",attempt_number:v,max_attempts:M,outcome:k,message:j(y),will_retry:w})),await ht(a,{type:"finished",attemptNumber:v,maxAttempts:M,outcome:k,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,questionCount:0,durationMs:Date.now()-I,error:j(y),willRetry:w,cleanup:{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:null,browserCloseError:null},debug:null,completedAt:new Date().toISOString()}),L=y,w)continue;if(k==="captcha")break;throw y}}throw L&&!(L instanceof K)?L:(console.warn(JSON.stringify({event:"harvest_captcha_exhausted",max_attempts:M,session_kind:U?"\u006b\u0065\u0072\u006e\u0065\u006c":"local"})),new K(Te(`CAPTCHA on all ${M} fresh sessions. Try again in a few minutes.`)))}export{ti as a,Lt as b,Ot as c,ii as d,Re as e,Vn as f,Bt as g,De as h,Ve as i,Ke as j,Rt as k,je as l,ae as m,st as n,Dt as o,as as p,Kt as q,is as r,ss as s,Ss as t,kn as u,pn as v,Ns as w};
21710
+ `)}};import{randomInt as ya}from"crypto";var Ca="pr.oxylabs.io",Ma=7777,ka=10,os=2;function gn(){return process.env.OXYLABS_USERNAME?.trim()||void 0}function yn(){return process.env.OXYLABS_PASSWORD?.trim()||void 0}function pa(){return(process.env.OXYLABS_COUNTRY?.trim()||"US").toUpperCase()}function Kt(){return!!(gn()&&yn())}function ma(){let e="";for(let t=0;t<10;t++)e+=String(ya(0,10));return e}function va(e={}){let t=gn();if(!t)return;let n=t.startsWith("customer-")?t:`customer-${t}`,a=(e.country?.trim()||pa()).toUpperCase(),s=e.sticky?`-sessid-${ma()}-sesstime-${ka}`:"";return`${n}-cc-${a}${s}`}function le(e){return e.replace(/pr\.oxylabs\.io(:\d+)?/gi,"backup proxy").replace(/oxylabs/gi,"backup proxy")}function Na(e){return`mcp-backup-custom-${`${Date.now()}-${e??0}-${Math.random().toString(36).slice(2,8)}`}`}async function Jt(e,t={}){let n=va({sticky:t.sticky}),a=yn();if(!n||!a)throw new Error("backup proxy pool is not configured");let s=new X({apiKey:e});try{let i=await s.proxies.create({type:"custom",name:Na(t.attemptIndex),protocol:"http",config:{host:Ca,port:Ma,username:n,password:a}});if(!i.id)throw new Error("backup proxy creation did not return a proxy id");return i.id}catch(i){let d=i instanceof Error?i.message:String(i);throw new Error(le(d))}}async function ds(e,t){if(!(!e||!Kt()))try{return await Jt(e,{attemptIndex:t})}catch{return}}async function rs(e,t){if(!(!e||!t))try{await new X({apiKey:e}).proxies.delete(t)}catch{}}var Ta={alabama:"AL",alaska:"AK",arizona:"AZ",arkansas:"AR",california:"CA",colorado:"CO",connecticut:"CT",delaware:"DE",florida:"FL",georgia:"GA",hawaii:"HI",idaho:"ID",illinois:"IL",indiana:"IN",iowa:"IA",kansas:"KS",kentucky:"KY",louisiana:"LA",maine:"ME",maryland:"MD",massachusetts:"MA",michigan:"MI",minnesota:"MN",mississippi:"MS",missouri:"MO",montana:"MT",nebraska:"NE",nevada:"NV","new hampshire":"NH","new jersey":"NJ","new mexico":"NM","new york":"NY","north carolina":"NC","north dakota":"ND",ohio:"OH",oklahoma:"OK",oregon:"OR",pennsylvania:"PA","rhode island":"RI","south carolina":"SC","south dakota":"SD",tennessee:"TN",texas:"TX",utah:"UT",vermont:"VT",virginia:"VA",washington:"WA","west virginia":"WV",wisconsin:"WI",wyoming:"WY"},fa={"atlanta|GA":"30303","austin|TX":"78701","baltimore|MD":"21201","boston|MA":"02108","boulder|CO":"80302","charlotte|NC":"28202","chicago|IL":"60601","colorado_springs|CO":"80903","columbus|OH":"43215","dallas|TX":"75201","denver|CO":"80202","detroit|MI":"48226","fort_collins|CO":"80524","fort_worth|TX":"76102","houston|TX":"77002","indianapolis|IN":"46204","jacksonville|FL":"32202","las_vegas|NV":"89101","los_angeles|CA":"90012","louisville|KY":"40202","loveland|CO":"80537","memphis|TN":"38103","miami|FL":"33131","minneapolis|MN":"55401","nashville|TN":"37203","new_york|NY":"10001","orlando|FL":"32801","philadelphia|PA":"19103","phoenix|AZ":"85004","portland|OR":"97205","raleigh|NC":"27601","richmond|VA":"23219","sacramento|CA":"95814","salt_lake_city|UT":"84101","san_antonio|TX":"78205","san_diego|CA":"92101","san_francisco|CA":"94103","san_jose|CA":"95113","seattle|WA":"98101"};function Pa(e){return e?e.slice(-6):null}function Y(e,t,n,a,s,i=!1){return{\u006b\u0065\u0072\u006e\u0065\u006cProxyId:n,...i&&n?{disposableProxyId:n}:{},resolution:{source:e,proxyType:e==="disabled"?"none":e==="configured_fallback"?"configured":e==="isp_created"?"isp":e==="backup_custom"?"custom":e==="location_created"||e==="location_reused"?"residential":"unknown",proxyMode:t,proxyIdPresent:!!n,proxyIdSuffix:Pa(n),target:a,error:s,disposable:i}}}function ba(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function Wa(e){return e.trim().toLowerCase().replace(/\./g,"").replace(/\s+/g," ")}function Ia(e){if(!e)return!0;let t=Wa(e);return t==="united states"||t==="united states of america"||t==="usa"||t==="us"}function Cn(e){let t=e.trim();return/^[A-Za-z]{2}$/.test(t)?t.toUpperCase():Ta[ba(t)]??null}function Aa(e){let n=e.normalize("NFKD").replace(/[^\x00-\x7F]/g,"").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean),a=n.join("_"),s=n.join("");return Array.from(new Set([a,s].filter(Boolean)))}function at(e,t,n){return n?`mcp-serp-residential-${e.toLowerCase()}-${t.toLowerCase()}-${n}`:`mcp-serp-residential-${e.toLowerCase()}-${t.toLowerCase()}`}function _t(e,t){let n=`${Date.now()}-${t??0}-${Math.random().toString(36).slice(2,8)}`;return`${e}-fresh-${n}`}function La(e){return`mcp-serp-residential-us-zip-${e}`}function Oa(e,t){if(!e||t.toLowerCase()!=="us")return null;let n=Ze(e),a=n.split(",").map(h=>h.trim()).filter(Boolean);if(a.length>1&&Ia(a[a.length-1])&&(a=a.slice(0,-1)),a.length===1){let h=Cn(a[0]);return h?{canonicalLocation:n,level:"state",country:"US",state:h,city:"",cityCandidates:[],proxyName:at("US",h),config:{country:"US",state:h}}:null}let[s="",i=""]=a;if(!s||!i)return null;let d=Cn(i);if(!d)return null;let S=Aa(s),U=S[0];return U?{canonicalLocation:n,level:"city",country:"US",state:d,city:U,cityCandidates:S,proxyName:at("US",d,U),config:{country:"US",state:d,city:U}}:null}function xa(e){return`${e.city}|${e.state}`}function Mn(e,t){return t&&/^\d{5}$/.test(t)?t:fa[xa(e)]??null}function kn(e,t){return{...e,level:"zip",zip:t,proxyName:La(t),config:{country:e.country,state:e.state,zip:t}}}function Se(e,t){return{...e,proxyName:t}}function he(e,t,n){return t.level==="zip"?e?.country?.toUpperCase()===t.country&&e?.zip===t.zip:e?.country?.toUpperCase()===t.country&&e?.state?.toUpperCase()===t.state&&(n?e?.city===n:!e?.city)}function Ba(e,t){return e.find(n=>n.type==="residential"&&n.status!=="unavailable"&&!!n.id&&(n.name===t.proxyName||he(n.config,t,t.level==="city"?t.city:void 0)))??null}function Ha(e,t){for(let n of t.cityCandidates){let a=at(t.country,t.state,n),s=e.find(i=>i.type==="residential"&&i.status!=="unavailable"&&!!i.id&&(i.name===a||he(i.config,t,n)));if(s)return s}return null}function zt(e){return{...e,level:"state",proxyName:at(e.country,e.state),config:{country:e.country,state:e.state}}}function Fa(e,t){let n=at(t.country,t.state);return e.find(a=>a.type==="residential"&&a.status!=="unavailable"&&!!a.id&&(a.name===n||he(a.config,t)))??null}function Ra(e,t){return zt(e)}function nt(e){return e instanceof Error?e.message:String(e)}function Ga(e,t,n){let a=[],s=Mn(e,t);if(s){let d=kn(e,s);a.push(Se(d,_t(d.proxyName,n)))}for(let d of e.cityCandidates){let S={...e,level:"city",city:d,proxyName:at(e.country,e.state,d),config:{country:e.country,state:e.state,city:d}};a.push(Se(S,_t(S.proxyName,n)))}let i=zt(e);return a.push(Se(i,_t(i.proxyName,n))),a}async function Ue(e,t,n){if(e.backupOnExhaustion&&n.length>0&&e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey&&Kt())try{let a=await Jt(e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,{attemptIndex:e.attemptIndex});return Y("backup_custom",e.proxyMode,a,t,null,!0)}catch(a){n.push(`backup: ${le(nt(a))}`)}return Y("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,t,n.join(" | "))}async function us(e){if(!e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey||!Kt())return null;try{let t=await Jt(e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,{attemptIndex:e.attemptIndex});return Y("backup_custom",e.proxyMode,t,null,null,!0)}catch{return null}}async function Da(e,t,n){let a=[];for(let s of Ga(n,t.proxyZip,t.attemptIndex))try{let i=await e.proxies.create({type:"residential",name:s.proxyName,config:s.level==="zip"?{country:s.country,zip:s.zip}:s.config});if(i.id)return Y("location_created",t.proxyMode,i.id,s,null,!0);a.push(`${s.proxyName}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(i){a.push(`${s.proxyName}: ${nt(i)}`)}if(process.env.\u004b\u0045\u0052\u004e\u0045\u004c_PROXY_TYPE!=="residential"){let s=zt(n);try{let i=await e.proxies.create({type:"isp",name:_t(`mcp-serp-isp-${s.country.toLowerCase()}-${(s.state??"").toLowerCase()}`,t.attemptIndex),config:{country:s.country,...s.state?{state:s.state}:{}}});if(i.id)return Y("isp_created",t.proxyMode,i.id,s,null,!0);a.push("isp: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id")}catch(i){a.push(`isp: ${nt(i)}`)}}return Ue(t,n,a)}async function pn(e,t){if(!e||!t)return;await new X({apiKey:e}).proxies.delete(t)}async function mn(e){if(e.proxyMode==="none")return Y("disabled",e.proxyMode,void 0,null,null);if(e.proxyMode==="configured")return Y("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,null,null);let t=Oa(e.location,e.gl);if(!t||!e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey)return Y("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,t,t?null:"location could not be normalized to a US city/state proxy target");let n=new X({apiKey:e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey});try{let a=e.attemptIndex??0;if(e.fresh)return await Da(n,e,t);if(a>=1){let l=Ra(t,a),o=[];try{let r=await n.proxies.create({type:"residential",name:l.proxyName,config:l.config});if(r.id)return Y("location_created",e.proxyMode,r.id,l,null);o.push(`${l.state}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(r){o.push(`${l.state}: ${nt(r)}`)}return Ue(e,l,o)}let s=[];for await(let l of await n.proxies.list())s.push(l);let i=Mn(t,e.proxyZip),d=[];if(i){let l=kn(t,i),o=Ba(s,l);if(o?.id)return Y("location_reused",e.proxyMode,o.id,l,null);try{let r=await n.proxies.create({type:"residential",name:l.proxyName,config:{country:l.country,zip:i}});if(r.id)return Y("location_created",e.proxyMode,r.id,l,null);d.push(`${i}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(r){d.push(`${i}: ${nt(r)}`)}}let S=Ha(s,t);if(S?.id)return Y("location_reused",e.proxyMode,S.id,t,d.join(" | ")||null);for(let l of t.cityCandidates)try{let o=await n.proxies.create({type:"residential",name:at(t.country,t.state,l),config:{country:t.country,state:t.state,city:l}});if(o.id)return Y("location_created",e.proxyMode,o.id,{...t,level:"city",city:l,proxyName:at(t.country,t.state,l),config:{country:t.country,state:t.state,city:l}},null);d.push(`${l}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(o){d.push(`${l}: ${nt(o)}`)}let U=zt(t),h=Fa(s,U);if(h?.id)return Y("location_reused",e.proxyMode,h.id,U,d.join(" | "));try{let l=await n.proxies.create({type:"residential",name:U.proxyName,config:U.config});if(l.id)return Y("location_created",e.proxyMode,l.id,U,d.join(" | "));d.push(`${U.state}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(l){d.push(`${U.state}: ${nt(l)}`)}return Ue(e,t,d)}catch(a){return Y("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,t,nt(a))}}var ce=2,Va=2,Ya=3e3;function we(e){return e.reason instanceof DOMException&&e.reason.name==="TimeoutError"?e.reason:new $}function Ea(e){if(!e||typeof e!="object")return;let t=e.signal;if(t instanceof AbortSignal)return t}function Ka(e){if(!e||typeof e!="object")return;let t=e.onAttemptEvent;return typeof t=="function"?t:void 0}function Ja(e){if(!e||typeof e!="object")return;let t=e.onPaaProgress;return typeof t=="function"?t:void 0}function _a(e){if(!e||typeof e!="object")return;let t=e.onPaaDomEvidence;return typeof t=="function"?t:void 0}async function za(e){let t=await e.evaluate(n=>{let a=n,s=Array.from(document.querySelectorAll(a.item)),i=s.map(U=>U.querySelector(a.clickTarget)).filter(U=>U!=null),d=U=>{let h=U.getBoundingClientRect();if(h.width<=0||h.height<=0)return!1;let l=h.left+h.width/2,o=h.top+h.height/2;if(l<0||o<0||l>=window.innerWidth||o>=window.innerHeight)return!1;let r=document.elementFromPoint(l,o);return r!=null&&r!==U&&!U.contains(r)&&!r.contains(U)},S=Array.from(document.querySelectorAll("body *")).filter(U=>{let h=window.getComputedStyle(U);if(h.position!=="fixed"&&h.position!=="sticky")return!1;let l=U.getBoundingClientRect();return l.width*l.height>=window.innerWidth*window.innerHeight*.15&&h.visibility!=="hidden"&&h.display!=="none"});return{itemCount:s.length,expandedItemCount:s.filter(U=>U.classList.contains(a.expandedClass)||U.querySelector(a.clickTarget)?.getAttribute("aria-expanded")==="true").length,answeredItemCount:s.filter(U=>(U.querySelector(a.answerContainer)?.textContent?.trim().length??0)>=10).length,sourcedItemCount:s.filter(U=>U.querySelector(`${a.answerContainer} a[href]`)!=null).length,clickTargetCount:i.length,clickTargetsWithButtonRole:i.filter(U=>U.getAttribute("role")==="button"||U.tagName==="BUTTON").length,clickTargetsWithExpandedState:i.filter(U=>U.hasAttribute("aria-expanded")).length,clickTargetsOffscreen:i.filter(U=>{let h=U.getBoundingClientRect(),l=h.left+h.width/2,o=h.top+h.height/2;return l<0||o<0||l>=window.innerWidth||o>=window.innerHeight}).length,clickTargetsBlockedAtCenter:i.filter(d).length,fixedOrStickyOverlayCount:S.length}},{item:H.item,answerContainer:H.answerContainer,clickTarget:H.clickTarget,expandedClass:H.expandedClass});return{capturedAt:new Date().toISOString(),...t,selectorVersion:Re}}async function ct(e,t){if(e)try{await e(t)}catch(n){console.warn(JSON.stringify({event:"harvest_attempt_log_failed",attempt_number:t.attemptNumber,message:n instanceof Error?n.message:String(n)}))}}function qt(e){if(e instanceof E)return"captcha";if(e instanceof Qt)return"location_mismatch";if(e instanceof $)return"request_aborted";if(e instanceof yt)return"browser_session_interrupted";if(e instanceof DOMException&&(e.name==="TimeoutError"||e.name==="AbortError"))return"timeout";let t=e instanceof Error?e.message:String(e);return/browser (?:has been )?closed|context (?:has been )?closed|target page, context or browser has been closed|session closed|page has been closed/i.test(t)?"browser_session_interrupted":Za(t)?"proxy_tunnel_failed":Xa(t)?"proxy_unavailable":/timeout|timed out|Timeout \d+ms exceeded|deadline/i.test(t)?"timeout":"error"}function qa(e){return e.diagnostics.degradedResult?"degraded_result":e.diagnostics?.completionStatus??(e.totalQuestions>0?"paa_found":"no_paa")}function $a(e){return e.flat.length>0||e.organicResults.length>0||e.localPack.length>0||e.videos.length>0||e.forums.length>0||e.whatPeopleSaying.length>0||e.aiOverview.detected||e.aiMode.detected}function vn(e,t,n){let a=$a(e),s=(e.diagnostics.warnings?.length??0)>0,i=new Set(e.flat.map(y=>y.question.toLowerCase().replace(/[^\w\s]/g,"").replace(/\s+/g," ").trim())).size,d=n?0:e.flat.filter(y=>!y.answer?.trim()).length,S=n?0:e.flat.filter(y=>!y.source_cite?.trim()).length,U=e.diagnostics.completionStatus==="no_paa"&&(e.diagnostics.noPaaObserved===!0||a),h=e.diagnostics.completionStatus==="paa_found",l=e.diagnostics.paaLifecycle?.discoveryStatus,o=l==="interrupted"||l==="recovery_exhausted",r=h&&(i<t&&l!=="frontier_exhausted"||d>0||S>0||!!e.diagnostics.interruption||o),u=U?"complete":h&&i>0?r||s?"partial":"complete":a?s?"partial":"complete":"degraded",c=u==="degraded";return e.diagnostics={...e.diagnostics,resultQuality:u,degradedResult:c,degradationReasons:c?["empty_primary_serp"]:[],retryRecommended:c||u==="partial"&&(r||e.diagnostics.warnings?.some(y=>y.retryable)===!0),completeness:{paaWithoutAnswer:d,paaWithoutSource:S,paaAnswersRecovered:e.diagnostics.completeness?.paaAnswersRecovered??0,aioShareCaptured:e.diagnostics.completeness?.aioShareCaptured??null,paaRequested:t,paaReturned:e.flat.length,paaUnique:i},...e.diagnostics.paaLifecycle?{paaLifecycle:{...e.diagnostics.paaLifecycle,questionsFound:i,targetStatus:i>=t?"met":"not_met",materialStatus:d>0||S>0?"partial":"complete"}}:{}},e}function Nn(e,t,n){let a=e.diagnostics.paaLifecycle;if(!a)return e;let s={...a.retryBreakdown,browserRetries:t,providerFallbacks:n};return{...e,diagnostics:{...e.diagnostics,paaLifecycle:{...a,retryBreakdown:s,automaticRetries:s.controlRetries+s.browserRetries+s.runtimeRecoveries}}}}function ja(e){return(e.diagnostics.degradationReasons??[]).includes("empty_primary_serp")?"No usable primary SERP surface was captured; the result may be incomplete.":"The harvest result was marked degraded."}function j(e){return e instanceof Error?e.message:String(e)}function Qa(e){return e==="location"?Va:ce}function Za(e){return/ERR_TUNNEL_CONNECTION_FAILED|ERR_PROXY_CONNECTION_FAILED|ERR_SOCKS_CONNECTION_FAILED|tunnel connection failed|proxy connection failed|transport error: proxy/i.test(e)}function Xa(e){return/proxy unavailable|proxy_unavailable|connection_test_failed|did not return a proxy id|configured fallback/i.test(e)}function Tn(e){return e==="captcha"||e==="proxy_tunnel_failed"||e==="proxy_unavailable"}function fn(e){return e==="browser_session_interrupted"}function ti(e){let t=e.diagnostics.debug?.locationEvidence,n=t?.expected?.canonicalLocation??e.location??"requested location",a=t?.candidates.slice(0,3).map(s=>`${s.city}, ${s.regionCode}`).join("; ");return a?`Google returned results for ${a}, not ${n}`:`Google returned results for a different location than ${n}`}function ei(e,t){return t==="location"&&e.diagnostics.debug?.locationEvidence?.status==="mismatch"}function Pn(e,t){if(t||!e.diagnostics.debug)return e;let n={...e.diagnostics};return delete n.debug,{...e,diagnostics:n}}async function bn(e,t){let n=t==null?3e3:t-Date.now();if(n<=0)return e;try{return await Un(e,{totalBudgetMs:Math.min(3e3,n)})}catch(a){return console.warn(JSON.stringify({event:"harvest_goto_resolution_failed",message:j(a)})),e}}async function ue(e,t){if(!(!e||!t))try{await pn(e,t),console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_proxy_deleted",proxy_id_suffix:t.slice(-6)}))}catch(n){console.warn(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_proxy_delete_failed",proxy_id_suffix:t.slice(-6),message:j(n)}))}}async function Wn(e,t,n=!1,a=!1,s,i,d){let S=_e(e,{forceManaged:n,force\u004b\u0065\u0072\u006e\u0065\u006c:a}),U=new Et,h=new Vt(S,U,s,i);if(t?.aborted)return{result:null,error:we(t),cleanup:await S.close(),debug:null};let l,o=t?new Promise((m,f)=>{l=()=>f(we(t)),t.addEventListener("abort",l,{once:!0})}):null,r=null,u=null,c,y=null;try{let m=h.extract(e,t);o&&m.catch(()=>{}),r=await(o?Promise.race([m,o]):m)}catch(m){u=m}finally{if(t&&l&&t.removeEventListener("abort",l),d){let m;try{let f=za(S);f.catch(()=>{});let C=await Promise.race([f,new Promise((O,L)=>{m=setTimeout(()=>L(new DOMException("PAA DOM evidence timed out","TimeoutError")),2e3)})]);await d(C)}catch(f){console.warn(JSON.stringify({event:"paa_dom_evidence_failed",message:j(f)}))}finally{m&&clearTimeout(m)}}y=r?.diagnostics.debug??(e.debug?{enabled:!0,request:{query:e.query,locationInput:e.location??null,canonicalLocation:null,locationResolved:null,locationMatchSource:null,locationAmbiguousCandidates:null,uule:null,gl:e.gl,hl:e.hl,device:e.device,proxyMode:e.proxyMode,proxyZip:e.proxyZip??null,serpIdentity:e.serpIdentity??null,serpOnly:e.serpOnly,pages:e.pages??1},browser:S.getDebugSnapshot()}:null),c=await S.close()}if(u){let m=qt(u),f=m==="timeout"||m==="request_aborted"||m==="browser_session_interrupted"?m:null,C=null;if(f)try{C=typeof h.getPartialResult=="function"?h.getPartialResult():null}catch{C=null}return C&&f?(C.diagnostics={...C.diagnostics,interruption:{code:f,reasonSource:"client_runtime",message:j(u)}},{result:C,error:u,cleanup:c,debug:y,salvagedFrom:u}):{result:null,error:u,cleanup:c,debug:y}}return{result:r,error:null,cleanup:c,debug:y}}async function bs(e){let t=typeof e=="object"&&e!==null?e:{},n=Ea(e),a=Ka(e),s=Ja(e),i=_a(e),d=t.forceManagedSerp===!0,U=!(t.force\u004b\u0065\u0072\u006e\u0065\u006cSerp===!0)&&(d||Rt()&&!t.serpIdentity),h=t.proxyMode,l=h==="location"||h==="none"||h==="configured"?h:pe,o=typeof t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey=="string"?t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey.trim():ve(),r=typeof t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId=="string"?t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId.trim():void 0,u={\u006b\u0065\u0072\u006e\u0065\u006cApiKey:o,proxyMode:l,configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId:r,location:typeof t.location=="string"?t.location:void 0,proxyZip:typeof t.proxyZip=="string"?t.proxyZip:void 0,gl:typeof t.gl=="string"?t.gl:"us"},c=typeof t.debug=="boolean"?t.debug:!1,y=l==="location"&&!!u.location,m=t.maxAttempts,f=typeof m=="number"&&Number.isInteger(m)&&m>=1?Math.min(ce,m):Qa(l),C=Math.min(ce,f),O=typeof t.softDeadlineMs=="number"?t.softDeadlineMs:null,L=new Yt,x=null,N=l,p=0,A=()=>O==null||O-Date.now()>=Ya;for(let T=0;T<C;T++){let g=T+1,P=Date.now();try{if(n?.aborted)throw we(n);let w=U&&T>0&&!!o,M=jt.parse({...t,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:o,proxyMode:N,debug:c||y}),k=U&&!w?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser":M.serpIdentity?"\u006b\u0065\u0072\u006e\u0065\u006c_persistent_identity":"\u006b\u0065\u0072\u006e\u0065\u006c_browser";await ct(a,{type:"started",attemptNumber:g,maxAttempts:C,method:k,provider:k==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061":"\u006b\u0065\u0072\u006e\u0065\u006c",retryKind:g===1?null:w?"provider_fallback":"same_method",retryReason:g===1||x==null?null:qt(x),query:M.query,location:M.location??null,maxQuestions:M.maxQuestions,startedAt:new Date(P).toISOString()});let v=k==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser"?null:await mn({...u,proxyMode:N,attemptIndex:T,fresh:N==="location"});if(k!=="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser"&&!v)throw new Error("\u004b\u0065\u0072\u006e\u0065\u006c proxy resolution did not produce an execution plan");let I={...t,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:o,...v?{\u006b\u0065\u0072\u006e\u0065\u006cProxyId:v.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution:v.resolution}:{},proxyMode:N,keepDefaultProxy:T>0,debug:c||y};N==="none"&&(I.\u006b\u0065\u0072\u006e\u0065\u006cProxyId=void 0);let b=jt.parse(I);console.info(JSON.stringify({event:"harvest_attempt_started",attempt_number:g,max_attempts:C,query:b.query,location:b.location??null,max_questions:b.maxQuestions}));let W=Wt(),V=G=>ct(a,{type:"provider_session_started",attemptNumber:g,maxAttempts:C,provider:G.provider,providerSessionId:G.providerSessionId,observedAt:new Date().toISOString()}),z=W?.harvestBrowserMode==="headless-test"&&process.env[fe]==="true",B=W?await Pe({...W,forceHeadless:z,forceHeadful:!z},()=>Wn(b,n,U&&!w,w,s,V,i)):await Wn(b,n,U&&!w,w,s,V,i);if(B.error){let G=B.error,D=qt(G);(D==="captcha"||D==="proxy_tunnel_failed")&&N==="location"&&(p++,p>=2&&(N="none"));let q=!B.result&&T<C-1&&A()&&(D==="captcha"||fn(D)||l==="location"&&Tn(D));if(D==="captcha"?console.warn(JSON.stringify({event:"harvest_attempt_captcha",attempt_number:g,max_attempts:C,message:j(G),will_retry:q})):q&&console.warn(JSON.stringify({event:"harvest_attempt_proxy_retry",attempt_number:g,max_attempts:C,outcome:D,message:j(G),will_retry:q})),await ct(a,{type:"finished",attemptNumber:g,maxAttempts:C,outcome:D,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:B.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:B.result?.totalQuestions??0,durationMs:Date.now()-P,error:j(G),willRetry:q,cleanup:B.cleanup,debug:B.debug,completedAt:new Date().toISOString()}),await ue(o,v?.disposableProxyId),x=G,q)continue;if(B.result){let it=await bn(B.result,O);return Nn(vn(Pn(it,c),b.maxQuestions,b.questionsOnly),T,w?1:0)}break}let J=B.result;if(!J)throw new Error("Harvest attempt completed without a result");if(ei(J,l)){let G=new Qt(ti(J)),D=T<C-1&&A();if(console.warn(JSON.stringify({event:"harvest_attempt_location_mismatch",attempt_number:g,max_attempts:C,message:G.message,will_retry:D})),await ct(a,{type:"finished",attemptNumber:g,maxAttempts:C,outcome:"location_mismatch",\u006b\u0065\u0072\u006e\u0065\u006cSessionId:B.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:J.totalQuestions,durationMs:Date.now()-P,error:G.message,willRetry:D,cleanup:B.cleanup,debug:B.debug,completedAt:new Date().toISOString()}),await ue(o,v?.disposableProxyId),x=G,D)continue;break}let Z=await bn(J,O),F=Nn(vn(Pn(Z,c),b.maxQuestions,b.questionsOnly),T,w?1:0),_=qa(F),Q=_==="degraded_result"&&T<C-1&&A(),R=_==="degraded_result"?ja(F):null;if(Q&&console.warn(JSON.stringify({event:"harvest_attempt_degraded_result",attempt_number:g,max_attempts:C,degradation_reasons:F.diagnostics.degradationReasons,will_retry:!0})),await ct(a,{type:"finished",attemptNumber:g,maxAttempts:C,outcome:_,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:B.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:F.totalQuestions,durationMs:Date.now()-P,error:R,willRetry:Q,cleanup:B.cleanup,debug:B.debug,completedAt:new Date().toISOString()}),await ue(o,v?.disposableProxyId),Q)continue;return(b.format==="json"||b.format==="both")&&await L.writeJSON(F,b.outputDir),(b.format==="csv"||b.format==="both")&&await Promise.all([L.writeCSV(F.flat,b.outputDir),F.videos.length>0?L.writeVideoCSV(F.videos,F.seed,b.outputDir):Promise.resolve(""),F.forums.length>0?L.writeForumCSV(F.forums,F.seed,b.outputDir):Promise.resolve(""),F.aiOverview.detected?L.writeAIOverviewCSV(F.aiOverview.citations,F.aiOverview.text,F.seed,b.outputDir):Promise.resolve(""),F.aiMode.detected?L.writeAIModeCSV(F.aiMode.citations,F.aiMode.text,F.seed,b.outputDir):Promise.resolve(""),F.whatPeopleSaying.length>0?L.writeWhatPeopleSayingCSV(F.whatPeopleSaying,F.seed,b.outputDir):Promise.resolve("")]),F}catch(w){let M=qt(w);(M==="captcha"||M==="proxy_tunnel_failed")&&N==="location"&&(p++,p>=2&&(N="none"));let k=T<C-1&&A()&&(M==="captcha"||fn(M)||l==="location"&&Tn(M));if(M==="captcha"?console.warn(JSON.stringify({event:"harvest_attempt_captcha",attempt_number:g,max_attempts:C,message:j(w),will_retry:k})):k&&console.warn(JSON.stringify({event:"harvest_attempt_proxy_retry",attempt_number:g,max_attempts:C,outcome:M,message:j(w),will_retry:k})),await ct(a,{type:"finished",attemptNumber:g,maxAttempts:C,outcome:M,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,questionCount:0,durationMs:Date.now()-P,error:j(w),willRetry:k,cleanup:{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:null,browserCloseError:null},debug:null,completedAt:new Date().toISOString()}),x=w,k)continue;if(M==="captcha")break;throw w}}throw x&&!(x instanceof E)?x:(console.warn(JSON.stringify({event:"harvest_captcha_exhausted",max_attempts:C,session_kind:o?"\u006b\u0065\u0072\u006e\u0065\u006c":"local"})),new E(Te(`CAPTCHA on all ${C} fresh sessions. Try again in a few minutes.`)))}export{ai as a,Lt as b,Ot as c,di as d,Ge as e,Yn as f,Bt as g,Ve as h,Ye as i,Je as j,Rt as k,Qe as l,se as m,dt as n,Dt as o,os as p,Kt as q,ds as r,rs as s,us as t,pn as u,mn as v,bs as w};