mcp-scraper 0.95.1 → 0.96.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +98 -39
- package/README.md +25 -7
- package/THIRD_PARTY_NOTICES.html +203 -0
- package/dist/actions-YCMJY3PF.js +1 -0
- package/dist/artifacts-4ZDNP2JW.js +1 -0
- package/dist/artifacts-N62OPIT5.js +1 -0
- package/dist/artifacts-PSADD5OC.js +1 -0
- package/dist/artifacts-RUR3OHAK.js +1 -0
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.js +22 -22
- package/dist/bin/mcp-scraper-core.js +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.js +1 -1
- package/dist/bin/paa-harvest.js +1 -1
- package/dist/blob-store-GIH26EDO.js +1 -0
- package/dist/bundle-TTJP6DHU.js +1 -0
- package/dist/chunk-24YDQ3EO.js +5 -0
- package/dist/chunk-2PRH4Z3N.js +181 -0
- package/dist/chunk-3F7AFM53.js +1 -0
- package/dist/chunk-4HZXATHB.js +27 -0
- package/dist/chunk-55ZANTHL.js +3 -0
- package/dist/chunk-5BKSKLHX.js +1 -0
- package/dist/chunk-63VWBMYR.js +3 -0
- package/dist/chunk-6N5EC7ZO.js +1 -0
- package/dist/chunk-6SNOUSSZ.js +182 -0
- package/dist/chunk-7POHNTVW.js +1 -0
- package/dist/chunk-7SR7MEU5.js +62 -0
- package/dist/chunk-7UHDOIUE.js +1 -0
- package/dist/chunk-ARSQZCTJ.js +945 -0
- package/dist/chunk-B3JRL45T.js +1 -0
- package/dist/chunk-B4ZKPLSP.js +1 -0
- package/dist/chunk-C7MGJUTU.js +1 -0
- package/dist/{chunk-W2BVJ7S2.js → chunk-CNSVZTTT.js} +4 -4
- package/dist/chunk-DGAW7FD7.js +12 -0
- package/dist/chunk-FRXKMOXI.js +41 -0
- package/dist/chunk-GVYGAZV7.js +1 -0
- package/dist/chunk-HCK6PLM3.js +3 -0
- package/dist/{chunk-I3HNHCIJ.js → chunk-HJIOH7HF.js} +199 -84
- package/dist/chunk-HNNYXMSI.js +1 -0
- package/dist/chunk-HUNSEGUN.js +57 -0
- package/dist/chunk-IFPION5D.js +121 -0
- package/dist/{chunk-DYDAQQMC.js → chunk-JAV5V3JT.js} +41 -8
- package/dist/chunk-JMZIDHYQ.js +2 -0
- package/dist/{chunk-FN7U6KRI.js → chunk-JW4GDY7S.js} +1 -1
- package/dist/chunk-KXJCGV3H.js +1 -0
- package/dist/chunk-LFRAA3MY.js +4 -0
- package/dist/{chunk-Y6STAKF3.js → chunk-M5QHXNFZ.js} +3 -3
- package/dist/chunk-MVMWPKRC.js +2 -0
- package/dist/chunk-NALXKTUU.js +1 -0
- package/dist/chunk-NNOX3FYG.js +198 -0
- package/dist/chunk-OB6E6UTD.js +1 -0
- package/dist/chunk-OILOHQNL.js +2 -0
- package/dist/chunk-OLYPLX5C.js +1 -0
- package/dist/chunk-QER2ELZP.js +1 -0
- package/dist/chunk-QWE7VKIX.js +1 -0
- package/dist/chunk-R5LJL6IR.js +225 -0
- package/dist/chunk-RDHGQ2WZ.js +1 -0
- package/dist/chunk-SDQW7IJN.js +1 -0
- package/dist/chunk-SEZETSB3.js +1 -0
- package/dist/chunk-SNJR5N36.js +1 -0
- package/dist/chunk-TPN25AFZ.js +159 -0
- package/dist/{chunk-AK6HVF5F.js → chunk-U4WIJZCX.js} +1 -1
- package/dist/chunk-UIOSADPB.js +1718 -0
- package/dist/{chunk-DYKSPHHR.js → chunk-UNEJYZ4T.js} +1 -1
- package/dist/chunk-VAC3SQ5T.js +16 -0
- package/dist/chunk-VVSHZV5S.js +73 -0
- package/dist/chunk-WNUXMPVX.js +1 -0
- package/dist/chunk-WP3QS4CJ.js +1 -0
- package/dist/chunk-ZPQNY5TI.js +1 -0
- package/dist/contracts-GUXGFCVV.js +1 -0
- package/dist/core-schema-423BSTE6.js +936 -0
- package/dist/dispatch-3HY4735M.js +1 -0
- package/dist/index.cjs +104 -214
- package/dist/index.d.cts +192 -180
- package/dist/index.d.ts +192 -180
- package/dist/index.js +1 -1
- package/dist/media-artifacts-67CJWI7O.js +1 -0
- package/dist/metering-ZH2P62IC.js +1 -0
- package/dist/migrations-3AKEC5QE.js +1 -0
- package/dist/queue-HUP2GNXF.js +1 -0
- package/dist/reconciliation-ANXNJWME.js +1 -0
- package/dist/report-artifact-offload-6OOY2PTM.js +1 -0
- package/dist/repository-4EC5EXVN.js +1 -0
- package/dist/{location-data-repository-NWWKDYG6.js → repository-CYXVMYAI.js} +1 -1
- package/dist/server-VQU6S24A.js +5825 -0
- package/dist/settlement-6CCE2PDH.js +1 -0
- package/dist/worker-5G5BK23B.js +1 -0
- package/package.json +18 -138
- package/dist/analytics-repository-A7VMA24D.js +0 -1
- package/dist/chunk-56C243PX.js +0 -2595
- package/dist/chunk-6ND5AFV5.js +0 -27
- package/dist/chunk-6NE4OIXR.js +0 -6
- package/dist/chunk-DOJMTFLB.js +0 -1
- package/dist/chunk-EDQ57S4P.js +0 -1
- package/dist/chunk-FCJXL4PU.js +0 -182
- package/dist/chunk-GPSPSJBJ.js +0 -1
- package/dist/chunk-HE45FFBU.js +0 -1
- package/dist/chunk-HUV2WTRW.js +0 -1
- package/dist/chunk-L552AQQY.js +0 -84
- package/dist/chunk-MVDMZ3N2.js +0 -1282
- package/dist/chunk-NA76FFGD.js +0 -73
- package/dist/chunk-NZSDHDX3.js +0 -1
- package/dist/chunk-OS4XFDIG.js +0 -21
- package/dist/chunk-QQ7OD7BJ.js +0 -100
- package/dist/chunk-RPA5ADXW.js +0 -16
- package/dist/chunk-TMB56NCA.js +0 -1
- package/dist/chunk-WO3N5FH2.js +0 -5
- package/dist/chunk-XPEJB4BZ.js +0 -1
- package/dist/chunk-YK4OAZRQ.js +0 -4
- package/dist/chunk-YWUNN24S.js +0 -1
- package/dist/chunk-ZJTUAWZA.js +0 -19
- package/dist/chunk-ZPK5LYEN.js +0 -1565
- package/dist/chunk-ZUGTYD2I.js +0 -63
- package/dist/db-B6RNXKEI.js +0 -1
- package/dist/extract-bundle-X7SRN63Y.js +0 -26
- package/dist/gmail-service-FZVJBSUT.js +0 -1
- package/dist/lead-list-enrichment-repository-SXYSS7ZX.js +0 -1
- package/dist/operation-metering-OBKSWJVJ.js +0 -1
- package/dist/server-JV6L7F2X.js +0 -5014
- package/dist/site-extract-repository-UVE7TWJO.js +0 -1
- package/dist/stripe-event-worker-2LSUVQOM.js +0 -1
- package/dist/worker-XPIO5TAV.js +0 -1
- /package/dist/{chunk-YGBTTW5D.js → chunk-2IATUJO6.js} +0 -0
- /package/dist/{chunk-6DTXIZY2.js → chunk-4ZVO6GX4.js} +0 -0
|
@@ -1,4 +1,36 @@
|
|
|
1
|
-
import{f as at}from"./chunk-Y6STAKF3.js";import{b as Pe}from"./chunk-GPSPSJBJ.js";import{c as xe,g as Le}from"./chunk-NA76FFGD.js";import{a as We,b as Ae,c as Ot}from"./chunk-6DTXIZY2.js";import{c as xt,e as Xt,l as Oe}from"./chunk-XPEJB4BZ.js";import{a as be,i as Ie,j as _,k as Lt,m as Z,n as kt,o as te}from"./chunk-ZPK5LYEN.js";import{z as v}from"zod";var ee=v.object({query:v.string().min(1),location:v.string().optional(),gl:v.string().length(2).default("us"),hl:v.string().length(2).default("en"),device:v.enum(["desktop","mobile"]).default("desktop"),proxyMode:v.enum(["location","configured","none"]).default(xt),proxyZip:v.string().regex(/^\d{5}$/).optional(),keepDefaultProxy:v.boolean().optional(),requireUsEgress:v.boolean().optional(),maxAttempts:v.number().int().min(1).max(12).optional(),debug:v.boolean().default(!1),depth:v.number().int().min(1).max(30).default(3),maxQuestions:v.number().int().min(1).max(100).default(100),headless:v.boolean().default(!1),profileDir:v.string().optional(),proxy:v.string().url().optional(),kernelApiKey:v.string().optional(),kernelProxyId:v.string().optional(),kernelProfileName:v.string().optional(),kernelProfileSaveChanges:v.boolean().optional(),kernelStealth:v.boolean().optional(),serpIdentity:v.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/).optional(),kernelProxyResolution:v.unknown().optional(),outputDir:v.string().default("./paa-output"),format:v.enum(["json","csv","both"]).default("both"),serpOnly:v.boolean().default(!1),questionsOnly:v.boolean().default(!1),questionGrowthRecoveryRounds:v.number().int().min(0).max(4).default(2),pages:v.number().int().min(1).max(2).default(1),includeAllSerpFeatures:v.boolean().default(!1),includeLocalPack:v.boolean().default(!1),includeForums:v.boolean().default(!1),includeVideos:v.boolean().default(!1),includeAiOverview:v.boolean().default(!1),includeWhatPeopleSaying:v.boolean().default(!1),includeShortVideos:v.boolean().default(!1),recency:v.enum(["day","week","month","year"]).optional(),softDeadlineMs:v.number().optional()}),Be=v.object({questionId:v.string().min(1),googleLinkId:v.string().nullable(),googleEvidenceId:v.string().nullable(),question:v.string().min(1),answer:v.string().optional(),sourceTitle:v.string().optional(),sourceSite:v.string().optional(),sourceCite:v.string().optional(),sources:v.array(v.object({title:v.string().nullable(),site:v.string().nullable(),url:v.string().min(1),rawUrl:v.string().min(1),resolvedUrl:v.string().nullable(),linkType:v.enum(["plain","google_url_redirect","google_goto_redirect"]),resolutionStatus:v.enum(["not_needed","resolved","unresolved","rejected"])})).default([])});import{chromium as ie}from"playwright-extra";import En from"puppeteer-extra-plugin-stealth";import{chromium as Yn}from"playwright";var Q={paaItem:".related-question-pair",captchaMarker:'#captcha-form, #recaptcha, form[action*="/sorry/"], .g-recaptcha, [data-sitekey]'},He={container:'div[jscontroller="HWk0Gf"]',sectionHeading:'.mgAbYb[role="heading"]',item:"a.rIRoqf"},Bt={udm:"39",item:"a.rIRoqf",durationPattern:/^\d+:\d+$/,platforms:["YouTube","TikTok","Instagram","Facebook","X"]},Fe={section:".ULSxyf",item:"a.KYg7td.INpicf",title:".hyYc0c",source:".K4ETW"},Re={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"},Ge={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"},De={root:'[data-hveid="CAUQAA"]',wrapper:".Fgyi2e",citations:'.Fgyi2e [data-hveid] a[jsname="pxBnId"]'},Ve={result:".wHYlTd.tF2Cxc",title:"h3.LC20lb",siteName:".VuuXrf",cite:"cite.tjvcx",snippet:".VwiC3b",redditCite:"cite.qLRx3b",ratingWrap:".Y0A0hc",ratingValue:".yi40Hd",reviewCount:".RDApEe"},Ee={headingText:"Businesses",card:".w7Dbne",name:".OSrXXb",ratingValue:".yi40Hd",reviewCount:".RDApEe"},Ye="2026-05-07",yi={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 Ht(e,t,n,a){let s,i=!1,d,h=()=>{},S=()=>a?.reason instanceof DOMException&&a.reason.name==="TimeoutError"?a.reason:new Z,U=()=>h(S()),l=new Promise((r,u)=>{h=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 S();a?.addEventListener("abort",U,{once:!0}),d=setTimeout(()=>h(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 Z;if(s=r,await t(r),i)throw new Z;return n(r)})(),l])}finally{i=!0,d&&clearTimeout(d),a?.removeEventListener("abort",U),s&&await o(s)}}var Vn=/\b(?:HeadlessChrome|Chrome|Chromium|Firefox)\/\d+|\bVersion\/\d+.*\bSafari\//;async function Ft(e){try{let t=await e.evaluate(()=>navigator.userAgent);return typeof t=="string"&&Vn.test(t)?t:null}catch{return null}}async function Rt(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 Ft(n)}catch{return null}finally{t&&await t.close().catch(()=>{})}}function pi(e,t){return t?{...e,userAgent:t}:e}ie.use(En());var Kn=180,Jn=3e3,_n=5e3,zn='#search, #rso, a[href] h3, [data-snhf], [role="main"]';function ne(e,t){return e?Math.max(1,Math.min(t,e-Date.now())):t}function qn(e,t){let n=process.env[e];if(!n)return t;let a=Number(n);return Number.isInteger(a)&&a>0?a:t}function ae(e){return e?e.slice(-6):null}function Ke(e,t){let n=(t??process.env.SERP_REDIRECT_BASE)?.trim().replace(/\/+$/,"");return n?`${n}/g/${Buffer.from(e,"utf8").toString("base64url")}`:e}function jn(e){return e?/united states|u\.?s\.?a?\.?|^us$/i.test(e.trim()):!1}function wt(e){return e instanceof Error?e.message:String(e)}function $n(e){return/\b409\b|conflict|already exists/i.test(wt(e))}function Qn(e){return/\b404\b|not[ _-]?found|already (?:gone|deleted|closed)|does not exist/i.test(wt(e))}async function Zn(e,t){try{await e.profiles.create({name:t})}catch(n){if(!$n(n))throw n}}function Gt(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 ct(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 Xn(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 S=d.pathname.split("/").filter(Boolean),U=S[0]??"",l=S[1]??"";if(U.startsWith("@"))return`https://www.youtube.com/${U}/videos`;if(U==="channel"&&l)return`https://www.youtube.com/channel/${l}/videos`;if((U==="c"||U==="user")&&l)return`https://www.youtube.com/${U}/${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 Dt=class{browser=null;context=null;page=null;kernelClient=null;kernelSessionId=null;kernelOpenedAtMs=null;kernelStealth=null;kernelProxyUsed=null;kernelProxySource=null;kernelProxyType=null;kernelHeadlessSent=null;lastKernelBillingMode=null;lastKernelOpenedAtMs=null;lastKernelClosedAtMs=null;debugEnabled=!1;debugSnapshot={kernel:null,context:null,networkLocation:null,serpNavigation:null};async launch(t){this.debugEnabled=t.debug===!0;let n=t.proxyMode??(t.kernelProxyId?"configured":"none"),a=t.isMobile?"mobile":"desktop";if(this.debugSnapshot={kernel: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.kernelApiKey){this.kernelClient=new at({apiKey:t.kernelApiKey});let i=Number.isInteger(t.kernelTimeoutSeconds)&&Number(t.kernelTimeoutSeconds)>0?Number(t.kernelTimeoutSeconds):qn("KERNEL_BROWSER_TIMEOUT_SECONDS",Kn),d=Math.min(i,600);t.kernelProfileName&&t.kernelProfileSaveChanges===!0&&await Zn(this.kernelClient,t.kernelProfileName);let h=Ot(),S;t.headlessMode==="headful"||h?.forceHeadful===!0?S=!1:t.headlessMode==="headless"?S=!0:S=h?.forceHeadless===!0||process.env.KERNEL_HEADLESS_DISABLED!=="true"&&!!h?.op&&xe.has(h.op),this.kernelHeadlessSent=S?!0:null,this.lastKernelBillingMode=S?"headless":"headful",h?.headlessSentOut&&(h.headlessSentOut.value=this.kernelHeadlessSent);let U=await this.kernelClient.browsers.create({stealth:t.kernelStealth===!0,timeout_seconds:d,...S?{headless:!0}:{},...t.kernelProxyId?{proxy_id:t.kernelProxyId}:{},...t.kernelProfileName?{profile:{name:t.kernelProfileName,...typeof t.kernelProfileSaveChanges=="boolean"?{save_changes:t.kernelProfileSaveChanges}:{}}}:{}});this.kernelSessionId=U.session_id,this.kernelOpenedAtMs=Date.now(),this.lastKernelOpenedAtMs=this.kernelOpenedAtMs,this.lastKernelClosedAtMs=null,this.kernelStealth=typeof U.stealth=="boolean"?U.stealth:null,this.kernelProxyUsed=typeof U.proxy_id=="string"?!!U.proxy_id:!!t.kernelProxyId,this.kernelProxySource=t.kernelProxyResolution?.source??null,this.kernelProxyType=t.kernelProxyResolution?.proxyType??null;let l=null,o=null;if(!t.kernelProxyId&&!t.keepDefaultProxy)try{await ct(this.kernelClient.browsers.update(this.kernelSessionId,{disable_default_proxy:!0}),5e3,`Kernel session ${this.kernelSessionId} disable default proxy`),l=!0}catch(u){l=!1,o=wt(u)}let r={sessionId:this.kernelSessionId,proxyMode:n,requestedProxyIdPresent:!!t.kernelProxyId,requestedProxyIdSuffix:ae(t.kernelProxyId),createdProxyIdPresent:typeof U.proxy_id=="string"?!!U.proxy_id:null,createdProxyIdSuffix:ae(U.proxy_id),retrievedProxyIdPresent:null,retrievedProxyIdSuffix:null,retrievedProxyIdMatchesRequested:null,defaultProxyDisabled:l,defaultProxyDisableError:o,proxyResolution:t.kernelProxyResolution??null,timeoutSeconds:d,stealth:typeof U.stealth=="boolean"?U.stealth:null,profilePresent:null,poolPresent:null,retrieveError:null};if(this.debugSnapshot.kernel=r,console.info(JSON.stringify({event:"kernel_browser_created",kernel_session_id:this.kernelSessionId,timeout_seconds:d,proxy_mode:n,proxy_id_present:!!t.kernelProxyId,profile_name_present:!!t.kernelProfileName,proxy_resolution_source:t.kernelProxyResolution?.source})),this.debugEnabled&&await this.populateKernelRetrieveDebug(r,t.kernelProxyId),this.browser=await Yn.connectOverCDP(U.cdp_ws_url),t.kernelProfileName||t.preserveKernelContext)this.context=this.browser.contexts()[0]??await this.browser.newContext(Gt(t)),this.page=this.context.pages()[0]??await this.context.newPage(),this.debugSnapshot.context.userAgent=await Ft(this.page);else{let u=await Rt(this.browser);this.debugSnapshot.context.userAgent=u,this.context=await this.browser.newContext(Gt(t,u)),this.page=await this.context.newPage()}if(await this.installEsbuildHelperShims(this.context),t.preserveKernelContext||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(!jn(u))throw new _(`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 ie.launchPersistentContext(t.profileDir,{...s,...Gt(t)}),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage(),this.debugSnapshot.context.userAgent=await Ft(this.page);else{this.browser=await ie.launch(s);let i=await Rt(this.browser);this.debugSnapshot.context.userAgent=i,this.context=await this.browser.newContext(Gt(t,i)),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage()}this.debugEnabled&&(this.debugSnapshot.networkLocation=await this.captureBrowserNetworkLocation())}async populateKernelRetrieveDebug(t,n){if(!(!this.kernelClient||!this.kernelSessionId))try{let a=await ct(this.kernelClient.browsers.retrieve(this.kernelSessionId),5e3,`Kernel session ${this.kernelSessionId} retrieve`);t.retrievedProxyIdPresent=typeof a.proxy_id=="string"?!!a.proxy_id:!1,t.retrievedProxyIdSuffix=ae(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=wt(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 h=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 h.org=="string"?h.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 ct(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(wt(a))}finally{await n?.close().catch(()=>{})}}async loadJsonInDebugPage(t,n){try{await ct(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 Ht(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 h="https://www.google.com/search?"+d.toString(),S=Ke(h),U=i?.debug?{requestedUrl:h,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(S,{waitUntil:"domcontentloaded",timeout:ne(i?.deadlineMs,i?.purpose==="serp"?8e3:45e3)})}catch(o){await this.updateSerpNavigationDebug(U,h,{hasPaa:null,captchaDetected:null});let r=await this.captureDiagnostics(h);throw new Lt(`page.goto failed: ${o.message} | ${r}`)}if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(U,h,{hasPaa:!1,captchaDetected:!0}),new _(this.captchaMessage());if(i?.purpose==="serp"){await this.page.waitForSelector(zn,{timeout:ne(i.deadlineMs,1500)}).catch(()=>null);let o=await this.page.locator(Q.paaItem).count().catch(()=>0)>0;return await this.updateSerpNavigationDebug(U,h,{hasPaa:o,captchaDetected:!1}),{hasPaa:o}}if(await this.page.waitForSelector(Q.paaItem,{timeout:ne(i?.deadlineMs,4e3)}).catch(()=>null))return await this.updateSerpNavigationDebug(U,h,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(U,h,{hasPaa:!1,captchaDetected:!0}),new _(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(Q.paaItem).count()>0)return await this.updateSerpNavigationDebug(U,h,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};return await this.updateSerpNavigationDebug(U,h,{hasPaa:!1,captchaDetected:!1}),{hasPaa:!1}}async isSerpChallengeVisible(){if(!this.page)return!1;if(await this.page.locator(Q.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(()=>""),h=/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??h,t.googleSorryUrl=/google\.[^/]+\/sorry\//i.test(s),t.redirected=s!==n}catch(s){t.bodySnippet=`debug capture failed: ${wt(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),h=[i?"CONSENT_WALL":"",d?"BOT_CHALLENGE":"",n!==t?"REDIRECTED":""].filter(Boolean).join(",");return`intended=${t} | final=${n} | title="${a}" | flags=[${h}] | body="${s}"`}catch(n){return`diagnostics-failed: ${n.message}`}}captchaMessage(){return this.kernelClient?"Google returned a CAPTCHA on this session \u2014 retrying with a fresh session.":be}async navigateTo(t){let n=process.env.ADS_ARRIVAL_REDIRECT_BASE?.trim(),a=n?Ke(t,n):t;try{if(await this.page.goto(a,{waitUntil:"domcontentloaded",timeout:45e3}),/google\.[^/]+\/search\?/i.test(t)&&await this.isSerpChallengeVisible())throw new _(this.captchaMessage())}catch(s){if(s instanceof _)throw s;let i=await this.captureDiagnostics(t);throw new Lt(`page.goto failed: ${s.message} | ${i}`)}}async navigateToChannel(t){let n=Xn(t);try{await this.page.goto(n,{waitUntil:"networkidle",timeout:3e4})}catch(a){let s=await this.captureDiagnostics(n);throw new Lt(`navigateToChannel failed: ${a.message} | ${s}`)}}async evaluate(t,n){return this.page.evaluate(t,n)}getPage(){return this.page}getKernelSessionId(){return this.kernelSessionId}getKernelMeteringEvidence(){return{sessionId:this.kernelSessionId??this.debugSnapshot.kernel?.sessionId??null,billingMode:this.lastKernelBillingMode,openedAtMs:this.lastKernelOpenedAtMs,closedAtMs:this.lastKernelClosedAtMs}}getProviderSessionMetadata(){return{provider:this.kernelSessionId?"kernel":"local",providerSessionId:this.kernelSessionId,disconnectObservation:null,billingMode:this.kernelSessionId?this.kernelHeadlessSent?"headless":"headful":null}}getDebugSnapshot(){return this.debugSnapshot}async close(){if(this.browser){let t=this.browser,n=this.kernelSessionId,a=this.kernelClient,s=this.kernelOpenedAtMs,i=this.kernelStealth,d=this.kernelProxyUsed,h=this.kernelProxySource,S=this.kernelProxyType,U=this.kernelHeadlessSent,l=this.getProviderSessionMetadata();if(this.browser=null,this.context=null,this.page=null,this.kernelSessionId=null,this.kernelClient=null,this.kernelOpenedAtMs=null,this.kernelHeadlessSent=null,this.kernelProxySource=null,this.kernelProxyType=null,a&&n){console.info(JSON.stringify({event:"kernel_browser_delete_started",kernel_session_id:n}));let o=ct(a.browsers.deleteByID(n),_n,`Kernel session ${n} delete`),r=ct(t.close(),Jn,`Kernel browser ${n} close`),[u,c]=await Promise.allSettled([o,r]);this.lastKernelClosedAtMs=Date.now(),s!=null&&Le({kernelSessionId:n,source:"browser_driver",stealth:i,headlessSent:U,proxyUsed:d,proxySource:h,proxyType:S,openedAtMs:s,closedAtMs:this.lastKernelClosedAtMs});let g=u.status==="rejected"&&Qn(u.reason),N={kernelSessionId:n,kernelDeleteStarted:!0,kernelDeleteSucceeded:u.status==="fulfilled"||g,kernelDeleteError:u.status==="rejected"&&!g?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"&&!g?(console.warn(JSON.stringify({event:"kernel_browser_delete_failed",kernel_session_id:n,message:N.kernelDeleteError})),console.warn(`Kernel session cleanup failed for ${n}:`,u.reason)):console.info(JSON.stringify({event:"kernel_browser_delete_succeeded",kernel_session_id:n})),c.status==="rejected"&&(console.warn(JSON.stringify({event:"kernel_browser_close_failed",kernel_session_id:n,message:N.browserCloseError})),console.warn(`Kernel browser close failed for ${n}:`,c.reason)),N}return await t.close(),{kernelSessionId:null,kernelDeleteStarted:!1,kernelDeleteSucceeded:null,kernelDeleteError: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(),{kernelSessionId:null,kernelDeleteStarted:!1,kernelDeleteSucceeded:null,kernelDeleteError:null,browserCloseSucceeded:!0,browserCloseError:null,provider:"local",providerSessionId:null,providerDisconnectObserved:!1,providerDisconnectMessage:null}}return{kernelSessionId:null,kernelDeleteStarted:!1,kernelDeleteSucceeded:null,kernelDeleteError:null,browserCloseSucceeded:null,browserCloseError:null,provider:"local",providerSessionId:null,providerDisconnectObserved:!1,providerDisconnectMessage:null}}};import{chromium as na}from"playwright";function ta(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 Je(e){let t=ta(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 _e(e){return Je(e)}function ze(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("Bright Data did not return a valid browser session ID");return e}function se(e,t,n=new Date().toISOString()){let a=Je(t);return{source:e,message:a??e.replaceAll("_"," "),observedAt:n}}function ea(e){return{provider:e.provider,providerDisconnectObserved:e.disconnectObservation!==null,providerDisconnectMessage:e.disconnectObservation?.message??null}}function qe(e){return{...ea(e),providerSessionId:e.providerSessionId}}function oe(){return process.env.BRIGHTDATA_BROWSER_WSS?.trim()||null}function je(){return process.env.SERP_BROWSER_PROVIDER?.trim().toLowerCase()==="kernel"?!1:!!oe()}var aa=new Set(["image","media","font","stylesheet","ping"]),ia=["doubleclick.net","googleadservices.com","googlesyndication.com","google-analytics.com"],sa='#search, #rso, a[href] h3, [data-snhf], [role="main"]',oa=3e4,$e=1500;function rt(e,t){return e?Math.max(1,Math.min(t,e-Date.now())):t}async function de(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 Vt=class{constructor(t={}){this.resourcePolicy=t}resourcePolicy;browser=null;context=null;page=null;cdpSession=null;providerSessionId=null;disconnectObservation=null;closing=!1;observeDisconnect(t,n){this.closing||this.disconnectObservation||(this.disconnectObservation=se(t,n))}async launch(t){if(this.page)return;this.closing=!1,this.providerSessionId=null,this.disconnectObservation=null;let n=oe();if(!n)throw new Error("SERP browser service is not configured");this.browser=await na.connectOverCDP(n,{timeout:rt(t.operationDeadlineMs,oa)}),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,h,S)=>(d[h]=S,S))}),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=ze(s?.sessionId),await this.setupPage(this.page),this.resourcePolicy.startupSettleMs&&await this.page.waitForTimeout(this.resourcePolicy.startupSettleMs)}async setupPage(t){this.resourcePolicy.nativeGoogleAssets||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 de(n,!0))&&!(i.pathname.includes("/shared_dict/")&&await de(n))&&!(s==="script"&&(d==="www.google.com"||d==="www.gstatic.com")&&await de(n))){if(aa.has(s)&&!(s==="image"&&this.resourcePolicy.allowImages)&&!(s==="stylesheet"&&this.resourcePolicy.allowStylesheets)){await n.abort("blockedbyclient");return}if(ia.some(h=>d===h||d.endsWith(`.${h}`))){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 Ht(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"});if(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:rt(i?.deadlineMs,i?.purpose==="serp"?12e4:45e3)}),i?.purpose==="serp"&&new URL(this.page.url()).pathname.startsWith("/sorry")&&this.cdpSession){let S=this.cdpSession,U;(await Promise.race([S.send("Captcha.solve",{detectTimeout:rt(i.deadlineMs,3e4)}).catch(()=>null),new Promise(o=>{U=setTimeout(()=>o(null),rt(i.deadlineMs,75e3))})]).finally(()=>{U&&clearTimeout(U)}))?.status==="solve_finished"&&await this.page.waitForURL(o=>new URL(o.toString()).pathname==="/search",{timeout:rt(i.deadlineMs,25e3)}).catch(()=>{})}return i?.purpose==="serp"?(await this.page.waitForSelector(sa,{timeout:rt(i.deadlineMs,8e3)}).catch(()=>null),{hasPaa:await this.page.locator(Q.paaItem).count().catch(()=>0)>0}):{hasPaa:!!await this.page.waitForSelector(Q.paaItem,{timeout:rt(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}getKernelSessionId(){return null}getBrightDataSessionId(){return this.providerSessionId}getProviderSessionMetadata(){return{provider:"bright_data_browser_api",providerSessionId:this.providerSessionId,disconnectObservation:this.disconnectObservation}}getDebugSnapshot(){return{kernel: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 ${$e}ms`)),$e)})])}catch(s){t=_e(s instanceof Error?s.message:String(s))??"Bright Data browser close failed",this.disconnectObservation??=se("browser_close_error",t)}finally{n&&clearTimeout(n)}let a=qe(this.getProviderSessionMetadata());return this.browser=null,this.context=null,this.page=null,this.cdpSession=null,{kernelSessionId:null,kernelDeleteStarted:!1,kernelDeleteSucceeded:null,kernelDeleteError:null,browserCloseSucceeded:t===null,browserCloseError:t,...a}}};function Qe(e,t){return e.plannedProvider==="brightdata"?new Vt({nativeGoogleAssets:t?.nativeGoogleAssets}):new Dt}var D={container:".eJH8qe.adDDi",dataInitq:"[data-initq]",item:Q.paaItem,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:Q.captchaMarker};var lt={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
|
|
1
|
+
import{f as st}from"./chunk-M5QHXNFZ.js";import{a as Kt,b as de,d as je,g as le,h as et,i as nn}from"./chunk-B4ZKPLSP.js";import{f as en}from"./chunk-VVSHZV5S.js";import{a as Qe,i as Ze,j as z,k as X,m as tt,n as xt,o as Jt}from"./chunk-C7MGJUTU.js";import{a as Xe,b as tn,c as _t}from"./chunk-4ZVO6GX4.js";import{a as Yt}from"./chunk-WNUXMPVX.js";import{a as $e}from"./chunk-6N5EC7ZO.js";import{c as ze,d as Tt,f as qe}from"./chunk-HNNYXMSI.js";var lt=class extends Error{constructor(t,n){super(`SERP provider mismatch: planned ${t}, observed ${n}`),this.name="SerpProviderMismatchError"}};function qt(e){return e==="\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061":"\u006b\u0065\u0072\u006e\u0065\u006c"}function an(e){return va({intent:e.intent,\u0062\u0072\u0069\u0067\u0068\u0074\u0044\u0061\u0074\u0061Available:e.\u0062\u0072\u0069\u0067\u0068\u0074\u0044\u0061\u0074\u0061Available,\u006b\u0065\u0072\u006e\u0065\u006cAvailable:!0,persistent\u004b\u0065\u0072\u006e\u0065\u006cIdentityRequested:e.persistent\u004b\u0065\u0072\u006e\u0065\u006cIdentityRequested,retryIndex:e.retryIndex,priorTerminalReason:e.priorTerminalReason,allowedFallbacks:e.\u006b\u0065\u0072\u006e\u0065\u006cFallbackAvailable&&e.intent!=="\u006b\u0065\u0072\u006e\u0065\u006c"?["\u006b\u0065\u0072\u006e\u0065\u006c"]:[],timeoutMs:e.softDeadlineMs==null?4e5:Math.max(1,e.softDeadlineMs-Date.now())})}function sn(e){if(e.forceManagedSerp&&e.force\u004b\u0065\u0072\u006e\u0065\u006cSerp)throw new Error("forceManagedSerp and force\u004b\u0065\u0072\u006e\u0065\u006cSerp cannot both be true");return e.forceManagedSerp?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061":e.force\u004b\u0065\u0072\u006e\u0065\u006cSerp?"\u006b\u0065\u0072\u006e\u0065\u006c":"auto"}function zt(e,t){if(!t)throw new Error(`Requested SERP provider is unavailable: ${e}`);return e}function va(e){if(!Number.isInteger(e.retryIndex)||e.retryIndex<0)throw new Error("retryIndex must be a non-negative integer");if(!Number.isFinite(e.timeoutMs)||e.timeoutMs<=0)throw new Error("timeoutMs must be a positive number");let t,n;e.intent==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?(t=zt("\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",e.\u0062\u0072\u0069\u0067\u0068\u0074\u0044\u0061\u0074\u0061Available),n="explicit_\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"):e.intent==="\u006b\u0065\u0072\u006e\u0065\u006c"?(t=zt("\u006b\u0065\u0072\u006e\u0065\u006c",e.\u006b\u0065\u0072\u006e\u0065\u006cAvailable),n="explicit_\u006b\u0065\u0072\u006e\u0065\u006c"):e.persistent\u004b\u0065\u0072\u006e\u0065\u006cIdentityRequested?(t=zt("\u006b\u0065\u0072\u006e\u0065\u006c",e.\u006b\u0065\u0072\u006e\u0065\u006cAvailable),n="persistent_\u006b\u0065\u0072\u006e\u0065\u006c_identity"):e.\u0062\u0072\u0069\u0067\u0068\u0074\u0044\u0061\u0074\u0061Available?(t="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",n="managed_default"):(t=zt("\u006b\u0065\u0072\u006e\u0065\u006c",e.\u006b\u0065\u0072\u006e\u0065\u006cAvailable),n="\u006b\u0065\u0072\u006e\u0065\u006c_default");let a=e.allowedFallbacks.find(S=>S!==t&&(S==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?e.\u0062\u0072\u0069\u0067\u0068\u0074\u0044\u0061\u0074\u0061Available:e.\u006b\u0065\u0072\u006e\u0065\u006cAvailable)),i=e.retryIndex>0&&a?a:t,s=e.retryIndex===0?"primary":i===t?"same_provider_retry":"provider_fallback";return Object.freeze({plannedProvider:i,attemptKind:s,reasonCode:s==="primary"?n:s==="provider_fallback"?"provider_fallback":"same_provider_retry",retryIndex:e.retryIndex,priorTerminalReason:e.priorTerminalReason??null,timeoutMs:Math.floor(e.timeoutMs),fallbackAllowed:!!a})}function fa(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 on(e){let t=fa(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 St(e){return on(e)}function rn(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 Se(e,t,n=new Date().toISOString()){let a=on(t);return{source:e,message:a??e.replaceAll("_"," "),observedAt:n}}function Na(e){return{provider:e.provider,providerDisconnectObserved:e.disconnectObservation!==null,providerDisconnectMessage:e.disconnectObservation?.message??null}}function dn(e){return{...Na(e),providerSessionId:e.providerSessionId}}function ln(e,t,n,a){return new Proxy(e,{get(i,s,S){if(s==="launch")return async d=>{await t.start(n,"browser"),await i.launch(d);let U=i.getProviderSessionMetadata();if(await t.resource(n,"browser",U.providerSessionId,U.provider),!U.providerSessionId)throw new Error("Browser connection returned no attributable session identity");if(qt(U.provider)!==a)throw new lt(a,U.provider);await t.assertActive(n)};let o=Reflect.get(i,s,S);return typeof o=="function"?o.bind(i):o}})}function Ue(e,t,n,a=null){let i=n.\u006b\u0065\u0072\u006e\u0065\u006cSessionId??n.providerSessionId??null,s=n.\u006b\u0065\u0072\u006e\u0065\u006cSessionId!=null?n.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded===!0:n.physicalOutcome==="terminated",S=n.browserCloseSucceeded===!0&&n.localDisconnectSucceeded!==!1&&s,o=n.physicalOutcome==="not_started"&&n.browserCloseSucceeded===null,d={drained:n.extractionDrained===!0,effects:{browser:{resourceId:i,state:S?"terminated":o?"not_started":"unknown"},proxy:{resourceId:a,state:n.disposableProxyDeleted===!0?a===null?"not_started":"terminated":"unknown"}},details:{browserCloseSucceeded:n.browserCloseSucceeded??null,localDisconnectSucceeded:n.localDisconnectSucceeded??null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:n.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded??null,browserCloseError:St(n.browserCloseError),\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:St(n.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError),localDisconnectError:St(n.localDisconnectError)}};return e.complete(t,d)}import{randomUUID as Un}from"crypto";var Sn="2026-10-10-operation-physical-attempts.1",Ut="operation_physical_attempts";async function he(e){let[t,n,a,i,s]=await Promise.all([e.execute(`PRAGMA table_info(${Ut})`),e.execute("PRAGMA index_info(operation_physical_identity)"),e.execute(`PRAGMA foreign_key_list(${Ut})`),e.execute("SELECT name,sql FROM sqlite_master WHERE name IN ('operation_physical_attempts','operation_physical_unresolved','operation_physical_identity')"),e.execute({sql:"SELECT 1 FROM schema_migrations WHERE version=?",args:[Sn]})]),S=o=>String(i.rows.find(d=>d.name===o)?.sql??"").replace(/\s+/g," ");return["id","parent_run_id","user_id","controller_token","claim_token","scope","attempt_number","provider","profile","intent_json","state","effects_json","resources_json","created_at","updated_at"].every(o=>t.rows.some(d=>d.name===o&&Number(d.notnull)===1))&&t.rows.some(o=>o.name==="id"&&Number(o.pk)===1)&&t.rows.some(o=>o.name==="receipt_json")&&n.rows.map(o=>o.name).join(",")==="parent_run_id,scope,attempt_number"&&a.rows.some(o=>o.table==="operation_runs"&&o.from==="parent_run_id"&&o.to==="id"&&o.on_delete==="CASCADE")&&S(Ut).includes("state IN ('prepared','effects_started','terminated','not_started','unknown')")&&S(Ut).includes("CHECK (json_valid(intent_json))")&&S(Ut).includes("CHECK (json_valid(effects_json))")&&S(Ut).includes("CHECK (json_valid(resources_json))")&&S(Ut).includes("CHECK (receipt_json IS NULL OR json_valid(receipt_json))")&&S(Ut).includes("CHECK ((state IN ('terminated','not_started','unknown') AND receipt_json IS NOT NULL)")&&S("operation_physical_identity").includes("CREATE UNIQUE INDEX")&&S("operation_physical_unresolved").includes("CREATE UNIQUE INDEX")&&S("operation_physical_unresolved").includes("WHERE state IN ('prepared','effects_started','unknown')")&&s.rows.length===1}async function ue(e){if(!await he(e)){try{await e.batch([`CREATE TABLE IF NOT EXISTS operation_physical_attempts (
|
|
2
|
+
id TEXT NOT NULL PRIMARY KEY,
|
|
3
|
+
parent_run_id TEXT NOT NULL REFERENCES operation_runs(id) ON DELETE CASCADE,
|
|
4
|
+
user_id INTEGER NOT NULL CHECK (user_id > 0),
|
|
5
|
+
controller_token TEXT NOT NULL,
|
|
6
|
+
claim_token TEXT NOT NULL,
|
|
7
|
+
scope TEXT NOT NULL,
|
|
8
|
+
attempt_number INTEGER NOT NULL CHECK (attempt_number > 0),
|
|
9
|
+
provider TEXT NOT NULL CHECK (length(provider) BETWEEN 1 AND 100),
|
|
10
|
+
profile TEXT NOT NULL CHECK (profile IN ('customer-funded','funded-parent')),
|
|
11
|
+
intent_json TEXT NOT NULL CHECK (json_valid(intent_json)),
|
|
12
|
+
state TEXT NOT NULL CHECK (state IN ('prepared','effects_started','terminated','not_started','unknown')),
|
|
13
|
+
effects_json TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(effects_json)),
|
|
14
|
+
resources_json TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(resources_json)),
|
|
15
|
+
receipt_json TEXT CHECK (receipt_json IS NULL OR json_valid(receipt_json)),
|
|
16
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
17
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
18
|
+
CHECK ((state IN ('terminated','not_started','unknown') AND receipt_json IS NOT NULL)
|
|
19
|
+
OR (state IN ('prepared','effects_started') AND receipt_json IS NULL))
|
|
20
|
+
)`,"CREATE UNIQUE INDEX IF NOT EXISTS operation_physical_identity ON operation_physical_attempts(parent_run_id,scope,attempt_number)","CREATE UNIQUE INDEX IF NOT EXISTS operation_physical_unresolved ON operation_physical_attempts(parent_run_id) WHERE state IN ('prepared','effects_started','unknown')",{sql:"INSERT OR IGNORE INTO schema_migrations(version) VALUES (?)",args:[Sn]}],"write")}catch(t){if(!await he(e).catch(()=>!1))throw t}if(!await he(e))throw Error("Physical attempt schema is incomplete")}}var hn="(CAST(strftime('%s','now') AS INTEGER)*1000)",E=class extends Error{constructor(){super("physical_permission_or_receipt_unknown"),this.name="PhysicalPermissionError"}},Ta=1e3,Pa=1e3,cn=new WeakSet;function wn(e){let t=e&&typeof e=="object"?e.physicalExecution:void 0;if(t!==void 0){if(!t||typeof t!="object"||!cn.has(t))throw new E;return t}}var un=e=>{if(e!==null&&(!e||e.length>512||/[\s\u0000-\u001f\u007f]/.test(e)||e.includes("://")))throw new E;return e};function Us(e){let t={...e.claim},n={...e.gate,args:[...e.gate.args]},a=e.db,i=()=>a??=Yt();if(qe({userId:t.userId,tool:n.tool,jobId:n.jobId},n),!t.runId||!t.token||!/^[a-z0-9_-]{1,100}$/.test(e.scope)||!Number.isSafeInteger(e.deadlineAt)||!["customer-funded","funded-parent"].includes(e.profile))throw new E;let{scope:s,profile:S,deadlineAt:o}=e,d={sql:`EXISTS (SELECT 1 FROM operation_runs r JOIN operation_executions x ON x.run_id=r.id
|
|
21
|
+
WHERE r.id=? AND r.user_id=? AND r.tool=? AND r.job_id=? AND r.status='running'
|
|
22
|
+
AND x.claim_token=? AND x.phase='effects_started' AND x.expires_at_ms>${hn} AND ${hn}<?) AND (${n.sql})`,args:[t.runId,t.userId,n.tool,n.jobId,t.token,o,...n.args]},U=new Set,h=async l=>{if(!U.has(l.token))throw new E;let c=(await i().execute({sql:"SELECT * FROM operation_physical_attempts WHERE id=? AND claim_token=? AND parent_run_id=? AND user_id=? AND controller_token=?",args:[l.id,l.token,t.runId,t.userId,t.token]})).rows[0];if(!c)throw new E;return c},r={watch(l,u){if(!U.has(l.token))throw new E;let c=new AbortController,w,g=!1,f,M,p=k=>{!g&&!c.signal.aborted&&c.abort(k)},P=()=>p(u?.reason);u?.addEventListener("abort",P,{once:!0}),u?.aborted&&P();let b=setTimeout(()=>p(new DOMException("Physical execution deadline exceeded","TimeoutError")),Math.max(0,Math.min(2147483647,o-Date.now()))),x=async()=>{if(!(g||c.signal.aborted)){try{let k=i().execute({sql:`SELECT 1 FROM operation_physical_attempts
|
|
23
|
+
WHERE id=? AND claim_token=? AND parent_run_id=? AND user_id=? AND controller_token=?
|
|
24
|
+
AND state IN ('prepared','effects_started') AND (${d.sql})`,args:[l.id,l.token,t.runId,t.userId,t.token,...d.args]});(await Promise.race([k,new Promise((N,m)=>{w=m,M=setTimeout(()=>m(new E),Pa)})])).rows.length||p(new E)}catch(k){p(k)}finally{M&&clearTimeout(M),M=void 0,w=void 0}!g&&!c.signal.aborted&&(f=setTimeout(()=>{x()},Ta))}};return x(),Object.freeze({signal:c.signal,stop:()=>{g||(g=!0,w?.(new E),f&&clearTimeout(f),M&&clearTimeout(M),clearTimeout(b),u?.removeEventListener("abort",P))}})},async prepare(l,u){if(!/^[a-z][a-z0-9_-]{0,99}$/.test(l)||!Number.isSafeInteger(u)||u<1||u>100)throw new E;let c=i();await ue(c);let w="physical:"+ze(`${t.runId}\0${s}\0${u}`),g=Un(),f=Tt({provider:l,profile:S,scope:s,attemptNumber:u}),M;try{await c.execute({sql:`INSERT INTO operation_physical_attempts
|
|
25
|
+
(id,parent_run_id,user_id,controller_token,claim_token,scope,attempt_number,provider,profile,intent_json,state)
|
|
26
|
+
SELECT ?,?,?,?,?,?,?,?,?,?,'prepared' WHERE (${d.sql})
|
|
27
|
+
AND NOT EXISTS (SELECT 1 FROM operation_physical_attempts WHERE parent_run_id=? AND state IN ('prepared','effects_started','unknown'))`,args:[w,t.runId,t.userId,t.token,g,s,u,l,S,f,...d.args,t.runId]})}catch(b){M=b}U.add(g);let p=Object.freeze({id:w,token:g}),P=await h(p).catch(()=>null);if(!P||P.state!=="prepared"||P.intent_json!==f)throw U.delete(g),M??new E;return p},async start(l,u){if(!["proxy","browser"].includes(u))throw new E;let c=i(),w=await h(l);if(JSON.parse(String(w.effects_json))[u]!==void 0)throw new E;let g=Un(),f;try{if((await c.execute({sql:`UPDATE operation_physical_attempts SET state='effects_started',effects_json=json_set(effects_json,?,?),updated_at=datetime('now')
|
|
28
|
+
WHERE id=? AND claim_token=? AND parent_run_id=? AND user_id=? AND controller_token=?
|
|
29
|
+
AND state IN ('prepared','effects_started') AND json_type(effects_json,?) IS NULL AND (${d.sql})`,args:[`$.${u}`,g,l.id,l.token,t.runId,t.userId,t.token,`$.${u}`,...d.args]})).rowsAffected!==1)throw new E;return}catch(P){f=P}if(f instanceof E)throw f;let M=await h(l).catch(()=>null),p=(await c.execute({sql:`SELECT (${d.sql}) AS current`,args:d.args}).catch(()=>({rows:[]}))).rows[0]?.current;if(!(M?.state==="effects_started"&&JSON.parse(String(M.effects_json))[u]===g&&p))throw f??new E},async assertActive(l){let u=i(),c=await h(l),w=(await u.execute({sql:`SELECT (${d.sql}) AS current`,args:d.args})).rows[0]?.current;if(c.state!=="effects_started"||!w)throw new E},async resource(l,u,c,w){if(!["proxy","browser"].includes(u))throw new E;let g=i(),f=await h(l),M=un(c);if(!JSON.parse(String(f.effects_json))[u])throw new E;let p=w??String(f.provider);if(!/^[a-z][a-z0-9_-]{0,99}$/.test(p))throw new E;let P=Tt({resourceId:M,provider:p});try{await g.execute({sql:`UPDATE operation_physical_attempts SET resources_json=json_set(resources_json,?,json(?)),updated_at=datetime('now')
|
|
30
|
+
WHERE id=? AND claim_token=? AND parent_run_id=? AND user_id=? AND state IN ('effects_started','unknown') AND json_type(resources_json,?) IS NULL`,args:[`$.${u}`,P,l.id,l.token,t.runId,t.userId,`$.${u}`]})}catch{}let b=await h(l),x=JSON.parse(String(b.resources_json))[u];if(Tt(x)!==P)throw new E},async complete(l,u){let c=i(),w=await h(l),g=JSON.parse(String(w.effects_json)),f=JSON.parse(String(w.resources_json));if(typeof u.drained!="boolean"||!u.effects||!u.details)throw new E;let M=JSON.parse(Tt(u));if(Buffer.byteLength(JSON.stringify(M))>16*1024)throw new E;let p=Object.keys(g).every(B=>{let N=M.effects[B],m=f[B];return N&&m&&N.state!=="unknown"&&un(N.resourceId)===m.resourceId&&(N.state==="not_started"?m.resourceId===null:N.state==="terminated"&&m.resourceId!==null)}),P=M.drained&&p?Object.keys(g).length?"terminated":"not_started":"unknown",b={id:l.id,state:P,cleanup:M},x=Tt(b);try{await c.execute({sql:`UPDATE operation_physical_attempts SET state=?,receipt_json=?,updated_at=datetime('now')
|
|
31
|
+
WHERE id=? AND claim_token=? AND parent_run_id=? AND user_id=? AND state IN ('prepared','effects_started') AND receipt_json IS NULL`,args:[P,x,l.id,l.token,t.runId,t.userId]})}catch{}let k=await h(l);if(k.receipt_json!==x||k.state!==P)throw new E;return b}};return cn.add(r),Object.freeze(r)}async function hs(e,t,n=Yt()){if(!Number.isSafeInteger(t)||t<=0||!e)throw new E;return(await n.execute({sql:`SELECT id,scope,attempt_number,provider,profile,state,effects_json,resources_json,receipt_json FROM operation_physical_attempts
|
|
32
|
+
WHERE parent_run_id=? AND user_id=? ORDER BY attempt_number`,args:[e,t]})).rows.map(i=>({id:String(i.id),scope:String(i.scope),attemptNumber:Number(i.attempt_number),provider:String(i.provider),profile:String(i.profile),state:String(i.state),effects:JSON.parse(String(i.effects_json)),resources:JSON.parse(String(i.resources_json)),receipt:i.receipt_json==null?null:JSON.parse(String(i.receipt_json))}))}async function us(e,t=Yt()){if(!Number.isSafeInteger(e.userId)||e.userId<=0||!e.runId&&(!e.jobId||!e.tool))throw new E;await ue(t);let n=e.runId?"p.parent_run_id=?":"r.job_id=? AND r.tool=?";return(await t.execute({sql:`SELECT 1 FROM operation_physical_attempts p JOIN operation_runs r ON r.id=p.parent_run_id
|
|
33
|
+
WHERE p.user_id=? AND r.user_id=p.user_id AND ${n} AND p.state IN ('prepared','effects_started','unknown') LIMIT 1`,args:[e.userId,...e.runId?[e.runId]:[e.jobId,e.tool]]})).rows.length>0}function cs(e,t){if(!Number.isSafeInteger(e)||e<=0||!t||t.length>512)throw new E;return{sql:"NOT EXISTS(SELECT 1 FROM operation_physical_attempts p JOIN operation_runs r ON r.id=p.parent_run_id WHERE p.user_id=? AND r.user_id=p.user_id AND r.job_id=? AND p.state IN ('prepared','effects_started','unknown'))",args:[e,t]}}import{z as W}from"zod";var ce=W.object({query:W.string().min(1),location:W.string().optional(),gl:W.string().length(2).default("us"),hl:W.string().length(2).default("en"),device:W.enum(["desktop","mobile"]).default("desktop"),proxyMode:W.enum(["location","configured","none"]).default(Kt),proxyZip:W.string().regex(/^\d{5}$/).optional(),keepDefaultProxy:W.boolean().optional(),requireUsEgress:W.boolean().optional(),maxAttempts:W.number().int().min(1).max(12).optional(),debug:W.boolean().default(!1),depth:W.number().int().min(1).max(30).default(3),maxQuestions:W.number().int().min(1).max(100).default(100),headless:W.boolean().default(!1),profileDir:W.string().optional(),proxy:W.string().url().optional(),\u006b\u0065\u0072\u006e\u0065\u006cApiKey:W.string().optional(),\u006b\u0065\u0072\u006e\u0065\u006cProxyId:W.string().optional(),\u006b\u0065\u0072\u006e\u0065\u006cProfileName:W.string().optional(),\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges:W.boolean().optional(),\u006b\u0065\u0072\u006e\u0065\u006cStealth:W.boolean().optional(),serpIdentity:W.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/).optional(),\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution:W.unknown().optional(),outputDir:W.string().default("./paa-output"),format:W.enum(["json","csv","both"]).default("both"),serpOnly:W.boolean().default(!1),questionsOnly:W.boolean().default(!1),questionGrowthRecoveryRounds:W.number().int().min(0).max(4).default(2),pages:W.number().int().min(1).max(2).default(1),includeAllSerpFeatures:W.boolean().default(!1),includeLocalPack:W.boolean().default(!1),includeForums:W.boolean().default(!1),includeVideos:W.boolean().default(!1),includeAiOverview:W.boolean().default(!1),includeWhatPeopleSaying:W.boolean().default(!1),includeShortVideos:W.boolean().default(!1),recency:W.enum(["day","week","month","year"]).optional(),softDeadlineMs:W.number().optional()}),gn=W.object({questionId:W.string().min(1),googleLinkId:W.string().nullable(),googleEvidenceId:W.string().nullable(),question:W.string().min(1),answer:W.string().optional(),answerExpansionIncomplete:W.boolean().optional(),sourceTitle:W.string().optional(),sourceSite:W.string().optional(),sourceCite:W.string().optional(),sources:W.array(W.object({title:W.string().nullable(),site:W.string().nullable(),description:W.string().nullable().optional(),url:W.string().min(1),rawUrl:W.string().min(1),resolvedUrl:W.string().nullable(),linkType:W.enum(["plain","google_url_redirect","google_goto_redirect"]),resolutionStatus:W.enum(["not_needed","resolved","unresolved","rejected"])})).default([])});import{promises as $}from"fs";import Ct from"path";import Pt from"papaparse";var jt=class{async writeJSON(t,n){await $.mkdir(n,{recursive:!0});let i=`${t.seed.toLowerCase().replace(/\W+/g,"-").slice(0,40)}-${Date.now()}.json`,s=Ct.join(n,i);return await $.writeFile(s,JSON.stringify(t,null,2),"utf8"),await $e({title:`${t.seed} scrape`,content:JSON.stringify(t),source:`mcp-scraper:${s}`}),s}async writeCSV(t,n){await $.mkdir(n,{recursive:!0});let i=(t[0]?.seed_query??"paa").toLowerCase().replace(/\W+/g,"-").slice(0,40),s=Pt.unparse(t.map(({sources:d,...U})=>({...U,sources_json:JSON.stringify(d)})),{header:!0}),S=`${i}-${Date.now()}.csv`,o=Ct.join(n,S);return await $.writeFile(o,s,"utf8"),o}async writeVideoCSV(t,n,a){await $.mkdir(a,{recursive:!0});let i=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),s=Pt.unparse(t,{header:!0}),S=`${i}-videos-${Date.now()}.csv`,o=Ct.join(a,S);return await $.writeFile(o,s,"utf8"),o}async writeForumCSV(t,n,a){await $.mkdir(a,{recursive:!0});let i=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),s=Pt.unparse(t,{header:!0}),S=`${i}-forums-${Date.now()}.csv`,o=Ct.join(a,S);return await $.writeFile(o,s,"utf8"),o}async writeAIOverviewCSV(t,n,a,i){await $.mkdir(i,{recursive:!0});let s=a.toLowerCase().replace(/\W+/g,"-").slice(0,40),S=t.map((h,r)=>({seed_query:a,response_text:r===0?n??"":"",citation_text:h.text,citation_href:h.href})),o=Pt.unparse(S,{header:!0}),d=`${s}-ai-overview-${Date.now()}.csv`,U=Ct.join(i,d);return await $.writeFile(U,o,"utf8"),U}async writeAIModeCSV(t,n,a,i){await $.mkdir(i,{recursive:!0});let s=a.toLowerCase().replace(/\W+/g,"-").slice(0,40),S=t.map((h,r)=>({seed_query:a,response_text:r===0?n??"":"",citation_text:h.text,citation_href:h.href})),o=Pt.unparse(S,{header:!0}),d=`${s}-ai-mode-${Date.now()}.csv`,U=Ct.join(i,d);return await $.writeFile(U,o,"utf8"),U}async writeWhatPeopleSayingCSV(t,n,a){await $.mkdir(a,{recursive:!0});let i=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),s=t.map(U=>({seed_query:n,...U})),S=Pt.unparse(s,{header:!0}),o=`${i}-what-people-saying-${Date.now()}.csv`,d=Ct.join(a,o);return await $.writeFile(d,S,"utf8"),d}};import{randomInt as Ia}from"crypto";var Wa="pr.oxylabs.io",Aa=7777,xa=10,Ps=2;function yn(){return process.env.OXYLABS_USERNAME?.trim()||void 0}function pn(){return process.env.OXYLABS_PASSWORD?.trim()||void 0}function La(){return(process.env.OXYLABS_COUNTRY?.trim()||"US").toUpperCase()}function $t(){return!!(yn()&&pn())}function Oa(){let e="";for(let t=0;t<10;t++)e+=String(Ia(0,10));return e}function Ba(e={}){let t=yn();if(!t)return;let n=t.startsWith("customer-")?t:`customer-${t}`,a=(e.country?.trim()||La()).toUpperCase(),i=e.sticky?`-sessid-${Oa()}-sesstime-${xa}`:"";return`${n}-cc-${a}${i}`}function we(e){return e.replace(/pr\.oxylabs\.io(:\d+)?/gi,"backup proxy").replace(/oxylabs/gi,"backup proxy")}function Ha(e){return`mcp-backup-custom-${`${Date.now()}-${e??0}-${Math.random().toString(36).slice(2,8)}`}`}async function Qt(e,t={}){let n=Ba({sticky:t.sticky}),a=pn();if(!n||!a)throw new Error("backup proxy pool is not configured");let i=new st({apiKey:e});try{let s=await i.proxies.create({type:"custom",name:Ha(t.attemptIndex),protocol:"http",config:{host:Wa,port:Aa,username:n,password:a}});if(!s.id)throw new Error("backup proxy creation did not return a proxy id");return s.id}catch(s){let S=s instanceof Error?s.message:String(s);throw new Error(we(S))}}async function bs(e,t){if(!(!e||!$t()))try{return await Qt(e,{attemptIndex:t})}catch{return}}async function Is(e,t){if(!(!e||!t))try{await new st({apiKey:e}).proxies.delete(t)}catch{}}var kt={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 mn=`3, Nanjemoy,Maryland,United States
|
|
2
34
|
Aaronsburg,Pennsylvania,United States
|
|
3
35
|
Abbeville,Alabama,United States
|
|
4
36
|
Abbeville,Georgia,United States
|
|
@@ -21690,21 +21722,22 @@ Zortman,Montana,United States
|
|
|
21690
21722
|
Zuehl,Texas,United States
|
|
21691
21723
|
Zumbrota,Minnesota,United States
|
|
21692
21724
|
Zuni,New Mexico,United States
|
|
21693
|
-
Zwolle,Louisiana,United States`,
|
|
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(Xe)){let a=String(n).toLowerCase();e.has(a)||e.set(a,String(n))}le=e,en=t}function ra(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 nn(e){let t=Buffer.from(e,"utf8");return`w+${Buffer.concat([Buffer.from([8,2,16,32,34]),Buffer.from(ra(t.length)),t]).toString("base64")}`}function tn(){return{canonical:null,matched:!1,source:"unresolved",ambiguousCandidates:0}}function it(e,t){return{canonical:e,matched:!0,source:t,ambiguousCandidates:0}}function Se(e){let t=e.toLowerCase().trim();if(!t)return tn();if(lt[t])return it(lt[t],"alias");da();let n=le,a=en,s=n.get(t);if(s)return it(s,"exact");let i=n.get(`${t},united states`);if(i)return it(i,"state-or-country");let d=t.split(",");if(d.length>=2){let o=d[0].trim(),r=d.slice(1).join(",").trim(),u=re[r.toUpperCase()]??r,c=n.get(`${o},${u.toLowerCase()},united states`);if(c)return it(c,"city-state")}let h=t.match(/^(.*?)[\s,]+([a-z]{2})$/);if(h){let o=re[h[2].toUpperCase()];if(o){let r=n.get(`${h[1].trim()},${o.toLowerCase()},united states`);if(r)return it(r,"city-state")}}let S=a.get(t);if(S?.length===1)return it(S[0],"city-unique");if(S&&S.length>1)return{canonical:null,matched:!1,source:"unresolved",ambiguousCandidates:S.length};let U=d[0].trim();if(U!==t&<[U])return it(lt[U],"alias-partial");let l=t.replace(/\s+[a-z]{2}$/,"").trim();return l!==t&<[l]?it(lt[l],"alias-partial"):tn()}function an(e){return Se(e).canonical??e}var Ue={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"},la=[...Object.keys(Ue).map(e=>e.replace(/\s+/g,"\\s+")),...Object.values(Ue)].join("|"),Sa=new RegExp(`\\b([A-Z][A-Za-z]+(?:[\\s.-][A-Z][A-Za-z]+){0,4}),?\\s+(${la})\\b`,"gi");function on(e){if(!e)return null;let t=e.trim();return/^[A-Z]{2}$/i.test(t)?t.toUpperCase():Ue[t.toLowerCase()]??null}function dn(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 Ua(e){if(!e)return null;let[t="",n=""]=e.split(",").map(a=>a.trim());return{city:dn(t),regionCode:on(n),canonicalLocation:e}}function ha(e,t,n,a){let s=dn(t),i=on(n);if(!s||!i)return;let d=`${s.toLowerCase()}|${i}`,h=e.get(d);if(h){h.count++,h.examples.length<3&&!h.examples.includes(a)&&h.examples.push(a);return}e.set(d,{city:s,regionCode:i,count:1,examples:[a]})}function ua(e){try{return decodeURIComponent(e)}catch{}try{return decodeURIComponent(e.replace(/%(?![0-9a-fA-F]{2})/g,"%25"))}catch{return e}}function sn(e,t){let n=ua(t).replace(/[+/|_-]+/g," ");for(let a of n.matchAll(Sa))ha(e,a[1]??"",a[2]??"",n.slice(0,180))}function pt(e,t,n){let a=Ua(e),s=new Map;for(let h of t)sn(s,[h.title,h.snippet??"",h.cite??"",h.url].join(" "));for(let h of n)sn(s,[h.name,...h.metadata,h.websiteUrl??"",h.directionsUrl??""].join(" "));let i=Array.from(s.values()).sort((h,S)=>S.count-h.count||h.city.localeCompare(S.city)).slice(0,8);return a?i.length===0?{status:"unknown",expected:a,candidates:[]}:{status:i.some(h=>h.city.toLowerCase()===a.city.toLowerCase()&&(a.regionCode==null||h.regionCode===a.regionCode))?"matched":"mismatch",expected:a,candidates:i}:{status:"not_requested",expected:null,candidates:i}}var ca=[/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],wa=[/\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 Et(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 ga(e){let t=-1;for(let n of wa){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 ya(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 Ca(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 h=a.slice(d.index+1).trim(),S=h.slice(0,160),U=/^(?:Best|Top|What|How|Why|When|Where|Which|Can|Should|Is|Are|Do|Does)\b/i.test(h);if(h.length>20&&U&&/(?:\s[-|]\s|Heating|Cooling|Company|Services|Blog|Guide|Review)/i.test(S))return n+d.index+1}let i=s.at(-1);return i?.index!==void 0?n+i.index+1:e.length}function Ma(e){let t=e.match(/https?:\/\/\S+/i);if(!t?.index)return e;let n=e.slice(0,t.index);return n.slice(0,Ca(n))}function ka(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 rn(e,t,n){if(!e)return;let a=Et(e),s=t?Et(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 ca)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=Et(a),a=ga(a),a=ya(a,n),a=Ma(a),a=Et(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=ka(a),!!a&&!/^An error has occurred\.?\s*Please try again later\.?$/i.test(a))return a}}async function ln(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 P=y.replace(/\s+/g," ").trim();return P.length>=16&&P.split(" ").filter(Boolean).length>=2}function d(y){let P=y.querySelector(t.aio.heading);if(s(P)==="AI Overview")return!0;let w=y.querySelector(t.aio.header);return!!s(w).split(/\n|\s{2,}/).some(C=>C.trim()==="AI Overview")}function h(){let P=Array.from(document.querySelectorAll(t.aio.root)).find(d);if(P)return P;if(t.aio.legacyRoot){let C=document.querySelector(t.aio.legacyRoot);if(C&&d(C))return C}let w=document.querySelectorAll(`${t.aio.heading}, h1, h2, h3, [role="heading"]`);for(let C of w){if(s(C)!=="AI Overview")continue;let M=C.parentElement;for(let m=0;m<8&&M;m++){if(M.matches(t.aio.root)||M.querySelector(t.aio.controller)||M.querySelector(t.aio.contentSubtree))return M;M=M.parentElement}return C.parentElement}return null}function S(y){if(!y)return null;let P=y.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(I=>I.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(P),document.body.append(w);let C=P.innerText||P.textContent||"";w.remove();let M=C.replace(/\r/g,"").replace(/[ \t]+\n/g,`
|
|
21725
|
+
Zwolle,Louisiana,United States`,Cn={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 ge={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 ye=null,Mn=null;function Fa(){if(ye)return;let e=new Map,t=new Map;for(let n of mn.split(`
|
|
21726
|
+
`)){let a=n.trim();if(!a)continue;let i=a.toLowerCase();e.has(i)||e.set(i,a);let s=i.split(",",1)[0],S=t.get(s);S?S.push(a):t.set(s,[a])}for(let n of Object.values(Cn)){let a=String(n).toLowerCase();e.has(a)||e.set(a,String(n))}ye=e,Mn=t}function Ra(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 vn(e){let t=Buffer.from(e,"utf8");return`w+${Buffer.concat([Buffer.from([8,2,16,32,34]),Buffer.from(Ra(t.length)),t]).toString("base64")}`}function kn(){return{canonical:null,matched:!1,source:"unresolved",ambiguousCandidates:0}}function ht(e,t){return{canonical:e,matched:!0,source:t,ambiguousCandidates:0}}function pe(e){let t=e.toLowerCase().trim();if(!t)return kn();if(kt[t])return ht(kt[t],"alias");Fa();let n=ye,a=Mn,i=n.get(t);if(i)return ht(i,"exact");let s=n.get(`${t},united states`);if(s)return ht(s,"state-or-country");let S=t.split(",");if(S.length>=2){let r=S[0].trim(),l=S.slice(1).join(",").trim(),u=ge[l.toUpperCase()]??l,c=n.get(`${r},${u.toLowerCase()},united states`);if(c)return ht(c,"city-state")}let o=t.match(/^(.*?)[\s,]+([a-z]{2})$/);if(o){let r=ge[o[2].toUpperCase()];if(r){let l=n.get(`${o[1].trim()},${r.toLowerCase()},united states`);if(l)return ht(l,"city-state")}}let d=a.get(t);if(d?.length===1)return ht(d[0],"city-unique");if(d&&d.length>1)return{canonical:null,matched:!1,source:"unresolved",ambiguousCandidates:d.length};let U=S[0].trim();if(U!==t&&kt[U])return ht(kt[U],"alias-partial");let h=t.replace(/\s+[a-z]{2}$/,"").trim();return h!==t&&kt[h]?ht(kt[h],"alias-partial"):kn()}function fn(e){return pe(e).canonical??e}var Nn={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"},Da={"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 Ga(e){return e?e.slice(-6):null}function q(e,t,n,a,i,s=!1){return{\u006b\u0065\u0072\u006e\u0065\u006cProxyId:n,...s&&n?{disposableProxyId:n}:{},resolution:{source:e,proxyType:e==="disabled"?"none":e==="configured_fallback"?"configured":e==="mobile_created"?"mobile":e==="isp_created"?"isp":e==="backup_custom"?"custom":e==="location_created"||e==="location_reused"?"residential":"unknown",proxyMode:t,proxyIdPresent:!!n,proxyIdSuffix:Ga(n),target:a,error:i,disposable:s}}}function Ea(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function Va(e){return e.trim().toLowerCase().replace(/\./g,"").replace(/\s+/g," ")}function Ya(e){if(!e)return!0;let t=Va(e);return t==="united states"||t==="united states of america"||t==="usa"||t==="us"}function Ce(e){let t=e.trim();if(/^[A-Za-z]{2}$/.test(t)){let n=t.toUpperCase();return Object.values(Nn).includes(n)?n:null}return Nn[Ea(t)]??null}function Ka(e){let n=e.normalize("NFKD").replace(/[^\x00-\x7F]/g,"").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean),a=n.join("_"),i=n.join("");return Array.from(new Set([a,i].filter(Boolean)))}function ct(e,t,n){return n?`mcp-serp-residential-${e.toLowerCase()}-${t.toLowerCase()}-${n}`:`mcp-serp-residential-${e.toLowerCase()}-${t.toLowerCase()}`}function Lt(e,t){let n=`${Date.now()}-${t??0}-${Math.random().toString(36).slice(2,8)}`;return`${e}-fresh-${n}`}function Ja(e){return`mcp-serp-residential-us-zip-${e}`}function Tn(e,t){if(!e||t.toLowerCase()!=="us")return null;let n=fn(e),a=n.split(",").map(U=>U.trim()).filter(Boolean);if(a.length>1&&Ya(a[a.length-1])&&(a=a.slice(0,-1)),a.length===1){let U=Ce(a[0]);return U?{canonicalLocation:n,level:"state",country:"US",state:U,city:"",cityCandidates:[],proxyName:ct("US",U),config:{country:"US",state:U}}:null}let[i="",s=""]=a;if(!i||!s)return null;let S=Ce(s);if(!S)return null;let o=Ka(i),d=o[0];return d?{canonicalLocation:n,level:"city",country:"US",state:S,city:d,cityCandidates:o,proxyName:ct("US",S,d),config:{country:"US",state:S,city:d}}:null}function _a(e){return`${e.city}|${e.state}`}function Pn(e,t){return t&&/^\d{5}$/.test(t)?t:Da[_a(e)]??null}function bn(e,t){return{...e,level:"zip",zip:t,proxyName:Ja(t),config:{country:e.country,state:e.state,zip:t}}}function me(e,t){return{...e,proxyName:t}}function Me(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 za(e,t){return e.find(n=>n.type==="residential"&&n.status!=="unavailable"&&!!n.id&&(n.name===t.proxyName||Me(n.config,t,t.level==="city"?t.city:void 0)))??null}function qa(e,t){for(let n of t.cityCandidates){let a=ct(t.country,t.state,n),i=e.find(s=>s.type==="residential"&&s.status!=="unavailable"&&!!s.id&&(s.name===a||Me(s.config,t,n)));if(i)return i}return null}function Zt(e){return{...e,level:"state",proxyName:ct(e.country,e.state),config:{country:e.country,state:e.state}}}function ja(e,t){let n=ct(t.country,t.state);return e.find(a=>a.type==="residential"&&a.status!=="unavailable"&&!!a.id&&(a.name===n||Me(a.config,t)))??null}function $a(e,t){return Zt(e)}function ut(e){return e instanceof Error?e.message:String(e)}function Qa(e,t,n){let a=[],i=Pn(e,t);if(i){let S=bn(e,i);a.push(me(S,Lt(S.proxyName,n)))}for(let S of e.cityCandidates){let o={...e,level:"city",city:S,proxyName:ct(e.country,e.state,S),config:{country:e.country,state:e.state,city:S}};a.push(me(o,Lt(o.proxyName,n)))}let s=Zt(e);return a.push(me(s,Lt(s.proxyName,n))),a}async function ke(e,t,n){if(e.backupOnExhaustion&&n.length>0&&e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey&&$t())try{let a=await Qt(e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,{attemptIndex:e.attemptIndex});return q("backup_custom",e.proxyMode,a,t,null,!0)}catch(a){n.push(`backup: ${we(ut(a))}`)}return q("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,t,n.join(" | "))}async function Es(e){if(!e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey||!$t())return null;try{let t=await Qt(e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,{attemptIndex:e.attemptIndex});return q("backup_custom",e.proxyMode,t,null,null,!0)}catch{return null}}async function Za(e,t,n){let a=[];for(let i of Qa(n,t.proxyZip,t.attemptIndex))try{let s=await e.proxies.create({type:"residential",name:i.proxyName,config:i.level==="zip"?{country:i.country,zip:i.zip}:i.config});if(s.id)return q("location_created",t.proxyMode,s.id,i,null,!0);a.push(`${i.proxyName}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(s){a.push(`${i.proxyName}: ${ut(s)}`)}if(process.env.\u004b\u0045\u0052\u004e\u0045\u004c_PROXY_TYPE!=="residential"){let i=Zt(n);try{let s=await e.proxies.create({type:"isp",name:Lt(`mcp-serp-isp-${i.country.toLowerCase()}-${(i.state??"").toLowerCase()}`,t.attemptIndex),config:{country:i.country,...i.state?{state:i.state}:{}}});if(s.id)return q("isp_created",t.proxyMode,s.id,i,null,!0);a.push("isp: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id")}catch(s){a.push(`isp: ${ut(s)}`)}}return ke(t,n,a)}async function In(e,t){if(!e||!t)return;await new st({apiKey:e}).proxies.delete(t)}async function Vs(e){let t=Ce(e.state);if(!t)throw new Error("A valid US state is required for a mobile Maps proxy");let n=new st({apiKey:e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey}),a=Tn(t,"us");if(!a)throw new Error("Could not resolve the mobile Maps proxy state");let i=await n.proxies.create({type:"mobile",name:Lt(`mcp-maps-mobile-us-${t.toLowerCase()}`,e.attemptIndex),config:{country:"US",state:t}});if(!i.id)throw new Error("\u004b\u0065\u0072\u006e\u0065\u006c did not return a mobile proxy id");if(i.type!=="mobile"||i.status==="unavailable"||i.config?.state?.toUpperCase()!==t)throw await n.proxies.delete(i.id),new Error(`\u004b\u0065\u0072\u006e\u0065\u006c did not confirm a mobile proxy for ${t}`);return q("mobile_created","configured",i.id,a,null,!0)}async function Wn(e){if(e.proxyMode==="none")return q("disabled",e.proxyMode,void 0,null,null);if(e.proxyMode==="configured")return q("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,null,null);let t=Tn(e.location,e.gl);if(!t||!e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey)return q("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 st({apiKey:e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey});try{let a=e.attemptIndex??0;if(e.fresh)return await Za(n,e,t);if(a>=1){let h=$a(t,a),r=[];try{let l=await n.proxies.create({type:"residential",name:h.proxyName,config:h.config});if(l.id)return q("location_created",e.proxyMode,l.id,h,null);r.push(`${h.state}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(l){r.push(`${h.state}: ${ut(l)}`)}return ke(e,h,r)}let i=[];for await(let h of await n.proxies.list())i.push(h);let s=Pn(t,e.proxyZip),S=[];if(s){let h=bn(t,s),r=za(i,h);if(r?.id)return q("location_reused",e.proxyMode,r.id,h,null);try{let l=await n.proxies.create({type:"residential",name:h.proxyName,config:{country:h.country,zip:s}});if(l.id)return q("location_created",e.proxyMode,l.id,h,null);S.push(`${s}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(l){S.push(`${s}: ${ut(l)}`)}}let o=qa(i,t);if(o?.id)return q("location_reused",e.proxyMode,o.id,t,S.join(" | ")||null);for(let h of t.cityCandidates)try{let r=await n.proxies.create({type:"residential",name:ct(t.country,t.state,h),config:{country:t.country,state:t.state,city:h}});if(r.id)return q("location_created",e.proxyMode,r.id,{...t,level:"city",city:h,proxyName:ct(t.country,t.state,h),config:{country:t.country,state:t.state,city:h}},null);S.push(`${h}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(r){S.push(`${h}: ${ut(r)}`)}let d=Zt(t),U=ja(i,d);if(U?.id)return q("location_reused",e.proxyMode,U.id,d,S.join(" | "));try{let h=await n.proxies.create({type:"residential",name:d.proxyName,config:d.config});if(h.id)return q("location_created",e.proxyMode,h.id,d,S.join(" | "));S.push(`${d.state}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(h){S.push(`${d.state}: ${ut(h)}`)}return ke(e,t,S)}catch(a){return q("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,t,ut(a))}}function ve(){return process.env.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_BROWSER_WSS?.trim()||null}function An(){return process.env.SERP_BROWSER_PROVIDER?.trim().toLowerCase()==="\u006b\u0065\u0072\u006e\u0065\u006c"?!1:!!ve()}import{chromium as Ie}from"playwright-extra";import ri from"puppeteer-extra-plugin-stealth";import{chromium as di}from"playwright";var j={paaItem:".related-question-pair",captchaMarker:'#captcha-form, #recaptcha, form[action*="/sorry/"], .g-recaptcha, [data-sitekey]'},Ot={container:'div[jscontroller="HWk0Gf"]',sectionHeading:'.mgAbYb[role="heading"]',item:"a.rIRoqf"},Bt={udm:"39",item:"a.rIRoqf",durationPattern:/^\d+:\d+$/,platforms:["YouTube","TikTok","Instagram","Facebook","X"]},xn={section:".ULSxyf",item:"a.KYg7td.INpicf",title:".hyYc0c",source:".K4ETW"},Ln={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"},On={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"},Bn={root:'[data-hveid="CAUQAA"]',wrapper:".Fgyi2e",citations:'.Fgyi2e [data-hveid] a[jsname="pxBnId"]'},Hn={result:".wHYlTd.tF2Cxc",title:"h3.LC20lb",siteName:".VuuXrf",cite:"cite.tjvcx",snippet:".VwiC3b",redditCite:"cite.qLRx3b",ratingWrap:".Y0A0hc",ratingValue:".yi40Hd",reviewCount:".RDApEe"},Fn={headingText:"Businesses",card:".w7Dbne",name:".OSrXXb",ratingValue:".yi40Hd",reviewCount:".RDApEe"},Rn="2026-05-07",Js={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 Xt(e,t,n,a){let i,s=!1,S,o=()=>{},d=()=>a?.reason instanceof DOMException&&a.reason.name==="TimeoutError"?a.reason:new tt,U=()=>o(d()),h=new Promise((l,u)=>{o=u}),r=async l=>{let u;try{await Promise.race([l.close().catch(()=>{}),new Promise(c=>{u=setTimeout(c,2e3)})])}finally{u&&clearTimeout(u)}};if(a?.aborted)throw d();a?.addEventListener("abort",U,{once:!0}),S=setTimeout(()=>o(new DOMException("Optional pagination timed out","TimeoutError")),3e4);try{return await Promise.race([(async()=>{let l=await e.newPage();if(s)throw await r(l),new tt;if(i=l,await t(l),s)throw new tt;return n(l)})(),h])}finally{s=!0,S&&clearTimeout(S),a?.removeEventListener("abort",U),i&&await r(i)}}var Xa=/\b(?:HeadlessChrome|Chrome|Chromium|Firefox)\/\d+|\bVersion\/\d+.*\bSafari\//;async function fe(e){try{let t=await e.evaluate(()=>navigator.userAgent);return typeof t=="string"&&Xa.test(t)?t:null}catch{return null}}async function Ne(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 fe(n)}catch{return null}finally{t&&await t.close().catch(()=>{})}}function js(e,t){return t?{...e,userAgent:t}:e}function Dn(e){let{headless:t,viewport:n,userAgent:a,user_agent:i,...s}=e;return s}async function Gn(e,t={}){return t.blockServiceWorkers?e.newContext({viewport:null,serviceWorkers:"block"}):e.contexts()[0]??await e.newContext({viewport:null})}async function En(e){return e.pages()[0]??await e.newPage()}function te(e={}){let t=e.nowMs??Date.now(),n=Math.max(0,e.waitMs??3e4);return Math.min(e.deadlineMs??1/0,t+n)}var Xs=te({nowMs:0});async function Vn(e){let t=te(e),n=async()=>{if(e.signal?.aborted)throw le(e.signal);let i=t-Date.now();if(i<=0)return!0;let s;try{return await et(Promise.race([e.observeChallenge(),new Promise(S=>{s=setTimeout(()=>S(!0),i)})]),e.signal)}finally{s&&clearTimeout(s)}},a=await n();if(!e.solverEnabled)return a;for(;a&&Date.now()<t;){let i;try{await et(new Promise(s=>{i=setTimeout(s,Math.min(500,t-Date.now()))}),e.signal)}finally{i&&clearTimeout(i)}if(e.signal?.aborted)throw le(e.signal);if(Date.now()>t)break;a=await n()}return a}var ti=`#search h3, #rso h3, #search .related-question-pair, #rso .related-question-pair, #search ${Ot.item}, #rso ${Ot.item}, #search .isv-r, #rso .isv-r`,ei=75e3,ni=3e3;async function Te(e,t){if(t.signal?.aborted)throw new tt;let n=Math.min(Date.now()+ei,t.deadlineMs===void 0?1/0:t.deadlineMs-ni);if(n<=Date.now())throw new X("Google search navigation has no remaining time");let a=nn(Math.max(1,n-Date.now()),t.signal),i=!1,s,S=async()=>{if(!await et(Yn(e),a))return!1;if(i=!0,s??=te({deadlineMs:n}),await Vn({solverEnabled:t.solverEnabled,deadlineMs:s,signal:a,observeChallenge:()=>Yn(e)}))throw new z("Google challenge did not clear within the remaining browser time.");return!0};try{await si(e,{params:ai(t),deadlineMs:n,signal:a},S,ii);let o=()=>et(oi(e,{query:t.query,deadlineMs:n,signal:a,readySelector:ti},S),a);if(await o(),t.purpose==="paa"){let d=Math.min(n,Date.now()+4e3);await et(e.waitForSelector(j.paaItem,{state:"visible",timeout:Math.max(1,d-Date.now())}).catch(()=>null),a);for(let U=1;U<=6&&Date.now()<n&&(await S(),!await et(e.locator(j.paaItem).count(),a));U+=1)await et(e.evaluate(h=>{window.scrollTo(0,document.body.scrollHeight*h)},U/6),a),await et(new Promise(h=>setTimeout(h,Math.min(400,n-Date.now()))),a)}for(;Date.now()<n;){await o();let d=await et(e.locator(j.paaItem).count(),a)>0;if(!await S())return{hasPaa:d,challengeObserved:i}}throw new X("Google search results did not reach a readable state")}catch(o){throw t.signal?.aborted?new tt:o instanceof z||o instanceof X?o:o instanceof Error&&o.message==="Google search results did not reach a readable state"?new X(o.message):o instanceof Error&&/^Google search (?:homepage|consent inspection|consent|search box readiness|search box inspection|search box focus|search box clear|query typing|suggestion dismissal|search parameters|search button inspection|search submit) (?:failed|timed out)$/.test(o.message)?new X(o.message):o instanceof Error&&["Google homepage did not expose a visible search box","Google search form did not expose a visible Search button"].includes(o.message)?new X(o.message):new X(a.aborted?"Google search navigation timed out before results were ready":"Google homepage search interaction failed")}}async function Yn(e){if(/google\.[^/]+\/sorry(?:\/|\?|$)/i.test(e.url())||await e.locator(j.captchaMarker).count())return!0;let t=await e.locator("body").innerText({timeout:1e3}).catch(()=>"");return/recaptcha|unusual traffic|are you a robot|about this page|detected unusual traffic/i.test(t.slice(0,3e3))}function ai(e){let t={...e.extraParams,q:e.query,gl:e.gl,hl:e.hl,pws:"0"};return e.tbs&&(t.tbs=e.tbs),e.uule&&(t.uule=e.uule),t}async function ii(e,t={}){let n=t.deadlineMs??Date.now()+1e4,a=async(o,d,U=8e3)=>{let h=Math.min(U,n-Date.now());if(t.signal?.aborted){let c=new Error("Google search navigation aborted");throw c.name="AbortError",c}if(h<=0)throw new Error("Google search navigation deadline exhausted");let r,l,u=new Promise((c,w)=>{r=setTimeout(()=>w(new Error(`Google search ${o} timed out`)),h),t.signal&&(l=()=>{let g=new Error("Google search navigation aborted");g.name="AbortError",w(g)},t.signal.addEventListener("abort",l,{once:!0}))});try{return await Promise.race([d(h),u])}catch{if(t.signal?.aborted){let c=new Error("Google search navigation aborted");throw c.name="AbortError",c}throw new Error(`Google search ${o} failed`)}finally{r&&clearTimeout(r),l&&t.signal?.removeEventListener("abort",l)}},i=/^(reject all|reject optional|continue without accepting|only necessary|alle ablehnen|tout refuser|rechazar todo|rifiuta tutto|rejeitar tudo|alles afwijzen)$/i;if(!await a("consent inspection",()=>e.evaluate(o=>{let d=new RegExp(o,"i");return/^consent\.google\./i.test(window.location.hostname)||!!document.querySelector("#W0wltc")||Array.from(document.querySelectorAll('button, [role="button"]')).some(U=>d.test(U.textContent?.trim()??""))},i.source),2e3))return!1;let S=e.locator("#W0wltc").or(e.getByRole("button",{name:i}));for(let o=0,d=await a("consent inspection",()=>S.count(),2e3);o<d;o+=1){let U=S.nth(o);if(await a("consent inspection",()=>U.isVisible(),2e3))return await a("consent",h=>U.click({timeout:h})),!0}if(/consent\.google\./i.test(e.url()))throw new Error("Google consent did not expose a reject option");return!1}async function si(e,t,n,a){let i=async(u,c,w=8e3)=>{let g=Math.min(w,t.deadlineMs-Date.now());if(t.signal?.aborted){let P=new Error("Google search navigation aborted");throw P.name="AbortError",P}if(g<=0)throw new Error("Google search navigation deadline exhausted");let f,M,p=new Promise((P,b)=>{f=setTimeout(()=>b(new Error(`Google search ${u} timed out`)),g),t.signal&&(M=()=>{let x=new Error("Google search navigation aborted");x.name="AbortError",b(x)},t.signal.addEventListener("abort",M,{once:!0}))});try{return await Promise.race([c(g),p])}catch{if(t.signal?.aborted){let b=new Error("Google search navigation aborted");throw b.name="AbortError",b}throw new Error(`Google search ${u} failed`)}finally{f&&clearTimeout(f),M&&t.signal?.removeEventListener("abort",M)}},s=()=>a(e,t);await i("homepage",u=>e.goto("https://www.google.com",{waitUntil:"domcontentloaded",timeout:u}),15e3),await n(),await s(),await n();let S='textarea[name="q"], input[name="q"]';await i("search box readiness",u=>e.waitForSelector(S,{state:"visible",timeout:u}));let o=e.locator(S),d;for(let u=0,c=await i("search box inspection",()=>o.count());u<c;u+=1)if(await i("search box inspection",()=>o.nth(u).isVisible())){d=o.nth(u);break}if(!d)throw new Error("Google homepage did not expose a visible search box");let U=d;await i("search box focus",u=>U.click({timeout:u})),await i("search box clear",u=>U.fill("",{timeout:u}));for(let u of t.params.q)await i("query typing",c=>U.pressSequentially(u,{delay:35+Math.floor(Math.random()*65),timeout:c}));let h=U.locator("xpath=ancestor::form[1]");await i("search parameters",()=>h.evaluate((u,c)=>{if(!(u instanceof HTMLFormElement))throw new Error("Google search form is unavailable");u.method="get";for(let[g,f]of Object.entries(c)){if(g==="q")continue;let M=Array.from(u.querySelectorAll("input")).filter(p=>p.name===g);for(let p of M)p.value=f,p.disabled=!1;if(M.length===0){let p=document.createElement("input");p.type="hidden",p.name=g,p.value=f,u.appendChild(p)}}let w=new URL(u.action,location.href);for(let g of Object.keys(c))w.searchParams.delete(g);u.action=w.toString()},t.params));let r=h.locator('input[name="btnK"], button[name="btnK"], button[type="submit"]'),l=!1;for(let u=0,c=await i("search button inspection",()=>r.count());u<c;u+=1){let w=r.nth(u);if(await i("search button inspection",()=>w.isVisible())){await i("search submit",g=>w.click({timeout:g,noWaitAfter:!0})),l=!0;break}}if(!l)throw new Error("Google search form did not expose a visible Search button");await n(),await s(),await n()}async function oi(e,t,n){let a=t.readySelector.split(",").map(s=>`${s.trim()}:visible`).join(", "),i;for(;Date.now()<t.deadlineMs;){if(t.signal?.aborted)throw new Error("Google search navigation aborted");let s=await n();if((i===void 0||s===!0)&&(i=Math.min(t.deadlineMs,Date.now()+15e3)),Date.now()>=i)break;let S=!1;try{let d=new URL(e.url());S=/(^|\.)google\.[a-z.]+$/i.test(d.hostname)&&d.pathname==="/search"&&d.searchParams.get("q")===t.query}catch{}if(S){let d=await e.waitForSelector(a,{state:"visible",timeout:Math.min(500,Math.max(1,i-Date.now()))}).catch(()=>null),U=d?!1:await e.locator("body").innerText({timeout:Math.min(1e3,Math.max(1,i-Date.now()))}).then(h=>/did not match any documents|no results found/i.test(h)).catch(()=>!1);if(d||U){if(await n()===!0)continue;return}}if(t.signal?.aborted)throw new Error("Google search navigation aborted");let o=Math.min(200,i-Date.now(),t.deadlineMs-Date.now());o>0&&await e.waitForTimeout(o)}throw new Error("Google search results did not reach a readable state")}Ie.use(ri());var li=180,Si=3e3,Ui=5e3,hi='#search, #rso, a[href] h3, [data-snhf], [role="main"]';function Pe(e,t){return e?Math.max(1,Math.min(t,e-Date.now())):t}function ui(e,t){let n=process.env[e];if(!n)return t;let a=Number(n);return Number.isInteger(a)&&a>0?a:t}function be(e){return e?e.slice(-6):null}function Kn(e,t){let n=(t??process.env.SERP_REDIRECT_BASE)?.trim().replace(/\/+$/,"");return n?`${n}/g/${Buffer.from(e,"utf8").toString("base64url")}`:e}function ci(e){return e?/united states|u\.?s\.?a?\.?|^us$/i.test(e.trim()):!1}function bt(e){return e instanceof Error?e.message:String(e)}function wi(e){return/\b409\b|conflict|already exists/i.test(bt(e))}function gi(e){return/\b404\b|not[ _-]?found|already (?:gone|deleted|closed)|does not exist/i.test(bt(e))}async function yi(e,t){try{await e.profiles.create({name:t})}catch(n){if(!wi(n))throw n}}function Jn(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 Mt(e,t,n){let a;try{return await Promise.race([e,new Promise((i,s)=>{a=setTimeout(()=>s(new Error(`${n} timed out after ${t}ms`)),t)})])}finally{a&&clearTimeout(a)}}function pi(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 S=new URL(/^https?:\/\//i.test(t)?t:`https://${t}`);if(S.hostname.replace(/^www\./,"").replace(/^m\./,"").toLowerCase()!=="youtube.com")throw new Error("channel URL must be on youtube.com");let d=S.pathname.split("/").filter(Boolean),U=d[0]??"",h=d[1]??"";if(U.startsWith("@"))return`https://www.youtube.com/${U}/videos`;if(U==="channel"&&h)return`https://www.youtube.com/channel/${h}/videos`;if((U==="c"||U==="user")&&h)return`https://www.youtube.com/${U}/${h}/videos`;throw new Error("channel URL must be a YouTube handle, /channel/UC..., /c/..., or /user/... URL")}let i=t.replace(/^\/+/,"").replace(/\/+$/,"").replace(/\/videos$/i,"");if(/^UC[\w-]{20,}$/.test(i))return`https://www.youtube.com/channel/${i}/videos`;let s=i.startsWith("@")?i:`@${i}`;if(!/^@[\w.-]+$/.test(s))throw new Error("channelHandle must be an @handle, UC channel ID, or YouTube channel URL");return`https://www.youtube.com/${s}/videos`}var ee=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\u006cSolverEnabled=!1;operationDeadlineMs;\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;last\u004b\u0065\u0072\u006e\u0065\u006cBillingMode=null;last\u004b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=null;last\u004b\u0065\u0072\u006e\u0065\u006cClosedAtMs=null;debugEnabled=!1;debugSnapshot={\u006b\u0065\u0072\u006e\u0065\u006c:null,context:null,networkLocation:null,serpNavigation:null};async launch(t){if(t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey&&t.isMobile)throw new X("\u004b\u0065\u0072\u006e\u0065\u006c acquisition requires a native desktop browser; mobile capture needs provider-native mobile support.");this.operationDeadlineMs=t.operationDeadlineMs,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 st({apiKey:t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey});let s=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):ui("\u004b\u0045\u0052\u004e\u0045\u004c_BROWSER_TIMEOUT_SECONDS",li),S=Math.min(s,600);t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName&&t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges===!0&&await yi(this.\u006b\u0065\u0072\u006e\u0065\u006cClient,t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName);let o=_t();this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=null,this.last\u004b\u0065\u0072\u006e\u0065\u006cBillingMode="headful",o?.headlessSentOut&&(o.headlessSentOut.value=this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent);let d=await this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.create(Dn({stealth:t.\u006b\u0065\u0072\u006e\u0065\u006cStealth===!0,timeout_seconds:S,...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=d.session_id,this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=Date.now(),this.last\u004b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs,this.last\u004b\u0065\u0072\u006e\u0065\u006cClosedAtMs=null,this.\u006b\u0065\u0072\u006e\u0065\u006cStealth=typeof d.stealth=="boolean"?d.stealth:null,this.\u006b\u0065\u0072\u006e\u0065\u006cSolverEnabled=t.\u006b\u0065\u0072\u006e\u0065\u006cStealth===!0&&d.stealth!==!1,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed=typeof d.proxy_id=="string"?!!d.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 U=null,h=null;if(!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId&&!t.keepDefaultProxy)try{await Mt(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`),U=!0}catch(l){U=!1,h=bt(l)}let r={sessionId:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,proxyMode:n,requestedProxyIdPresent:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,requestedProxyIdSuffix:be(t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId),createdProxyIdPresent:typeof d.proxy_id=="string"?!!d.proxy_id:null,createdProxyIdSuffix:be(d.proxy_id),retrievedProxyIdPresent:null,retrievedProxyIdSuffix:null,retrievedProxyIdMatchesRequested:null,defaultProxyDisabled:U,defaultProxyDisableError:h,proxyResolution:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution??null,timeoutSeconds:S,stealth:typeof d.stealth=="boolean"?d.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:S,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 di.connectOverCDP(d.cdp_ws_url),this.context=await Gn(this.browser),this.page=await En(this.context),await this.capture\u004b\u0065\u0072\u006e\u0065\u006cContextDebug(),await this.installEsbuildHelperShims(this.context),(this.debugEnabled||t.requireUsEgress)&&(this.debugSnapshot.networkLocation=await this.captureBrowserNetworkLocation()),t.requireUsEgress){let l=this.debugSnapshot.networkLocation?.country??null;if(!ci(l))throw new z(`Non-US egress (${l??"unknown"}) \u2014 retrying with a fresh session`)}return}let i={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 Ie.launchPersistentContext(t.profileDir,{...i,...Jn(t)}),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage(),this.debugSnapshot.context.userAgent=await fe(this.page);else{this.browser=await Ie.launch(i);let s=await Ne(this.browser);this.debugSnapshot.context.userAgent=s,this.context=await this.browser.newContext(Jn(t,s)),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage()}this.debugEnabled&&(this.debugSnapshot.networkLocation=await this.captureBrowserNetworkLocation())}async capture\u004b\u0065\u0072\u006e\u0065\u006cContextDebug(){if(this.debugSnapshot.context={viewport:null,locale:null,device:"desktop",requestedDevice:"desktop",userAgent:null,deviceScaleFactor:null,isMobile:!1,hasTouch:!1},!this.page)return;let t=await this.page.evaluate(()=>({viewport:{width:window.innerWidth,height:window.innerHeight},locale:navigator.language,userAgent:navigator.userAgent,deviceScaleFactor:window.devicePixelRatio,isMobile:!1,hasTouch:navigator.maxTouchPoints>0})).catch(()=>null);!t||typeof t!="object"||!t.viewport||typeof t.viewport.width!="number"||typeof t.viewport.height!="number"||typeof t.locale!="string"||typeof t.userAgent!="string"||(this.debugSnapshot.context={...t,device:"desktop",requestedDevice:"desktop"})}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 Mt(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=be(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=bt(a)}}async captureBrowserNetworkLocation(){let t=(a,i="ipapi.co")=>({source:i,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 o=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 o.org=="string"?o.org:null,timezone:typeof a.timezone=="object"&&a.timezone!==null&&typeof a.timezone.id=="string"?a.timezone.id:null,error:null}}let i=await this.loadJsonInDebugPage(n,"https://api64.ipify.org?format=json");if(i)return{source:"api64.ipify.org",ip:typeof i.ip=="string"?i.ip:null,city:null,region:null,country:null,org:null,timezone:null,error:null};await Mt(n.goto("https://ipapi.co/json/",{waitUntil:"domcontentloaded",timeout:7e3}),8e3,"browser network location navigation");let s=await n.locator("body").innerText({timeout:2e3}),S=JSON.parse(s);return{source:"ipapi.co",ip:typeof S.ip=="string"?S.ip:null,city:typeof S.city=="string"?S.city:null,region:typeof S.region=="string"?S.region:null,country:typeof S.country_name=="string"?S.country_name:typeof S.country=="string"?S.country:null,org:typeof S.org=="string"?S.org:null,timezone:typeof S.timezone=="string"?S.timezone:null,error:null}}catch(a){return t(bt(a))}finally{await n?.close().catch(()=>{})}}async loadJsonInDebugPage(t,n){try{await Mt(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,i,s)=>(a[i]=s,s))})}async withTemporaryPage(t,n){if(!this.context)throw new Error("Browser context is not available");return Xt(this.context,async()=>{},t,n)}async navigateToSERP(t,n,a,i,s){let S=new URLSearchParams({q:t,gl:a,hl:i,pws:"0"});s?.tbs&&S.set("tbs",s.tbs),n&&S.set("uule",n);let o="https://www.google.com/search?"+S.toString(),d=Kn(o),U=s?.debug?{requestedUrl:o,finalUrl:null,title:null,bodySnippet:null,hasPaa:null,captchaDetected:null,googleSorryUrl:null,redirected:null}:null;if(U&&(this.debugSnapshot.serpNavigation=U),this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId){let r={deadlineMs:s?.deadlineMs??this.operationDeadlineMs,signal:s?.signal};try{let l=await Te(this.page,{query:t,gl:a,hl:i,uule:n??void 0,tbs:s?.tbs,purpose:s?.purpose,deadlineMs:s?.deadlineMs??this.operationDeadlineMs,signal:s?.signal,solverEnabled:this.\u006b\u0065\u0072\u006e\u0065\u006cSolverEnabled});return await this.updateSerpNavigationDebug(U,o,{hasPaa:l.hasPaa,captchaDetected:l.challengeObserved===!0},r),{hasPaa:l.hasPaa}}catch(l){throw await this.updateSerpNavigationDebug(U,o,{hasPaa:null,captchaDetected:l instanceof z?!0:null},r),l}}try{await this.page.goto(d,{waitUntil:"domcontentloaded",timeout:Pe(s?.deadlineMs,s?.purpose==="serp"?8e3:45e3)})}catch(r){await this.updateSerpNavigationDebug(U,o,{hasPaa:null,captchaDetected:null});let l=await this.captureDiagnostics(o);throw new X(`page.goto failed: ${r.message} | ${l}`)}if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(U,o,{hasPaa:!1,captchaDetected:!0}),new z(this.captchaMessage());if(s?.purpose==="serp"){await this.page.waitForSelector(hi,{timeout:Pe(s.deadlineMs,1500)}).catch(()=>null);let r=await this.page.locator(j.paaItem).count().catch(()=>0)>0;return await this.updateSerpNavigationDebug(U,o,{hasPaa:r,captchaDetected:!1}),{hasPaa:r}}if(await this.page.waitForSelector(j.paaItem,{timeout:Pe(s?.deadlineMs,4e3)}).catch(()=>null))return await this.updateSerpNavigationDebug(U,o,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(U,o,{hasPaa:!1,captchaDetected:!0}),new z(this.captchaMessage());for(let r=1;r<=6;r++)if(await this.page.evaluate(u=>{window.scrollTo(0,document.body.scrollHeight*u)},r/6),await this.page.waitForTimeout(600),await this.page.locator(j.paaItem).count()>0)return await this.updateSerpNavigationDebug(U,o,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};return await this.updateSerpNavigationDebug(U,o,{hasPaa:!1,captchaDetected:!1}),{hasPaa:!1}}async isSerpChallengeVisible(){if(!this.page)return!1;if(await this.page.locator(j.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,i){if(!(!t||!this.page))try{let s=this.page.url();t.finalUrl=s,t.hasPaa=a.hasPaa,t.captchaDetected=a.captchaDetected,t.googleSorryUrl=/google\.[^/]+\/sorry\//i.test(s),t.redirected=s!==n;let S=Math.min(1e3,i?.deadlineMs===void 0?1e3:i.deadlineMs-Date.now());if(i&&(i.signal?.aborted||S<=0))return;let o=Promise.all([this.page.title().catch(()=>""),this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,500)).catch(()=>"")]),[d,U]=i?await et(Mt(o,S,"\u004b\u0065\u0072\u006e\u0065\u006c navigation debug"),i.signal):await o;t.title=d,t.bodySnippet=U,t.captchaDetected=a.captchaDetected??/recaptcha|unusual traffic|are you a robot/i.test(U)}catch(s){t.bodySnippet=`debug capture failed: ${bt(s)}`}}async captureDiagnostics(t){try{let n=this.page.url(),a=await this.page.title().catch(()=>""),i=await this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,400)).catch(()=>""),s=/consent\.google\./.test(n)||/before you continue/i.test(i),S=/recaptcha|unusual traffic|are you a robot/i.test(i),o=[s?"CONSENT_WALL":"",S?"BOT_CHALLENGE":"",n!==t?"REDIRECTED":""].filter(Boolean).join(",");return`intended=${t} | final=${n} | title="${a}" | flags=[${o}] | body="${i}"`}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.":Qe}async navigateTo(t){if(this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId){let i=new URL(t);if(/^(?:www\.)?google\.[a-z.]+$/i.test(i.hostname)&&i.pathname==="/search"&&i.searchParams.has("q")){await Te(this.page,{query:i.searchParams.get("q"),gl:i.searchParams.get("gl")??"us",hl:i.searchParams.get("hl")??"en",uule:i.searchParams.get("uule")??void 0,tbs:i.searchParams.get("tbs")??void 0,extraParams:Object.fromEntries([...i.searchParams].filter(([s])=>!["q","gl","hl","uule","tbs","pws"].includes(s))),purpose:"serp",deadlineMs:this.operationDeadlineMs,solverEnabled:this.\u006b\u0065\u0072\u006e\u0065\u006cSolverEnabled});return}}let n=process.env.ADS_ARRIVAL_REDIRECT_BASE?.trim(),a=n?Kn(t,n):t;try{if(await this.page.goto(a,{waitUntil:"domcontentloaded",timeout:45e3}),/google\.[^/]+\/search\?/i.test(t)&&await this.isSerpChallengeVisible())throw new z(this.captchaMessage())}catch(i){if(i instanceof z)throw i;let s=await this.captureDiagnostics(t);throw new X(`page.goto failed: ${i.message} | ${s}`)}}async navigateToChannel(t){let n=pi(t);try{await this.page.goto(n,{waitUntil:"networkidle",timeout:3e4})}catch(a){let i=await this.captureDiagnostics(n);throw new X(`navigateToChannel failed: ${a.message} | ${i}`)}}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}get\u004b\u0065\u0072\u006e\u0065\u006cMeteringEvidence(){return{sessionId:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId??this.debugSnapshot.\u006b\u0065\u0072\u006e\u0065\u006c?.sessionId??null,billingMode:this.last\u004b\u0065\u0072\u006e\u0065\u006cBillingMode,openedAtMs:this.last\u004b\u0065\u0072\u006e\u0065\u006cOpenedAtMs,closedAtMs:this.last\u004b\u0065\u0072\u006e\u0065\u006cClosedAtMs}}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,billingMode:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId?this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent?"headless":"headful":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,i=this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs,s=this.\u006b\u0065\u0072\u006e\u0065\u006cStealth,S=this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed,o=this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource,d=this.\u006b\u0065\u0072\u006e\u0065\u006cProxyType,U=this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent,h=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\u006cSolverEnabled=!1,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){console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_started",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n}));let r=Mt(a.browsers.deleteByID(n),Ui,`\u004b\u0065\u0072\u006e\u0065\u006c session ${n} delete`),l=Mt(t.close(),Si,`\u004b\u0065\u0072\u006e\u0065\u006c browser ${n} close`),[u,c]=await Promise.allSettled([r,l]);this.last\u004b\u0065\u0072\u006e\u0065\u006cClosedAtMs=Date.now(),i!=null&&en({\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,source:"browser_driver",stealth:s,headlessSent:U,proxyUsed:S,proxySource:o,proxyType:d,openedAtMs:i,closedAtMs:this.last\u004b\u0065\u0072\u006e\u0065\u006cClosedAtMs});let w=u.status==="rejected"&&gi(u.reason),g={\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!0,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:u.status==="fulfilled"||w,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:u.status==="rejected"&&!w?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:h.provider,providerSessionId:h.providerSessionId,providerDisconnectObserved:!1,providerDisconnectMessage:null};return u.status==="rejected"&&!w?(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:h.provider,providerSessionId:h.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 mi}from"playwright";var Ci=new Set(["image","media","font","stylesheet","ping"]),ki=["doubleclick.net","googleadservices.com","googlesyndication.com","google-analytics.com"],Mi='#search, #rso, a[href] h3, [data-snhf], [role="main"]',vi=3e4,_n=1500;function vt(e,t){return e?Math.max(1,Math.min(t,e-Date.now())):t}async function We(e,t=!1){let n=e.request();try{let a=await n.allHeaders(),i=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(!i.ok)return!1;let s=Buffer.from(await i.arrayBuffer());return await e.fulfill({status:i.status,contentType:i.headers.get("content-type")??"application/octet-stream",headers:{"cache-control":"public, max-age=3600"},body:s}),!0}catch{return!1}}var ne=class{constructor(t={}){this.resourcePolicy=t}resourcePolicy;browser=null;context=null;page=null;cdpSession=null;providerSessionId=null;disconnectObservation=null;closing=!1;connectionStarted=!1;closeReceipt=null;observeDisconnect(t,n){this.closing||this.disconnectObservation||(this.disconnectObservation=Se(t,n))}async launch(t){if(this.page)return;this.closing=!1,this.providerSessionId=null,this.disconnectObservation=null;let n=ve();if(!n)throw new Error("SERP browser service is not configured");if(this.connectionStarted)throw new Error("Previous browser connection outcome is unresolved");if(this.closeReceipt)throw new Error("Browser driver has already been closed");this.connectionStarted=!0;try{this.browser=await mi.connectOverCDP(n,{timeout:vt(t.operationDeadlineMs,vi)})}catch(s){let S=(s instanceof Error?s.message:String(s)).replaceAll(n,"[redacted endpoint]");throw new Error(St(S)??"\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 browser connection failed")}this.context=this.browser.contexts()[0]??await this.browser.newContext(),await this.context.addInitScript(()=>{let s=globalThis;typeof s.__name!="function"&&(s.__name=S=>S),typeof s.__publicField!="function"&&(s.__publicField=(S,o,d)=>(S[o]=d,d))}),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 i=await this.cdpSession.send("Browser.getSessionId");this.providerSessionId=rn(i?.sessionId),await this.setupPage(this.page),this.resourcePolicy.startupSettleMs&&await this.page.waitForTimeout(this.resourcePolicy.startupSettleMs)}async setupPage(t){this.resourcePolicy.nativeGoogleAssets||await t.route("**/*",async n=>{let a=n.request(),i=a.resourceType(),s;try{s=new URL(a.url())}catch{await n.continue();return}let S=s.hostname.toLowerCase();if(!(s.pathname==="/sgasync"&&await We(n,!0))&&!(s.pathname.includes("/shared_dict/")&&await We(n))&&!(i==="script"&&(S==="www.google.com"||S==="www.gstatic.com")&&await We(n))){if(Ci.has(i)&&!(i==="image"&&this.resourcePolicy.allowImages)&&!(i==="stylesheet"&&this.resourcePolicy.allowStylesheets)){await n.abort("blockedbyclient");return}if(ki.some(o=>S===o||S.endsWith(`.${o}`))){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 Xt(this.context,a=>this.setupPage(a),t,n)}async navigateToSERP(t,n,a,i,s){if(!this.page)throw new Error("Browser page is not available");let S=new URLSearchParams({q:t,gl:a,hl:i,pws:"0"});if(s?.tbs&&S.set("tbs",s.tbs),n&&S.set("uule",n),await this.page.goto(`https://www.google.com/search?${S}`,{waitUntil:"domcontentloaded",timeout:vt(s?.deadlineMs,s?.purpose==="serp"?12e4:45e3)}),s?.purpose==="serp"&&new URL(this.page.url()).pathname.startsWith("/sorry")&&this.cdpSession){let d=this.cdpSession,U;(await Promise.race([d.send("Captcha.solve",{detectTimeout:vt(s.deadlineMs,3e4)}).catch(()=>null),new Promise(r=>{U=setTimeout(()=>r(null),vt(s.deadlineMs,75e3))})]).finally(()=>{U&&clearTimeout(U)}))?.status==="solve_finished"&&await this.page.waitForURL(r=>new URL(r.toString()).pathname==="/search",{timeout:vt(s.deadlineMs,25e3)}).catch(()=>{})}return s?.purpose==="serp"?(await this.page.waitForSelector(Mi,{timeout:vt(s.deadlineMs,8e3)}).catch(()=>null),{hasPaa:await this.page.locator(j.paaItem).count().catch(()=>0)>0}):{hasPaa:!!await this.page.waitForSelector(j.paaItem,{timeout:vt(s?.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}get\u0042\u0072\u0069\u0067\u0068\u0074\u0044\u0061\u0074\u0061SessionId(){return this.providerSessionId}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(){return this.closeReceipt??=this.closePhysicalSession()}async closePhysicalSession(){this.closing=!0;let t=dn(this.getProviderSessionMetadata()),n=!1,a=null,i=null,s=null,S=async(o,d)=>{let U;try{await Promise.race([o(),new Promise((h,r)=>{U=setTimeout(()=>r(new Error(`${d} acknowledgement exceeded ${_n}ms`)),_n)})])}finally{U&&clearTimeout(U)}};if(this.connectionStarted)if(!this.browser)a="Browser connection outcome is unknown; no remote termination receipt";else{try{await S(async()=>{let o=this.cdpSession??(this.context&&this.page?await this.context.newCDPSession(this.page):null);if(!o)throw new Error("Remote browser termination channel is unavailable");await o.send("Browser.close")},"Remote browser close"),n=!0}catch(o){a=St(o instanceof Error?o.message:String(o))??"Remote browser termination is unconfirmed",this.disconnectObservation??=Se("browser_close_error",a)}try{await S(()=>this.browser.close(),"Local browser disconnect"),i=!0}catch(o){i=!1,s=St(o instanceof Error?o.message:String(o))??"Local browser disconnect failed"}}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:this.connectionStarted?n:null,browserCloseError:a,localDisconnectSucceeded:i,localDisconnectError:s,physicalOutcome:this.connectionStarted?n?"terminated":"unknown":"not_started",...t}}};function zn(e,t){return e.plannedProvider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?new ne({nativeGoogleAssets:t?.nativeGoogleAssets}):new ee}var V={container:".eJH8qe.adDDi",dataInitq:"[data-initq]",item:j.paaItem,itemDataQ:"data-q",itemDataInitQ:"data-initq",itemQuestionEl:".JlqpRe",answerContainer:".bCOlv, .hgKElc, .wDYxhc, .LGOjhe, .fo7IQd, .fmW3u",aiAnswerBody:".pWvJNd",answerBody:".hgKElc, .LGOjhe, .fo7IQd, .fmW3u",answerControl:'button, [role="button"], a',answerEntity:".q224lc",citationBadge:".WBgIic",sourceCard:"[data-src-id]",sourceCardTitle:".vFyWT",sourceDescription:"[data-crb-snippet-text]",aiCitation:"a.PMDqCb[href]",aiSourceCard:"a.vIWmYe[href], a.Zbfntb[href]",sourceTitle:"h3",sourceSite:".VuuXrf",sourceCite:"cite",clickTarget:".JlqpRe",expandedClass:"aoRk1c",captchaMarker:j.captchaMarker};var Ae={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"},fi=[...Object.keys(Ae).map(e=>e.replace(/\s+/g,"\\s+")),...Object.values(Ae)].join("|"),Ni=new RegExp(`\\b([A-Z][A-Za-z]+(?:[\\s.-][A-Z][A-Za-z]+){0,4}),?\\s+(${fi})\\b`,"gi");function jn(e){if(!e)return null;let t=e.trim();return/^[A-Z]{2}$/i.test(t)?t.toUpperCase():Ae[t.toLowerCase()]??null}function $n(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 Ti(e){if(!e)return null;let[t="",n=""]=e.split(",").map(a=>a.trim());return{city:$n(t),regionCode:jn(n),canonicalLocation:e}}function Pi(e,t,n,a){let i=$n(t),s=jn(n);if(!i||!s)return;let S=`${i.toLowerCase()}|${s}`,o=e.get(S);if(o){o.count++,o.examples.length<3&&!o.examples.includes(a)&&o.examples.push(a);return}e.set(S,{city:i,regionCode:s,count:1,examples:[a]})}function bi(e){try{return decodeURIComponent(e)}catch{}try{return decodeURIComponent(e.replace(/%(?![0-9a-fA-F]{2})/g,"%25"))}catch{return e}}function qn(e,t){let n=bi(t).replace(/[+/|_-]+/g," ");for(let a of n.matchAll(Ni))Pi(e,a[1]??"",a[2]??"",n.slice(0,180))}function Ht(e,t,n){let a=Ti(e),i=new Map;for(let o of t)qn(i,[o.title,o.snippet??"",o.cite??"",o.url].join(" "));for(let o of n)qn(i,[o.name,...o.metadata,o.websiteUrl??"",o.directionsUrl??""].join(" "));let s=Array.from(i.values()).sort((o,d)=>d.count-o.count||o.city.localeCompare(d.city)).slice(0,8);return a?s.length===0?{status:"unknown",expected:a,candidates:[]}:{status:s.some(o=>o.city.toLowerCase()===a.city.toLowerCase()&&(a.regionCode==null||o.regionCode===a.regionCode))?"matched":"mismatch",expected:a,candidates:s}:{status:"not_requested",expected:null,candidates:s}}var Ii=/^(?:an error has occurred(?:[.!…]\s*)?(?:please try again later[.!…]?)?|loading|please wait|try again|something went wrong|an AI overview is not available for this search|can't generate an AI overview right now\.?\s*try again later\.?)[.!…\s]*$/i,Wi=/^(?:AI Overview|View all|Show more|Show less|Related Links|Ask anything in AI Mode|AI can make mistakes)[.!…\s]*$/i;function xe(e){return e.replace(/\u00a0/g," ").replace(/\s+/g," ").trim()}function Qn(e,t){if(!e)return;let n=xe(e.split(/\r?\n/).filter(i=>!Wi.test(xe(i))).join(`
|
|
21727
|
+
`)),a=t?xe(t):"";return a&&n.toLowerCase().startsWith(a.toLowerCase())&&(n=n.slice(a.length).trim()),!n||Ii.test(n)?void 0:n}function ae({selectors:e,onlyQuestion:t}){let n=d=>(d??"").replace(/\u00a0/g," ").replace(/\s+/g," ").trim(),a=d=>n(d).replace(/\s*\(\+\d+\)\s*-\s*View related links.*$/i,"").replace(/\s*(?:[-.]\s*)?Opens in new tab[.!]?$/i,"").trim(),i=d=>{if(d.matches(e.clickTarget)||d.getAttribute("aria-expanded")==="true")return!1;let U=d.getAttribute("href");return U&&!/^(?:#|javascript:void\(0\);?$)/i.test(U)||d.closest(e.aiSourceCard+","+e.sourceCard)?!1:[d.getAttribute("aria-label"),d.textContent].map(n).some(r=>/^(?:(?:show|read|see) more(?: (?:AI Overview|(?:of )?(?:this |the )?answer))?|continue reading|expand(?: (?:this |the )?answer)?)(?:[.!…]|\s*[▼⌄+])?$/i.test(r))},s=d=>d.hasAttribute("hidden")||d.getAttribute("aria-hidden")==="true"||/(?:display\s*:\s*none|visibility\s*:\s*hidden)/i.test(d.getAttribute("style")??""),S=d=>{let U=d.ownerDocument.defaultView?.getComputedStyle(d);return U?.display==="none"||U?.visibility==="hidden"},o=(d,U,h)=>{if(!d||d!==U&&(s(d)||d.matches("style,script,noscript,button")||d.matches('[role="button"]')&&!d.matches(e.answerEntity)||d.matches(e.aiSourceCard+","+e.sourceCard+","+e.citationBadge)||h&&(d.matches("cite,"+e.sourceSite)||d.matches("a[href]")&&d.querySelector("h3"))))return"";let r=[];for(let l of d.childNodes)l.nodeType===Node.TEXT_NODE?r.push(l.textContent??""):l.nodeType===Node.ELEMENT_NODE&&r.push(o(l,U,h));return n(r.join(" "))};return Array.from(document.querySelectorAll(e.item)).flatMap((d,U)=>{let h=n(d.getAttribute(e.itemDataQ)||d.getAttribute(e.itemDataInitQ)||d.querySelector(e.itemQuestionEl)?.innerText||d.querySelector(e.itemQuestionEl)?.textContent);if(!h||t&&h!==t)return[];let r=d.classList.contains(e.expandedClass)||d.querySelector(e.clickTarget)?.getAttribute("aria-expanded")==="true",l=d.querySelector(e.answerContainer),u=l?.querySelector(e.aiAnswerBody)||(l?.matches(e.aiAnswerBody)?l:null)||l?.querySelector(e.answerBody)||(l?.matches(e.answerBody)?l:null),c=u||l,w=o(c,c,!u),g=/^(?:an error has occurred(?:[.!…]\s*)?(?:please try again later[.!…]?)?|loading|please wait|try again|something went wrong)[.!…\s]*$/i.test(w),f=[...Array.from((c||d).querySelectorAll("a[href]")),...Array.from(l?.querySelectorAll("a[href]")||[]),...Array.from(d.querySelectorAll(e.aiCitation+","+e.aiSourceCard))],M=!g&&(r&&w.length>=10||w.length>30&&f.some(N=>/^https?:\/\//i.test(N.href))),p=Array.from(l?.querySelectorAll(e.answerControl)||[]),P=M?p.flatMap((N,m)=>{if(!i(N))return[];for(let v=N;v&&v!==l;v=v.parentElement)if(s(v)||S(v))return[];return[m]}):[],b=new Map;if(M)for(let N of f){if(!/^https?:\/\//i.test(N.href))continue;let m=N.closest(e.sourceCard),v=m?n(m.querySelector(e.sourceDescription)?.textContent):"",A=(m?n(m.querySelector(e.sourceCardTitle)?.textContent):"")||a(N.getAttribute("aria-label"))||n(N.querySelector("h3")?.textContent)||n(N.textContent),y=b.get(N.href);b.set(N.href,{title:m&&A?A:y?.title||A,rawHref:N.href,...v||y?.description?{description:v||y?.description}:{}})}let x=[...b.values()],k=M&&n(d.querySelector(e.sourceTitle)?.textContent)||void 0,B=M&&n(d.querySelector(e.sourceSite)?.textContent)||void 0;return k||=x.find(N=>N.title.length>2)?.title||x[0]?.title||void 0,[{googleLinkId:d.getAttribute("data-lk")||d.querySelector("[data-lk]")?.getAttribute("data-lk")||null,googleEvidenceId:d.getAttribute("data-ved")||d.querySelector("[data-ved]")?.getAttribute("data-ved")||null,question:h,answer:M?w:void 0,sourceTitle:k,sourceSite:B,sources:x,...P.length||d.getAttribute("data-mcp-answer-expansion")==="pending"?{answerExpansionIncomplete:!0}:{},itemIndex:U,expanded:r,answerControls:P}]})}async function Le(e,t,n,a){let i=Math.min(n.deadlineMs??1/0,Date.now()+1e4),s=()=>Math.max(0,i-Date.now()),S=async()=>(await e.evaluate(a,{selectors:n.selectors,onlyQuestion:t}))[0],o=await S(),d=async U=>{let h=Math.min(i,Date.now()+2500),r=null,l=U;for(;!n.signal?.aborted&&Date.now()<h;){if(await e.waitForTimeout(Math.min(150,h-Date.now())),o=await S(),!o||n.signal?.aborted)return;if(o.answer!==l&&(l=o.answer,r=Date.now()),!o.answerControls.length&&o.answer){r??=Date.now();let u=o.answer!==U?300:1e3;if(Date.now()-r>=u){await e.locator(n.selectors.item).nth(o.itemIndex).evaluate(c=>{c.removeAttribute("data-mcp-answer-expansion")}).catch(()=>{});return}}else if(o.answerControls.length&&o.answer!==U&&r!==null&&Date.now()-r>=300)return}};if(o?.answerExpansionIncomplete&&!o.answerControls.length){await d(o.answer);return}for(let U=0;o?.answerControls.length&&U<8;U+=1){if(n.signal?.aborted||s()<=0)return;let h=e.locator(n.selectors.item).nth(o.itemIndex);try{if(!o.expanded&&(await h.locator(n.selectors.clickTarget).first().click({timeout:Math.min(1200,s())}),s()<=0||n.signal?.aborted||(await e.waitForTimeout(Math.min(250,s())),o=await S(),!o?.answerControls.length))||n.signal?.aborted||s()<=0)return;let l=e.locator(n.selectors.item).nth(o.itemIndex).locator(n.selectors.answerContainer).first().locator(n.selectors.answerControl).nth(o.answerControls[0]);if(!await l.evaluate((c,w)=>c.getAttribute("data-mcp-answer-expansion")==="pending"?!1:(c.setAttribute("data-mcp-answer-expansion","pending"),c.closest(w)?.setAttribute("data-mcp-answer-expansion","pending"),!0),n.selectors.item)){await d(o.answer);return}if(n.signal?.aborted||s()<=0)return;await l.click({timeout:Math.min(1200,s())})}catch{return}let r=o.answer;if(await d(r),!o?.answerControls.length||o.answer===r)return;await e.locator(n.selectors.item).nth(o.itemIndex).locator(n.selectors.answerContainer).first().locator(n.selectors.answerControl).nth(o.answerControls[0]).evaluate(l=>{l.setAttribute("data-mcp-answer-expansion","confirmed")}).catch(()=>{})}}async function Zn(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 i(m){return m?(m.innerText??m.textContent??"").trim():""}function s(m){if(!m)return!1;let v=m.replace(/\s+/g," ").trim();return v.length>=16&&v.split(" ").filter(Boolean).length>=2}function S(m){let v=m.querySelector(t.aio.heading);if(i(v)==="AI Overview")return!0;let A=m.querySelector(t.aio.header);return!!i(A).split(/\n|\s{2,}/).some(y=>y.trim()==="AI Overview")}function o(){let v=Array.from(document.querySelectorAll(t.aio.root)).find(S);if(v)return v;if(t.aio.legacyRoot){let y=document.querySelector(t.aio.legacyRoot);if(y&&S(y))return y}let A=document.querySelectorAll(`${t.aio.heading}, h1, h2, h3, [role="heading"]`);for(let y of A){if(i(y)!=="AI Overview")continue;let C=y.parentElement;for(let H=0;H<8&&C;H++){if(C.matches(t.aio.root)||C.querySelector(t.aio.controller)||C.querySelector(t.aio.contentSubtree))return C;C=C.parentElement}return y.parentElement}return null}function d(m){if(!m)return null;let v=m.cloneNode(!0);v.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(I=>I.remove());let A=document.createElement("div");A.style.position="fixed",A.style.left="-10000px",A.style.top="0",A.style.width=`${Math.max(320,Math.round(m.getBoundingClientRect?.().width||960))}px`,A.style.opacity="0",A.style.pointerEvents="none",A.append(v),document.body.append(A);let y=v.innerText||v.textContent||"";A.remove();let C=y.replace(/\r/g,"").replace(/[ \t]+\n/g,`
|
|
21695
21728
|
`).replace(/\n[ \t]+/g,`
|
|
21696
21729
|
`).replace(/\n{3,}/g,`
|
|
21697
21730
|
|
|
21698
21731
|
`).replace(/[ \t]{2,}/g," ").trim().split(`
|
|
21699
|
-
`).map(I=>I.replace(/\u00a0/g," ").trim()).filter(Boolean),
|
|
21732
|
+
`).map(I=>I.replace(/\u00a0/g," ").trim()).filter(Boolean),H=[];for(let I=0;I<C.length;I++){let T=C[I],L=C[I+1]??"";if(T!=="AI Overview"&&T!=="Show more"&&!/^AI can make mistakes/i.test(T)&&!/^Thank you\b/i.test(T)&&!/^Your feedback helps Google improve/i.test(T)&&!/^\+?\d+$/.test(T)){if(/^\+\d+$/.test(L)&&T.length<=80){I++;continue}H.push(T)}}let O=H.join(`
|
|
21700
21733
|
`).replace(/\n{3,}/g,`
|
|
21701
21734
|
|
|
21702
|
-
`).trim();return!
|
|
21703
|
-
`).map(C=>C.trim()).filter(C=>/^\d+\.\s+.+/.test(C)),c=l(r)}let k=document.querySelector(t.aim.root),x=a==="aim"&&!!k,O=k?.closest(t.aim.wrapper)??k,H=x?S(O):null,f=x&&i(H),p=f?H:null,L=f?l(O):[],T=!!r&&i(u);return{surface:a,aiOverview:{detected:T,text:T?u:null,citations:T?c:[],expanded:T?g:!1,fullyExpanded:T?N:!1,sections:T?b:[]},aiMode:{detected:f&&p!==null,text:p,citations:L}}}import{createHash as pa}from"crypto";var Un=8e3,hn=3e3,un=1e4,ma=8;function st(e){return/(^|\.)google\.(?:com|[a-z]{2,3}(?:\.[a-z]{2})?)$/i.test(e)}function vt(e){if(!e||e.length>Un)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 va(e,t){if(!e||e.length>Un||/^javascript:/i.test(e))return null;try{let n=new URL(e,t);return vt(n.href)}catch{return null}}function mt(e){let t=vt(e);return!t||t.protocol!=="https:"||!st(t.hostname)||t.pathname!=="/goto"?null:t.searchParams.get("url")?t:null}function he(e){if(e.linkType!=="google_goto_redirect"||e.resolutionStatus!=="resolved"||!mt(e.rawUrl)||!e.resolvedUrl)return!1;let t=vt(e.resolvedUrl);return!!(t&&!st(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_${pa("sha256").update(t).digest("hex").slice(0,16)}`}function Yt(e,t){let n=va(e,t);if(!n)return null;let a=n.href;if(!st(n.hostname))return{url:a,rawUrl:a,resolvedUrl:a,linkType:"plain",resolutionStatus:"not_needed"};if(n.pathname==="/url"){let s=vt(n.searchParams.get("q")??n.searchParams.get("url")??"");return!s||st(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 ue(e){return mt(e)?.searchParams.get("url")??null}function cn(e,t){try{let n=new URL(e),a=vt(new URL(t,n).href);return!a||st(a.hostname)?null:(!a.hash&&n.hash&&(a.hash=n.hash),a.href)}catch{return null}}async function wn(e,t={}){let n=[...new Set([...e].flatMap(o=>mt(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??hn),h=Date.now()+Math.max(1,t.totalBudgetMs??un),S=Math.max(1,Math.min(16,Math.floor(t.concurrency??ma))),U=0,l=async()=>{for(;U<n.length;){let o=n[U++],r=mt(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 N=h-Date.now();if(N<=0)return;let b=new AbortController,k=setTimeout(()=>b.abort(),Math.min(d,N)),x;try{x=await i(c,{method:"GET",redirect:"manual",headers:{accept:"*/*","user-agent":"Mozilla/5.0"},signal:b.signal})}catch{break}finally{clearTimeout(k)}if(x.status<300||x.status>=400)break;let O=x.headers.get("location");if(!O)break;let H=cn(o,O);if(H){a.set(o,{rawUrl:o,resolvedUrl:H,resolutionStatus:"resolved"});break}let f;try{f=new URL(O,c)}catch{a.set(o,{rawUrl:o,resolvedUrl:null,resolutionStatus:"rejected"});break}if(!st(f.hostname)||ue(f.href)!==u){a.set(o,{rawUrl:o,resolvedUrl:null,resolutionStatus:"rejected"});break}c=f.href}}};return await Promise.all(Array.from({length:Math.min(S,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 gn(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 wn(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 h=o=>({...o,...i.get(o.rawUrl)??o}),S=o=>o.map(r=>{let u=h(r);return{...u,site:Sn(u,r.site)}});for(let o of e.flat){o.sources=S(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=S(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=h(e.organicResults[o]);e.organicResults[o]={...r,domain:Sn(r,e.organicResults[o].domain)??""}}let U=o=>{let r=h({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 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 yn(e,t,n={}){let a=new Map;for(let r of t){let u=a.get(r.rawUrl);u&&he(u)||a.set(r.rawUrl,r.linkType==="google_goto_redirect"&&!he(r)?{...r,url:r.rawUrl,resolvedUrl:null,resolutionStatus:"unresolved"}:r)}let s=[...a.values()].filter(r=>r.linkType==="google_goto_redirect"&&!he(r));if(s.length===0)return a;let i=Date.now()+(n.totalBudgetMs??un),d=await wn(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 h=s.filter(r=>a.get(r.rawUrl)?.resolutionStatus==="unresolved");if(h.length===0||n.browserFallback===!1||Date.now()>=i)return n.onNetworkAudit?.({nonGoogleRequestsObserved:0}),a;let S=n.timeoutMs??hn,U=await e.context().newPage().catch(()=>null);if(!U)return n.onNetworkAudit?.({nonGoogleRequestsObserved:0}),a;let l=null,o=0;try{await U.route("**/*",async r=>{let u=r.request().url();try{st(new URL(u).hostname)||(o+=1)}catch{}let c=ue(u);if(!l||c!==l.token){await r.abort("blockedbyclient").catch(()=>{});return}let g=l;try{let N=await r.fetch({maxRedirects:0,timeout:g.timeoutMs});g.location=N.headers().location??null}finally{await r.abort("blockedbyclient").catch(()=>{}),g.finish()}});for(let r of h){let u=i-Date.now();if(u<=0)break;let c=mt(r.rawUrl),g=c?.searchParams.get("url");if(!c||!g){a.set(r.rawUrl,{...r,resolutionStatus:"rejected"});continue}let N=Math.min(S,u);c.hash="";let b=c.href,k=!1;for(let x=0;x<2;x++){let O,H=new Promise(y=>{O=y}),f=`mcp-goto-${Math.random().toString(36).slice(2)}`;l={token:g,timeoutMs:N,location:null,finish:O},await U.evaluate(({url:y,id:P})=>{let w=document.createElement("iframe");w.id=P,w.hidden=!0,w.src=y,document.body.append(w)},{url:b,id:f}).catch(()=>null),await Promise.race([H,new Promise(y=>setTimeout(y,N))]);let p=l.location;if(l=null,await U.evaluate(y=>document.getElementById(y)?.remove(),f).catch(()=>null),!p)break;let L=cn(r.rawUrl,p);if(L){a.set(r.rawUrl,{...r,url:L,resolvedUrl:L,resolutionStatus:"resolved"});break}let T;try{T=new URL(p,b)}catch{k=!0;break}if(!st(T.hostname)||ue(T.href)!==g){k=!0;break}b=T.href}k&&a.get(r.rawUrl)?.resolutionStatus!=="resolved"&&a.set(r.rawUrl,{...r,resolutionStatus:"rejected"})}}finally{l=null,await U.close().catch(()=>{}),n.onNetworkAudit?.({nonGoogleRequestsObserved:o})}return a}var Cn=String.raw`^(?:an error has occurred(?:[.!…]\s*)?(?:please try again later[.!…]?)?|loading|please wait|try again|something went wrong)[.!…\s]*$`,Na=700,fa=1e3,Ta=1400,Mn=900,Pa=3,kn=250,Kt=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=Yt(s.rawHref??s.href,t);if(!i||a.has(i.rawUrl))return[];a.add(i.rawUrl);let{url:d,...h}=i;return[{...h,text:s.text,href:d}]})}async resolveMaterialLinks(t,n,a,s,i){let d=Date.now(),h=[...n.flatMap(c=>c.sources??[]),...a,...s.citations.map(({text:c,href:g,...N})=>({...N,url:g})),...i.citations.map(({text:c,href:g,...N})=>({...N,url:g}))],S=new Map(h.map(c=>[c.rawUrl,c])),U=0,l=await yn(t,h,{onNetworkAudit:c=>{U=c.nonGoogleRequestsObserved}}),o=c=>({...c,...l.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:N,...b}=g;return{...b,text:c.text,href:N}};s.citations=s.citations.map(r),i.citations=i.citations.map(r);let u=[...l.values()];this.linkDiagnostics={linkCandidatesObserved:S.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 Z}async throwIfCaptcha(t,n){if(await t.locator(D.captchaMarker).count().catch(()=>0)>0)throw new _(`${n} returned a CAPTCHA \u2014 retrying with a fresh session.`)}async extractVisibleItems(t,n){let a=D,s=await t.evaluate(({selectors:d,onlyQuestion:h,answerPlaceholderPattern:S})=>{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 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=>!h||(o.getAttribute(d.itemDataQ)||o.getAttribute(d.itemDataInitQ)||o.querySelector(d.itemQuestionEl)?.innerText?.trim()||"")===h).map(o=>{let r=o.querySelector(d.clickTarget),u=o.classList.contains(d.expandedClass)||r?.getAttribute("aria-expanded")==="true",c=o.querySelector(d.answerContainer),N=c?.querySelector(d.aiAnswerBody)??c,b=U(N),k=new RegExp(S,"i").test(b),x=[...Array.from((N??o).querySelectorAll("a[href]")),...Array.from(o.querySelectorAll(d.aiCitation)),...Array.from(o.querySelectorAll(d.aiSourceCard))],O=!k&&(u&&b.length>=10||b.length>30&&x.some(L=>/^https?:\/\//.test(L.href))),H=O&&o.querySelector(d.sourceTitle)?.innerText?.trim()||void 0,f=O&&o.querySelector(d.sourceSite)?.innerText?.trim()||void 0,p=[];if(O){let L=new Set;for(let y of x)!/^https?:\/\//.test(y.href)||L.has(y.href)||(L.add(y.href),p.push({title:l(y.getAttribute("aria-label"))||(y.textContent||"").trim(),rawHref:y.href}));let T=p.find(y=>y.title.length>2)??p[0];T&&(H=H||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:O&&b||void 0,sourceTitle:H,sourceSite:f,sources:p}})},{selectors:a,onlyQuestion:n,answerPlaceholderPattern:Cn}),i=typeof t.url=="function"?t.url():"https://www.google.com/";return s.flatMap(d=>{let h=[],S=new Set;for(let r of d.sources){let u=Yt(r.rawHref,i);if(!u||S.has(u.rawUrl))continue;S.add(u.rawUrl);let c=d.sourceSite??null;try{c||=new URL(u.resolvedUrl??u.rawUrl).hostname.replace(/^www\./,"")}catch{}h.push({...u,title:r.title||d.sourceTitle||null,site:c})}let U=h[0],l={questionId:St(d.question),googleLinkId:d.googleLinkId,googleEvidenceId:d.googleEvidenceId,question:d.question,answer:rn(d.answer,d.question,d.sourceTitle),sourceTitle:U?.title??d.sourceTitle,sourceSite:U?.site??d.sourceSite,sourceCite:U?.url,sources:h},o=Be.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(`${D.item}[data-q="${n}"], ${D.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(h=>this.normalizeQuestion(h.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(h=>({...h})),a=this.checkpointMaterial,s=t.questionsOnly?0:n.filter(h=>!h.answer?.trim()).length,i=t.questionsOnly?0:n.filter(h=>(h.sources??[]).length===0).length,d={seed:t.seed,totalQuestions:n.length,maxDepthReached:n.reduce((h,S)=>Math.max(h,S.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 h=new Set,S=new Map,U=new Set,l=new Set,o=new Map,r=2,u=3,c=0,g={sel:D.item,dataQ:D.itemDataQ,dataInitQ:D.itemDataInitQ,questionEl:D.itemQuestionEl,answerSel:D.answerContainer,expandedClass:D.expandedClass,clickTarget:D.clickTarget,answerPlaceholderPattern:Cn,questionsOnly:n.questionsOnly,sourceSel:"a[href]"},N=()=>t.evaluate(({sel:f,dataQ:p,dataInitQ:L,questionEl:T,expandedClass:y,clickTarget:P,answerSel:w,answerPlaceholderPattern:C,questionsOnly:M})=>{let m=A=>{if(!A)return"";let I=[];for(let W of A.childNodes){if(W.nodeType===Node.TEXT_NODE){let J=W.textContent?.trim();J&&I.push(J);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 q=m(V);q&&I.push(q)}return I.join(" ").replace(/\s+/g," ").trim()};return Array.from(document.querySelectorAll(f)).map((A,I)=>{let W=m(A.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=A.classList.contains(y)||A.querySelector(P)?.getAttribute("aria-expanded")==="true",q=W.length>=10&&!new RegExp(C,"i").test(W);return{q:A.getAttribute(p)||A.getAttribute(L)||A.querySelector(T)?.innerText?.trim()||"",done:V&&(M||q),expanded:V,index:I}}).filter(A=>A.q)},g),b=async(f,p,L,T,y,P)=>{let w=Date.now(),C={id:`${P}:${St(f)}:${y}`,questionId:St(f),question:f,batchNumber:P,controlAttempt:y,observedAt:new Date(w).toISOString(),beforeQuestionCount:p,expandedBefore:T},M=L>=0?t.locator(g.sel).nth(L).locator(g.clickTarget):null,m=null,A=M?await(async()=>(T&&(await M.click({timeout:Mn,force:!0}),await t.waitForTimeout(120)),await M.click({timeout:Mn,force:!0}),!0))().catch(B=>(m=B instanceof Error&&(B.name==="TimeoutError"||/timeout/i.test(B.message))?"click_ack_timeout":"click_failed",!1)):!1,I=Date.now()-w;if(!A&&m!=="click_ack_timeout")return{dispatched:!1,confirmed:!1,observation:{...C,dispatched:!1,outcome:"dispatch_failed",confirmationSignals:[],confirmationCheckpointMs:null,confirmedAtMs:null,dispatchDurationMs:I,totalDurationMs:I,afterQuestionCount:p,newQuestionCount:0,expandedAfter:T,answerObserved:!1,sourceCount:0,errorCode:L<0?"control_missing":m??"click_failed"}};let W={exists:!0,expanded:T,answerReady:!1,sourceCount:0,questionCount:p},V=[],q=null,J=null,G=!1;for(let B of[Na,fa,Ta]){let tt=w+B-Date.now();if(tt>0&&await t.waitForTimeout(tt),W=await t.evaluate(({sel:F,dataQ:Y,dataInitQ:R,questionEl:E,expandedClass:$,clickTarget:et,answerSel:Pt,answerPlaceholderPattern:ht,sourceSel:Mt,target:bt})=>{let nt=ut=>{if(!ut)return"";let Zt=[];for(let Wt of ut.childNodes){if(Wt.nodeType===Node.TEXT_NODE){let Te=Wt.textContent?.trim();Te&&Zt.push(Te);continue}if(Wt.nodeType!==Node.ELEMENT_NODE)continue;let At=Wt;if(At.tagName==="STYLE"||At.tagName==="SCRIPT"||At.getAttribute("aria-hidden")==="true")continue;let fe=nt(At);fe&&Zt.push(fe)}return Zt.join(" ").replace(/\s+/g," ").trim()},Qt=Array.from(document.querySelectorAll(F)),It=Qt.find(ut=>(ut.getAttribute(Y)||ut.getAttribute(R)||ut.querySelector(E)?.innerText?.trim())===bt);if(!It)return{exists:!1,expanded:!1,answerReady:!1,sourceCount:0,questionCount:Qt.length};let Gn=It.classList.contains($)||It.querySelector(et)?.getAttribute("aria-expanded")==="true",me=It.querySelector(Pt),ve=nt(me).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(),Ne=ve.length>=10&&!new RegExp(ht,"i").test(ve);return{exists:!0,expanded:Gn,answerReady:Ne,sourceCount:Ne?me?.querySelectorAll(Mt).length??0:0,questionCount:Qt.length}},{...g,target:f}).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){G=!0,q=B,J=Date.now()-w;break}}let j=Date.now()-w,Ct={...C,dispatched:A,outcome:G?"confirmed":A?"unconfirmed":"dispatch_failed",confirmationSignals:V,confirmationCheckpointMs:q,confirmedAtMs:J,dispatchDurationMs:I,totalDurationMs:j,afterQuestionCount:W.questionCount,newQuestionCount:Math.max(0,W.questionCount-p),expandedAfter:W.expanded,answerObserved:W.answerReady,sourceCount:W.sourceCount,errorCode:A?G?null:W.exists?"confirmation_timeout":"control_missing":m};return{dispatched:A,confirmed:G,observation:Ct}},k=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 kt(this.paaLifecycle.completionReason);this.throwIfAborted(a);let f=await N(),p=!1;for(let w of f)i.has(w.q)||(i.add(w.q),d.push(w.q),d.length<=n.maxQuestions&&(p=this.upsertCollectedRow(this.toFlatRow({questionId:St(w.q),googleLinkId:null,googleEvidenceId:null,question:w.q,sources:[]},1,null,n.query))||p)),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:l.size,visibleControls:f.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,C=new Set(d.slice(0,n.maxQuestions));for(let M of await this.extractVisibleItems(t)){if(!C.has(M.question))continue;let m=o.get(M.question),A={...M,answer:M.answer??m?.answer,sourceTitle:M.sourceTitle??m?.sourceTitle,sourceSite:M.sourceSite??m?.sourceSite,sourceCite:M.sourceCite??m?.sourceCite,sources:this.mergePaaSources(m?.sources,M.sources)};o.set(M.question,A),w=this.upsertCollectedRow(this.toFlatRow(A,1,null,n.query))||w}if(w&&await this.emitProgress("answer_captured"),[...C].every(M=>{let m=o.get(M);return!!(m?.answer?.trim()&&m.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 L=new Set(d.slice(0,n.maxQuestions)),T=f.filter(w=>L.has(w.q)&&!w.done&&(S.get(w.q)??0)<r&&!h.has(w.q)),y=T.slice(-Pa);if(this.paaLifecycle={...this.paaLifecycle,eligibleControls:T.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(f.map(M=>M.q)),C=d.slice(0,n.maxQuestions).filter(M=>!U.has(M)&&(l.has(M)||!w.has(M)));if(C.length>0)throw this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"interrupted",failedInteractions:new Set([...l,...C]).size,completionReason:"At least one known PAA control failed or disappeared before it could be confirmed."},await this.emitProgress("expansion_finished"),new kt(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 m=await t.waitForFunction(({sel:I,min:W})=>document.querySelectorAll(I).length>W,{sel:D.item,min:f.length},{timeout:1500,polling:100}).catch(()=>null);if(this.paaLifecycle={...this.paaLifecycle,noGrowthConfirmations:M},m||(await N()).some(I=>!i.has(I.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(++k),(S.get(w.q)??0)>0){let C=this.paaLifecycle.retryBreakdown.controlRetries+1;this.paaLifecycle={...this.paaLifecycle,automaticRetries:C+this.paaLifecycle.retryBreakdown.browserRetries+this.paaLifecycle.retryBreakdown.runtimeRecoveries,retryBreakdown:{...this.paaLifecycle.retryBreakdown,controlRetries:C}}}S.set(w.q,(S.get(w.q)??0)+1)}let P=await Promise.all(y.map(async w=>({target:w,result:await b(w.q,f.length,w.index,w.expanded,S.get(w.q)??1,c)})));for(let{target:w,result:C}of P)(C.dispatched||C.confirmed)&&this.clickedQuestions.add(w.q),this.interactionObservations.push(C.observation);if(this.interactionObservations.length>kn&&this.interactionObservations.splice(0,this.interactionObservations.length-kn),!n.questionsOnly){let w=new Set(y.map(C=>C.q));for(let C of await this.extractVisibleItems(t))w.has(C.question)&&(o.set(C.question,C),this.upsertCollectedRow(this.toFlatRow(C,1,null,n.query))&&await this.emitProgress("answer_captured"))}for(let{target:w,result:C}of P){let M=o.get(w.q);C.confirmed||M?.answer?.trim()?(U.add(w.q),l.delete(w.q)):(S.get(w.q)??0)>=r&&(l.add(w.q),h.add(w.q))}this.paaLifecycle={...this.paaLifecycle,processedQuestions:U.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 x=n.questionsOnly?new Map:new Map(o);n.questionsOnly||await this.fillIncompleteItems(t,d,x,n,h);let O=[];for(let f of d){if(O.length>=n.maxQuestions)break;let p=this.normalizeQuestion(f);if(s.has(p))continue;s.add(p);let L=x.get(f);if(L){let T=this.toFlatRow(L,1,null,n.query);this.upsertCollectedRow(T),O.push(T),this.reporter.onQuestion({questionId:L.questionId,googleLinkId:L.googleLinkId,googleEvidenceId:L.googleEvidenceId,question:L.question,answer:L.answer??null,sourceTitle:L.sourceTitle??null,sourceSite:L.sourceSite??null,sourceCite:L.sourceCite??null,sources:L.sources,depth:1,parentQuestion:null,children:[]})}else{let T=this.toFlatRow({questionId:St(f),googleLinkId:null,googleEvidenceId:null,question:f,answer:void 0,sourceTitle:void 0,sourceSite:void 0,sourceCite:void 0,sources:[]},1,null,n.query);this.upsertCollectedRow(T),O.push(T)}}this.completeness.paaWithoutAnswer=n.questionsOnly?0:O.filter(f=>!f.answer).length,this.completeness.paaWithoutSource=n.questionsOnly?0:O.filter(f=>(f.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:l.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)),h=l=>!l?.answer||(l.sources??[]).length===0,S=new Set([...d].filter(l=>h(a.get(l)))),U=new Set([...S].filter(l=>!a.get(l)?.answer));if(S.size!==0){for(let l of S){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=[...U].filter(l=>a.get(l)?.answer).length}}async reExpandCollapsedItems(t){let n=`${D.item}:not(.${D.expandedClass}) ${D.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=He;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",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 g=u.slice(0,c).trim(),b=u.slice(c+7).replace(/^[·\s·]+/,"").match(/^([^·\n]+)/),k=b?b[1].trim():"";g&&s.push({type:U,title:g,channel:k,platform:"YouTube",duration:"",url:r})}}return s},n)}async extractForums(t){let n=Fe;return t.evaluate(a=>{let s=[],d=Array.from(document.querySelectorAll(a.section)).find(S=>S.textContent?.includes("Discussions"));if(!d)return s;let h=Array.from(d.querySelectorAll(a.item));for(let S of h){let U=S.href;if(!U)continue;let l=S.querySelector(a.title),o=S.querySelector(a.source),r=l?.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:Bt.item,platforms:[...Bt.platforms]};return(await t.evaluate(i=>{let d=new Set,h=[],S=Array.from(document.querySelectorAll(i.item)),U=["youtube.com","youtu.be","tiktok.com","instagram.com","facebook.com","fb.watch"],l=new Map;for(let o of S){let r=o.href;if(!r||!U.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(k=>/^\d+:\d+$/.test(k))??"",c=r.find(k=>!/^\d+:\d+$/.test(k)&&k.length>5)??"";if(!c)continue;let g=c,N="",b="";for(let k of i.platforms){let x=-1,O=0;for(;;){let T=c.indexOf(k,O);if(T===-1)break;x=T,O=T+1}if(x===-1)continue;let H=c.slice(x+k.length);if(!(/^[\s·]/.test(H)||H.trim()===""))continue;g=c.slice(0,x).trim(),N=k;let p=H.replace(/^[\s·]+/,""),L=p.indexOf("\xB7");b=(L===-1?p:p.slice(0,L)).trim();break}g&&h.push({title:g,channel:b,platform:N,duration:u,url:o})}return h},a)).map(i=>({type:"short_video",...i}))}async extractWhatPeopleSaying(t){let n=Re;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 h=i.querySelector(a.cardLink)?.href??"",S=i.querySelector(a.titleH1)?.textContent?.trim(),U=i.querySelector(a.titleDiv)?.textContent?.trim(),l=S??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()??"",N=i.querySelector(a.authorNote)?.textContent?.trim()??null,b=i.querySelector(a.popularCommentLabel),k=null;if(b){let m=b.nextSibling;for(;m;){let A=m.textContent?.trim();if(A){k=A;break}m=m.nextSibling}}let x=Array.from(i.querySelectorAll("span")),O=x.find(m=>/^\d+:\d+$/.test(m.textContent?.trim()??""))?.textContent?.trim()??null,f=x.map(m=>m.textContent?.trim()??"").filter(m=>/\d/.test(m)&&(m.includes("comment")||m.includes("reaction")||m.includes("view")||m.includes("like")||m.includes("share")))[0]??"",p=x.map(m=>m.textContent?.trim()??"").filter(m=>/\d+ (day|week|month|year|hour)s? ago|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/.test(m)),L=g||(p[0]??""),T=u||(c?"YouTube":""),y=c||o,P="unknown",w=T.toLowerCase(),C=y.toLowerCase(),M=o.toLowerCase();return w.includes("reddit")||C.startsWith("r/")?P="reddit":w.includes("facebook")||M.includes("facebook")?P="facebook":w.includes("instagram")||M.includes("instagram")?P="instagram":w.includes("tiktok")||M.includes("tiktok")?P="tiktok":w.includes("youtube")||c?P="youtube":P="news",{type:P,title:l,url:h,source:y,platform:T,popularComment:k,engagement:f,date:L,duration:O,authorNote:N}}):[]},n)}async extractOrganicResults(t){let n=Ve,a=await t.evaluate(i=>{let d=[],h=0;return document.querySelectorAll(i.result).forEach(S=>{let U=S.querySelector(i.title);if(!U)return;let l=U.textContent?.trim()??"",r=U.closest("a")?.href??"";if(!l||!r)return;h++;let u=S.querySelector(i.cite)?.textContent?.trim()??null,c=S.querySelector(i.snippet)?.textContent?.trim()??null,g=!!S.querySelector(i.redditCite),N=S.querySelector(i.ratingWrap),b=N?{value:N.querySelector(i.ratingValue)?.textContent?.trim()??"",count:N.querySelector(i.reviewCount)?.textContent?.trim()??""}:null,k="";try{k=new URL(r).hostname.replace(/^www\./,"")}catch{k=S.querySelector(i.siteName)?.textContent?.trim()??""}d.push({position:h,title:l,url:r,domain:k,cite:u,snippet:c,isRedditStyle:g,inlineRating:b})}),d},n),s=typeof t.url=="function"?t.url():"https://www.google.com/";return a.flatMap(i=>{let d=Yt(i.url,s);if(!d)return[];let h=i.domain;try{h=new URL(d.resolvedUrl??d.rawUrl).hostname.replace(/^www\./,"")}catch{}return[{...i,...d,domain:h}]})}async extractLocalPack(t){let n=Ee;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,h)=>{let S=d.querySelector(a.name)?.textContent?.trim()??"";if(!S)return;let U=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 b of Array.from(d.querySelectorAll("a[href]"))){let k=b.href.match(/[?&]cid=(\d+)/);if(k){r=k[1];break}let x=b.href.match(/!1s0x[0-9a-f]+:0x([0-9a-f]+)/i);if(x){try{r=BigInt("0x"+x[1]).toString()}catch{}if(r)break}}let u=[];d.querySelectorAll("div, span").forEach(b=>{let k=Array.from(b.childNodes).filter(x=>x.nodeType===3).map(x=>x.textContent?.trim()??"").filter(x=>x.length>1&&x.length<120).join(" ");k&&!u.includes(k)&&u.push(k)});let c=Array.from(d.querySelectorAll("a[href]")),g=c.find(b=>b.href.includes("google.com/maps"))?.href??null,N=c.find(b=>!b.href.includes("google.com")&&b.href.startsWith("http"))?.href??null;s.push({position:h+1,name:S,cid:r,rating:U,reviewCount:o,metadata:u,websiteUrl:N,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(S){let U=[".OSrXXb",".dbg0pd",".tzt0oe",'[role="heading"]',"h3"];for(let l of U){let o=S.querySelector(l);if(o?.textContent?.trim())return o.textContent.trim()}return""}document.querySelectorAll('[id^="pv-/g/"]').forEach(S=>{let U=S.getAttribute("id");if(!U)return;let l=U.replace("pv-","");n.add(l);let o=d(S),u=S.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(S=>{let U=S.getAttribute("data-mid");if(U?.startsWith("/g/")&&(n.add(U),!i.has(U))){let l=d(S);l&&i.set(U,{name:l,kgId:U,cid:null,gcid:null})}}),document.querySelectorAll(".w7Dbne").forEach(S=>{let l=S.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;if(!l)return;a.add(l);let o=S.querySelector(".OSrXXb")?.textContent?.trim()??"";if(!o)return;let r=S.querySelector('[id^="pv-/g/"]'),u=r?r.getAttribute("id").replace("pv-",""):null,c=u??`cid:${l}`;if(i.has(c)){let g=i.get(c);g.cid||i.set(c,{...g,cid:l})}else i.set(c,{name:o,kgId:u,cid:l,gcid:null})}),document.querySelectorAll("a[data-cid]").forEach(S=>{let U=S.getAttribute("data-cid");if(!U)return;if(a.add(U),![...i.values()].some(o=>o.cid===U)){let o=S.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 h=Array.from(document.querySelectorAll("script:not([src])")).map(S=>S.textContent??"").filter(S=>S.length>1e4).join(`
|
|
21704
|
-
`);for(let S of h.matchAll(/\/g\/[a-zA-Z0-9_-]{5,20}/g))n.add(S[0]);for(let S of h.matchAll(/gcid:[a-zA-Z0-9_]+/g))s.add(S[0]);for(let S of h.matchAll(/0x[0-9a-f]+:0x([0-9a-f]+)/gi))try{a.add(BigInt("0x"+S[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(),h=s.find(S=>S.name.toLowerCase().trim()===d);h?h.cid||(h.cid=i.cid):s.find(S=>S.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(ln,{aio:Ge,aim:De,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 h=d;for(let S=0;S<8&&h;S++){let U=h.querySelector('[aria-label="Share"]');if(U)return U.scrollIntoView({block:"center"}),U.click(),!0;h=h.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 h=(d.currentNode.textContent||"").match(/https:\/\/share\.google\/aimode\/\S+/);if(h)return h[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),!n.serpOnly&&!this.driver.withTemporaryPage)return{organic:[],status:"failed",failureCode:"unsupported_driver"};let s;try{let i=new URL(t.url()),d=U=>{try{let l=new URL(U,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}},h=await t.evaluate(U=>document.querySelector(U?'a[aria-label="Page 2"], a#pnnext, a[rel="next"]':'a#pnnext, a[rel="next"]')?.getAttribute("href")??null,n.serpOnly);if(!h)return{organic:[],status:"unavailable",failureCode:"missing_next"};if(!d(h))return{organic:[],status:"unavailable",failureCode:"invalid_next"};if(n.serpOnly){let U=t.locator('a[aria-label="Page 2"], a#pnnext, a[rel="next"]').first();if(await U.scrollIntoViewIfNeeded({timeout:1e4}),await U.click({timeout:2e4}),this.throwIfAborted(a),await this.throwIfCaptcha(t,"Google SERP page 2"),!d(t.url()))throw s="invalid_next",new Error("Invalid pagination landing");let l=await this.extractOrganicResults(t);return l.length>0?{organic:l.map(o=>({...o,position:o.position+10})),status:"captured"}:{organic:[],status:"unavailable",failureCode:"empty_page"}}let S=await this.driver.withTemporaryPage(async U=>{if(await U.route("**/*",async l=>{let o=l.request();o.isNavigationRequest()&&o.frame()===U.mainFrame()&&!d(o.url())?(s=/^https:\/\/www\.google\.com\/sorry(?:\/|\?)/.test(o.url())?"captcha":"invalid_next",await l.abort("blockedbyclient")):await l.fallback()}),await U.goto(new URL(h,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),S.length>0?{organic:S.map(U=>({...U,position:U.position+10})),status:"captured"}:{organic:[],status:"unavailable",failureCode:"empty_page"}}catch(i){if(this.throwIfAborted(a),i instanceof Z)throw i;return{organic:[],status:"failed",failureCode:s??(i instanceof _?"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,kernelApiKey:t.kernelApiKey,kernelProxyId:t.kernelProxyId,kernelProfileName:t.kernelProfileName,kernelProfileSaveChanges:t.kernelProfileSaveChanges,kernelStealth:t.kernelStealth,kernelProxyResolution:t.kernelProxyResolution,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,h=[];try{this.throwIfAborted(n);let S=Date.now();await this.driver.launch(i),this.phaseTimings.providerConnectMs=Date.now()-S;let U=this.driver.getProviderSessionMetadata();if(U?.providerSessionId&&this.onProviderSession)try{await this.onProviderSession(U)}catch(F){console.warn(JSON.stringify({event:"paa_provider_session_sink_failed",provider:U.provider,message:F instanceof Error?F.message:String(F)}))}this.throwIfAborted(n);let l=t.location?Se(t.location):null,o=t.location?l?.canonical??t.location:null,r=o?nn(o):null,u=t,c=t.includeAllSerpFeatures,g=c||t.includeLocalPack,N=c||t.includeForums,b=c||t.includeVideos,k=c||t.includeAiOverview,x=c||t.includeWhatPeopleSaying,O={surface:"web",aiOverview:{detected:!1,text:null,citations:[]},aiMode:{detected:!1,text:null,citations:[]}},H=Date.now(),{hasPaa:f}=await this.driver.navigateToSERP(u.query,r,t.gl,t.hl,{...Xt(t.recency)?{tbs:Xt(t.recency)}:{},debug:t.debug,purpose:t.serpOnly?"serp":"paa",pages:t.pages===2?2:1,...t.softDeadlineMs?{deadlineMs:t.softDeadlineMs}:{}});this.phaseTimings.navigationMs=Date.now()-H,this.throwIfAborted(n);let p=this.driver.getPage();if(await this.throwIfCaptcha(p,"Google SERP"),f||(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 F=Date.now(),Y=f?await this.runBFS(p,u,n):[];this.phaseTimings.paaExpansionMs=Date.now()-F,await this.resolveMaterialLinks(p,Y,[],O.aiOverview,O.aiMode);let R={seed:u.query,totalQuestions:Y.length,maxDepthReached:Y.reduce((E,$)=>Math.max(E,$.depth),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:f?"paa_found":"no_paa",...f?{}:{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:Y.length,surface:"web",aiOverview:{detected:!1,text:null,citations:[]},aiMode:{detected:!1,text:null,citations:[]},whatPeopleSaying:[],tree:this.buildTree(Y,u.query),flat:Y,videos:[],forums:[],organicResults:[],localPack:[],entityIds:{entities:[],kgIds:[],cids:[],gcids:[]},stats:R}}if(k&&(this.aioShareUrlEarly=await this.captureAIOverviewShareUrl(p,t).catch(()=>null)),t.serpOnly){let F=Date.now(),[Y,R,E]=await Promise.all([this.extractOrganicResults(p),g?this.extractLocalPack(p):Promise.resolve([]),this.extractEntityIds(p)]),$=this.mergeLocalPackIntoEntities(E,R),et=k?await this.extractAISurfaces(p,t):O;this.phaseTimings.serpParseMs=Date.now()-F;let Pt=t.debug?pt(o,Y,R):void 0,ht=Y,Mt={requestedPages:(t.pages??1)>=2?2:1,capturedPages:1,page2Status:(t.pages??1)>=2?"not_attempted":"not_requested",page1OrganicCount:Y.length,page2OrganicCount:0};if((t.pages??1)>=2){let nt=await this.captureSecondOrganicPage(p,u,n);ht=[...Y,...nt.organic],Mt={...Mt,capturedPages:nt.status==="captured"?2:1,page2Status:nt.status,page2OrganicCount:nt.organic.length,...nt.failureCode?{failureCode:nt.failureCode}:{}},t.debug&&(Pt=pt(o,ht,R))}await this.resolveMaterialLinks(p,[],ht,et.aiOverview,et.aiMode);let bt={seed:u.query,totalQuestions:0,maxDepthReached:0,durationMs:Date.now()-a,errorCount:d};return this.reporter.onComplete(bt),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"serp_only",problem:null,pagination:Mt,completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,o,r,Pt,l)}:{}},totalQuestions:0,surface:et.surface,aiOverview:et.aiOverview,aiMode:et.aiMode,whatPeopleSaying:[],tree:[],flat:[],videos:[],forums:[],organicResults:ht,localPack:R,entityIds:$,stats:bt}}let[L,T,y,P,w,C]=await Promise.all([b?this.extractVideos(p):Promise.resolve([]),N?this.extractForums(p):Promise.resolve([]),x?this.extractWhatPeopleSaying(p):Promise.resolve([]),this.extractEntityIds(p),this.extractOrganicResults(p),g?this.extractLocalPack(p):Promise.resolve([])]),M=this.mergeLocalPackIntoEntities(P,C),m=t.debug?pt(o,w,C):void 0;this.reporter.onVideos(L),this.reporter.onForums(T);let A=k?await this.extractAISurfaces(p,t):O,I={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:A.surface,aiOverview:A.aiOverview,aiMode:A.aiMode,whatPeopleSaying:y,videos:L,forums:T,organicResults:W,localPack:C,entityIds:M,pagination:I},await this.emitProgress("serp_captured"),I.requestedPages===2){let F=await this.captureSecondOrganicPage(p,u,n);W=[...w,...F.organic],I={...I,capturedPages:F.status==="captured"?2:1,page2Status:F.status,page2OrganicCount:F.organic.length,...F.failureCode?{failureCode:F.failureCode}:{}},this.checkpointMaterial={...this.checkpointMaterial,organicResults:W,pagination:I},await this.emitProgress("serp_captured"),await this.resolveMaterialLinks(p,[],W,A.aiOverview,A.aiMode),this.checkpointMaterial={...this.checkpointMaterial,organicResults:W},await this.emitProgress("serp_captured")}let V=t.debug?pt(o,W,C):m;if(!f){await this.resolveMaterialLinks(p,[],W,A.aiOverview,A.aiMode),this.checkpointMaterial={...this.checkpointMaterial,organicResults:W},await this.emitProgress("serp_captured");let F={seed:u.query,totalQuestions:0,maxDepthReached:0,durationMs:Date.now()-a,errorCount:d};return this.reporter.onComplete(F),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"no_paa",noPaaObserved:!0,problem:null,pagination:I,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,o,r,V,l)}:{}},totalQuestions:0,surface:A.surface,aiOverview:A.aiOverview,aiMode:A.aiMode,whatPeopleSaying:y,tree:[],flat:[],videos:L,forums:T,organicResults:W,localPack:C,entityIds:M,stats:F}}let q=Date.now(),J=await this.runBFS(p,u,n);this.phaseTimings.paaExpansionMs=Date.now()-q,this.throwIfAborted(n);let G=new URLSearchParams({q:u.query,gl:t.gl,hl:t.hl,pws:"0",udm:Bt.udm});r&&G.set("uule",r);let j=[];if(t.includeShortVideos!==!1)try{j=await this.extractShortVideos(p,"https://www.google.com/search?"+G.toString())}catch(F){if(!(F instanceof _))throw F;d++,h.push({code:"short_videos_captcha_skipped",surface:"short_videos",message:F.message,retryable:!0})}this.reporter.onVideos(j),await this.resolveMaterialLinks(p,J,W,A.aiOverview,A.aiMode),this.checkpointMaterial={...this.checkpointMaterial,surface:A.surface,aiOverview:A.aiOverview,aiMode:A.aiMode,videos:[...L,...j],organicResults:W},await this.emitProgress("expansion_finished");let Ct=[...L,...j],B=this.buildTree(J,u.query),tt={seed:u.query,totalQuestions:J.length,maxDepthReached:J.reduce((F,Y)=>Math.max(F,Y.depth),0),durationMs:Date.now()-a,errorCount:d};return this.reporter.onComplete(tt),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"paa_found",problem:null,pagination:I,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...h.length>0?{warnings:h}:{},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,o,r,V,l)}:{}},totalQuestions:J.length,surface:A.surface,aiOverview:A.aiOverview,aiMode:A.aiMode,whatPeopleSaying:y,tree:B,flat:J,videos:Ct,forums:T,organicResults:W,localPack:C,entityIds:M,stats:tt}}catch(S){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(S instanceof Error?S:new Error(String(S))),S}}};import{promises as z}from"fs";import Ut from"path";import gt from"papaparse";var Jt=class{async writeJSON(t,n){await z.mkdir(n,{recursive:!0});let s=`${t.seed.toLowerCase().replace(/\W+/g,"-").slice(0,40)}-${Date.now()}.json`,i=Ut.join(n,s);return await z.writeFile(i,JSON.stringify(t,null,2),"utf8"),await Oe({title:`${t.seed} scrape`,content:JSON.stringify(t),source:`mcp-scraper:${i}`}),i}async writeCSV(t,n){await z.mkdir(n,{recursive:!0});let s=(t[0]?.seed_query??"paa").toLowerCase().replace(/\W+/g,"-").slice(0,40),i=gt.unparse(t.map(({sources:S,...U})=>({...U,sources_json:JSON.stringify(S)})),{header:!0}),d=`${s}-${Date.now()}.csv`,h=Ut.join(n,d);return await z.writeFile(h,i,"utf8"),h}async writeVideoCSV(t,n,a){await z.mkdir(a,{recursive:!0});let s=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),i=gt.unparse(t,{header:!0}),d=`${s}-videos-${Date.now()}.csv`,h=Ut.join(a,d);return await z.writeFile(h,i,"utf8"),h}async writeForumCSV(t,n,a){await z.mkdir(a,{recursive:!0});let s=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),i=gt.unparse(t,{header:!0}),d=`${s}-forums-${Date.now()}.csv`,h=Ut.join(a,d);return await z.writeFile(h,i,"utf8"),h}async writeAIOverviewCSV(t,n,a,s){await z.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})),h=gt.unparse(d,{header:!0}),S=`${i}-ai-overview-${Date.now()}.csv`,U=Ut.join(s,S);return await z.writeFile(U,h,"utf8"),U}async writeAIModeCSV(t,n,a,s){await z.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})),h=gt.unparse(d,{header:!0}),S=`${i}-ai-mode-${Date.now()}.csv`,U=Ut.join(s,S);return await z.writeFile(U,h,"utf8"),U}async writeWhatPeopleSayingCSV(t,n,a){await z.mkdir(a,{recursive:!0});let s=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),i=t.map(U=>({seed_query:n,...U})),d=gt.unparse(i,{header:!0}),h=`${s}-what-people-saying-${Date.now()}.csv`,S=Ut.join(a,h);return await z.writeFile(S,d,"utf8"),S}};var _t=class{onQuestion(t){process.stdout.write(JSON.stringify({event:"question",depth:t.depth,question:t.question})+`
|
|
21735
|
+
`).trim();return!O||/not available|try again|can't generate/i.test(O)?null:O}function U(m){if(!m||m.startsWith("javascript:"))return null;try{let v=new URL(m,window.location.href);return!["http:","https:"].includes(v.protocol)||v.username||v.password?null:{href:v.href,rawHref:v.href}}catch{return null}}function h(m){if(!m)return[];let v=new Set,A=[];for(let y of Array.from(m.querySelectorAll("a[href]"))){let C=U(y.getAttribute("href")??"");if(!C||v.has(C.rawHref))continue;v.add(C.rawHref);let H="";try{H=new URL(C.href).hostname.replace(/^www\./,"")}catch{}A.push({text:i(y)||H||C.href,href:C.href,rawHref:C.rawHref})}return A}async function r(m){let v=m.querySelector(t.aio.showMoreButton);if(!v||v.getAttribute("aria-expanded")!=="false")return!1;v.click();let A=t.expandWaitMs??1500;return A>0&&await new Promise(y=>setTimeout(y,A)),!0}let l=o(),u=null,c=[],w=!1,g=!1,f=[];if(l){w=await r(l);let m=l.querySelector(t.aio.controller),v=l.querySelector(t.aio.contentSubtree),A=l.querySelector(t.aio.showMoreButton);g=m?.getAttribute("data-trnct")==="false"||A?.getAttribute("aria-expanded")==="true"||!A,u=d(v??m??l),f=(u??"").split(`
|
|
21736
|
+
`).map(y=>y.trim()).filter(y=>/^\d+\.\s+.+/.test(y)),c=h(l)}let M=document.querySelector(t.aim.root),p=a==="aim"&&!!M,P=M?.closest(t.aim.wrapper)??M,b=p?d(P):null,x=p&&s(b),k=x?b:null,B=x?h(P):[],N=!!l&&s(u);return{surface:a,aiOverview:{detected:N,text:N?u:null,citations:N?c:[],expanded:N?w:!1,fullyExpanded:N?g:!1,sections:N?f:[]},aiMode:{detected:x&&k!==null,text:k,citations:B}}}import{createHash as Ai}from"crypto";var ta=8e3,ea=3e3,na=1e4,xi=8;function wt(e){return/(^|\.)google\.(?:com|[a-z]{2,3}(?:\.[a-z]{2})?)$/i.test(e)}function Rt(e){if(!e||e.length>ta)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 Li(e,t){if(!e||e.length>ta||/^javascript:/i.test(e))return null;try{let n=new URL(e,t);return Rt(n.href)}catch{return null}}function Ft(e){let t=Rt(e);return!t||t.protocol!=="https:"||!wt(t.hostname)||t.pathname!=="/goto"?null:t.searchParams.get("url")?t:null}function Oe(e){if(e.linkType!=="google_goto_redirect"||e.resolutionStatus!=="resolved"||!Ft(e.rawUrl)||!e.resolvedUrl)return!1;let t=Rt(e.resolvedUrl);return!!(t&&!wt(t.hostname)&&t.href===e.resolvedUrl&&e.url===t.href)}function ft(e){let t=e.normalize("NFKC").toLocaleLowerCase("en-US").replace(/[^\p{L}\p{N}\s]/gu,"").replace(/\s+/g," ").trim();return`paa_${Ai("sha256").update(t).digest("hex").slice(0,16)}`}function Dt(e,t){let n=Li(e,t);if(!n)return null;let a=n.href;if(!wt(n.hostname))return{url:a,rawUrl:a,resolvedUrl:a,linkType:"plain",resolutionStatus:"not_needed"};if(n.pathname==="/url"){let i=Rt(n.searchParams.get("q")??n.searchParams.get("url")??"");return!i||wt(i.hostname)?null:{url:i.href,rawUrl:a,resolvedUrl:i.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 Be(e){return Ft(e)?.searchParams.get("url")??null}function aa(e,t){try{let n=new URL(e),a=Rt(new URL(t,n).href);return!a||wt(a.hostname)?null:(!a.hash&&n.hash&&(a.hash=n.hash),a.href)}catch{return null}}async function ia(e,t={}){let n=[...new Set([...e].flatMap(r=>Ft(r)?[r]:[]))],a=new Map(n.map(r=>[r,{rawUrl:r,resolvedUrl:null,resolutionStatus:"unresolved"}])),i=typeof globalThis.fetch=="function"?globalThis.fetch.bind(globalThis):null,s=t.fetchImpl??i;if(n.length===0||!s)return{resolutions:[...a.values()],nonGoogleRequestsObserved:0};let S=Math.max(1,t.timeoutMs??ea),o=Date.now()+Math.max(1,t.totalBudgetMs??na),d=Math.max(1,Math.min(16,Math.floor(t.concurrency??xi))),U=0,h=async()=>{for(;U<n.length;){let r=n[U++],l=Ft(r),u=l?.searchParams.get("url");if(!l||!u){a.set(r,{rawUrl:r,resolvedUrl:null,resolutionStatus:"rejected"});continue}l.hash="";let c=l.href;for(let w=0;w<2;w++){let g=o-Date.now();if(g<=0)return;let f=new AbortController,M=setTimeout(()=>f.abort(),Math.min(S,g)),p;try{p=await s(c,{method:"GET",redirect:"manual",headers:{accept:"*/*","user-agent":"Mozilla/5.0"},signal:f.signal})}catch{break}finally{clearTimeout(M)}if(p.status<300||p.status>=400)break;let P=p.headers.get("location");if(!P)break;let b=aa(r,P);if(b){a.set(r,{rawUrl:r,resolvedUrl:b,resolutionStatus:"resolved"});break}let x;try{x=new URL(P,c)}catch{a.set(r,{rawUrl:r,resolvedUrl:null,resolutionStatus:"rejected"});break}if(!wt(x.hostname)||Be(x.href)!==u){a.set(r,{rawUrl:r,resolvedUrl:null,resolutionStatus:"rejected"});break}c=x.href}}};return await Promise.all(Array.from({length:Math.min(d,n.length)},()=>h())),{resolutions:[...a.values()],nonGoogleRequestsObserved:0}}function Xn(e,t){try{return new URL(e.resolvedUrl??e.url).hostname.replace(/^www\./,"")}catch{return t}}async function sa(e,t={}){let n=[],a=r=>{for(let l of r)n.push(l),a(l.children??[])};a(e.tree??[]);let i=[...e.flat.flatMap(r=>r.sources??[]),...n.flatMap(r=>r.sources),...e.organicResults??[],...(e.aiOverview?.citations??[]).map(({text:r,href:l,...u})=>({...u,url:l})),...(e.aiMode?.citations??[]).map(({text:r,href:l,...u})=>({...u,url:l}))],s=new Map(i.filter(r=>!!r?.rawUrl).map(r=>[r.rawUrl,r])),S=[...s.values()].filter(r=>r.linkType==="google_goto_redirect"&&r.resolutionStatus!=="resolved").map(r=>r.rawUrl);if(S.length>0){let r=await ia(S,t);for(let l of r.resolutions){let u=s.get(l.rawUrl);u&&s.set(l.rawUrl,l.resolutionStatus==="resolved"&&l.resolvedUrl?{...u,url:l.resolvedUrl,resolvedUrl:l.resolvedUrl,resolutionStatus:"resolved"}:{...u,resolutionStatus:l.resolutionStatus})}}let o=r=>({...r,...s.get(r.rawUrl)??r}),d=r=>r.map(l=>{let u=o(l);return{...u,site:Xn(u,l.site)}});for(let r of e.flat){r.sources=d(r.sources??[]);let l=r.sources[0];r.source_title=l?.title??r.source_title,r.source_site=l?.site??r.source_site,r.source_cite=l?.url??r.source_cite}for(let r of n){r.sources=d(r.sources??[]);let l=r.sources[0];r.sourceTitle=l?.title??r.sourceTitle,r.sourceSite=l?.site??r.sourceSite,r.sourceCite=l?.url??r.sourceCite}for(let r=0;r<(e.organicResults?.length??0);r++){let l=o(e.organicResults[r]);e.organicResults[r]={...l,domain:Xn(l,e.organicResults[r].domain)??""}}let U=r=>{let l=o({url:r.href,rawUrl:r.rawUrl,resolvedUrl:r.resolvedUrl,linkType:r.linkType,resolutionStatus:r.resolutionStatus}),{url:u,...c}=l;return{...r,...c,href:u}};e.aiOverview&&(e.aiOverview.citations=(e.aiOverview.citations??[]).map(U)),e.aiMode&&(e.aiMode.citations=(e.aiMode.citations??[]).map(U));let h=[...s.values()];return e.diagnostics.links={linkCandidatesObserved:s.size,plainLinksObserved:h.filter(r=>r.linkType==="plain").length,googleUrlRedirectsObserved:h.filter(r=>r.linkType==="google_url_redirect").length,googleGotoRedirectsObserved:h.filter(r=>r.linkType==="google_goto_redirect").length,redirectsResolved:h.filter(r=>r.linkType!=="plain"&&r.resolutionStatus==="resolved").length,redirectsUnresolved:h.filter(r=>r.resolutionStatus==="unresolved").length,redirectsRejected:h.filter(r=>r.resolutionStatus==="rejected").length,resolverNonGoogleRequestsObserved:0,paaSourcesPreserved:e.flat.reduce((r,l)=>r+l.sources.length,0),aiOverviewLabelValidated:e.aiOverview?.detected??!1},e}async function oa(e,t,n={}){let a=new Map;for(let l of t){let u=a.get(l.rawUrl);u&&Oe(u)||a.set(l.rawUrl,l.linkType==="google_goto_redirect"&&!Oe(l)?{...l,url:l.rawUrl,resolvedUrl:null,resolutionStatus:"unresolved"}:l)}let i=[...a.values()].filter(l=>l.linkType==="google_goto_redirect"&&!Oe(l));if(i.length===0)return a;let s=Date.now()+(n.totalBudgetMs??na),S=await ia(i.map(l=>l.rawUrl),n);for(let l of S.resolutions){let u=a.get(l.rawUrl);u&&a.set(l.rawUrl,l.resolutionStatus==="resolved"&&l.resolvedUrl?{...u,url:l.resolvedUrl,resolvedUrl:l.resolvedUrl,resolutionStatus:"resolved"}:{...u,resolutionStatus:l.resolutionStatus})}let o=i.filter(l=>a.get(l.rawUrl)?.resolutionStatus==="unresolved");if(o.length===0||n.browserFallback===!1||Date.now()>=s)return n.onNetworkAudit?.({nonGoogleRequestsObserved:0}),a;let d=n.timeoutMs??ea,U=await e.context().newPage().catch(()=>null);if(!U)return n.onNetworkAudit?.({nonGoogleRequestsObserved:0}),a;let h=null,r=0;try{await U.route("**/*",async l=>{let u=l.request().url();try{wt(new URL(u).hostname)||(r+=1)}catch{}let c=Be(u);if(!h||c!==h.token){await l.abort("blockedbyclient").catch(()=>{});return}let w=h;try{let g=await l.fetch({maxRedirects:0,timeout:w.timeoutMs});w.location=g.headers().location??null}finally{await l.abort("blockedbyclient").catch(()=>{}),w.finish()}});for(let l of o){let u=s-Date.now();if(u<=0)break;let c=Ft(l.rawUrl),w=c?.searchParams.get("url");if(!c||!w){a.set(l.rawUrl,{...l,resolutionStatus:"rejected"});continue}let g=Math.min(d,u);c.hash="";let f=c.href,M=!1;for(let p=0;p<2;p++){let P,b=new Promise(m=>{P=m}),x=`mcp-goto-${Math.random().toString(36).slice(2)}`;h={token:w,timeoutMs:g,location:null,finish:P},await U.evaluate(({url:m,id:v})=>{let A=document.createElement("iframe");A.id=v,A.hidden=!0,A.src=m,document.body.append(A)},{url:f,id:x}).catch(()=>null),await Promise.race([b,new Promise(m=>setTimeout(m,g))]);let k=h.location;if(h=null,await U.evaluate(m=>document.getElementById(m)?.remove(),x).catch(()=>null),!k)break;let B=aa(l.rawUrl,k);if(B){a.set(l.rawUrl,{...l,url:B,resolvedUrl:B,resolutionStatus:"resolved"});break}let N;try{N=new URL(k,f)}catch{M=!0;break}if(!wt(N.hostname)||Be(N.href)!==w){M=!0;break}f=N.href}M&&a.get(l.rawUrl)?.resolutionStatus!=="resolved"&&a.set(l.rawUrl,{...l,resolutionStatus:"rejected"})}}finally{h=null,await U.close().catch(()=>{}),n.onNetworkAudit?.({nonGoogleRequestsObserved:r})}return a}async function ra(e){let t=Ot;return e.evaluate(n=>{let a=[],i=Array.from(document.querySelectorAll(n.container));for(let s of i){let d=(s.querySelector(n.sectionHeading)?.textContent?.trim()??"").toLowerCase().includes("short")?"short_video":"video",U=Array.from(s.querySelectorAll(n.item));for(let h of U){let r=h.href;if(!r||!r.includes("youtube")&&!r.includes("youtu.be"))continue;let l=h.textContent?.trim()??"",u=l.indexOf("YouTube");if(u===-1)continue;let c=l.slice(0,u).trim(),g=l.slice(u+7).replace(/^[·\s·]+/,"").match(/^([^·\n]+)/),f=g?g[1].trim():"";c&&a.push({type:d,title:c,channel:f,platform:"YouTube",duration:"",url:r})}}return a},t)}async function da(e){let t=xn;return e.evaluate(n=>{let a=[],s=Array.from(document.querySelectorAll(n.section)).find(o=>o.textContent?.includes("Discussions"));if(!s)return a;let S=Array.from(s.querySelectorAll(n.item));for(let o of S){let d=o.href;if(!d)continue;let U=o.querySelector(n.title),h=o.querySelector(n.source),r=U?.textContent?.trim()??"",l=h?.textContent?.trim()??"";r&&a.push({title:r,source:l,url:d})}return a},t)}async function la(e,t,n){try{await e.goto(t,{waitUntil:"domcontentloaded"}),await e.waitForTimeout(1500)}catch{return[]}await n(e,"Google short video search");let a={item:Bt.item,platforms:[...Bt.platforms]};return(await e.evaluate(s=>{let S=new Set,o=[],d=Array.from(document.querySelectorAll(s.item)),U=["youtube.com","youtu.be","tiktok.com","instagram.com","facebook.com","fb.watch"],h=new Map;for(let r of d){let l=r.href;if(!l||!U.some(c=>l.includes(c)))continue;let u=r.textContent?.trim()??"";h.has(l)||h.set(l,[]),h.get(l).push(u)}for(let[r,l]of h.entries()){if(S.has(r))continue;S.add(r);let u=l.find(M=>/^\d+:\d+$/.test(M))??"",c=l.find(M=>!/^\d+:\d+$/.test(M)&&M.length>5)??"";if(!c)continue;let w=c,g="",f="";for(let M of s.platforms){let p=-1,P=0;for(;;){let N=c.indexOf(M,P);if(N===-1)break;p=N,P=N+1}if(p===-1)continue;let b=c.slice(p+M.length);if(!(/^[\s·]/.test(b)||b.trim()===""))continue;w=c.slice(0,p).trim(),g=M;let k=b.replace(/^[\s·]+/,""),B=k.indexOf("\xB7");f=(B===-1?k:k.slice(0,B)).trim();break}w&&o.push({title:w,channel:f,platform:g,duration:u,url:r})}return o},a)).map(s=>({type:"short_video",...s}))}async function Sa(e){let t=Ln;return e.evaluate(n=>{let a=Array.from(document.querySelectorAll(n.sectionTag)).find(i=>i.textContent?.includes(n.sectionHeadingText))??document.querySelector(".yG4QQe.TBC9ub.NbhJ1c");return a?Array.from(a.querySelectorAll(n.card)).map(i=>{let S=i.querySelector(n.cardLink)?.href??"",o=i.querySelector(n.titleH1)?.textContent?.trim(),d=i.querySelector(n.titleDiv)?.textContent?.trim(),U=o??d??"",h=i.querySelector(n.source)?.textContent?.trim()??"",l=i.querySelector(n.platformBadge)?.textContent?.trim()??"",u=i.querySelector(n.ytChannel)?.textContent?.trim()??"",c=i.querySelector(n.ytDate)?.textContent?.trim()??"",w=i.querySelector(n.authorNote)?.textContent?.trim()??null,g=i.querySelector(n.popularCommentLabel),f=null;if(g){let C=g.nextSibling;for(;C;){let H=C.textContent?.trim();if(H){f=H;break}C=C.nextSibling}}let M=Array.from(i.querySelectorAll("span")),p=M.find(C=>/^\d+:\d+$/.test(C.textContent?.trim()??""))?.textContent?.trim()??null,b=M.map(C=>C.textContent?.trim()??"").filter(C=>/\d/.test(C)&&(C.includes("comment")||C.includes("reaction")||C.includes("view")||C.includes("like")||C.includes("share")))[0]??"",x=M.map(C=>C.textContent?.trim()??"").filter(C=>/\d+ (day|week|month|year|hour)s? ago|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/.test(C)),k=c||(x[0]??""),B=l||(u?"YouTube":""),N=u||h,m="unknown",v=B.toLowerCase(),A=N.toLowerCase(),y=h.toLowerCase();return v.includes("reddit")||A.startsWith("r/")?m="reddit":v.includes("facebook")||y.includes("facebook")?m="facebook":v.includes("instagram")||y.includes("instagram")?m="instagram":v.includes("tiktok")||y.includes("tiktok")?m="tiktok":v.includes("youtube")||u?m="youtube":m="news",{type:m,title:U,url:S,source:N,platform:B,popularComment:f,engagement:b,date:k,duration:p,authorNote:w}}):[]},t)}async function Ua(e){let t=Hn,n=await e.evaluate(i=>{let s=[],S=0;return document.querySelectorAll(i.result).forEach(o=>{let d=o.querySelector(i.title);if(!d)return;let U=d.textContent?.trim()??"",r=d.closest("a")?.href??"";if(!U||!r)return;S++;let l=o.querySelector(i.cite)?.textContent?.trim()??null,u=o.querySelector(i.snippet)?.textContent?.trim()??null,c=!!o.querySelector(i.redditCite),w=o.querySelector(i.ratingWrap),g=w?{value:w.querySelector(i.ratingValue)?.textContent?.trim()??"",count:w.querySelector(i.reviewCount)?.textContent?.trim()??""}:null,f="";try{f=new URL(r).hostname.replace(/^www\./,"")}catch{f=o.querySelector(i.siteName)?.textContent?.trim()??""}s.push({position:S,title:U,url:r,domain:f,cite:l,snippet:u,isRedditStyle:c,inlineRating:g})}),s},t),a=typeof e.url=="function"?e.url():"https://www.google.com/";return n.flatMap(i=>{let s=Dt(i.url,a);if(!s)return[];let S=i.domain;try{S=new URL(s.resolvedUrl??s.rawUrl).hostname.replace(/^www\./,"")}catch{}return[{...i,...s,domain:S}]})}async function ha(e){let t=Fn;return e.evaluate(n=>{let a=[],i=null;return document.querySelectorAll('[role="heading"]').forEach(s=>{!i&&s.textContent?.includes(n.headingText)&&(i=s.closest("[data-hveid]"))}),i&&i.querySelectorAll(n.card).forEach((s,S)=>{let o=s.querySelector(n.name)?.textContent?.trim()??"";if(!o)return;let d=s.querySelector(n.ratingValue)?.textContent?.trim()??null,U=s.querySelector(n.reviewCount)?.textContent?.trim()??null,h=U?U.replace(/[()]/g,"").trim():null,r=s.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;if(!r)for(let g of Array.from(s.querySelectorAll("a[href]"))){let f=g.href.match(/[?&]cid=(\d+)/);if(f){r=f[1];break}let M=g.href.match(/!1s0x[0-9a-f]+:0x([0-9a-f]+)/i);if(M){try{r=BigInt("0x"+M[1]).toString()}catch{}if(r)break}}let l=[];s.querySelectorAll("div, span").forEach(g=>{let f=Array.from(g.childNodes).filter(M=>M.nodeType===3).map(M=>M.textContent?.trim()??"").filter(M=>M.length>1&&M.length<120).join(" ");f&&!l.includes(f)&&l.push(f)});let u=Array.from(s.querySelectorAll("a[href]")),c=u.find(g=>g.href.includes("google.com/maps"))?.href??null,w=u.find(g=>!g.href.includes("google.com")&&g.href.startsWith("http"))?.href??null;a.push({position:S+1,name:o,cid:r,rating:d,reviewCount:h,metadata:l,websiteUrl:w,directionsUrl:c})}),a},t)}async function ua(e){return e.evaluate(()=>{let t=new Set,n=new Set,a=new Set,i=new Map;function s(o){let d=[".OSrXXb",".dbg0pd",".tzt0oe",'[role="heading"]',"h3"];for(let U of d){let h=o.querySelector(U);if(h?.textContent?.trim())return h.textContent.trim()}return""}document.querySelectorAll('[id^="pv-/g/"]').forEach(o=>{let d=o.getAttribute("id");if(!d)return;let U=d.replace("pv-","");t.add(U);let h=s(o),l=o.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;l&&n.add(l),h&&i.set(U,{name:h,kgId:U,cid:l,gcid:null})}),document.querySelectorAll("[data-mid]").forEach(o=>{let d=o.getAttribute("data-mid");if(d?.startsWith("/g/")&&(t.add(d),!i.has(d))){let U=s(o);U&&i.set(d,{name:U,kgId:d,cid:null,gcid:null})}}),document.querySelectorAll(".w7Dbne").forEach(o=>{let U=o.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;if(!U)return;n.add(U);let h=o.querySelector(".OSrXXb")?.textContent?.trim()??"";if(!h)return;let r=o.querySelector('[id^="pv-/g/"]'),l=r?r.getAttribute("id").replace("pv-",""):null,u=l??`cid:${U}`;if(i.has(u)){let c=i.get(u);c.cid||i.set(u,{...c,cid:U})}else i.set(u,{name:h,kgId:l,cid:U,gcid:null})}),document.querySelectorAll("a[data-cid]").forEach(o=>{let d=o.getAttribute("data-cid");if(!d)return;if(n.add(d),![...i.values()].some(h=>h.cid===d)){let h=o.parentElement,r="";for(let l=0;l<8&&h;l++){let u=h.querySelector('.OSrXXb, .dbg0pd, [role="heading"], h3');if(u?.textContent?.trim()){r=u.textContent.trim();break}h=h.parentElement}r&&i.set(`cid:${d}`,{name:r,kgId:null,cid:d,gcid:null})}});let S=Array.from(document.querySelectorAll("script:not([src])")).map(o=>o.textContent??"").filter(o=>o.length>1e4).join(`
|
|
21737
|
+
`);for(let o of S.matchAll(/\/g\/[a-zA-Z0-9_-]{5,20}/g))t.add(o[0]);for(let o of S.matchAll(/gcid:[a-zA-Z0-9_]+/g))a.add(o[0]);for(let o of S.matchAll(/0x[0-9a-f]+:0x([0-9a-f]+)/gi))try{n.add(BigInt("0x"+o[1]).toString())}catch{}return{entities:[...i.values()],kgIds:[...t],cids:[...n],gcids:[...a]}})}function ca(e,t){let n=new Set(e.cids),a=e.entities.map(i=>({...i}));for(let i of t){if(!i.cid)continue;n.add(i.cid);let s=i.name.toLowerCase().trim(),S=a.find(o=>o.name.toLowerCase().trim()===s);S?S.cid||(S.cid=i.cid):a.find(o=>o.cid===i.cid)||a.push({name:i.name,kgId:null,cid:i.cid,gcid:null})}return{...e,entities:a,cids:[...n]}}var Bi=String.raw`^(?:an error has occurred(?:[.!…]\s*)?(?:please try again later[.!…]?)?|loading|please wait|try again|something went wrong)[.!…\s]*$`,Hi=700,Fi=1e3,Ri=1400,wa=900,Di=3,ga=250,ie=class{constructor(t,n,a,i){this.driver=t;this.reporter=n;this.onPaaProgress=a;this.onProviderSession=i}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 i of[...t,...n]){let s=a.get(i.rawUrl);if(!s){a.set(i.rawUrl,i);continue}let S=i.resolutionStatus==="resolved"&&s.resolutionStatus!=="resolved"?i:s,o=i.description?.trim()&&!s.description?.trim()?i:s.description?.trim()?s:S;a.set(i.rawUrl,{...S,title:o.title??S.title??s.title??i.title,site:S.site??s.site??i.site,...(o.description??s.description??i.description)!==void 0?{description:o.description??s.description??i.description}:{}})}return[...a.values()]}normalizeAICitations(t,n){let a=new Set;return n.flatMap(i=>{let s=Dt(i.rawHref??i.href,t);if(!s||a.has(s.rawUrl))return[];a.add(s.rawUrl);let{url:S,...o}=s;return[{...o,text:i.text,href:S}]})}async resolveMaterialLinks(t,n,a,i,s){let S=Date.now(),o=[...n.flatMap(c=>c.sources??[]),...a,...i.citations.map(({text:c,href:w,...g})=>({...g,url:w})),...s.citations.map(({text:c,href:w,...g})=>({...g,url:w}))],d=new Map(o.map(c=>[c.rawUrl,c])),U=0,h=await oa(t,o,{onNetworkAudit:c=>{U=c.nonGoogleRequestsObserved}}),r=c=>({...c,...h.get(c.rawUrl)??c});for(let c of n){c.sources=(c.sources??[]).map(r);let w=c.sources[0];c.source_title=w?.title??c.source_title,c.source_site=w?.site??c.source_site,c.source_cite=w?.url??c.source_cite}for(let c=0;c<a.length;c++){let w=r(a[c]);if(w.resolvedUrl)try{w.domain=new URL(w.resolvedUrl).hostname.replace(/^www\./,"")}catch{}a[c]=w}let l=c=>{let w=r({url:c.href,rawUrl:c.rawUrl,resolvedUrl:c.resolvedUrl,linkType:c.linkType,resolutionStatus:c.resolutionStatus}),{url:g,...f}=w;return{...f,text:c.text,href:g}};i.citations=i.citations.map(l),s.citations=s.citations.map(l);let u=[...h.values()];this.linkDiagnostics={linkCandidatesObserved:d.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,w)=>c+(w.sources??[]).length,0),aiOverviewLabelValidated:i.detected},this.phaseTimings.linkResolutionMs=(this.phaseTimings.linkResolutionMs??0)+(Date.now()-S)}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 tt}async throwIfCaptcha(t,n){if(await t.locator(V.captchaMarker).count().catch(()=>0)>0)throw new z(`${n} returned a CAPTCHA \u2014 retrying with a fresh session.`)}async extractVisibleItems(t,n){let a=await t.evaluate(ae,{selectors:V,onlyQuestion:n}),i=typeof t.url=="function"?t.url():"https://www.google.com/";return a.flatMap(s=>{let S=[],o=new Set;for(let r of s.sources){let l=Dt(r.rawHref,i);if(!l||o.has(l.rawUrl))continue;o.add(l.rawUrl);let u=s.sourceSite??null;try{u||=new URL(l.resolvedUrl??l.rawUrl).hostname.replace(/^www\./,"")}catch{}S.push({...l,title:r.title||s.sourceTitle||null,site:u,...r.description?{description:r.description}:{}})}let d=S[0],U={questionId:ft(s.question),googleLinkId:s.googleLinkId,googleEvidenceId:s.googleEvidenceId,question:s.question,answer:Qn(s.answer,s.question),sourceTitle:d?.title??s.sourceTitle,sourceSite:d?.site??s.sourceSite,sourceCite:d?.url,sources:S,...s.answerExpansionIncomplete?{answerExpansionIncomplete:!0}:{}},h=gn.safeParse(U);return h.success?[h.data]:(console.warn("[PAAExtractor] item parse failed:",s.question,h.error.issues[0]?.message),[])})}jitteredDelayMs(t,n){return t+Math.floor(Math.random()*(n-t+1))}async clickItem(t,n){try{await t.locator(`${V.item}[data-q="${n}"], ${V.item}[data-initq="${n}"]`).first().click()}catch{}}toFlatRow(t,n,a,i){return{seed_query:i,question_id:t.questionId??ft(t.question),google_link_id:t.googleLinkId??"",google_evidence_id:t.googleEvidenceId??"",question:t.question,answer:t.answer??"",...t.answerExpansionIncomplete?{answerExpansionIncomplete:!0}:{},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(o=>this.normalizeQuestion(o.question)===n);if(a<0)return this.collectedRows.push({...t}),!0;let i=this.collectedRows[a],s={...i,...t,answer:t.answer||i.answer,answerExpansionIncomplete:t.answer?t.answerExpansionIncomplete:i.answerExpansionIncomplete,source_title:t.source_title||i.source_title,source_site:t.source_site||i.source_site,source_cite:t.source_cite||i.source_cite,sources:this.mergePaaSources(i.sources,t.sources),extracted_at:t.extracted_at||i.extracted_at},S=s.answerExpansionIncomplete!==i.answerExpansionIncomplete||s.answer!==i.answer||s.source_title!==i.source_title||s.source_site!==i.source_site||s.source_cite!==i.source_cite||JSON.stringify(s.sources)!==JSON.stringify(i.sources);return S&&(this.collectedRows[a]=s),S}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(d=>({...d})),a=this.checkpointMaterial,i=t.questionsOnly?0:n.filter(d=>!d.answer?.trim()).length,s=t.questionsOnly?0:n.filter(d=>(d.sources??[]).length===0).length,S=t.questionsOnly?0:n.filter(d=>d.answerExpansionIncomplete).length,o={seed:t.seed,totalQuestions:n.length,maxDepthReached:n.reduce((d,U)=>Math.max(d,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:i>0||s>0||S>0?"partial":"complete",completionReason:"The browser attempt ended before frontier exhaustion could be proven."},completeness:{...this.completeness,paaWithoutAnswer:i,paaWithoutSource:s,paaIncompleteAnswers:S,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:o}}async runBFS(t,n,a){await t.waitForTimeout(700);let i=new Set,s=new Set,S=[];this.clickedQuestions=new Set,this.interactionObservations=[],this.phaseTimings={};let o=new Set,d=new Map,U=new Set,h=new Set,r=new Map,l=new Set,u=2,c=3,w=0,g={sel:V.item,dataQ:V.itemDataQ,dataInitQ:V.itemDataInitQ,questionEl:V.itemQuestionEl,answerSel:V.answerContainer,expandedClass:V.expandedClass,clickTarget:V.clickTarget,answerPlaceholderPattern:Bi,questionsOnly:n.questionsOnly,sourceSel:"a[href]"},f=()=>t.evaluate(({sel:k,dataQ:B,dataInitQ:N,questionEl:m,expandedClass:v,clickTarget:A,answerSel:y,answerPlaceholderPattern:C,questionsOnly:H})=>{let O=I=>{if(!I)return"";let T=[];for(let L of I.childNodes){if(L.nodeType===Node.TEXT_NODE){let nt=L.textContent?.trim();nt&&T.push(nt);continue}if(L.nodeType!==Node.ELEMENT_NODE)continue;let J=L;if(J.tagName==="STYLE"||J.tagName==="SCRIPT"||J.getAttribute("aria-hidden")==="true")continue;let Y=O(J);Y&&T.push(Y)}return T.join(" ").replace(/\s+/g," ").trim()};return Array.from(document.querySelectorAll(k)).map((I,T)=>{let L=O(I.querySelector(y)).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(),J=I.classList.contains(v)||I.querySelector(A)?.getAttribute("aria-expanded")==="true",Y=L.length>=10&&!new RegExp(C,"i").test(L);return{q:I.getAttribute(B)||I.getAttribute(N)||I.querySelector(m)?.innerText?.trim()||"",done:J&&(H||Y),expanded:J,index:T}}).filter(I=>I.q)},g),M=async(k,B,N,m,v,A)=>{let y=Date.now(),C={id:`${A}:${ft(k)}:${v}`,questionId:ft(k),question:k,batchNumber:A,controlAttempt:v,observedAt:new Date(y).toISOString(),beforeQuestionCount:B,expandedBefore:m},H=N>=0?t.locator(g.sel).nth(N).locator(g.clickTarget):null,O=null,I=H?await(async()=>(m&&(await H.click({timeout:wa,force:!0}),await t.waitForTimeout(120)),await H.click({timeout:wa,force:!0}),!0))().catch(Q=>(O=Q instanceof Error&&(Q.name==="TimeoutError"||/timeout/i.test(Q.message))?"click_ack_timeout":"click_failed",!1)):!1,T=Date.now()-y;if(!I&&O!=="click_ack_timeout")return{dispatched:!1,confirmed:!1,observation:{...C,dispatched:!1,outcome:"dispatch_failed",confirmationSignals:[],confirmationCheckpointMs:null,confirmedAtMs:null,dispatchDurationMs:T,totalDurationMs:T,afterQuestionCount:B,newQuestionCount:0,expandedAfter:m,answerObserved:!1,sourceCount:0,errorCode:N<0?"control_missing":O??"click_failed"}};let L={exists:!0,expanded:m,answerReady:!1,sourceCount:0,questionCount:B},J=[],Y=null,nt=null,D=!1;for(let Q of[Hi,Fi,Ri]){let G=y+Q-Date.now();if(G>0&&await t.waitForTimeout(G),L=await t.evaluate(({sel:F,dataQ:Z,dataInitQ:at,questionEl:pt,expandedClass:R,clickTarget:rt,answerSel:it,answerPlaceholderPattern:mt,sourceSel:K,target:_})=>{let dt=Nt=>{if(!Nt)return"";let re=[];for(let Et of Nt.childNodes){if(Et.nodeType===Node.TEXT_NODE){let _e=Et.textContent?.trim();_e&&re.push(_e);continue}if(Et.nodeType!==Node.ELEMENT_NODE)continue;let Vt=Et;if(Vt.tagName==="STYLE"||Vt.tagName==="SCRIPT"||Vt.getAttribute("aria-hidden")==="true")continue;let Je=dt(Vt);Je&&re.push(Je)}return re.join(" ").replace(/\s+/g," ").trim()},At=Array.from(document.querySelectorAll(F)),Gt=At.find(Nt=>(Nt.getAttribute(Z)||Nt.getAttribute(at)||Nt.querySelector(pt)?.innerText?.trim())===_);if(!Gt)return{exists:!1,expanded:!1,answerReady:!1,sourceCount:0,questionCount:At.length};let Ma=Gt.classList.contains(R)||Gt.querySelector(rt)?.getAttribute("aria-expanded")==="true",Ve=Gt.querySelector(it),Ye=dt(Ve).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(),Ke=Ye.length>=10&&!new RegExp(mt,"i").test(Ye);return{exists:!0,expanded:Ma,answerReady:Ke,sourceCount:Ke?Ve?.querySelectorAll(K).length??0:0,questionCount:At.length}},{...g,target:k}).catch(()=>L),J=[...L.expanded?["expanded"]:[],...L.answerReady?["answer"]:[],...L.sourceCount>0?["source"]:[],...L.questionCount>B?["question_growth"]:[]],L.answerReady||L.sourceCount>0||L.questionCount>B){D=!0,Y=Q,nt=Date.now()-y;break}}let yt=Date.now()-y,ot={...C,dispatched:I,outcome:D?"confirmed":I?"unconfirmed":"dispatch_failed",confirmationSignals:J,confirmationCheckpointMs:Y,confirmedAtMs:nt,dispatchDurationMs:T,totalDurationMs:yt,afterQuestionCount:L.questionCount,newQuestionCount:Math.max(0,L.questionCount-B),expandedAfter:L.expanded,answerObserved:L.answerReady,sourceCount:L.sourceCount,errorCode:I?D?null:L.exists?"confirmation_timeout":"control_missing":O};return{dispatched:I,confirmed:D,observation:ot}},p=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 xt(this.paaLifecycle.completionReason);this.throwIfAborted(a);let k=await f(),B=!1;for(let y of k)s.has(y.q)||(s.add(y.q),S.push(y.q),S.length<=n.maxQuestions&&(B=this.upsertCollectedRow(this.toFlatRow({questionId:ft(y.q),googleLinkId:null,googleEvidenceId:null,question:y.q,sources:[]},1,null,n.query))||B)),y.done&&U.add(y.q);if(this.paaLifecycle={...this.paaLifecycle,questionsFound:Math.min(S.length,n.maxQuestions),targetStatus:S.length>=n.maxQuestions?"met":"not_met",knownQuestions:S.length,processedQuestions:U.size,failedInteractions:h.size,visibleControls:k.length},B&&await this.emitProgress("discovered"),n.questionsOnly&&s.size>=n.maxQuestions){this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"target_reached",targetStatus:"met",completionReason:"The requested unique-question count was observed."};break}if(!n.questionsOnly&&s.size>=n.maxQuestions){let y=!1,C=new Set(S.slice(0,n.maxQuestions)),H=await this.extractVisibleItems(t),O=H.filter(I=>C.has(I.question)&&I.answerExpansionIncomplete&&!l.has(I.question));for(let I of O)l.add(I.question),await Le(t,I.question,{selectors:V,deadlineMs:n.softDeadlineMs,signal:a},ae);O.length&&(H=await this.extractVisibleItems(t));for(let I of H){if(!C.has(I.question))continue;let T=r.get(I.question),L={...I,answer:I.answer||T?.answer,answerExpansionIncomplete:I.answer?I.answerExpansionIncomplete:T?.answerExpansionIncomplete,sourceTitle:I.sourceTitle??T?.sourceTitle,sourceSite:I.sourceSite??T?.sourceSite,sourceCite:I.sourceCite??T?.sourceCite,sources:this.mergePaaSources(T?.sources,I.sources)};r.set(I.question,L),y=this.upsertCollectedRow(this.toFlatRow(L,1,null,n.query))||y}if(y&&await this.emitProgress("answer_captured"),[...C].every(I=>{let T=r.get(I);return!!(T?.answer?.trim()&&T.sources.length>0&&!T.answerExpansionIncomplete)})){h.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 N=new Set(S.slice(0,n.maxQuestions)),m=k.filter(y=>N.has(y.q)&&!y.done&&(d.get(y.q)??0)<u&&!o.has(y.q)),v=m.slice(-Di);if(this.paaLifecycle={...this.paaLifecycle,eligibleControls:m.length},v.length===0){if(s.size>=n.maxQuestions){this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"target_reached",targetStatus:"met",completionReason:"The requested unique-question count was observed."};break}let y=new Set(k.map(H=>H.q)),C=S.slice(0,n.maxQuestions).filter(H=>!U.has(H)&&(h.has(H)||!y.has(H)));if(C.length>0)throw this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"interrupted",failedInteractions:new Set([...h,...C]).size,completionReason:"At least one known PAA control failed or disappeared before it could be confirmed."},await this.emitProgress("expansion_finished"),new xt(this.paaLifecycle.completionReason);for(let H=1;H<=c;H++){this.throwIfAborted(a),await this.throwIfCaptcha(t,"Google PAA exhaustion confirmation"),await t.mouse.wheel(0,320);let O=await t.waitForFunction(({sel:T,min:L})=>document.querySelectorAll(T).length>L,{sel:V.item,min:k.length},{timeout:1500,polling:100}).catch(()=>null);if(this.paaLifecycle={...this.paaLifecycle,noGrowthConfirmations:H},O||(await f()).some(T=>!s.has(T.q)))continue t}this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"frontier_exhausted",targetStatus:"not_met",failedInteractions:0,noGrowthConfirmations:c,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"),w+=1;for(let y of v){if(this.reporter.onDepth(++p),(d.get(y.q)??0)>0){let C=this.paaLifecycle.retryBreakdown.controlRetries+1;this.paaLifecycle={...this.paaLifecycle,automaticRetries:C+this.paaLifecycle.retryBreakdown.browserRetries+this.paaLifecycle.retryBreakdown.runtimeRecoveries,retryBreakdown:{...this.paaLifecycle.retryBreakdown,controlRetries:C}}}d.set(y.q,(d.get(y.q)??0)+1)}let A=await Promise.all(v.map(async y=>({target:y,result:await M(y.q,k.length,y.index,y.expanded,d.get(y.q)??1,w)})));for(let{target:y,result:C}of A)(C.dispatched||C.confirmed)&&this.clickedQuestions.add(y.q),this.interactionObservations.push(C.observation);if(this.interactionObservations.length>ga&&this.interactionObservations.splice(0,this.interactionObservations.length-ga),!n.questionsOnly){let y=new Set(v.map(C=>C.q));for(let C of await this.extractVisibleItems(t))y.has(C.question)&&(r.set(C.question,C),this.upsertCollectedRow(this.toFlatRow(C,1,null,n.query))&&await this.emitProgress("answer_captured"))}for(let{target:y,result:C}of A){let H=r.get(y.q);C.confirmed||H?.answer?.trim()?(U.add(y.q),h.delete(y.q)):(d.get(y.q)??0)>=u&&(h.add(y.q),o.add(y.q))}this.paaLifecycle={...this.paaLifecycle,processedQuestions:U.size,failedInteractions:h.size,noGrowthConfirmations:0,dispatchedInteractions:this.interactionObservations.filter(y=>y.dispatched).length,confirmedInteractions:this.interactionObservations.filter(y=>y.outcome==="confirmed").length,unconfirmedInteractions:this.interactionObservations.filter(y=>y.outcome!=="confirmed").length},await this.emitProgress("click_observed")}let P=n.questionsOnly?new Map:new Map(r);n.questionsOnly||await this.fillIncompleteItems(t,S,P,n,o,a);let b=[];for(let k of S){if(b.length>=n.maxQuestions)break;let B=this.normalizeQuestion(k);if(i.has(B))continue;i.add(B);let N=P.get(k);if(N){let m=this.toFlatRow(N,1,null,n.query);this.upsertCollectedRow(m),b.push(m),this.reporter.onQuestion({questionId:N.questionId,googleLinkId:N.googleLinkId,googleEvidenceId:N.googleEvidenceId,question:N.question,answer:N.answer??null,sourceTitle:N.sourceTitle??null,sourceSite:N.sourceSite??null,sourceCite:N.sourceCite??null,sources:N.sources,...N.answerExpansionIncomplete?{answerExpansionIncomplete:!0}:{},depth:1,parentQuestion:null,children:[]})}else{let m=this.toFlatRow({questionId:ft(k),googleLinkId:null,googleEvidenceId:null,question:k,answer:void 0,sourceTitle:void 0,sourceSite:void 0,sourceCite:void 0,sources:[]},1,null,n.query);this.upsertCollectedRow(m),b.push(m)}}this.completeness.paaWithoutAnswer=n.questionsOnly?0:b.filter(k=>!k.answer).length,this.completeness.paaWithoutSource=n.questionsOnly?0:b.filter(k=>(k.sources??[]).length===0).length,this.completeness.paaIncompleteAnswers=n.questionsOnly?0:b.filter(k=>k.answerExpansionIncomplete).length,this.completeness.paaRequested=n.maxQuestions,this.completeness.paaReturned=b.length,this.completeness.paaUnique=i.size;let x=!n.questionsOnly&&(this.completeness.paaWithoutAnswer>0||this.completeness.paaWithoutSource>0||this.completeness.paaIncompleteAnswers>0);return this.paaLifecycle={...this.paaLifecycle,questionsFound:b.length,targetStatus:b.length>=n.maxQuestions?"met":"not_met",materialStatus:x?"partial":"complete",processedQuestions:U.size,failedInteractions:h.size},await this.emitProgress("fill_incomplete"),await this.emitProgress("expansion_finished"),b}async fillIncompleteItems(t,n,a,i,s,S){let o=new Set(n.slice(0,i.maxQuestions)),d=r=>!r?.answer||(r.sources??[]).length===0||!!r.answerExpansionIncomplete,U=new Set([...o].filter(r=>d(a.get(r)))),h=new Set([...U].filter(r=>!a.get(r)?.answer));if(U.size!==0){for(let r of U){if(i.softDeadlineMs&&Date.now()>=i.softDeadlineMs)break;let l=(await this.extractVisibleItems(t,r))[0];if(l?.answerExpansionIncomplete&&(await Le(t,r,{selectors:V,deadlineMs:i.softDeadlineMs,signal:S},ae),l=(await this.extractVisibleItems(t,r))[0]),!l)continue;let u=a.get(r);a.set(r,{...l,answer:l.answer||u?.answer,answerExpansionIncomplete:l.answer?l.answerExpansionIncomplete:u?.answerExpansionIncomplete,sourceTitle:l.sourceTitle??u?.sourceTitle,sourceSite:l.sourceSite??u?.sourceSite,sourceCite:l.sourceCite??u?.sourceCite,sources:this.mergePaaSources(u?.sources,l.sources)});let c=a.get(r);c&&this.upsertCollectedRow(this.toFlatRow(c,1,null,i.query))&&await this.emitProgress("fill_incomplete")}this.completeness.paaAnswersRecovered=[...h].filter(r=>a.get(r)?.answer).length}}async reExpandCollapsedItems(t){let n=`${V.item}:not(.${V.expandedClass}) ${V.clickTarget}`,a=await t.locator(n).count().catch(()=>0);if(a===0)return!1;for(let i=0;i<a;i++)try{let s=t.locator(n).first();await s.scrollIntoViewIfNeeded(),await s.click({force:!0}),await t.waitForTimeout(this.jitteredDelayMs(300,500))}catch{}return!0}extractVideos(t){return ra(t)}extractForums(t){return da(t)}extractShortVideos(t,n){return la(t,n,(a,i)=>this.throwIfCaptcha(a,i))}extractWhatPeopleSaying(t){return Sa(t)}extractOrganicResults(t){return Ua(t)}extractLocalPack(t){return ha(t)}extractEntityIds(t){return ua(t)}mergeLocalPackIntoEntities(t,n){return ca(t,n)}async extractAISurfaces(t,n){let a=await t.evaluate(Zn,{aio:On,aim:Bn,expandWaitMs:1500}),i=typeof t.url=="function"?t.url():"https://www.google.com/",s={surface:a.surface,aiOverview:{...a.aiOverview,citations:this.normalizeAICitations(i,a.aiOverview.citations)},aiMode:{...a.aiMode,citations:this.normalizeAICitations(i,a.aiMode.citations)}};if(!s.aiOverview.detected)return this.completeness.aioShareCaptured=null,s;let S=this.aioShareUrlEarly??await this.captureAIOverviewShareUrl(t,n).catch(()=>null);return this.completeness.aioShareCaptured=S!==null,{...s,aiOverview:{...s.aiOverview,shareUrl:S}}}async captureAIOverviewShareUrl(t,n){if(n?.softDeadlineMs&&Date.now()>=n.softDeadlineMs||!await t.evaluate(()=>{let s=Array.from(document.querySelectorAll('h1,h2,h3,[role="heading"],div')).filter(S=>(S.textContent||"").trim()==="AI Overview");for(let S of s){let o=S;for(let d=0;d<8&&o;d++){let U=o.querySelector('[aria-label="Share"]');if(U)return U.scrollIntoView({block:"center"}),U.click(),!0;o=o.parentElement}}return!1}).catch(()=>!1))return null;let i=null;try{i=await(await t.waitForFunction(()=>{let S=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT);for(;S.nextNode();){let o=(S.currentNode.textContent||"").match(/https:\/\/share\.google\/aimode\/\S+/);if(o)return o[0]}return!1},void 0,{timeout:4500,polling:250})).jsonValue()}catch{i=null}return await t.keyboard.press("Escape").catch(()=>{}),i}buildTree(t,n){let a=[],i=new Map;for(let s of t){let S={questionId:s.question_id,googleLinkId:s.google_link_id||null,googleEvidenceId:s.google_evidence_id||null,question:s.question,answer:s.answer||null,...s.answerExpansionIncomplete?{answerExpansionIncomplete:!0}:{},sourceTitle:s.source_title||null,sourceSite:s.source_site||null,sourceCite:s.source_cite||null,sources:s.sources??[],depth:s.depth,parentQuestion:s.parent_question||null,children:[]};i.set(s.question,S)}for(let s of i.values())s.parentQuestion&&i.has(s.parentQuestion)?i.get(s.parentQuestion).children.push(s):a.push(s);return a}getBrowserDebugSnapshot(){return this.driver.getDebugSnapshot()}buildHarvestDebugSnapshot(t,n,a,i,s){if(t.debug)return{enabled:!0,request:{query:t.query,locationInput:t.location??null,canonicalLocation:n,locationResolved:s?s.matched:null,locationMatchSource:s?s.source:null,locationAmbiguousCandidates:s?s.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(),...i?{locationEvidence:i}:{}}}async captureSecondOrganicPage(t,n,a){if(this.throwIfAborted(a),!n.serpOnly&&!this.driver.withTemporaryPage)return{organic:[],status:"failed",failureCode:"unsupported_driver"};let i;try{let s=new URL(t.url()),S=U=>{try{let h=new URL(U,s);return s.origin==="https://www.google.com"&&h.origin===s.origin&&!h.username&&!h.password&&h.pathname==="/search"&&h.searchParams.getAll("q").length===1&&h.searchParams.get("q")===n.query&&h.searchParams.getAll("start").length===1&&h.searchParams.get("start")==="10"&&(!h.searchParams.has("num")||h.searchParams.get("num")==="10")&&["gl","hl"].every(r=>!h.searchParams.has(r)||h.searchParams.getAll(r).length===1&&h.searchParams.get(r)===n[r])&&["uule","tbs","udm","tbm","pws"].every(r=>h.searchParams.getAll(r).length<=1&&h.searchParams.get(r)===s.searchParams.get(r))}catch{return!1}},o=await t.evaluate(U=>document.querySelector(U?'a[aria-label="Page 2"], a#pnnext, a[rel="next"]':'a#pnnext, a[rel="next"]')?.getAttribute("href")??null,n.serpOnly);if(!o)return{organic:[],status:"unavailable",failureCode:"missing_next"};if(!S(o))return{organic:[],status:"unavailable",failureCode:"invalid_next"};if(n.serpOnly){let U=t.locator('a[aria-label="Page 2"], a#pnnext, a[rel="next"]').first();if(await U.scrollIntoViewIfNeeded({timeout:1e4}),await U.click({timeout:2e4}),this.throwIfAborted(a),await this.throwIfCaptcha(t,"Google SERP page 2"),!S(t.url()))throw i="invalid_next",new Error("Invalid pagination landing");let h=await this.extractOrganicResults(t);return h.length>0?{organic:h.map(r=>({...r,position:r.position+10})),status:"captured"}:{organic:[],status:"unavailable",failureCode:"empty_page"}}let d=await this.driver.withTemporaryPage(async U=>{if(await U.route("**/*",async h=>{let r=h.request();r.isNavigationRequest()&&r.frame()===U.mainFrame()&&!S(r.url())?(i=/^https:\/\/www\.google\.com\/sorry(?:\/|\?)/.test(r.url())?"captcha":"invalid_next",await h.abort("blockedbyclient")):await h.fallback()}),await U.goto(new URL(o,s).href,{waitUntil:"domcontentloaded",timeout:2e4}),this.throwIfAborted(a),await this.throwIfCaptcha(U,"Google SERP page 2"),!S(U.url()))throw i="invalid_next",new Error("Invalid pagination landing");return this.extractOrganicResults(U)},a);return this.throwIfAborted(a),d.length>0?{organic:d.map(U=>({...U,position:U.position+10})),status:"captured"}:{organic:[],status:"unavailable",failureCode:"empty_page"}}catch(s){if(this.throwIfAborted(a),s instanceof tt)throw s;return{organic:[],status:"failed",failureCode:i??(s instanceof z?"captcha":s instanceof Error&&(s.name==="TimeoutError"||/timed? ?out/i.test(s.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 i=t.device==="mobile",s={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:i?{width:390,height:844}:{width:1280,height:800},locale:`${t.hl}-${t.gl.toUpperCase()}`,deviceScaleFactor:i?3:1,isMobile:i,hasTouch:i,debug:t.debug,operationDeadlineMs:t.softDeadlineMs},S=0,o=[];try{this.throwIfAborted(n);let d=Date.now();await this.driver.launch(s),this.phaseTimings.providerConnectMs=Date.now()-d;let U=this.driver.getProviderSessionMetadata();if(U?.providerSessionId&&this.onProviderSession)try{await this.onProviderSession(U)}catch(G){console.warn(JSON.stringify({event:"paa_provider_session_sink_failed",provider:U.provider,message:G instanceof Error?G.message:String(G)}))}this.throwIfAborted(n);let h=t.location?pe(t.location):null,r=t.location?h?.canonical??t.location:null,l=r?vn(r):null,u=t,c=t.includeAllSerpFeatures,w=c||t.includeLocalPack,g=c||t.includeForums,f=c||t.includeVideos,M=c||t.includeAiOverview,p=c||t.includeWhatPeopleSaying,P={surface:"web",aiOverview:{detected:!1,text:null,citations:[]},aiMode:{detected:!1,text:null,citations:[]}},b=Date.now(),{hasPaa:x}=await this.driver.navigateToSERP(u.query,l,t.gl,t.hl,{...de(t.recency)?{tbs:de(t.recency)}:{},debug:t.debug,purpose:t.serpOnly?"serp":"paa",pages:t.pages===2?2:1,...t.softDeadlineMs?{deadlineMs:t.softDeadlineMs}:{},...n?{signal:n}:{}});this.phaseTimings.navigationMs=Date.now()-b,this.throwIfAborted(n);let k=this.driver.getPage();if(await this.throwIfCaptcha(k,"Google SERP"),x||(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 G=Date.now(),F=x?await this.runBFS(k,u,n):[];this.phaseTimings.paaExpansionMs=Date.now()-G,await this.resolveMaterialLinks(k,F,[],P.aiOverview,P.aiMode);let Z={seed:u.query,totalQuestions:F.length,maxDepthReached:F.reduce((at,pt)=>Math.max(at,pt.depth),0),durationMs:Date.now()-a,errorCount:S};return this.reporter.onComplete(Z),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:x?"paa_found":"no_paa",...x?{}:{noPaaObserved:!0},problem:null,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,r,l,void 0,h)}:{}},totalQuestions:F.length,surface:"web",aiOverview:{detected:!1,text:null,citations:[]},aiMode:{detected:!1,text:null,citations:[]},whatPeopleSaying:[],tree:this.buildTree(F,u.query),flat:F,videos:[],forums:[],organicResults:[],localPack:[],entityIds:{entities:[],kgIds:[],cids:[],gcids:[]},stats:Z}}if(M&&(this.aioShareUrlEarly=await this.captureAIOverviewShareUrl(k,t).catch(()=>null)),t.serpOnly){let G=Date.now(),[F,Z,at]=await Promise.all([this.extractOrganicResults(k),w?this.extractLocalPack(k):Promise.resolve([]),this.extractEntityIds(k)]),pt=this.mergeLocalPackIntoEntities(at,Z),R=M?await this.extractAISurfaces(k,t):P;this.phaseTimings.serpParseMs=Date.now()-G;let rt=t.debug?Ht(r,F,Z):void 0,it=F,mt={requestedPages:(t.pages??1)>=2?2:1,capturedPages:1,page2Status:(t.pages??1)>=2?"not_attempted":"not_requested",page1OrganicCount:F.length,page2OrganicCount:0};if((t.pages??1)>=2){let _=await this.captureSecondOrganicPage(k,u,n);it=[...F,..._.organic],mt={...mt,capturedPages:_.status==="captured"?2:1,page2Status:_.status,page2OrganicCount:_.organic.length,..._.failureCode?{failureCode:_.failureCode}:{}},t.debug&&(rt=Ht(r,it,Z))}await this.resolveMaterialLinks(k,[],it,R.aiOverview,R.aiMode);let K={seed:u.query,totalQuestions:0,maxDepthReached:0,durationMs:Date.now()-a,errorCount:S};return this.reporter.onComplete(K),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"serp_only",problem:null,pagination:mt,completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,r,l,rt,h)}:{}},totalQuestions:0,surface:R.surface,aiOverview:R.aiOverview,aiMode:R.aiMode,whatPeopleSaying:[],tree:[],flat:[],videos:[],forums:[],organicResults:it,localPack:Z,entityIds:pt,stats:K}}let[B,N,m,v,A,y]=await Promise.all([f?this.extractVideos(k):Promise.resolve([]),g?this.extractForums(k):Promise.resolve([]),p?this.extractWhatPeopleSaying(k):Promise.resolve([]),this.extractEntityIds(k),this.extractOrganicResults(k),w?this.extractLocalPack(k):Promise.resolve([])]),C=this.mergeLocalPackIntoEntities(v,y),H=t.debug?Ht(r,A,y):void 0;this.reporter.onVideos(B),this.reporter.onForums(N);let O=M?await this.extractAISurfaces(k,t):P,I={requestedPages:(t.pages??1)>=2?2:1,capturedPages:1,page2Status:(t.pages??1)>=2?"not_attempted":"not_requested",page1OrganicCount:A.length,page2OrganicCount:0},T=A;if(this.checkpointMaterial={surface:O.surface,aiOverview:O.aiOverview,aiMode:O.aiMode,whatPeopleSaying:m,videos:B,forums:N,organicResults:T,localPack:y,entityIds:C,pagination:I},await this.emitProgress("serp_captured"),I.requestedPages===2){let G=await this.captureSecondOrganicPage(k,u,n);T=[...A,...G.organic],I={...I,capturedPages:G.status==="captured"?2:1,page2Status:G.status,page2OrganicCount:G.organic.length,...G.failureCode?{failureCode:G.failureCode}:{}},this.checkpointMaterial={...this.checkpointMaterial,organicResults:T,pagination:I},await this.emitProgress("serp_captured"),await this.resolveMaterialLinks(k,[],T,O.aiOverview,O.aiMode),this.checkpointMaterial={...this.checkpointMaterial,organicResults:T},await this.emitProgress("serp_captured")}let L=t.debug?Ht(r,T,y):H;if(!x){await this.resolveMaterialLinks(k,[],T,O.aiOverview,O.aiMode),this.checkpointMaterial={...this.checkpointMaterial,organicResults:T},await this.emitProgress("serp_captured");let G={seed:u.query,totalQuestions:0,maxDepthReached:0,durationMs:Date.now()-a,errorCount:S};return this.reporter.onComplete(G),{seed:u.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"no_paa",noPaaObserved:!0,problem:null,pagination:I,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,r,l,L,h)}:{}},totalQuestions:0,surface:O.surface,aiOverview:O.aiOverview,aiMode:O.aiMode,whatPeopleSaying:m,tree:[],flat:[],videos:B,forums:N,organicResults:T,localPack:y,entityIds:C,stats:G}}let J=Date.now(),Y=await this.runBFS(k,u,n);this.phaseTimings.paaExpansionMs=Date.now()-J,this.throwIfAborted(n);let nt=new URLSearchParams({q:u.query,gl:t.gl,hl:t.hl,pws:"0",udm:Bt.udm});l&&nt.set("uule",l);let D=[];if(t.includeShortVideos!==!1)try{D=await this.extractShortVideos(k,"https://www.google.com/search?"+nt.toString())}catch(G){if(!(G instanceof z))throw G;S++,o.push({code:"short_videos_captcha_skipped",surface:"short_videos",message:G.message,retryable:!0})}this.reporter.onVideos(D),await this.resolveMaterialLinks(k,Y,T,O.aiOverview,O.aiMode),this.checkpointMaterial={...this.checkpointMaterial,surface:O.surface,aiOverview:O.aiOverview,aiMode:O.aiMode,videos:[...B,...D],organicResults:T},await this.emitProgress("expansion_finished");let yt=[...B,...D],ot=this.buildTree(Y,u.query),Q={seed:u.query,totalQuestions:Y.length,maxDepthReached:Y.reduce((G,F)=>Math.max(G,F.depth),0),durationMs:Date.now()-a,errorCount:S};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:I,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...o.length>0?{warnings:o}:{},...t.debug?{debug:this.buildHarvestDebugSnapshot(u,r,l,L,h)}:{}},totalQuestions:Y.length,surface:O.surface,aiOverview:O.aiOverview,aiMode:O.aiMode,whatPeopleSaying:m,tree:ot,flat:Y,videos:yt,forums:N,organicResults:T,localPack:y,entityIds:C,stats:Q}}catch(d){throw S++,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(d instanceof Error?d:new Error(String(d))),d}}};var se=class{onQuestion(t){process.stdout.write(JSON.stringify({event:"question",depth:t.depth,question:t.question})+`
|
|
21705
21738
|
`)}onDepth(t){process.stdout.write(JSON.stringify({event:"depth",depth:t})+`
|
|
21706
21739
|
`)}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
21740
|
`)}onForums(t){for(let n of t)process.stdout.write(JSON.stringify({event:"forum",title:n.title,source:n.source,url:n.url})+`
|
|
21708
21741
|
`)}onComplete(t){process.stdout.write(JSON.stringify({event:"complete",...t})+`
|
|
21709
21742
|
`)}onError(t){process.stderr.write(JSON.stringify({event:"error",type:t.constructor.name,message:t.message})+`
|
|
21710
|
-
`)}};import{randomInt as ba}from"crypto";var Ia="pr.oxylabs.io",Wa=7777,Aa=10,Ts=2;function pn(){return process.env.OXYLABS_USERNAME?.trim()||void 0}function mn(){return process.env.OXYLABS_PASSWORD?.trim()||void 0}function xa(){return(process.env.OXYLABS_COUNTRY?.trim()||"US").toUpperCase()}function zt(){return!!(pn()&&mn())}function La(){let e="";for(let t=0;t<10;t++)e+=String(ba(0,10));return e}function Oa(e={}){let t=pn();if(!t)return;let n=t.startsWith("customer-")?t:`customer-${t}`,a=(e.country?.trim()||xa()).toUpperCase(),s=e.sticky?`-sessid-${La()}-sesstime-${Aa}`:"";return`${n}-cc-${a}${s}`}function ce(e){return e.replace(/pr\.oxylabs\.io(:\d+)?/gi,"backup proxy").replace(/oxylabs/gi,"backup proxy")}function Ba(e){return`mcp-backup-custom-${`${Date.now()}-${e??0}-${Math.random().toString(36).slice(2,8)}`}`}async function qt(e,t={}){let n=Oa({sticky:t.sticky}),a=mn();if(!n||!a)throw new Error("backup proxy pool is not configured");let s=new at({apiKey:e});try{let i=await s.proxies.create({type:"custom",name:Ba(t.attemptIndex),protocol:"http",config:{host:Ia,port:Wa,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(ce(d))}}async function Ps(e,t){if(!(!e||!zt()))try{return await qt(e,{attemptIndex:t})}catch{return}}async function bs(e,t){if(!(!e||!t))try{await new at({apiKey:e}).proxies.delete(t)}catch{}}var vn={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"},Ha={"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 K(e,t,n,a,s,i=!1){return{kernelProxyId:n,...i&&n?{disposableProxyId:n}:{},resolution:{source:e,proxyType:e==="disabled"?"none":e==="configured_fallback"?"configured":e==="mobile_created"?"mobile":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 Ra(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function Ga(e){return e.trim().toLowerCase().replace(/\./g,"").replace(/\s+/g," ")}function Da(e){if(!e)return!0;let t=Ga(e);return t==="united states"||t==="united states of america"||t==="usa"||t==="us"}function ge(e){let t=e.trim();if(/^[A-Za-z]{2}$/.test(t)){let n=t.toUpperCase();return Object.values(vn).includes(n)?n:null}return vn[Ra(t)]??null}function Va(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 dt(e,t,n){return n?`mcp-serp-residential-${e.toLowerCase()}-${t.toLowerCase()}-${n}`:`mcp-serp-residential-${e.toLowerCase()}-${t.toLowerCase()}`}function Nt(e,t){let n=`${Date.now()}-${t??0}-${Math.random().toString(36).slice(2,8)}`;return`${e}-fresh-${n}`}function Ea(e){return`mcp-serp-residential-us-zip-${e}`}function Nn(e,t){if(!e||t.toLowerCase()!=="us")return null;let n=an(e),a=n.split(",").map(U=>U.trim()).filter(Boolean);if(a.length>1&&Da(a[a.length-1])&&(a=a.slice(0,-1)),a.length===1){let U=ge(a[0]);return U?{canonicalLocation:n,level:"state",country:"US",state:U,city:"",cityCandidates:[],proxyName:dt("US",U),config:{country:"US",state:U}}:null}let[s="",i=""]=a;if(!s||!i)return null;let d=ge(i);if(!d)return null;let h=Va(s),S=h[0];return S?{canonicalLocation:n,level:"city",country:"US",state:d,city:S,cityCandidates:h,proxyName:dt("US",d,S),config:{country:"US",state:d,city:S}}:null}function Ya(e){return`${e.city}|${e.state}`}function fn(e,t){return t&&/^\d{5}$/.test(t)?t:Ha[Ya(e)]??null}function Tn(e,t){return{...e,level:"zip",zip:t,proxyName:Ea(t),config:{country:e.country,state:e.state,zip:t}}}function we(e,t){return{...e,proxyName:t}}function Ce(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 Ka(e,t){return e.find(n=>n.type==="residential"&&n.status!=="unavailable"&&!!n.id&&(n.name===t.proxyName||Ce(n.config,t,t.level==="city"?t.city:void 0)))??null}function Ja(e,t){for(let n of t.cityCandidates){let a=dt(t.country,t.state,n),s=e.find(i=>i.type==="residential"&&i.status!=="unavailable"&&!!i.id&&(i.name===a||Ce(i.config,t,n)));if(s)return s}return null}function jt(e){return{...e,level:"state",proxyName:dt(e.country,e.state),config:{country:e.country,state:e.state}}}function _a(e,t){let n=dt(t.country,t.state);return e.find(a=>a.type==="residential"&&a.status!=="unavailable"&&!!a.id&&(a.name===n||Ce(a.config,t)))??null}function za(e,t){return jt(e)}function ot(e){return e instanceof Error?e.message:String(e)}function qa(e,t,n){let a=[],s=fn(e,t);if(s){let d=Tn(e,s);a.push(we(d,Nt(d.proxyName,n)))}for(let d of e.cityCandidates){let h={...e,level:"city",city:d,proxyName:dt(e.country,e.state,d),config:{country:e.country,state:e.state,city:d}};a.push(we(h,Nt(h.proxyName,n)))}let i=jt(e);return a.push(we(i,Nt(i.proxyName,n))),a}async function ye(e,t,n){if(e.backupOnExhaustion&&n.length>0&&e.kernelApiKey&&zt())try{let a=await qt(e.kernelApiKey,{attemptIndex:e.attemptIndex});return K("backup_custom",e.proxyMode,a,t,null,!0)}catch(a){n.push(`backup: ${ce(ot(a))}`)}return K("configured_fallback",e.proxyMode,e.configuredKernelProxyId,t,n.join(" | "))}async function Ls(e){if(!e.kernelApiKey||!zt())return null;try{let t=await qt(e.kernelApiKey,{attemptIndex:e.attemptIndex});return K("backup_custom",e.proxyMode,t,null,null,!0)}catch{return null}}async function ja(e,t,n){let a=[];for(let s of qa(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 K("location_created",t.proxyMode,i.id,s,null,!0);a.push(`${s.proxyName}: Kernel did not return a proxy id`)}catch(i){a.push(`${s.proxyName}: ${ot(i)}`)}if(process.env.KERNEL_PROXY_TYPE!=="residential"){let s=jt(n);try{let i=await e.proxies.create({type:"isp",name:Nt(`mcp-serp-isp-${s.country.toLowerCase()}-${(s.state??"").toLowerCase()}`,t.attemptIndex),config:{country:s.country,...s.state?{state:s.state}:{}}});if(i.id)return K("isp_created",t.proxyMode,i.id,s,null,!0);a.push("isp: Kernel did not return a proxy id")}catch(i){a.push(`isp: ${ot(i)}`)}}return ye(t,n,a)}async function Pn(e,t){if(!e||!t)return;await new at({apiKey:e}).proxies.delete(t)}async function Os(e){let t=ge(e.state);if(!t)throw new Error("A valid US state is required for a mobile Maps proxy");let n=new at({apiKey:e.kernelApiKey}),a=Nn(t,"us");if(!a)throw new Error("Could not resolve the mobile Maps proxy state");let s=await n.proxies.create({type:"mobile",name:Nt(`mcp-maps-mobile-us-${t.toLowerCase()}`,e.attemptIndex),config:{country:"US",state:t}});if(!s.id)throw new Error("Kernel did not return a mobile proxy id");if(s.type!=="mobile"||s.status==="unavailable"||s.config?.state?.toUpperCase()!==t)throw await n.proxies.delete(s.id),new Error(`Kernel did not confirm a mobile proxy for ${t}`);return K("mobile_created","configured",s.id,a,null,!0)}async function bn(e){if(e.proxyMode==="none")return K("disabled",e.proxyMode,void 0,null,null);if(e.proxyMode==="configured")return K("configured_fallback",e.proxyMode,e.configuredKernelProxyId,null,null);let t=Nn(e.location,e.gl);if(!t||!e.kernelApiKey)return K("configured_fallback",e.proxyMode,e.configuredKernelProxyId,t,t?null:"location could not be normalized to a US city/state proxy target");let n=new at({apiKey:e.kernelApiKey});try{let a=e.attemptIndex??0;if(e.fresh)return await ja(n,e,t);if(a>=1){let l=za(t,a),o=[];try{let r=await n.proxies.create({type:"residential",name:l.proxyName,config:l.config});if(r.id)return K("location_created",e.proxyMode,r.id,l,null);o.push(`${l.state}: Kernel did not return a proxy id`)}catch(r){o.push(`${l.state}: ${ot(r)}`)}return ye(e,l,o)}let s=[];for await(let l of await n.proxies.list())s.push(l);let i=fn(t,e.proxyZip),d=[];if(i){let l=Tn(t,i),o=Ka(s,l);if(o?.id)return K("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 K("location_created",e.proxyMode,r.id,l,null);d.push(`${i}: Kernel did not return a proxy id`)}catch(r){d.push(`${i}: ${ot(r)}`)}}let h=Ja(s,t);if(h?.id)return K("location_reused",e.proxyMode,h.id,t,d.join(" | ")||null);for(let l of t.cityCandidates)try{let o=await n.proxies.create({type:"residential",name:dt(t.country,t.state,l),config:{country:t.country,state:t.state,city:l}});if(o.id)return K("location_created",e.proxyMode,o.id,{...t,level:"city",city:l,proxyName:dt(t.country,t.state,l),config:{country:t.country,state:t.state,city:l}},null);d.push(`${l}: Kernel did not return a proxy id`)}catch(o){d.push(`${l}: ${ot(o)}`)}let S=jt(t),U=_a(s,S);if(U?.id)return K("location_reused",e.proxyMode,U.id,S,d.join(" | "));try{let l=await n.proxies.create({type:"residential",name:S.proxyName,config:S.config});if(l.id)return K("location_created",e.proxyMode,l.id,S,d.join(" | "));d.push(`${S.state}: Kernel did not return a proxy id`)}catch(l){d.push(`${S.state}: ${ot(l)}`)}return ye(e,t,d)}catch(a){return K("configured_fallback",e.proxyMode,e.configuredKernelProxyId,t,ot(a))}}var ft=class extends Error{constructor(t,n){super(`SERP provider mismatch: planned ${t}, observed ${n}`),this.name="SerpProviderMismatchError"}};function In(e){return e==="bright_data_browser_api"?"brightdata":"kernel"}function Wn(e){return $a({intent:e.intent,brightDataAvailable:e.brightDataAvailable,kernelAvailable:!0,persistentKernelIdentityRequested:e.persistentKernelIdentityRequested,retryIndex:e.retryIndex,priorTerminalReason:e.priorTerminalReason,allowedFallbacks:e.kernelFallbackAvailable&&e.intent!=="kernel"?["kernel"]:[],timeoutMs:e.softDeadlineMs==null?4e5:Math.max(1,e.softDeadlineMs-Date.now())})}function An(e){if(e.forceManagedSerp&&e.forceKernelSerp)throw new Error("forceManagedSerp and forceKernelSerp cannot both be true");return e.forceManagedSerp?"brightdata":e.forceKernelSerp?"kernel":"auto"}function $t(e,t){if(!t)throw new Error(`Requested SERP provider is unavailable: ${e}`);return e}function $a(e){if(!Number.isInteger(e.retryIndex)||e.retryIndex<0)throw new Error("retryIndex must be a non-negative integer");if(!Number.isFinite(e.timeoutMs)||e.timeoutMs<=0)throw new Error("timeoutMs must be a positive number");let t,n;e.intent==="brightdata"?(t=$t("brightdata",e.brightDataAvailable),n="explicit_brightdata"):e.intent==="kernel"?(t=$t("kernel",e.kernelAvailable),n="explicit_kernel"):e.persistentKernelIdentityRequested?(t=$t("kernel",e.kernelAvailable),n="persistent_kernel_identity"):e.brightDataAvailable?(t="brightdata",n="managed_default"):(t=$t("kernel",e.kernelAvailable),n="kernel_default");let a=e.allowedFallbacks.find(d=>d!==t&&(d==="brightdata"?e.brightDataAvailable:e.kernelAvailable)),s=e.retryIndex>0&&a?a:t,i=e.retryIndex===0?"primary":s===t?"same_provider_retry":"provider_fallback";return Object.freeze({plannedProvider:s,attemptKind:i,reasonCode:i==="primary"?n:i==="provider_fallback"?"provider_fallback":"same_provider_retry",retryIndex:e.retryIndex,priorTerminalReason:e.priorTerminalReason??null,timeoutMs:Math.floor(e.timeoutMs),fallbackAllowed:!!a})}var ke=2,Qa=2,Za=3e3;function pe(e){return e.reason instanceof DOMException&&e.reason.name==="TimeoutError"?e.reason:new Z}function Xa(e){if(!e||typeof e!="object")return;let t=e.signal;if(t instanceof AbortSignal)return t}function ti(e){if(!e||typeof e!="object")return;let t=e.onAttemptEvent;return typeof t=="function"?t:void 0}function ei(e){if(!e||typeof e!="object")return;let t=e.onPaaProgress;return typeof t=="function"?t:void 0}function ni(e){if(!e||typeof e!="object")return;let t=e.onPaaDomEvidence;return typeof t=="function"?t:void 0}async function ai(e){let t=await e.evaluate(n=>{let a=n,s=Array.from(document.querySelectorAll(a.item)),i=s.map(S=>S.querySelector(a.clickTarget)).filter(S=>S!=null),d=S=>{let U=S.getBoundingClientRect();if(U.width<=0||U.height<=0)return!1;let l=U.left+U.width/2,o=U.top+U.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!==S&&!S.contains(r)&&!r.contains(S)},h=Array.from(document.querySelectorAll("body *")).filter(S=>{let U=window.getComputedStyle(S);if(U.position!=="fixed"&&U.position!=="sticky")return!1;let l=S.getBoundingClientRect();return l.width*l.height>=window.innerWidth*window.innerHeight*.15&&U.visibility!=="hidden"&&U.display!=="none"});return{itemCount:s.length,expandedItemCount:s.filter(S=>S.classList.contains(a.expandedClass)||S.querySelector(a.clickTarget)?.getAttribute("aria-expanded")==="true").length,answeredItemCount:s.filter(S=>(S.querySelector(a.answerContainer)?.textContent?.trim().length??0)>=10).length,sourcedItemCount:s.filter(S=>S.querySelector(`${a.answerContainer} a[href]`)!=null).length,clickTargetCount:i.length,clickTargetsWithButtonRole:i.filter(S=>S.getAttribute("role")==="button"||S.tagName==="BUTTON").length,clickTargetsWithExpandedState:i.filter(S=>S.hasAttribute("aria-expanded")).length,clickTargetsOffscreen:i.filter(S=>{let U=S.getBoundingClientRect(),l=U.left+U.width/2,o=U.top+U.height/2;return l<0||o<0||l>=window.innerWidth||o>=window.innerHeight}).length,clickTargetsBlockedAtCenter:i.filter(d).length,fixedOrStickyOverlayCount:h.length}},{item:D.item,answerContainer:D.answerContainer,clickTarget:D.clickTarget,expandedClass:D.expandedClass});return{capturedAt:new Date().toISOString(),...t,selectorVersion:Ye}}async function yt(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 Tt(e){if(e instanceof ft)return"error";if(e instanceof _)return"captcha";if(e instanceof te)return"location_mismatch";if(e instanceof Z)return"request_aborted";if(e instanceof kt)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":ri(t)?"proxy_tunnel_failed":li(t)?"proxy_unavailable":/timeout|timed out|Timeout \d+ms exceeded|deadline/i.test(t)?"timeout":"error"}function ii(e){return e.diagnostics.degradedResult?"degraded_result":e.diagnostics?.completionStatus??(e.totalQuestions>0?"paa_found":"no_paa")}function si(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 xn(e,t,n){let a=si(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,h=n?0:e.flat.filter(g=>!g.source_cite?.trim()).length,S=e.diagnostics.completionStatus==="no_paa"&&(e.diagnostics.noPaaObserved===!0||a),U=e.diagnostics.completionStatus==="paa_found",l=e.diagnostics.paaLifecycle?.discoveryStatus,o=l==="interrupted"||l==="recovery_exhausted",r=U&&(i<t&&l!=="frontier_exhausted"||d>0||h>0||!!e.diagnostics.interruption||o),u=S?"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:h,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||h>0?"partial":"complete"}}:{}},e}function Ln(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 oi(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 X(e){return e instanceof Error?e.message:String(e)}function di(e){return e==="location"?Qa:ke}function ri(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 li(e){return/proxy unavailable|proxy_unavailable|connection_test_failed|did not return a proxy id|configured fallback/i.test(e)}function On(e){return e==="captcha"||e==="proxy_tunnel_failed"||e==="proxy_unavailable"}function Bn(e){return e==="browser_session_interrupted"}function Si(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 Ui(e,t){return t==="location"&&e.diagnostics.debug?.locationEvidence?.status==="mismatch"}function Hn(e,t){if(t||!e.diagnostics.debug)return e;let n={...e.diagnostics};return delete n.debug,{...e,diagnostics:n}}async function Fn(e,t){let n=t==null?3e3:t-Date.now();if(n<=0)return e;try{return await gn(e,{totalBudgetMs:Math.min(3e3,n)})}catch(a){return console.warn(JSON.stringify({event:"harvest_goto_resolution_failed",message:X(a)})),e}}async function Me(e,t){if(!(!e||!t))try{await Pn(e,t),console.info(JSON.stringify({event:"kernel_proxy_deleted",proxy_id_suffix:t.slice(-6)}))}catch(n){console.warn(JSON.stringify({event:"kernel_proxy_delete_failed",proxy_id_suffix:t.slice(-6),message:X(n)}))}}async function Rn(e,t,n,a,s,i){let d=Qe(t,{nativeGoogleAssets:e.serpOnly}),h=new _t,S=new Kt(d,h,a,s);if(n?.aborted)return{result:null,error:pe(n),cleanup:await d.close(),debug:null};let U,l=n?new Promise((g,N)=>{U=()=>N(pe(n)),n.addEventListener("abort",U,{once:!0})}):null,o=null,r=null,u,c=null;try{let g=S.extract(e,n);l&&g.catch(()=>{}),o=await(l?Promise.race([g,l]):g)}catch(g){r=g}finally{if(n&&U&&n.removeEventListener("abort",U),i){let g;try{let N=ai(d);N.catch(()=>{});let b=await Promise.race([N,new Promise((k,x)=>{g=setTimeout(()=>x(new DOMException("PAA DOM evidence timed out","TimeoutError")),2e3)})]);await i(b)}catch(N){console.warn(JSON.stringify({event:"paa_dom_evidence_failed",message:X(N)}))}finally{g&&clearTimeout(g)}}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=Tt(r),N=g==="timeout"||g==="request_aborted"||g==="browser_session_interrupted"?g:null,b=null;if(N)try{b=typeof S.getPartialResult=="function"?S.getPartialResult():null}catch{b=null}return b&&N?(b.diagnostics={...b.diagnostics,interruption:{code:N,reasonSource:"client_runtime",message:X(r)}},{result:b,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 Xs(e){let t=typeof e=="object"&&e!==null?e:{},n=Xa(e),a=ti(e),s=ei(e),i=ni(e),d=t.forceManagedSerp===!0,h=t.forceKernelSerp===!0,S=An({forceManagedSerp:d,forceKernelSerp:h}),U=t.proxyMode,l=U==="location"||U==="none"||U==="configured"?U:xt,o=typeof t.kernelApiKey=="string"?t.kernelApiKey.trim():Pe(),r=typeof t.kernelProxyId=="string"?t.kernelProxyId.trim():void 0,u={kernelApiKey:o,proxyMode:l,configuredKernelProxyId: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,g=l==="location"&&!!u.location,N=t.maxAttempts,b=typeof N=="number"&&Number.isInteger(N)&&N>=1?Math.min(ke,N):di(l),k=Math.min(ke,b),x=typeof t.softDeadlineMs=="number"?t.softDeadlineMs:null,O=new Jt,H=null,f=l,p=0,L=()=>x==null||x-Date.now()>=Za;for(let T=0;T<k;T++){let y=T+1,P=Date.now();try{if(n?.aborted)throw pe(n);let w=Wn({intent:S,brightDataAvailable:je(),kernelFallbackAvailable:!!o,persistentKernelIdentityRequested:!!(t.serpIdentity||t.kernelProfileName),retryIndex:T,priorTerminalReason:H==null?null:Tt(H),softDeadlineMs:x}),C=ee.parse({...t,kernelApiKey:o,proxyMode:f,debug:c||g}),M=w.plannedProvider==="brightdata"?"brightdata_browser":C.serpIdentity?"kernel_persistent_identity":"kernel_browser";await yt(a,{type:"started",attemptNumber:y,maxAttempts:k,method:M,provider:M==="brightdata_browser"?"brightdata":"kernel",planReason:w.reasonCode,planTimeoutMs:w.timeoutMs,retryKind:y===1?null:w.attemptKind==="provider_fallback"?"provider_fallback":"same_method",retryReason:y===1||H==null?null:Tt(H),query:C.query,location:C.location??null,maxQuestions:C.maxQuestions,startedAt:new Date(P).toISOString()});let m=w.plannedProvider==="brightdata"?null:await bn({...u,proxyMode:f,attemptIndex:T,fresh:f==="location"});if(w.plannedProvider==="kernel"&&!m)throw new Error("Kernel proxy resolution did not produce an execution plan");let A={...t,kernelApiKey:o,...m?{kernelProxyId:m.kernelProxyId,kernelProxyResolution:m.resolution}:{},proxyMode:f,keepDefaultProxy:T>0,softDeadlineMs:x==null?void 0:P+w.timeoutMs,debug:c||g};f==="none"&&(A.kernelProxyId=void 0);let I=ee.parse(A);console.info(JSON.stringify({event:"harvest_attempt_started",attempt_number:y,max_attempts:k,query:I.query,location:I.location??null,max_questions:I.maxQuestions}));let W=Ot(),V=null,q=async R=>{In(R.provider)!==w.plannedProvider&&(V=new ft(w.plannedProvider,R.provider)),await yt(a,{type:"provider_session_started",attemptNumber:y,maxAttempts:k,provider:R.provider,providerSessionId:R.providerSessionId,billingMode:R.billingMode,observedAt:new Date().toISOString()})},J=W?.harvestBrowserMode==="headless-test"&&process.env[We]==="true",G=W?await Ae({...W,forceHeadless:J,forceHeadful:!J},()=>Rn(I,w,n,s,q,i)):await Rn(I,w,n,s,q,i);if(G.error||V){let R=V??G.error,E=Tt(R);(E==="captcha"||E==="proxy_tunnel_failed")&&f==="location"&&(p++,p>=2&&(f="none"));let $=!G.result&&T<k-1&&L()&&(E==="captcha"||Bn(E)||l==="location"&&On(E));if(E==="captcha"?console.warn(JSON.stringify({event:"harvest_attempt_captcha",attempt_number:y,max_attempts:k,message:X(R),will_retry:$})):$&&console.warn(JSON.stringify({event:"harvest_attempt_proxy_retry",attempt_number:y,max_attempts:k,outcome:E,message:X(R),will_retry:$})),await yt(a,{type:"finished",attemptNumber:y,maxAttempts:k,outcome:E,kernelSessionId:G.cleanup.kernelSessionId,questionCount:G.result?.totalQuestions??0,durationMs:Date.now()-P,error:X(R),willRetry:$,cleanup:G.cleanup,debug:G.debug,completedAt:new Date().toISOString()}),await Me(o,m?.disposableProxyId),H=R,$)continue;if(G.result&&!V){let et=await Fn(G.result,x);return Ln(xn(Hn(et,c),I.maxQuestions,I.questionsOnly),T,w.attemptKind==="provider_fallback"?1:0)}break}let j=G.result;if(!j)throw new Error("Harvest attempt completed without a result");if(Ui(j,l)){let R=new te(Si(j)),E=T<k-1&&L();if(console.warn(JSON.stringify({event:"harvest_attempt_location_mismatch",attempt_number:y,max_attempts:k,message:R.message,will_retry:E})),await yt(a,{type:"finished",attemptNumber:y,maxAttempts:k,outcome:"location_mismatch",kernelSessionId:G.cleanup.kernelSessionId,questionCount:j.totalQuestions,durationMs:Date.now()-P,error:R.message,willRetry:E,cleanup:G.cleanup,debug:G.debug,completedAt:new Date().toISOString()}),await Me(o,m?.disposableProxyId),H=R,E)continue;break}let Ct=await Fn(j,x),B=Ln(xn(Hn(Ct,c),I.maxQuestions,I.questionsOnly),T,w.attemptKind==="provider_fallback"?1:0),tt=ii(B),F=tt==="degraded_result"&&T<k-1&&L(),Y=tt==="degraded_result"?oi(B):null;if(F&&console.warn(JSON.stringify({event:"harvest_attempt_degraded_result",attempt_number:y,max_attempts:k,degradation_reasons:B.diagnostics.degradationReasons,will_retry:!0})),await yt(a,{type:"finished",attemptNumber:y,maxAttempts:k,outcome:tt,kernelSessionId:G.cleanup.kernelSessionId,questionCount:B.totalQuestions,durationMs:Date.now()-P,error:Y,willRetry:F,cleanup:G.cleanup,debug:G.debug,completedAt:new Date().toISOString()}),await Me(o,m?.disposableProxyId),F)continue;return(I.format==="json"||I.format==="both")&&await O.writeJSON(B,I.outputDir),(I.format==="csv"||I.format==="both")&&await Promise.all([O.writeCSV(B.flat,I.outputDir),B.videos.length>0?O.writeVideoCSV(B.videos,B.seed,I.outputDir):Promise.resolve(""),B.forums.length>0?O.writeForumCSV(B.forums,B.seed,I.outputDir):Promise.resolve(""),B.aiOverview.detected?O.writeAIOverviewCSV(B.aiOverview.citations,B.aiOverview.text,B.seed,I.outputDir):Promise.resolve(""),B.aiMode.detected?O.writeAIModeCSV(B.aiMode.citations,B.aiMode.text,B.seed,I.outputDir):Promise.resolve(""),B.whatPeopleSaying.length>0?O.writeWhatPeopleSayingCSV(B.whatPeopleSaying,B.seed,I.outputDir):Promise.resolve("")]),B}catch(w){let C=Tt(w);(C==="captcha"||C==="proxy_tunnel_failed")&&f==="location"&&(p++,p>=2&&(f="none"));let M=T<k-1&&L()&&(C==="captcha"||Bn(C)||l==="location"&&On(C));if(C==="captcha"?console.warn(JSON.stringify({event:"harvest_attempt_captcha",attempt_number:y,max_attempts:k,message:X(w),will_retry:M})):M&&console.warn(JSON.stringify({event:"harvest_attempt_proxy_retry",attempt_number:y,max_attempts:k,outcome:C,message:X(w),will_retry:M})),await yt(a,{type:"finished",attemptNumber:y,maxAttempts:k,outcome:C,kernelSessionId:null,questionCount:0,durationMs:Date.now()-P,error:X(w),willRetry:M,cleanup:{kernelSessionId:null,kernelDeleteStarted:!1,kernelDeleteSucceeded:null,kernelDeleteError:null,browserCloseSucceeded:null,browserCloseError:null},debug:null,completedAt:new Date().toISOString()}),H=w,M)continue;if(C==="captcha")break;throw w}}throw H&&!(H instanceof _)?H:(console.warn(JSON.stringify({event:"harvest_captcha_exhausted",max_attempts:k,session_kind:o?"kernel":"local"})),new _(Ie(`CAPTCHA on all ${k} fresh sessions. Try again in a few minutes.`)))}export{yi as a,Ft as b,Rt as c,pi as d,Ke as e,Xn as f,Dt as g,_e as h,ze as i,oe as j,je as k,Vt as l,nn as m,Se as n,St as o,Yt as p,Ts as q,zt as r,Ps as s,bs as t,ge as u,Ls as v,Pn as w,Os as x,bn as y,Xs as z};
|
|
21743
|
+
`)}};function oe(e){return e.reason instanceof DOMException&&e.reason.name==="TimeoutError"?e.reason:new tt}async function Gi(e){let t=await e.evaluate(n=>{let a=n,i=Array.from(document.querySelectorAll(a.item)),s=i.map(d=>d.querySelector(a.clickTarget)).filter(d=>d!=null),S=d=>{let U=d.getBoundingClientRect();if(U.width<=0||U.height<=0)return!1;let h=U.left+U.width/2,r=U.top+U.height/2;if(h<0||r<0||h>=window.innerWidth||r>=window.innerHeight)return!1;let l=document.elementFromPoint(h,r);return l!=null&&l!==d&&!d.contains(l)&&!l.contains(d)},o=Array.from(document.querySelectorAll("body *")).filter(d=>{let U=window.getComputedStyle(d);if(U.position!=="fixed"&&U.position!=="sticky")return!1;let h=d.getBoundingClientRect();return h.width*h.height>=window.innerWidth*window.innerHeight*.15&&U.visibility!=="hidden"&&U.display!=="none"});return{itemCount:i.length,expandedItemCount:i.filter(d=>d.classList.contains(a.expandedClass)||d.querySelector(a.clickTarget)?.getAttribute("aria-expanded")==="true").length,answeredItemCount:i.filter(d=>(d.querySelector(a.answerContainer)?.textContent?.trim().length??0)>=10).length,sourcedItemCount:i.filter(d=>d.querySelector(`${a.answerContainer} a[href]`)!=null).length,clickTargetCount:s.length,clickTargetsWithButtonRole:s.filter(d=>d.getAttribute("role")==="button"||d.tagName==="BUTTON").length,clickTargetsWithExpandedState:s.filter(d=>d.hasAttribute("aria-expanded")).length,clickTargetsOffscreen:s.filter(d=>{let U=d.getBoundingClientRect(),h=U.left+U.width/2,r=U.top+U.height/2;return h<0||r<0||h>=window.innerWidth||r>=window.innerHeight}).length,clickTargetsBlockedAtCenter:s.filter(S).length,fixedOrStickyOverlayCount:o.length}},{item:V.item,answerContainer:V.answerContainer,clickTarget:V.clickTarget,expandedClass:V.expandedClass});return{capturedAt:new Date().toISOString(),...t,selectorVersion:Rn}}function It(e){if(e instanceof lt)return"error";if(e instanceof z)return"captcha";if(e instanceof Jt)return"location_mismatch";if(e instanceof tt)return"request_aborted";if(e instanceof xt)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":Ei(t)?"proxy_tunnel_failed":Vi(t)?"proxy_unavailable":/timeout|timed out|Timeout \d+ms exceeded|deadline/i.test(t)?"timeout":"error"}function Ei(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 Vi(e){return/proxy unavailable|proxy_unavailable|connection_test_failed|did not return a proxy id|configured fallback/i.test(e)}async function He(e,t,n,a,i,s,S){let o=zn(t,{nativeGoogleAssets:e.serpOnly}),d=S?ln(o,S.execution,S.permit,t.plannedProvider):o,U=new se,h=new ie(d,U,a,i);if(n?.aborted)return{result:null,error:oe(n),cleanup:await d.close(),debug:null};let r,l=n?new Promise((p,P)=>{r=()=>P(oe(n)),n.addEventListener("abort",r,{once:!0})}):null,u=null,c=null,w,g=null,f=!1,M;try{M=h.extract(e,n),M.then(()=>{f=!0},()=>{f=!0}),u=await(l?Promise.race([M,l]):M)}catch(p){c=p}finally{if(n&&r&&n.removeEventListener("abort",r),s){let p;try{let P=Gi(d);P.catch(()=>{});let b=await Promise.race([P,new Promise((x,k)=>{p=setTimeout(()=>k(new DOMException("PAA DOM evidence timed out","TimeoutError")),2e3)})]);await s(b)}catch(P){console.warn(JSON.stringify({event:"paa_dom_evidence_failed",message:P instanceof Error?P.message:String(P)}))}finally{p&&clearTimeout(p)}}g=u?.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);try{w=await d.close()}catch(p){w={\u006b\u0065\u0072\u006e\u0065\u006cSessionId:d.get\u004b\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:!1,browserCloseError:p instanceof Error?p.message:String(p),physicalOutcome:"unknown"}}if(M&&!f){let p;try{await Promise.race([M.then(()=>{},()=>{}),new Promise(P=>{p=setTimeout(P,2e3)})])}finally{p&&clearTimeout(p)}}w.extractionDrained=f,f||(w.physicalOutcome="unknown")}if(c){let p=It(c),P=p==="timeout"||p==="request_aborted"||p==="browser_session_interrupted"?p:null,b=null;if(P)try{b=typeof h.getPartialResult=="function"?h.getPartialResult():null}catch{b=null}return b&&P?(b.diagnostics={...b.diagnostics,interruption:{code:P,reasonSource:"client_runtime",message:c instanceof Error?c.message:String(c)}},{result:b,error:c,cleanup:w,debug:g,salvagedFrom:c}):{result:null,error:c,cleanup:w,debug:g}}return{result:u,error:null,cleanup:w,debug:g}}function ya(e){return e.diagnostics.degradedResult?"degraded_result":e.diagnostics?.completionStatus??(e.totalQuestions>0?"paa_found":"no_paa")}function Yi(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 Fe(e,t,n){let a=Yi(e),i=(e.diagnostics.warnings?.length??0)>0,s=new Set(e.flat.map(g=>g.question.toLowerCase().replace(/[^\w\s]/g,"").replace(/\s+/g," ").trim())).size,S=n?0:e.flat.filter(g=>!g.answer?.trim()).length,o=n?0:e.flat.filter(g=>!g.source_cite?.trim()).length,d=n?0:e.flat.filter(g=>g.answerExpansionIncomplete===!0).length,U=e.diagnostics.completionStatus==="no_paa"&&(e.diagnostics.noPaaObserved===!0||a),h=e.diagnostics.completionStatus==="paa_found",r=e.diagnostics.paaLifecycle?.discoveryStatus,l=r==="interrupted"||r==="recovery_exhausted",u=h&&(s<t&&r!=="frontier_exhausted"||S>0||o>0||d>0||!!e.diagnostics.interruption||l),c=U?"complete":h&&s>0?u||i?"partial":"complete":a?i?"partial":"complete":"degraded",w=c==="degraded";return e.diagnostics={...e.diagnostics,resultQuality:c,degradedResult:w,degradationReasons:w?["empty_primary_serp"]:[],retryRecommended:w||c==="partial"&&(u||e.diagnostics.warnings?.some(g=>g.retryable)===!0),completeness:{paaWithoutAnswer:S,paaWithoutSource:o,paaIncompleteAnswers:d,paaAnswersRecovered:e.diagnostics.completeness?.paaAnswersRecovered??0,aioShareCaptured:e.diagnostics.completeness?.aioShareCaptured??null,paaRequested:t,paaReturned:e.flat.length,paaUnique:s},...e.diagnostics.paaLifecycle?{paaLifecycle:{...e.diagnostics.paaLifecycle,questionsFound:s,targetStatus:s>=t?"met":"not_met",materialStatus:S>0||o>0||d>0?"partial":"complete"}}:{}},e}function Re(e,t,n){let a=e.diagnostics.paaLifecycle;if(!a)return e;let i={...a.retryBreakdown,browserRetries:t,providerFallbacks:n};return{...e,diagnostics:{...e.diagnostics,paaLifecycle:{...a,retryBreakdown:i,automaticRetries:i.controlRetries+i.browserRetries+i.runtimeRecoveries}}}}function pa(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 De(e,t){if(t||!e.diagnostics.debug)return e;let n={...e.diagnostics};return delete n.debug,{...e,diagnostics:n}}async function Ge(e,t){let n=t==null?3e3:t-Date.now();if(n<=0)return e;try{return await sa(e,{totalBudgetMs:Math.min(3e3,n)})}catch(a){return console.warn(JSON.stringify({event:"harvest_goto_resolution_failed",message:a instanceof Error?a.message:String(a)})),e}}var Ee=2,Ki=2,Ji=3e3;function _i(e){if(!e||typeof e!="object")return;let t=e.signal;if(t instanceof AbortSignal)return t}function zi(e){if(!e||typeof e!="object")return;let t=e.onAttemptEvent;return typeof t=="function"?t:void 0}function qi(e){if(!e||typeof e!="object")return;let t=e.onPaaProgress;return typeof t=="function"?t:void 0}function ji(e){if(!e||typeof e!="object")return;let t=e.onPaaDomEvidence;return typeof t=="function"?t:void 0}async function Wt(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 gt(e){return e instanceof Error?e.message:String(e)}function $i(e){return e==="location"?Ki:Ee}function ma(e){return e==="captcha"||e==="proxy_tunnel_failed"||e==="proxy_unavailable"}function Ca(e){return e==="browser_session_interrupted"}function Qi(e){let t=e.diagnostics.debug?.locationEvidence,n=t?.expected?.canonicalLocation??e.location??"requested location",a=t?.candidates.slice(0,3).map(i=>`${i.city}, ${i.regionCode}`).join("; ");return a?`Google returned results for ${a}, not ${n}`:`Google returned results for a different location than ${n}`}function Zi(e,t){return t==="location"&&e.diagnostics.debug?.locationEvidence?.status==="mismatch"}function ka(e){return e.extractionDrained===!0&&e.browserCloseSucceeded===!0&&e.localDisconnectSucceeded!==!1&&(e.\u006b\u0065\u0072\u006e\u0065\u006cSessionId==null||e.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded===!0)&&e.physicalOutcome!=="unknown"}async function Xi(e,t){if(!t)return!0;if(!e)return!1;try{return await In(e,t),console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_proxy_deleted",proxy_id_suffix:t.slice(-6)})),!0}catch(n){return console.warn(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_proxy_delete_failed",proxy_id_suffix:t.slice(-6),message:gt(n)})),!1}}async function Nr(e){let t=typeof e=="object"&&e!==null?e:{},n=_i(e),a=wn(e),i=zi(e),s=qi(e),S=ji(e),o=t.forceManagedSerp===!0,d=t.force\u004b\u0065\u0072\u006e\u0065\u006cSerp===!0,U=sn({forceManagedSerp:o,force\u004b\u0065\u0072\u006e\u0065\u006cSerp:d}),h=t.proxyMode,r=h==="location"||h==="none"||h==="configured"?h:Kt,l=typeof t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey=="string"?t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey.trim():je(),u=typeof t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId=="string"?t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId.trim():void 0,c={\u006b\u0065\u0072\u006e\u0065\u006cApiKey:l,proxyMode:r,configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId:u,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"},w=typeof t.debug=="boolean"?t.debug:!1,g=r==="location"&&!!c.location,f=t.maxAttempts,M=typeof f=="number"&&Number.isInteger(f)&&f>=1?Math.min(Ee,f):$i(r),p=Math.min(Ee,M),P=typeof t.softDeadlineMs=="number"?t.softDeadlineMs:null,b=new jt,x=null,k=r,B=0,N=()=>P==null||P-Date.now()>=Ji;for(let m=0;m<p;m++){let v=m+1,A=Date.now(),y=!0,C,H=!1,O=n,I;try{if(O?.aborted)throw oe(O);let T=an({intent:U,\u0062\u0072\u0069\u0067\u0068\u0074\u0044\u0061\u0074\u0061Available:An(),\u006b\u0065\u0072\u006e\u0065\u006cFallbackAvailable:!!l,persistent\u004b\u0065\u0072\u006e\u0065\u006cIdentityRequested:!!(t.serpIdentity||t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName),retryIndex:m,priorTerminalReason:x==null?null:It(x),softDeadlineMs:P}),L=ce.parse({...t,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:l,proxyMode:k,debug:w||g});a&&(C=await a.prepare(T.plannedProvider,v),I=a.watch(C,n),O=I.signal);let J=T.plannedProvider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser":L.serpIdentity?"\u006b\u0065\u0072\u006e\u0065\u006c_persistent_identity":"\u006b\u0065\u0072\u006e\u0065\u006c_browser";await Wt(i,{type:"started",attemptNumber:v,maxAttempts:p,method:J,provider:J==="\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",planReason:T.reasonCode,planTimeoutMs:T.timeoutMs,retryKind:v===1?null:T.attemptKind==="provider_fallback"?"provider_fallback":"same_method",retryReason:v===1||x==null?null:It(x),query:L.query,location:L.location??null,maxQuestions:L.maxQuestions,startedAt:new Date(A).toISOString()}),T.plannedProvider==="\u006b\u0065\u0072\u006e\u0065\u006c"&&(y=!1,a&&C&&await a.start(C,"proxy"));let Y=T.plannedProvider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?null:await Wn({...c,proxyMode:k,attemptIndex:m,fresh:k==="location"});if(T.plannedProvider==="\u006b\u0065\u0072\u006e\u0065\u006c"&&!Y)throw new Error("\u004b\u0065\u0072\u006e\u0065\u006c proxy resolution did not produce an execution plan");a&&C&&T.plannedProvider==="\u006b\u0065\u0072\u006e\u0065\u006c"&&await a.resource(C,"proxy",Y?.disposableProxyId??null);let nt={...t,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:l,...Y?{\u006b\u0065\u0072\u006e\u0065\u006cProxyId:Y.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution:Y.resolution}:{},proxyMode:k,keepDefaultProxy:m>0,softDeadlineMs:P==null?void 0:A+T.timeoutMs,debug:w||g};k==="none"&&(nt.\u006b\u0065\u0072\u006e\u0065\u006cProxyId=void 0);let D=ce.parse(nt);console.info(JSON.stringify({event:"harvest_attempt_started",attempt_number:v,max_attempts:p,query:D.query,location:D.location??null,max_questions:D.maxQuestions}));let yt=_t(),ot=null,Q=async K=>{qt(K.provider)!==T.plannedProvider&&(ot=new lt(T.plannedProvider,K.provider)),await Wt(i,{type:"provider_session_started",attemptNumber:v,maxAttempts:p,provider:K.provider,providerSessionId:K.providerSessionId,billingMode:K.billingMode,observedAt:new Date().toISOString()})},G=yt?.harvestBrowserMode==="headless-test"&&process.env[Xe]==="true";y=!1;let F=yt?await tn({...yt,forceHeadless:G,forceHeadful:!G},()=>He(D,T,O,s,Q,S,a&&C?{execution:a,permit:C}:void 0)):await He(D,T,O,s,Q,S,a&&C?{execution:a,permit:C}:void 0),Z=await Xi(l,Y?.disposableProxyId);if(F.cleanup.disposableProxyDeleted=Z,a&&C){let K=await Ue(a,C,F.cleanup,Y?.disposableProxyId??null);H=!0,I?.stop(),y=K.state!=="unknown"&&ka(F.cleanup)&&Z}else y=ka(F.cleanup)&&Z;if(F.error||ot){let K=ot??F.error,_=It(K);(_==="captcha"||_==="proxy_tunnel_failed")&&k==="location"&&(B++,B>=2&&(k="none"));let dt=!F.result&&y&&!O?.aborted&&m<p-1&&N()&&(_==="captcha"||Ca(_)||r==="location"&&ma(_));if(_==="captcha"?console.warn(JSON.stringify({event:"harvest_attempt_captcha",attempt_number:v,max_attempts:p,message:gt(K),will_retry:dt})):dt&&console.warn(JSON.stringify({event:"harvest_attempt_proxy_retry",attempt_number:v,max_attempts:p,outcome:_,message:gt(K),will_retry:dt})),await Wt(i,{type:"finished",attemptNumber:v,maxAttempts:p,outcome:_,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:F.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:F.result?.totalQuestions??0,durationMs:Date.now()-A,error:gt(K),willRetry:dt,cleanup:F.cleanup,debug:F.debug,completedAt:new Date().toISOString()}),x=K,dt)continue;if(F.result&&!ot){let At=await Ge(F.result,P);return Re(Fe(De(At,w),D.maxQuestions,D.questionsOnly),m,T.attemptKind==="provider_fallback"?1:0)}break}let at=F.result;if(!at)throw new Error("Harvest attempt completed without a result");if(Zi(at,r)){let K=new Jt(Qi(at)),_=y&&!O?.aborted&&m<p-1&&N();if(console.warn(JSON.stringify({event:"harvest_attempt_location_mismatch",attempt_number:v,max_attempts:p,message:K.message,will_retry:_})),await Wt(i,{type:"finished",attemptNumber:v,maxAttempts:p,outcome:"location_mismatch",\u006b\u0065\u0072\u006e\u0065\u006cSessionId:F.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:at.totalQuestions,durationMs:Date.now()-A,error:K.message,willRetry:_,cleanup:F.cleanup,debug:F.debug,completedAt:new Date().toISOString()}),x=K,_)continue;break}let pt=await Ge(at,P),R=Re(Fe(De(pt,w),D.maxQuestions,D.questionsOnly),m,T.attemptKind==="provider_fallback"?1:0),rt=ya(R),it=rt==="degraded_result"&&y&&!O?.aborted&&m<p-1&&N(),mt=rt==="degraded_result"?pa(R):null;if(it&&console.warn(JSON.stringify({event:"harvest_attempt_degraded_result",attempt_number:v,max_attempts:p,degradation_reasons:R.diagnostics.degradationReasons,will_retry:!0})),await Wt(i,{type:"finished",attemptNumber:v,maxAttempts:p,outcome:rt,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:F.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:R.totalQuestions,durationMs:Date.now()-A,error:mt,willRetry:it,cleanup:F.cleanup,debug:F.debug,completedAt:new Date().toISOString()}),it)continue;return(D.format==="json"||D.format==="both")&&await b.writeJSON(R,D.outputDir),(D.format==="csv"||D.format==="both")&&await Promise.all([b.writeCSV(R.flat,D.outputDir),R.videos.length>0?b.writeVideoCSV(R.videos,R.seed,D.outputDir):Promise.resolve(""),R.forums.length>0?b.writeForumCSV(R.forums,R.seed,D.outputDir):Promise.resolve(""),R.aiOverview.detected?b.writeAIOverviewCSV(R.aiOverview.citations,R.aiOverview.text,R.seed,D.outputDir):Promise.resolve(""),R.aiMode.detected?b.writeAIModeCSV(R.aiMode.citations,R.aiMode.text,R.seed,D.outputDir):Promise.resolve(""),R.whatPeopleSaying.length>0?b.writeWhatPeopleSayingCSV(R.whatPeopleSaying,R.seed,D.outputDir):Promise.resolve("")]),R}catch(T){a&&C&&!H&&(y=!1,await Ue(a,C,{\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:gt(T),physicalOutcome:"unknown",extractionDrained:!0,disposableProxyDeleted:!1}).catch(()=>{}));let L=It(T);(L==="captcha"||L==="proxy_tunnel_failed")&&k==="location"&&(B++,B>=2&&(k="none"));let J=y&&!O?.aborted&&m<p-1&&N()&&(L==="captcha"||Ca(L)||r==="location"&&ma(L));if(L==="captcha"?console.warn(JSON.stringify({event:"harvest_attempt_captcha",attempt_number:v,max_attempts:p,message:gt(T),will_retry:J})):J&&console.warn(JSON.stringify({event:"harvest_attempt_proxy_retry",attempt_number:v,max_attempts:p,outcome:L,message:gt(T),will_retry:J})),await Wt(i,{type:"finished",attemptNumber:v,maxAttempts:p,outcome:L,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,questionCount:0,durationMs:Date.now()-A,error:gt(T),willRetry:J,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=T,J)continue;if(L==="captcha")break;throw T}finally{I?.stop()}}throw x&&!(x instanceof z)?x:(console.warn(JSON.stringify({event:"harvest_captcha_exhausted",max_attempts:p,session_kind:l?"\u006b\u0065\u0072\u006e\u0065\u006c":"local"})),new z(Ze(`CAPTCHA on all ${p} fresh sessions. Try again in a few minutes.`)))}export{St as a,rn as b,Us as c,hs as d,us as e,cs as f,Ps as g,$t as h,bs as i,Is as j,vn as k,pe as l,Ce as m,Es as n,In as o,Vs as p,Wn as q,ve as r,An as s,Js as t,fe as u,Ne as v,js as w,Dn as x,Gn as y,En as z,te as A,Vn as B,ii as C,Kn as D,pi as E,ee as F,ne as G,ft as H,Dt as I,Nr as J};
|