mcp-scraper 0.97.0 → 0.97.1
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 +18 -1
- package/README.md +1 -1
- package/dist/actions-5X5CQAKO.js +1 -0
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- 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/bundle-GS657HXG.js +1 -0
- package/dist/chunk-2L7CHN5N.js +4 -0
- package/dist/{chunk-4P3LZNVA.js → chunk-4AEW53RU.js} +145 -145
- package/dist/{chunk-U3NV72AL.js → chunk-4YZ74SJ6.js} +1 -8
- package/dist/{chunk-AMYPXA2F.js → chunk-5RQWFYXY.js} +74 -74
- package/dist/{chunk-PD7BI7TR.js → chunk-5TQINRZN.js} +1 -1
- package/dist/{chunk-Z4EHBBL4.js → chunk-5UQAL7HV.js} +1 -1
- package/dist/{chunk-GLCR4KJI.js → chunk-6D25Q5BR.js} +20 -14
- package/dist/chunk-C3JWX6KM.js +10 -0
- package/dist/{chunk-NULRGHJ4.js → chunk-F3M7INSN.js} +7 -7
- package/dist/chunk-FLAWC5PF.js +5 -0
- package/dist/{chunk-PQRT4T2G.js → chunk-FM7BX2LU.js} +1 -1
- package/dist/chunk-IPQOBOFY.js +1 -0
- package/dist/chunk-J7XDXIB6.js +163 -0
- package/dist/chunk-JHDD6R3O.js +8 -0
- package/dist/chunk-KBZY2OGP.js +11 -0
- package/dist/{chunk-JNPM3U3L.js → chunk-NQFTETVC.js} +1 -1
- package/dist/{chunk-A4UASMEQ.js → chunk-P6CDR3RM.js} +1 -1
- package/dist/chunk-QCBCOEH5.js +1 -0
- package/dist/chunk-SJNSTO3C.js +42 -0
- package/dist/{chunk-MVMWPKRC.js → chunk-TZYITYL4.js} +1 -1
- package/dist/{chunk-YJPFEL2E.js → chunk-UUJYICAJ.js} +1 -1
- package/dist/{chunk-OSKCHEVM.js → chunk-XNTAHMPA.js} +1 -1
- package/dist/{chunk-ND4WIBXT.js → chunk-ZDECILF6.js} +1 -1
- package/dist/{chunk-OOB3RKWD.js → chunk-ZNPGM3XE.js} +1 -1
- package/dist/compatibility-UPPKZ4KY.js +1 -0
- package/dist/direct-completion-ZVPPEBDU.js +1 -0
- package/dist/dispatch-GRMMPKQD.js +1 -0
- package/dist/index.cjs +34 -34
- package/dist/index.js +1 -1
- package/dist/jobs-NRZHGQ7I.js +1 -0
- package/dist/queue-2VKW7SGH.js +1 -0
- package/dist/reconciliation-QC6SILLR.js +1 -0
- package/dist/{report-artifact-offload-6OOY2PTM.js → report-artifact-offload-PQNFDNPL.js} +1 -1
- package/dist/{server-6HUBN3OR.js → server-EYMJROPX.js} +530 -533
- package/dist/settlement-47EUTSGX.js +1 -0
- package/dist/vendor-errors-647LSH6H.js +1 -0
- package/dist/worker-AWJF7UYR.js +1 -0
- package/package.json +1 -1
- package/dist/actions-NCZNPYEY.js +0 -1
- package/dist/bundle-XR6XKYJM.js +0 -1
- package/dist/chunk-63VWBMYR.js +0 -3
- package/dist/chunk-6FAMBNHY.js +0 -1
- package/dist/chunk-M5QHXNFZ.js +0 -10
- package/dist/chunk-U4WIJZCX.js +0 -1
- package/dist/chunk-WHVK6FUB.js +0 -11
- package/dist/chunk-XYUJTIPE.js +0 -203
- package/dist/dispatch-ILBBKOSW.js +0 -1
- package/dist/queue-VOGXQDPR.js +0 -1
- package/dist/reconciliation-OXBG7JA2.js +0 -1
- package/dist/settlement-3PS32LQO.js +0 -1
- package/dist/worker-NXRU3TT3.js +0 -1
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{a as ot,c as Re}from"./chunk-C3JWX6KM.js";import{a as Et,b as oe,d as De,g as Ot,h as $,i as _e}from"./chunk-B4ZKPLSP.js";import{f as Je}from"./chunk-VVSHZV5S.js";import{a as se}from"./chunk-PKQHHCO4.js";import{a as Ye,b as Ke,c as Yt}from"./chunk-4ZVO6GX4.js";import{a as Ee,i as Ve,j,k as nt,m as at,n as ft,o as Vt}from"./chunk-C7MGJUTU.js";import{a as xt}from"./chunk-WNUXMPVX.js";import{a as Ge}from"./chunk-6N5EC7ZO.js";import{c as He,d as vt,f as Fe}from"./chunk-HNNYXMSI.js";import{randomUUID as qe}from"crypto";var Kt="(CAST(strftime('%s','now') AS INTEGER)*1000)",_=class extends Error{constructor(){super("physical_permission_or_receipt_unknown"),this.name="PhysicalPermissionError"}},je=new WeakSet;function $e(e){let t=e&&typeof e=="object"?e.physicalExecution:void 0;if(t!==void 0){if(!t||typeof t!="object"||!je.has(t))throw new _;return t}}var ze=e=>{if(e!==null&&(!e||e.length>512||/[\s\u0000-\u001f\u007f]/.test(e)||e.includes("://")))throw new _;return e};function qi(e){let t={...e.claim},n={...e.gate,args:[...e.gate.args]},a=e.db,i=()=>a??=xt();if(Fe({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 _;let{scope:s,profile:l,deadlineAt:d}=e,S={sql:`EXISTS (SELECT 1 FROM operation_runs r JOIN operation_executions x ON x.run_id=r.id
|
|
2
2
|
WHERE r.id=? AND r.user_id=? AND r.tool=? AND r.job_id=? AND r.status='running'
|
|
3
|
-
AND x.claim_token=? AND x.phase='effects_started' AND x.expires_at_ms>${
|
|
3
|
+
AND x.claim_token=? AND x.phase='effects_started' AND x.expires_at_ms>${Kt} AND ${Kt}<?) AND (${n.sql})`,args:[t.runId,t.userId,n.tool,n.jobId,t.token,d,...n.args]},u=new Set,h=async o=>{if(!u.has(o.token))throw new _;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:[o.id,o.token,t.runId,t.userId,t.token]})).rows[0];if(!c)throw new _;return c},r={watch(o,U){if(!u.has(o.token))throw new _;let c=new AbortController,g=!1,w=y=>{!g&&!c.signal.aborted&&c.abort(y)},p=()=>w(U?.reason);U?.addEventListener("abort",p,{once:!0}),U?.aborted&&p();let M=setTimeout(()=>w(new DOMException("Physical execution deadline exceeded","TimeoutError")),Math.max(0,Math.min(2147483647,d-Date.now())));return Object.freeze({signal:c.signal,stop:()=>{g||(g=!0,clearTimeout(M),U?.removeEventListener("abort",p))}})},async prepare(o,U){if(!/^[a-z][a-z0-9_-]{0,99}$/.test(o)||!Number.isSafeInteger(U)||U<1||U>100)throw new _;let c=i();await se(c);let g="physical:"+He(`${t.runId}\0${s}\0${U}`),w=qe(),p=vt({provider:o,profile:l,scope:s,attemptNumber:U}),M;try{await c.execute({sql:`INSERT INTO operation_physical_attempts
|
|
4
4
|
(id,parent_run_id,user_id,controller_token,claim_token,scope,attempt_number,provider,profile,intent_json,state)
|
|
5
5
|
SELECT ?,?,?,?,?,?,?,?,?,?,'prepared' WHERE (${S.sql})
|
|
6
|
-
AND NOT EXISTS (SELECT 1 FROM operation_physical_attempts WHERE parent_run_id=? AND state IN ('prepared','effects_started','unknown'))`,args:[g,t.runId,t.userId,t.token,w,s,U,o,l,p,...S.args,t.runId]})}catch(O){M=O}u.add(w);let y=Object.freeze({id:g,token:w}),T=await h(y).catch(()=>null);if(!T||T.state!=="prepared"||T.intent_json!==p)throw u.delete(w),M??new _;return y},async start(o,U){if(!["proxy","browser"].includes(U))throw new _;let c=i(),g=await h(o);if(JSON.parse(String(g.effects_json))[U]!==void 0)throw new _;let w=
|
|
6
|
+
AND NOT EXISTS (SELECT 1 FROM operation_physical_attempts WHERE parent_run_id=? AND state IN ('prepared','effects_started','unknown'))`,args:[g,t.runId,t.userId,t.token,w,s,U,o,l,p,...S.args,t.runId]})}catch(O){M=O}u.add(w);let y=Object.freeze({id:g,token:w}),T=await h(y).catch(()=>null);if(!T||T.state!=="prepared"||T.intent_json!==p)throw u.delete(w),M??new _;return y},async start(o,U){if(!["proxy","browser"].includes(U))throw new _;let c=i(),g=await h(o);if(JSON.parse(String(g.effects_json))[U]!==void 0)throw new _;let w=qe(),p;try{if((await c.execute({sql:`UPDATE operation_physical_attempts SET state='effects_started',effects_json=json_set(effects_json,?,?),updated_at=datetime('now')
|
|
7
7
|
WHERE id=? AND claim_token=? AND parent_run_id=? AND user_id=? AND controller_token=?
|
|
8
|
-
AND state IN ('prepared','effects_started') AND json_type(effects_json,?) IS NULL AND (${S.sql})`,args:[`$.${U}`,w,o.id,o.token,t.runId,t.userId,t.token,`$.${U}`,...S.args]})).rowsAffected!==1)throw new _;return}catch(T){p=T}if(p instanceof _)throw p;let M=await h(o).catch(()=>null),y=(await c.execute({sql:`SELECT (${S.sql}) AS current`,args:S.args}).catch(()=>({rows:[]}))).rows[0]?.current;if(!(M?.state==="effects_started"&&JSON.parse(String(M.effects_json))[U]===w&&y))throw p??new _},async assertActive(o){let U=i(),c=await h(o),g=(await U.execute({sql:`SELECT (${S.sql}) AS current`,args:S.args})).rows[0]?.current;if(c.state!=="effects_started"||!g)throw new _},async resource(o,U,c,g){if(!["proxy","browser"].includes(U))throw new _;let w=i(),p=await h(o),M=
|
|
9
|
-
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}`,T,o.id,o.token,t.runId,t.userId,`$.${U}`]})}catch{}let O=await h(o),x=JSON.parse(String(O.resources_json))[U];if(vt(x)!==T)throw new _},async complete(o,U){let c=i(),g=await h(o),w=JSON.parse(String(g.effects_json)),p=JSON.parse(String(g.resources_json));if(typeof U.drained!="boolean"||!U.effects||!U.details)throw new _;let M=JSON.parse(vt(U));if(Buffer.byteLength(JSON.stringify(M))>16*1024)throw new _;let y=Object.keys(w).every(G=>{let F=M.effects[G],P=p[G];return F&&P&&F.state!=="unknown"&&
|
|
10
|
-
WHERE id=? AND claim_token=? AND parent_run_id=? AND user_id=? AND state IN ('prepared','effects_started') AND receipt_json IS NULL`,args:[T,x,o.id,o.token,t.runId,t.userId]})}catch{}let b=await h(o);if(b.receipt_json!==x||b.state!==T)throw new _;return O}};return
|
|
11
|
-
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
|
|
12
|
-
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
|
|
8
|
+
AND state IN ('prepared','effects_started') AND json_type(effects_json,?) IS NULL AND (${S.sql})`,args:[`$.${U}`,w,o.id,o.token,t.runId,t.userId,t.token,`$.${U}`,...S.args]})).rowsAffected!==1)throw new _;return}catch(T){p=T}if(p instanceof _)throw p;let M=await h(o).catch(()=>null),y=(await c.execute({sql:`SELECT (${S.sql}) AS current`,args:S.args}).catch(()=>({rows:[]}))).rows[0]?.current;if(!(M?.state==="effects_started"&&JSON.parse(String(M.effects_json))[U]===w&&y))throw p??new _},async assertActive(o){let U=i(),c=await h(o),g=(await U.execute({sql:`SELECT (${S.sql}) AS current`,args:S.args})).rows[0]?.current;if(c.state!=="effects_started"||!g)throw new _},async resource(o,U,c,g){if(!["proxy","browser"].includes(U))throw new _;let w=i(),p=await h(o),M=ze(c);if(!JSON.parse(String(p.effects_json))[U])throw new _;let y=g??String(p.provider);if(!/^[a-z][a-z0-9_-]{0,99}$/.test(y))throw new _;let T=vt({resourceId:M,provider:y});try{await w.execute({sql:`UPDATE operation_physical_attempts SET resources_json=json_set(resources_json,?,json(?)),updated_at=datetime('now')
|
|
9
|
+
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}`,T,o.id,o.token,t.runId,t.userId,`$.${U}`]})}catch{}let O=await h(o),x=JSON.parse(String(O.resources_json))[U];if(vt(x)!==T)throw new _},async complete(o,U){let c=i(),g=await h(o),w=JSON.parse(String(g.effects_json)),p=JSON.parse(String(g.resources_json));if(typeof U.drained!="boolean"||!U.effects||!U.details)throw new _;let M=JSON.parse(vt(U));if(Buffer.byteLength(JSON.stringify(M))>16*1024)throw new _;let y=Object.keys(w).every(G=>{let F=M.effects[G],P=p[G];return F&&P&&F.state!=="unknown"&&ze(F.resourceId)===P.resourceId&&(F.state==="not_started"?P.resourceId===null:F.state==="terminated"&&P.resourceId!==null)}),T=M.drained&&y?Object.keys(w).length?"terminated":"not_started":"unknown",O={id:o.id,state:T,cleanup:M},x=vt(O);try{await c.execute({sql:`UPDATE operation_physical_attempts SET state=?,receipt_json=?,updated_at=datetime('now')
|
|
10
|
+
WHERE id=? AND claim_token=? AND parent_run_id=? AND user_id=? AND state IN ('prepared','effects_started') AND receipt_json IS NULL`,args:[T,x,o.id,o.token,t.runId,t.userId]})}catch{}let b=await h(o);if(b.receipt_json!==x||b.state!==T)throw new _;return O}};return je.add(r),Object.freeze(r)}async function zi(e,t,n=xt()){if(!Number.isSafeInteger(t)||t<=0||!e)throw new _;return(await n.execute({sql:`SELECT id,scope,attempt_number,provider,profile,state,effects_json,resources_json,receipt_json FROM operation_physical_attempts
|
|
11
|
+
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 ji(e,t=xt()){if(!Number.isSafeInteger(e.userId)||e.userId<=0||!e.runId&&(!e.jobId||!e.tool))throw new _;await se(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
|
|
12
|
+
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 $i(e,t){if(!Number.isSafeInteger(e)||e<=0||!t||t.length>512)throw new _;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]}}async function Qi(e,t=xt()){let{claim:n}=e,a=(await t.execute({sql:`SELECT p.* FROM operation_physical_attempts p
|
|
13
|
+
JOIN operation_runs r ON r.id=p.parent_run_id AND r.user_id=p.user_id
|
|
14
|
+
JOIN operation_executions x ON x.run_id=r.id
|
|
15
|
+
JOIN harvest_attempts a ON a.job_id=r.job_id AND a.user_id=r.user_id AND a.attempt_number=p.attempt_number
|
|
16
|
+
WHERE p.parent_run_id=? AND p.user_id=? AND p.attempt_number=? AND p.provider='\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061'
|
|
17
|
+
AND r.job_id=? AND r.status='unknown' AND x.phase='unknown' AND x.expires_at_ms>${Kt} AND x.claim_token=?
|
|
18
|
+
AND a.id=? AND a.status='finished' AND a.outcome='error' AND a.will_retry=0 AND a.completed_at IS NOT NULL`,args:[n.runId,n.userId,e.attemptNumber,e.jobId,n.token,e.evidenceId]})).rows[0];if(!a)return!1;let{isBrowserAdmissionRejected:i}=await import("./vendor-errors-647LSH6H.js"),s=(await t.execute({sql:"SELECT error FROM harvest_attempts WHERE id=? AND job_id=? AND user_id=?",args:[e.evidenceId,e.jobId,n.userId]})).rows[0];if(!i(String(s?.error??"")))return!1;let l=a.receipt_json==null?null:JSON.parse(String(a.receipt_json));if(a.state==="not_started"&&l?.cleanup?.details?.rejectionEvidenceId===e.evidenceId)return!0;let d=JSON.parse(String(a.resources_json)),S=JSON.parse(String(a.effects_json));if(a.state!=="unknown"||!l?.cleanup?.drained||d.browser?.resourceId!=null||Object.keys(S).some(h=>h!=="browser"))return!1;let u={id:String(a.id),state:"not_started",cleanup:{drained:!0,effects:{browser:{resourceId:null,state:"not_started"},proxy:{resourceId:null,state:"not_started"}},details:{rejectionEvidenceId:e.evidenceId,reconciliation:"explicit_admission_rejected",previousReceipt:l}}};return await t.execute({sql:`UPDATE operation_physical_attempts SET state='not_started',resources_json=json_set(resources_json,'$.browser',json(?)),receipt_json=?,updated_at=datetime('now') WHERE id=? AND state='unknown' AND receipt_json=? AND resources_json=? AND EXISTS(SELECT 1 FROM operation_executions WHERE run_id=? AND phase='unknown' AND expires_at_ms>${Kt} AND claim_token=?)`,args:[JSON.stringify({resourceId:null,provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"}),JSON.stringify(u),String(a.id),String(a.receipt_json),String(a.resources_json),n.runId,n.token]}),(await t.execute({sql:"SELECT 1 FROM operation_physical_attempts WHERE id=? AND state='not_started' AND json_extract(receipt_json,'$.cleanup.details.rejectionEvidenceId')=?",args:[String(a.id),e.evidenceId]})).rows.length===1}var dt=class extends Error{constructor(t,n){super(`SERP provider mismatch: planned ${t}, observed ${n}`),this.name="SerpProviderMismatchError"}};function _t(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 Qe(e){return ha({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 Ze(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 Jt(e,t){if(!t)throw new Error(`Requested SERP provider is unavailable: ${e}`);return e}function ha(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=Jt("\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=Jt("\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=Jt("\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=Jt("\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(l=>l!==t&&(l==="\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 ua(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 Xe(e){let t=ua(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 lt(e){return Xe(e)}function tn(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 re(e,t,n=new Date().toISOString()){let a=Xe(t);return{source:e,message:a??e.replaceAll("_"," "),observedAt:n}}function ca(e){return{provider:e.provider,providerDisconnectObserved:e.disconnectObservation!==null,providerDisconnectMessage:e.disconnectObservation?.message??null}}function en(e){return{...ca(e),providerSessionId:e.providerSessionId}}function nn(e,t,n,a){return new Proxy(e,{get(i,s,l){if(s==="launch")return async S=>{await t.start(n,"browser"),await i.launch(S);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(_t(u.provider)!==a)throw new dt(a,u.provider);await t.assertActive(n)};let d=Reflect.get(i,s,l);return typeof d=="function"?d.bind(i):d}})}function de(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",l=n.browserCloseSucceeded===!0&&n.localDisconnectSucceeded!==!1&&s,d=n.physicalOutcome==="not_started"&&n.browserCloseSucceeded===null,S={drained:n.extractionDrained===!0,effects:{browser:{resourceId:i,state:l?"terminated":d?"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:lt(n.browserCloseError),\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:lt(n.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError),localDisconnectError:lt(n.localDisconnectError)}};return(async()=>(d&&await e.resource(t,"browser",null),e.complete(t,S)))()}import{z as A}from"zod";var le=A.object({query:A.string().min(1),location:A.string().optional(),gl:A.string().length(2).default("us"),hl:A.string().length(2).default("en"),device:A.enum(["desktop","mobile"]).default("desktop"),proxyMode:A.enum(["location","configured","none"]).default(Et),proxyZip:A.string().regex(/^\d{5}$/).optional(),keepDefaultProxy:A.boolean().optional(),requireUsEgress:A.boolean().optional(),maxAttempts:A.number().int().min(1).max(12).optional(),debug:A.boolean().default(!1),depth:A.number().int().min(1).max(30).default(3),maxQuestions:A.number().int().min(1).max(100).default(100),headless:A.boolean().default(!1),profileDir:A.string().optional(),proxy:A.string().url().optional(),\u006b\u0065\u0072\u006e\u0065\u006cApiKey:A.string().optional(),\u006b\u0065\u0072\u006e\u0065\u006cProxyId:A.string().optional(),\u006b\u0065\u0072\u006e\u0065\u006cProfileName:A.string().optional(),\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges:A.boolean().optional(),\u006b\u0065\u0072\u006e\u0065\u006cStealth:A.boolean().optional(),serpIdentity:A.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/).optional(),\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution:A.unknown().optional(),outputDir:A.string().default("./paa-output"),format:A.enum(["json","csv","both"]).default("both"),serpOnly:A.boolean().default(!1),questionsOnly:A.boolean().default(!1),questionGrowthRecoveryRounds:A.number().int().min(0).max(4).default(2),pages:A.number().int().min(1).max(2).default(1),includeAllSerpFeatures:A.boolean().default(!1),includeLocalPack:A.boolean().default(!1),includeForums:A.boolean().default(!1),includeVideos:A.boolean().default(!1),includeAiOverview:A.boolean().default(!1),includeWhatPeopleSaying:A.boolean().default(!1),includeShortVideos:A.boolean().default(!1),recency:A.enum(["day","week","month","year"]).optional(),softDeadlineMs:A.number().optional()}),an=A.object({questionId:A.string().min(1),googleLinkId:A.string().nullable(),googleEvidenceId:A.string().nullable(),question:A.string().min(1),answer:A.string().optional(),answerExpansionIncomplete:A.boolean().optional(),sourceTitle:A.string().optional(),sourceSite:A.string().optional(),sourceCite:A.string().optional(),sources:A.array(A.object({title:A.string().nullable(),site:A.string().nullable(),description:A.string().nullable().optional(),url:A.string().min(1),rawUrl:A.string().min(1),resolvedUrl:A.string().nullable(),linkType:A.enum(["plain","google_url_redirect","google_goto_redirect"]),resolutionStatus:A.enum(["not_needed","resolved","unresolved","rejected"])})).default([])});import{promises as et}from"fs";import wt from"path";import Nt from"papaparse";var qt=class{async writeJSON(t,n){await et.mkdir(n,{recursive:!0});let i=`${t.seed.toLowerCase().replace(/\W+/g,"-").slice(0,40)}-${Date.now()}.json`,s=wt.join(n,i);return await et.writeFile(s,JSON.stringify(t,null,2),"utf8"),await Ge({title:`${t.seed} scrape`,content:JSON.stringify(t),source:`mcp-scraper:${s}`}),s}async writeCSV(t,n){await et.mkdir(n,{recursive:!0});let i=(t[0]?.seed_query??"paa").toLowerCase().replace(/\W+/g,"-").slice(0,40),s=Nt.unparse(t.map(({sources:S,...u})=>({...u,sources_json:JSON.stringify(S)})),{header:!0}),l=`${i}-${Date.now()}.csv`,d=wt.join(n,l);return await et.writeFile(d,s,"utf8"),d}async writeVideoCSV(t,n,a){await et.mkdir(a,{recursive:!0});let i=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),s=Nt.unparse(t,{header:!0}),l=`${i}-videos-${Date.now()}.csv`,d=wt.join(a,l);return await et.writeFile(d,s,"utf8"),d}async writeForumCSV(t,n,a){await et.mkdir(a,{recursive:!0});let i=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),s=Nt.unparse(t,{header:!0}),l=`${i}-forums-${Date.now()}.csv`,d=wt.join(a,l);return await et.writeFile(d,s,"utf8"),d}async writeAIOverviewCSV(t,n,a,i){await et.mkdir(i,{recursive:!0});let s=a.toLowerCase().replace(/\W+/g,"-").slice(0,40),l=t.map((h,r)=>({seed_query:a,response_text:r===0?n??"":"",citation_text:h.text,citation_href:h.href})),d=Nt.unparse(l,{header:!0}),S=`${s}-ai-overview-${Date.now()}.csv`,u=wt.join(i,S);return await et.writeFile(u,d,"utf8"),u}async writeAIModeCSV(t,n,a,i){await et.mkdir(i,{recursive:!0});let s=a.toLowerCase().replace(/\W+/g,"-").slice(0,40),l=t.map((h,r)=>({seed_query:a,response_text:r===0?n??"":"",citation_text:h.text,citation_href:h.href})),d=Nt.unparse(l,{header:!0}),S=`${s}-ai-mode-${Date.now()}.csv`,u=wt.join(i,S);return await et.writeFile(u,d,"utf8"),u}async writeWhatPeopleSayingCSV(t,n,a){await et.mkdir(a,{recursive:!0});let i=n.toLowerCase().replace(/\W+/g,"-").slice(0,40),s=t.map(u=>({seed_query:n,...u})),l=Nt.unparse(s,{header:!0}),d=`${i}-what-people-saying-${Date.now()}.csv`,S=wt.join(a,d);return await et.writeFile(S,l,"utf8"),S}};import{randomInt as ga}from"crypto";var ya="pr.oxylabs.io",pa=7777,ma=10,ws=2;function sn(){return process.env.OXYLABS_USERNAME?.trim()||void 0}function on(){return process.env.OXYLABS_PASSWORD?.trim()||void 0}function ka(){return(process.env.OXYLABS_COUNTRY?.trim()||"US").toUpperCase()}function zt(){return!!(sn()&&on())}function Ca(){let e="";for(let t=0;t<10;t++)e+=String(ga(0,10));return e}function Ma(e={}){let t=sn();if(!t)return;let n=t.startsWith("customer-")?t:`customer-${t}`,a=(e.country?.trim()||ka()).toUpperCase(),i=e.sticky?`-sessid-${Ca()}-sesstime-${ma}`:"";return`${n}-cc-${a}${i}`}function Se(e){return e.replace(/pr\.oxylabs\.io(:\d+)?/gi,"backup proxy").replace(/oxylabs/gi,"backup proxy")}function va(e){return`mcp-backup-custom-${`${Date.now()}-${e??0}-${Math.random().toString(36).slice(2,8)}`}`}async function jt(e,t={}){let n=Ma({sticky:t.sticky}),a=on();if(!n||!a)throw new Error("backup proxy pool is not configured");let i=new ot({apiKey:e});try{let s=await i.proxies.create({type:"custom",name:va(t.attemptIndex),protocol:"http",config:{host:ya,port:pa,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 l=s instanceof Error?s.message:String(s);throw new Error(Se(l))}}async function gs(e,t){if(!(!e||!zt()))try{return await jt(e,{attemptIndex:t})}catch{return}}async function ys(e,t){if(!(!e||!t))try{await new ot({apiKey:e}).proxies.delete(t)}catch{}}var gt={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 rn=`3, Nanjemoy,Maryland,United States
|
|
13
19
|
Aaronsburg,Pennsylvania,United States
|
|
14
20
|
Abbeville,Alabama,United States
|
|
15
21
|
Abbeville,Georgia,United States
|
|
@@ -21701,9 +21707,9 @@ Zortman,Montana,United States
|
|
|
21701
21707
|
Zuehl,Texas,United States
|
|
21702
21708
|
Zumbrota,Minnesota,United States
|
|
21703
21709
|
Zuni,New Mexico,United States
|
|
21704
|
-
Zwolle,Louisiana,United States`,
|
|
21705
|
-
`)){let a=n.trim();if(!a)continue;let i=a.toLowerCase();e.has(i)||e.set(i,a);let s=i.split(",",1)[0],l=t.get(s);l?l.push(a):t.set(s,[a])}for(let n of Object.values(rn)){let a=String(n).toLowerCase();e.has(a)||e.set(a,String(n))}Ue=e,ln=t}function fa(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 Sn(e){let t=Buffer.from(e,"utf8");return`w+${Buffer.concat([Buffer.from([8,2,16,32,34]),Buffer.from(fa(t.length)),t]).toString("base64")}`}function dn(){return{canonical:null,matched:!1,source:"unresolved",ambiguousCandidates:0}}function St(e,t){return{canonical:e,matched:!0,source:t,ambiguousCandidates:0}}function he(e){let t=e.toLowerCase().trim();if(!t)return dn();if(gt[t])return St(gt[t],"alias");va();let n=Ue,a=ln,i=n.get(t);if(i)return St(i,"exact");let s=n.get(`${t},united states`);if(s)return St(s,"state-or-country");let l=t.split(",");if(l.length>=2){let r=l[0].trim(),o=l.slice(1).join(",").trim(),U=Se[o.toUpperCase()]??o,c=n.get(`${r},${U.toLowerCase()},united states`);if(c)return St(c,"city-state")}let d=t.match(/^(.*?)[\s,]+([a-z]{2})$/);if(d){let r=Se[d[2].toUpperCase()];if(r){let o=n.get(`${d[1].trim()},${r.toLowerCase()},united states`);if(o)return St(o,"city-state")}}let S=a.get(t);if(S?.length===1)return St(S[0],"city-unique");if(S&&S.length>1)return{canonical:null,matched:!1,source:"unresolved",ambiguousCandidates:S.length};let u=l[0].trim();if(u!==t&>[u])return St(gt[u],"alias-partial");let h=t.replace(/\s+[a-z]{2}$/,"").trim();return h!==t&>[h]?St(gt[h],"alias-partial"):dn()}function Un(e){return he(e).canonical??e}var hn={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"},Na={"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 Ta(e){return e?e.slice(-6):null}function X(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:Ta(n),target:a,error:i,disposable:s}}}function Pa(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function ba(e){return e.trim().toLowerCase().replace(/\./g,"").replace(/\s+/g," ")}function Ia(e){if(!e)return!0;let t=ba(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(hn).includes(n)?n:null}return hn[Pa(t)]??null}function Wa(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 ht(e,t,n){return n?`mcp-serp-residential-${e.toLowerCase()}-${t.toLowerCase()}-${n}`:`mcp-serp-residential-${e.toLowerCase()}-${t.toLowerCase()}`}function Ot(e,t){let n=`${Date.now()}-${t??0}-${Math.random().toString(36).slice(2,8)}`;return`${e}-fresh-${n}`}function Aa(e){return`mcp-serp-residential-us-zip-${e}`}function un(e,t){if(!e||t.toLowerCase()!=="us")return null;let n=Un(e),a=n.split(",").map(u=>u.trim()).filter(Boolean);if(a.length>1&&Ia(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:ht("US",u),config:{country:"US",state:u}}:null}let[i="",s=""]=a;if(!i||!s)return null;let l=ce(s);if(!l)return null;let d=Wa(i),S=d[0];return S?{canonicalLocation:n,level:"city",country:"US",state:l,city:S,cityCandidates:d,proxyName:ht("US",l,S),config:{country:"US",state:l,city:S}}:null}function xa(e){return`${e.city}|${e.state}`}function cn(e,t){return t&&/^\d{5}$/.test(t)?t:Na[xa(e)]??null}function wn(e,t){return{...e,level:"zip",zip:t,proxyName:Aa(t),config:{country:e.country,state:e.state,zip:t}}}function ue(e,t){return{...e,proxyName:t}}function ge(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 Oa(e,t){return e.find(n=>n.type==="residential"&&n.status!=="unavailable"&&!!n.id&&(n.name===t.proxyName||ge(n.config,t,t.level==="city"?t.city:void 0)))??null}function La(e,t){for(let n of t.cityCandidates){let a=ht(t.country,t.state,n),i=e.find(s=>s.type==="residential"&&s.status!=="unavailable"&&!!s.id&&(s.name===a||ge(s.config,t,n)));if(i)return i}return null}function jt(e){return{...e,level:"state",proxyName:ht(e.country,e.state),config:{country:e.country,state:e.state}}}function Ba(e,t){let n=ht(t.country,t.state);return e.find(a=>a.type==="residential"&&a.status!=="unavailable"&&!!a.id&&(a.name===n||ge(a.config,t)))??null}function Ha(e,t){return jt(e)}function Ut(e){return e instanceof Error?e.message:String(e)}function Fa(e,t,n){let a=[],i=cn(e,t);if(i){let l=wn(e,i);a.push(ue(l,Ot(l.proxyName,n)))}for(let l of e.cityCandidates){let d={...e,level:"city",city:l,proxyName:ht(e.country,e.state,l),config:{country:e.country,state:e.state,city:l}};a.push(ue(d,Ot(d.proxyName,n)))}let s=jt(e);return a.push(ue(s,Ot(s.proxyName,n))),a}async function we(e,t,n){if(e.backupOnExhaustion&&n.length>0&&e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey&&qt())try{let a=await zt(e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,{attemptIndex:e.attemptIndex});return X("backup_custom",e.proxyMode,a,t,null,!0)}catch(a){n.push(`backup: ${le(Ut(a))}`)}return X("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,t,n.join(" | "))}async function Ps(e){if(!e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey||!qt())return null;try{let t=await zt(e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,{attemptIndex:e.attemptIndex});return X("backup_custom",e.proxyMode,t,null,null,!0)}catch{return null}}async function Ra(e,t,n){let a=[];for(let i of Fa(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 X("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=jt(n);try{let s=await e.proxies.create({type:"isp",name:Ot(`mcp-serp-isp-${i.country.toLowerCase()}-${(i.state??"").toLowerCase()}`,t.attemptIndex),config:{country:i.country,...i.state?{state:i.state}:{}}});if(s.id)return X("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 we(t,n,a)}async function gn(e,t){if(!e||!t)return;await new ot({apiKey:e}).proxies.delete(t)}async function bs(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 ot({apiKey:e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey}),a=un(t,"us");if(!a)throw new Error("Could not resolve the mobile Maps proxy state");let i=await n.proxies.create({type:"mobile",name:Ot(`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 X("mobile_created","configured",i.id,a,null,!0)}async function yn(e){if(e.proxyMode==="none")return X("disabled",e.proxyMode,void 0,null,null);if(e.proxyMode==="configured")return X("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,null,null);let t=un(e.location,e.gl);if(!t||!e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey)return X("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 ot({apiKey:e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey});try{let a=e.attemptIndex??0;if(e.fresh)return await Ra(n,e,t);if(a>=1){let h=Ha(t,a),r=[];try{let o=await n.proxies.create({type:"residential",name:h.proxyName,config:h.config});if(o.id)return X("location_created",e.proxyMode,o.id,h,null);r.push(`${h.state}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(o){r.push(`${h.state}: ${Ut(o)}`)}return we(e,h,r)}let i=[];for await(let h of await n.proxies.list())i.push(h);let s=cn(t,e.proxyZip),l=[];if(s){let h=wn(t,s),r=Oa(i,h);if(r?.id)return X("location_reused",e.proxyMode,r.id,h,null);try{let o=await n.proxies.create({type:"residential",name:h.proxyName,config:{country:h.country,zip:s}});if(o.id)return X("location_created",e.proxyMode,o.id,h,null);l.push(`${s}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(o){l.push(`${s}: ${Ut(o)}`)}}let d=La(i,t);if(d?.id)return X("location_reused",e.proxyMode,d.id,t,l.join(" | ")||null);for(let h of t.cityCandidates)try{let r=await n.proxies.create({type:"residential",name:ht(t.country,t.state,h),config:{country:t.country,state:t.state,city:h}});if(r.id)return X("location_created",e.proxyMode,r.id,{...t,level:"city",city:h,proxyName:ht(t.country,t.state,h),config:{country:t.country,state:t.state,city:h}},null);l.push(`${h}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(r){l.push(`${h}: ${Ut(r)}`)}let S=jt(t),u=Ba(i,S);if(u?.id)return X("location_reused",e.proxyMode,u.id,S,l.join(" | "));try{let h=await n.proxies.create({type:"residential",name:S.proxyName,config:S.config});if(h.id)return X("location_created",e.proxyMode,h.id,S,l.join(" | "));l.push(`${S.state}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(h){l.push(`${S.state}: ${Ut(h)}`)}return we(e,t,l)}catch(a){return X("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,t,Ut(a))}}function ye(){return process.env.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_BROWSER_WSS?.trim()||null}function pn(){return process.env.SERP_BROWSER_PROVIDER?.trim().toLowerCase()==="\u006b\u0065\u0072\u006e\u0065\u006c"?!1:!!ye()}import{chromium as ve}from"playwright-extra";import qa from"puppeteer-extra-plugin-stealth";import{chromium as za}from"playwright";var tt={paaItem:".related-question-pair",captchaMarker:'#captcha-form, #recaptcha, form[action*="/sorry/"], .g-recaptcha, [data-sitekey]'},Lt={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"]},mn={section:".ULSxyf",item:"a.KYg7td.INpicf",title:".hyYc0c",source:".K4ETW"},kn={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"},Cn={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"},Mn={root:'[data-hveid="CAUQAA"]',wrapper:".Fgyi2e",citations:'.Fgyi2e [data-hveid] a[jsname="pxBnId"]'},vn={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"},Nn="2026-05-07",As={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 $t(e,t,n,a){let i,s=!1,l,d=()=>{},S=()=>a?.reason instanceof DOMException&&a.reason.name==="TimeoutError"?a.reason:new at,u=()=>d(S()),h=new Promise((o,U)=>{d=U}),r=async o=>{let U;try{await Promise.race([o.close().catch(()=>{}),new Promise(c=>{U=setTimeout(c,2e3)})])}finally{U&&clearTimeout(U)}};if(a?.aborted)throw S();a?.addEventListener("abort",u,{once:!0}),l=setTimeout(()=>d(new DOMException("Optional pagination timed out","TimeoutError")),3e4);try{return await Promise.race([(async()=>{let o=await e.newPage();if(s)throw await r(o),new at;if(i=o,await t(o),s)throw new at;return n(o)})(),h])}finally{s=!0,l&&clearTimeout(l),a?.removeEventListener("abort",u),i&&await r(i)}}var Da=/\b(?:HeadlessChrome|Chrome|Chromium|Firefox)\/\d+|\bVersion\/\d+.*\bSafari\//;async function pe(e){try{let t=await e.evaluate(()=>navigator.userAgent);return typeof t=="string"&&Da.test(t)?t:null}catch{return null}}async function me(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 pe(n)}catch{return null}finally{t&&await t.close().catch(()=>{})}}function Bs(e,t){return t?{...e,userAgent:t}:e}function Tn(e){let{headless:t,viewport:n,userAgent:a,user_agent:i,...s}=e;return s}async function Pn(e,t={}){return t.blockServiceWorkers?e.newContext({viewport:null,serviceWorkers:"block"}):e.contexts()[0]??await e.newContext({viewport:null})}async function bn(e){return e.pages()[0]??await e.newPage()}function Qt(e={}){let t=e.nowMs??Date.now(),n=Math.max(0,e.waitMs??3e4);return Math.min(e.deadlineMs??1/0,t+n)}var Ds=Qt({nowMs:0});async function In(e){let t=Qt(e),n=async()=>{if(e.signal?.aborted)throw xt(e.signal);let i=t-Date.now();if(i<=0)return!0;let s;try{return await $(Promise.race([e.observeChallenge(),new Promise(l=>{s=setTimeout(()=>l(!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 $(new Promise(s=>{i=setTimeout(s,Math.min(500,t-Date.now()))}),e.signal)}finally{i&&clearTimeout(i)}if(e.signal?.aborted)throw xt(e.signal);if(Date.now()>t)break;a=await n()}return a}var Ga=`#search h3, #rso h3, #search .related-question-pair, #rso .related-question-pair, #search ${Lt.item}, #rso ${Lt.item}, #search .isv-r, #rso .isv-r`,Ea=75e3,Va=3e3;async function ke(e,t){if(t.signal?.aborted)throw new at;let n=Math.min(Date.now()+Ea,t.deadlineMs===void 0?1/0:t.deadlineMs-Va);if(n<=Date.now())throw new nt("Google search navigation has no remaining time");let a=Ke(Math.max(1,n-Date.now()),t.signal),i=!1,s,l=async()=>{if(!await $(Wn(e),a))return!1;if(i=!0,s??=Qt({deadlineMs:n}),await In({solverEnabled:t.solverEnabled,deadlineMs:s,signal:a,observeChallenge:()=>Wn(e)}))throw new j("Google challenge did not clear within the remaining browser time.");return!0};try{await Ja(e,{params:Ya(t),deadlineMs:n,signal:a},l,Ka);let d=()=>$(_a(e,{query:t.query,deadlineMs:n,signal:a,readySelector:Ga},l),a);if(await d(),t.purpose==="paa"){let S=Math.min(n,Date.now()+4e3);await $(e.waitForSelector(tt.paaItem,{state:"visible",timeout:Math.max(1,S-Date.now())}).catch(()=>null),a);for(let u=1;u<=6&&Date.now()<n&&(await l(),!await $(e.locator(tt.paaItem).count(),a));u+=1)await $(e.evaluate(h=>{window.scrollTo(0,document.body.scrollHeight*h)},u/6),a),await $(new Promise(h=>setTimeout(h,Math.min(400,n-Date.now()))),a)}for(;Date.now()<n;){await d();let S=await $(e.locator(tt.paaItem).count(),a)>0;if(!await l())return{hasPaa:S,challengeObserved:i}}throw new nt("Google search results did not reach a readable state")}catch(d){throw t.signal?.aborted?new at:d instanceof j||d instanceof nt?d:d instanceof Error&&d.message==="Google search results did not reach a readable state"?new nt(d.message):d 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(d.message)?new nt(d.message):d instanceof Error&&["Google homepage did not expose a visible search box","Google search form did not expose a visible Search button"].includes(d.message)?new nt(d.message):new nt(a.aborted?"Google search navigation timed out before results were ready":"Google homepage search interaction failed")}}async function Wn(e){if(/google\.[^/]+\/sorry(?:\/|\?|$)/i.test(e.url())||await e.locator(tt.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 Ya(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 Ka(e,t={}){let n=t.deadlineMs??Date.now()+1e4,a=async(d,S,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,o,U=new Promise((c,g)=>{r=setTimeout(()=>g(new Error(`Google search ${d} timed out`)),h),t.signal&&(o=()=>{let w=new Error("Google search navigation aborted");w.name="AbortError",g(w)},t.signal.addEventListener("abort",o,{once:!0}))});try{return await Promise.race([S(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 ${d} failed`)}finally{r&&clearTimeout(r),o&&t.signal?.removeEventListener("abort",o)}},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(d=>{let S=new RegExp(d,"i");return/^consent\.google\./i.test(window.location.hostname)||!!document.querySelector("#W0wltc")||Array.from(document.querySelectorAll('button, [role="button"]')).some(u=>S.test(u.textContent?.trim()??""))},i.source),2e3))return!1;let l=e.locator("#W0wltc").or(e.getByRole("button",{name:i}));for(let d=0,S=await a("consent inspection",()=>l.count(),2e3);d<S;d+=1){let u=l.nth(d);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 Ja(e,t,n,a){let i=async(U,c,g=8e3)=>{let w=Math.min(g,t.deadlineMs-Date.now());if(t.signal?.aborted){let T=new Error("Google search navigation aborted");throw T.name="AbortError",T}if(w<=0)throw new Error("Google search navigation deadline exhausted");let p,M,y=new Promise((T,O)=>{p=setTimeout(()=>O(new Error(`Google search ${U} timed out`)),w),t.signal&&(M=()=>{let x=new Error("Google search navigation aborted");x.name="AbortError",O(x)},t.signal.addEventListener("abort",M,{once:!0}))});try{return await Promise.race([c(w),y])}catch{if(t.signal?.aborted){let O=new Error("Google search navigation aborted");throw O.name="AbortError",O}throw new Error(`Google search ${U} failed`)}finally{p&&clearTimeout(p),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 l='textarea[name="q"], input[name="q"]';await i("search box readiness",U=>e.waitForSelector(l,{state:"visible",timeout:U}));let d=e.locator(l),S;for(let U=0,c=await i("search box inspection",()=>d.count());U<c;U+=1)if(await i("search box inspection",()=>d.nth(U).isVisible())){S=d.nth(U);break}if(!S)throw new Error("Google homepage did not expose a visible search box");let u=S;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[w,p]of Object.entries(c)){if(w==="q")continue;let M=Array.from(U.querySelectorAll("input")).filter(y=>y.name===w);for(let y of M)y.value=p,y.disabled=!1;if(M.length===0){let y=document.createElement("input");y.type="hidden",y.name=w,y.value=p,U.appendChild(y)}}let g=new URL(U.action,location.href);for(let w of Object.keys(c))g.searchParams.delete(w);U.action=g.toString()},t.params));let r=h.locator('input[name="btnK"], button[name="btnK"], button[type="submit"]'),o=!1;for(let U=0,c=await i("search button inspection",()=>r.count());U<c;U+=1){let g=r.nth(U);if(await i("search button inspection",()=>g.isVisible())){await i("search submit",w=>g.click({timeout:w,noWaitAfter:!0})),o=!0;break}}if(!o)throw new Error("Google search form did not expose a visible Search button");await n(),await s(),await n()}async function _a(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 l=!1;try{let S=new URL(e.url());l=/(^|\.)google\.[a-z.]+$/i.test(S.hostname)&&S.pathname==="/search"&&S.searchParams.get("q")===t.query}catch{}if(l){let S=await e.waitForSelector(a,{state:"visible",timeout:Math.min(500,Math.max(1,i-Date.now()))}).catch(()=>null),u=S?!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(S||u){if(await n()===!0)continue;return}}if(t.signal?.aborted)throw new Error("Google search navigation aborted");let d=Math.min(200,i-Date.now(),t.deadlineMs-Date.now());d>0&&await e.waitForTimeout(d)}throw new Error("Google search results did not reach a readable state")}ve.use(qa());var ja=180,$a=3e3,Qa=5e3,Za='#search, #rso, a[href] h3, [data-snhf], [role="main"]';function Ce(e,t){return e?Math.max(1,Math.min(t,e-Date.now())):t}function Xa(e,t){let n=process.env[e];if(!n)return t;let a=Number(n);return Number.isInteger(a)&&a>0?a:t}function Me(e){return e?e.slice(-6):null}function An(e,t){let n=(t??process.env.SERP_REDIRECT_BASE)?.trim().replace(/\/+$/,"");return n?`${n}/g/${Buffer.from(e,"utf8").toString("base64url")}`:e}function ti(e){return e?/united states|u\.?s\.?a?\.?|^us$/i.test(e.trim()):!1}function Tt(e){return e instanceof Error?e.message:String(e)}function ei(e){return/\b409\b|conflict|already exists/i.test(Tt(e))}function ni(e){return/\b404\b|not[ _-]?found|already (?:gone|deleted|closed)|does not exist/i.test(Tt(e))}async function ai(e,t){try{await e.profiles.create({name:t})}catch(n){if(!ei(n))throw n}}function xn(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 yt(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 ii(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 l=new URL(/^https?:\/\//i.test(t)?t:`https://${t}`);if(l.hostname.replace(/^www\./,"").replace(/^m\./,"").toLowerCase()!=="youtube.com")throw new Error("channel URL must be on youtube.com");let S=l.pathname.split("/").filter(Boolean),u=S[0]??"",h=S[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 Zt=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 nt("\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 ot({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):Xa("\u004b\u0045\u0052\u004e\u0045\u004c_BROWSER_TIMEOUT_SECONDS",ja),l=Math.min(s,600);t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName&&t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges===!0&&await ai(this.\u006b\u0065\u0072\u006e\u0065\u006cClient,t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName);let d=Yt();this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=null,this.last\u004b\u0065\u0072\u006e\u0065\u006cBillingMode="headful",d?.headlessSentOut&&(d.headlessSentOut.value=this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent);let S=await this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.create(Tn({stealth:t.\u006b\u0065\u0072\u006e\u0065\u006cStealth===!0,timeout_seconds:l,...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=S.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 S.stealth=="boolean"?S.stealth:null,this.\u006b\u0065\u0072\u006e\u0065\u006cSolverEnabled=t.\u006b\u0065\u0072\u006e\u0065\u006cStealth===!0&&S.stealth!==!1,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed=typeof S.proxy_id=="string"?!!S.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 yt(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(o){u=!1,h=Tt(o)}let r={sessionId:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,proxyMode:n,requestedProxyIdPresent:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,requestedProxyIdSuffix:Me(t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId),createdProxyIdPresent:typeof S.proxy_id=="string"?!!S.proxy_id:null,createdProxyIdSuffix:Me(S.proxy_id),retrievedProxyIdPresent:null,retrievedProxyIdSuffix:null,retrievedProxyIdMatchesRequested:null,defaultProxyDisabled:u,defaultProxyDisableError:h,proxyResolution:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution??null,timeoutSeconds:l,stealth:typeof S.stealth=="boolean"?S.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:l,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 za.connectOverCDP(S.cdp_ws_url),this.context=await Pn(this.browser),this.page=await bn(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 o=this.debugSnapshot.networkLocation?.country??null;if(!ti(o))throw new j(`Non-US egress (${o??"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 ve.launchPersistentContext(t.profileDir,{...i,...xn(t)}),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage(),this.debugSnapshot.context.userAgent=await pe(this.page);else{this.browser=await ve.launch(i);let s=await me(this.browser);this.debugSnapshot.context.userAgent=s,this.context=await this.browser.newContext(xn(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 yt(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=Me(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=Tt(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 d=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 d.org=="string"?d.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 yt(n.goto("https://ipapi.co/json/",{waitUntil:"domcontentloaded",timeout:7e3}),8e3,"browser network location navigation");let s=await n.locator("body").innerText({timeout:2e3}),l=JSON.parse(s);return{source:"ipapi.co",ip:typeof l.ip=="string"?l.ip:null,city:typeof l.city=="string"?l.city:null,region:typeof l.region=="string"?l.region:null,country:typeof l.country_name=="string"?l.country_name:typeof l.country=="string"?l.country:null,org:typeof l.org=="string"?l.org:null,timezone:typeof l.timezone=="string"?l.timezone:null,error:null}}catch(a){return t(Tt(a))}finally{await n?.close().catch(()=>{})}}async loadJsonInDebugPage(t,n){try{await yt(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 $t(this.context,async()=>{},t,n)}async navigateToSERP(t,n,a,i,s){let l=new URLSearchParams({q:t,gl:a,hl:i,pws:"0"});s?.tbs&&l.set("tbs",s.tbs),n&&l.set("uule",n);let d="https://www.google.com/search?"+l.toString(),S=An(d),u=s?.debug?{requestedUrl:d,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 o=await ke(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,d,{hasPaa:o.hasPaa,captchaDetected:o.challengeObserved===!0},r),{hasPaa:o.hasPaa}}catch(o){throw await this.updateSerpNavigationDebug(u,d,{hasPaa:null,captchaDetected:o instanceof j?!0:null},r),o}}try{await this.page.goto(S,{waitUntil:"domcontentloaded",timeout:Ce(s?.deadlineMs,s?.purpose==="serp"?8e3:45e3)})}catch(r){await this.updateSerpNavigationDebug(u,d,{hasPaa:null,captchaDetected:null});let o=await this.captureDiagnostics(d);throw new nt(`page.goto failed: ${r.message} | ${o}`)}if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(u,d,{hasPaa:!1,captchaDetected:!0}),new j(this.captchaMessage());if(s?.purpose==="serp"){await this.page.waitForSelector(Za,{timeout:Ce(s.deadlineMs,1500)}).catch(()=>null);let r=await this.page.locator(tt.paaItem).count().catch(()=>0)>0;return await this.updateSerpNavigationDebug(u,d,{hasPaa:r,captchaDetected:!1}),{hasPaa:r}}if(await this.page.waitForSelector(tt.paaItem,{timeout:Ce(s?.deadlineMs,4e3)}).catch(()=>null))return await this.updateSerpNavigationDebug(u,d,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(u,d,{hasPaa:!1,captchaDetected:!0}),new j(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(tt.paaItem).count()>0)return await this.updateSerpNavigationDebug(u,d,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};return await this.updateSerpNavigationDebug(u,d,{hasPaa:!1,captchaDetected:!1}),{hasPaa:!1}}async isSerpChallengeVisible(){if(!this.page)return!1;if(await this.page.locator(tt.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 l=Math.min(1e3,i?.deadlineMs===void 0?1e3:i.deadlineMs-Date.now());if(i&&(i.signal?.aborted||l<=0))return;let d=Promise.all([this.page.title().catch(()=>""),this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,500)).catch(()=>"")]),[S,u]=i?await $(yt(d,l,"\u004b\u0065\u0072\u006e\u0065\u006c navigation debug"),i.signal):await d;t.title=S,t.bodySnippet=u,t.captchaDetected=a.captchaDetected??/recaptcha|unusual traffic|are you a robot/i.test(u)}catch(s){t.bodySnippet=`debug capture failed: ${Tt(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),l=/recaptcha|unusual traffic|are you a robot/i.test(i),d=[s?"CONSENT_WALL":"",l?"BOT_CHALLENGE":"",n!==t?"REDIRECTED":""].filter(Boolean).join(",");return`intended=${t} | final=${n} | title="${a}" | flags=[${d}] | 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.":De}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 ke(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?An(t,n):t;try{if(await this.page.goto(a,{waitUntil:"domcontentloaded",timeout:45e3}),/google\.[^/]+\/search\?/i.test(t)&&await this.isSerpChallengeVisible())throw new j(this.captchaMessage())}catch(i){if(i instanceof j)throw i;let s=await this.captureDiagnostics(t);throw new nt(`page.goto failed: ${i.message} | ${s}`)}}async navigateToChannel(t){let n=ii(t);try{await this.page.goto(n,{waitUntil:"networkidle",timeout:3e4})}catch(a){let i=await this.captureDiagnostics(n);throw new nt(`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,l=this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed,d=this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource,S=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=yt(a.browsers.deleteByID(n),Qa,`\u004b\u0065\u0072\u006e\u0065\u006c session ${n} delete`),o=yt(t.close(),$a,`\u004b\u0065\u0072\u006e\u0065\u006c browser ${n} close`),[U,c]=await Promise.allSettled([r,o]);this.last\u004b\u0065\u0072\u006e\u0065\u006cClosedAtMs=Date.now(),i!=null&&Ye({\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,source:"browser_driver",stealth:s,headlessSent:u,proxyUsed:l,proxySource:d,proxyType:S,openedAtMs:i,closedAtMs:this.last\u004b\u0065\u0072\u006e\u0065\u006cClosedAtMs});let g=U.status==="rejected"&&ni(U.reason),w={\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!0,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:U.status==="fulfilled"||g,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError: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:h.provider,providerSessionId:h.providerSessionId,providerDisconnectObserved:!1,providerDisconnectMessage:null};return U.status==="rejected"&&!g?(console.warn(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_failed",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n,message:w.\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:w.browserCloseError})),console.warn(`\u004b\u0065\u0072\u006e\u0065\u006c browser close failed for ${n}:`,c.reason)),w}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 si}from"playwright";var oi=new Set(["image","media","font","stylesheet","ping"]),ri=["doubleclick.net","googleadservices.com","googlesyndication.com","google-analytics.com"],di='#search, #rso, a[href] h3, [data-snhf], [role="main"]',li=3e4,On=1500,Si=3e3,Ui=new Set(["https://www.google.com","https://www.gstatic.com","https://www.recaptcha.net","https://recaptcha.net"]);function Xt(e){return e.origin==="https://www.google.com"&&/^\/sorry(?:\/|$)/.test(e.pathname)}function hi(e,t){if(Xt(e)||Ui.has(e.origin)&&/^\/recaptcha(?:\/|$)/.test(e.pathname))return!0;try{return Xt(new URL(t))}catch{return!1}}function pt(e,t){return e?Math.max(1,Math.min(t,e-Date.now())):t}async function ui(e,t,n){let a=Math.min(Date.now()+Si,n??1/0);if(Date.now()>=a)return!1;let i=e.request(),s=new AbortController;t.add(s);let l=new Promise((u,h)=>{s.signal.addEventListener("abort",()=>h(s.signal.reason),{once:!0})}),d=setTimeout(()=>{s.abort(new DOMException("Controller asset transfer timed out","TimeoutError"))},Math.max(0,a-Date.now())),S=!1;try{let u=i.headers();if(s.signal.aborted||Date.now()>=a)return!1;let h=await Promise.race([fetch(i.url(),{method:i.method(),signal:s.signal,redirect:"error",headers:{accept:u.accept??"*/*","accept-language":u["accept-language"]??"en-US,en;q=0.9","user-agent":u["user-agent"]??"Mozilla/5.0"},body:i.method()==="GET"||i.method()==="HEAD"?void 0:i.postData()}),l]);if(!h.ok||s.signal.aborted||Date.now()>=a)return!1;let r=Buffer.from(await Promise.race([h.arrayBuffer(),l]));if(s.signal.aborted||Date.now()>=a)return!1;let o={status:h.status,contentType:h.headers.get("content-type")??"application/octet-stream",headers:{"cache-control":"public, max-age=3600"},body:r};return clearTimeout(d),S=!0,await e.fulfill(o),!0}catch{return S}finally{clearTimeout(d),t.delete(s),s.abort()}}var te=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;controllerAssetTransfers=new Set;operationDeadlineMs;observeDisconnect(t,n){this.closing||this.disconnectObservation||(this.disconnectObservation=oe(t,n))}async launch(t){if(this.page)return;this.operationDeadlineMs=t.operationDeadlineMs,this.closing=!1,this.providerSessionId=null,this.disconnectObservation=null;let n=ye();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 si.connectOverCDP(n,{timeout:pt(t.operationDeadlineMs,li)})}catch(s){let l=(s instanceof Error?s.message:String(s)).replaceAll(n,"[redacted endpoint]");throw new Error(lt(l)??"\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=l=>l),typeof s.__publicField!="function"&&(s.__publicField=(l,d,S)=>(l[d]=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 i=await this.cdpSession.send("Browser.getSessionId");this.providerSessionId=ze(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=>{if(this.closing)return;let a=n.request(),i=a.resourceType(),s;try{s=new URL(a.url())}catch{await n.continue();return}if(s.origin==="https://www.google.com"&&(s.pathname==="/sgasync"||/^\/async(?:\/|$)/.test(s.pathname))||hi(s,t.url())){await n.continue();return}let d=s.hostname.toLowerCase();if(!((s.origin==="https://www.google.com"||s.origin==="https://www.gstatic.com")&&(s.pathname.includes("/shared_dict/")||i==="script")&&await ui(n,this.controllerAssetTransfers,this.operationDeadlineMs))&&!this.closing){if(oi.has(i)&&!(i==="image"&&this.resourcePolicy.allowImages)&&!(i==="stylesheet"&&this.resourcePolicy.allowStylesheets)){await n.abort("blockedbyclient");return}if(ri.some(u=>d===u||d.endsWith(`.${u}`))){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 $t(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 l=()=>{if(s?.signal?.aborted)throw xt(s.signal);if(s?.deadlineMs!=null&&Date.now()>=s.deadlineMs)throw new DOMException("Google navigation exceeded the work deadline","TimeoutError")};l();let d=new URLSearchParams({q:t,gl:a,hl:i,pws:"0"});if(s?.tbs&&d.set("tbs",s.tbs),n&&d.set("uule",n),await $(this.page.goto(`https://www.google.com/search?${d}`,{waitUntil:"domcontentloaded",timeout:pt(s?.deadlineMs,s?.purpose==="serp"?12e4:45e3)}),s?.signal),l(),Xt(new URL(this.page.url()))&&this.cdpSession){let h=this.cdpSession,r,o=await $(Promise.race([h.send("Captcha.solve",{detectTimeout:pt(s?.deadlineMs,3e4)}).catch(()=>null),new Promise(U=>{r=setTimeout(()=>U(null),pt(s?.deadlineMs,75e3))})]),s?.signal).finally(()=>{r&&clearTimeout(r)});l(),o?.status==="solve_finished"&&(await $(this.page.waitForURL(U=>U.origin==="https://www.google.com"&&U.pathname==="/search",{timeout:pt(s?.deadlineMs,25e3)}).catch(()=>{}),s?.signal),l())}if(s?.purpose==="serp")return await $(this.page.waitForSelector(di,{timeout:pt(s.deadlineMs,8e3)}).catch(()=>null),s.signal),l(),{hasPaa:await $(this.page.locator(tt.paaItem).count().catch(()=>0),s.signal)>0};if(Xt(new URL(this.page.url())))throw new j("Google SERP returned a CAPTCHA \u2014 retrying with a fresh session.");let S=await $(this.page.evaluate(h=>!!document.querySelector(h),tt.paaItem).catch(()=>!1),s?.signal);if(l(),S)return{hasPaa:!0};let u=!!await $(this.page.waitForSelector(tt.paaItem,{state:"attached",timeout:pt(s?.deadlineMs,8e3)}).catch(()=>null),s?.signal);return l(),{hasPaa:u}}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;for(let d of this.controllerAssetTransfers)d.abort(new DOMException("Browser is closing","AbortError"));let t=je(this.getProviderSessionMetadata()),n=!1,a=null,i=null,s=null,l=async(d,S)=>{let u;try{await Promise.race([d(),new Promise((h,r)=>{u=setTimeout(()=>r(new Error(`${S} acknowledgement exceeded ${On}ms`)),On)})])}finally{u&&clearTimeout(u)}};if(this.connectionStarted)if(!this.browser)a="Browser connection outcome is unknown; no remote termination receipt";else{try{await l(async()=>{let d=this.cdpSession??(this.context&&this.page?await this.context.newCDPSession(this.page):null);if(!d)throw new Error("Remote browser termination channel is unavailable");await d.send("Browser.close")},"Remote browser close"),n=!0}catch(d){a=lt(d instanceof Error?d.message:String(d))??"Remote browser termination is unconfirmed",this.disconnectObservation??=oe("browser_close_error",a)}try{await l(()=>this.browser.close(),"Local browser disconnect"),i=!0}catch(d){i=!1,s=lt(d instanceof Error?d.message:String(d))??"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 Ln(e,t){return e.plannedProvider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?new te({nativeGoogleAssets:t?.nativeGoogleAssets}):new Zt}var q={container:".eJH8qe.adDDi",dataInitq:"[data-initq]",item:tt.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:tt.captchaMarker};var fe={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"},ci=[...Object.keys(fe).map(e=>e.replace(/\s+/g,"\\s+")),...Object.values(fe)].join("|"),wi=new RegExp(`\\b([A-Z][A-Za-z]+(?:[\\s.-][A-Z][A-Za-z]+){0,4}),?\\s+(${ci})\\b`,"gi");function Hn(e){if(!e)return null;let t=e.trim();return/^[A-Z]{2}$/i.test(t)?t.toUpperCase():fe[t.toLowerCase()]??null}function Fn(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 gi(e){if(!e)return null;let[t="",n=""]=e.split(",").map(a=>a.trim());return{city:Fn(t),regionCode:Hn(n),canonicalLocation:e}}function yi(e,t,n,a){let i=Fn(t),s=Hn(n);if(!i||!s)return;let l=`${i.toLowerCase()}|${s}`,d=e.get(l);if(d){d.count++,d.examples.length<3&&!d.examples.includes(a)&&d.examples.push(a);return}e.set(l,{city:i,regionCode:s,count:1,examples:[a]})}function pi(e){try{return decodeURIComponent(e)}catch{}try{return decodeURIComponent(e.replace(/%(?![0-9a-fA-F]{2})/g,"%25"))}catch{return e}}function Bn(e,t){let n=pi(t).replace(/[+/|_-]+/g," ");for(let a of n.matchAll(wi))yi(e,a[1]??"",a[2]??"",n.slice(0,180))}function Ht(e,t,n){let a=gi(e),i=new Map;for(let d of t)Bn(i,[d.title,d.snippet??"",d.cite??"",d.url].join(" "));for(let d of n)Bn(i,[d.name,...d.metadata,d.websiteUrl??"",d.directionsUrl??""].join(" "));let s=Array.from(i.values()).sort((d,S)=>S.count-d.count||d.city.localeCompare(S.city)).slice(0,8);return a?s.length===0?{status:"unknown",expected:a,candidates:[]}:{status:s.some(d=>d.city.toLowerCase()===a.city.toLowerCase()&&(a.regionCode==null||d.regionCode===a.regionCode))?"matched":"mismatch",expected:a,candidates:s}:{status:"not_requested",expected:null,candidates:s}}var mi=/^(?: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,ki=/^(?:AI Overview|View all|Show more|Show less|Related Links|Ask anything in AI Mode|AI can make mistakes)[.!…\s]*$/i;function Ne(e){return e.replace(/\u00a0/g," ").replace(/\s+/g," ").trim()}function Ft(e,t){if(!e)return;let n=Ne(e.split(/\r?\n/).filter(i=>!ki.test(Ne(i))).join(`
|
|
21706
|
-
`)),a=t?Ne(t):"";return a&&n.toLowerCase().startsWith(a.toLowerCase())&&(n=n.slice(a.length).trim()),!n||mi.test(n)?void 0:n}function mt({selectors:e,onlyQuestion:t}){let n=o=>(o??"").replace(/\u00a0/g," ").replace(/\s+/g," ").trim(),a=o=>n(o).replace(/\s*\(\+\d+\)\s*-\s*View related links.*$/i,"").replace(/\s*(?:[-.]\s*)?Opens in new tab[.!]?$/i,"").trim(),i=(o,U)=>{if(o.matches(e.clickTarget)||o.getAttribute("aria-expanded")==="true")return!1;let c=o.closest(".biJ8pb")?.closest(".hICk5e[data-collapsed]");if(c&&(c.getAttribute("data-collapsed")!=="1"||U?.closest(".hICk5e[data-collapsed]")===c))return!1;let g=o.getAttribute("href");return g&&!/^(?:#|javascript:void\(0\);?$)/i.test(g)||o.closest(e.aiSourceCard+","+e.sourceCard)?!1:[o.getAttribute("aria-label"),o.textContent].map(n).some(p=>/^(?:(?:show|read|see) more(?: (?:AI Overview|(?:of )?(?:this |the )?answer))?|continue reading|expand(?: (?:this |the )?answer)?)(?:[.!…]|\s*[▼⌄+])?$/i.test(p))},s=(o,U=!1)=>o.hasAttribute("hidden")||o.getAttribute("aria-hidden")==="true"&&!U||/(?:display\s*:\s*none|visibility\s*:\s*hidden)/i.test(o.getAttribute("style")??""),l=o=>{let U=o.ownerDocument.defaultView?.getComputedStyle(o);return U?.display==="none"||U?.visibility==="hidden"},d=(o,U)=>!U?.matches(e.aiAnswerBody)||!U.closest(".hICk5e[data-collapsed]")||!o?.matches("span.mTEjhd > span.dteT0b > div[data-xpm-copy-root][data-xpm-math-type]")||!o.querySelector(":scope > div > math > semantics")?"":n(o.querySelector(':scope > img[data-xpm-latex][role="presentation"][aria-hidden="true"]')?.getAttribute("data-xpm-latex")),S=(o,U)=>{let c=o?.closest('div.Q9iar.bliT4d.KfKEse.xRMEde[role="list"]');return!!(U?.matches(e.aiAnswerBody)&&U.closest(".hICk5e[data-collapsed]")&&c&&U.contains(c)&&o?.matches('div.Q9iar.BPUOre.bliT4d.KfKEse.xRMEde[role="listitem"]')&&o.querySelector(":scope > div.Q9iar.BPUOre.ua6Thd.bliT4d.KfKEse.xRMEde"))},u=(o,U)=>{if(!U?.matches(e.aiAnswerBody)||!U.closest(".hICk5e[data-collapsed]")||!o.matches('span.jAOkJc[role="button"]')||!o.parentElement?.matches("u.wfWfIf.fxyaSe")||!o.parentElement.parentElement?.matches("span.iNqyIf"))return!1;let c=o.firstElementChild;return!!(c?.matches("span.iNqyIf")&&o.children.length===1&&n(o.textContent)===n(c.textContent))},h=(o,U)=>{if(!U?.matches(e.aiAnswerBody)||!U.closest(".hICk5e[data-collapsed]"))return!1;if(o.matches("li.Z1qcYe, div.WYczDe, span.iNqyIf, ol.T9WCjf.qkgVBf")||S(o,U)||o.matches("strong.rQesXe.MPyX")&&o.closest("div.n6owBd.awi2gc")&&S(o.closest('[role="listitem"]'),U))return!0;if(o.closest("span.iNqyIf")){if(o.matches("strong.rQesXe.MPyX"))return!0;let g=o.matches("span")?o.querySelector(":scope > a.H23r4e[href]"):null;if(g&&/^(?:https?:\/\/|\/goto\?url=|\/url\?)/i.test(g.getAttribute("href")??"")&&o.children.length===1&&n(o.textContent)===n(g.textContent)&&o.parentElement?.matches("span")&&/display\s*:\s*contents/i.test(o.parentElement.getAttribute("style")??""))return!0}if(!o.matches("div.tYHU1b"))return!1;let c=o.querySelector(":scope > div.ID94bb[id]");return c?Array.from(o.querySelectorAll('[role="button"][aria-expanded="true"][aria-controls]')).some(g=>{if(g.closest(".tYHU1b")!==o||g.getAttribute("aria-controls")!==c.id||n(g.textContent)!=="Show less")return!1;for(let w=g;w&&w!==o;w=w.parentElement)if(s(w)||l(w))return!1;return!0}):!1},r=(o,U,c)=>{if(!o||o!==U&&(s(o,h(o,U))||o.matches('style,script,noscript,button,[data-artifact-type="map"]')||o.matches('[role="button"]')&&!o.matches(e.answerEntity)&&!u(o,U)||o.matches(e.aiSourceCard+","+e.sourceCard+","+e.citationBadge)||c&&(o.matches("cite,"+e.sourceSite)||o.matches("a[href]")&&o.querySelector("h3"))))return"";let g=d(o,U);if(g)return g;let w=[];for(let p of o.childNodes)p.nodeType===Node.TEXT_NODE?w.push(p.textContent??""):p.nodeType===Node.ELEMENT_NODE&&w.push(r(p,U,c));return n(w.join(" "))};return Array.from(document.querySelectorAll(e.item)).flatMap((o,U)=>{let c=n(o.getAttribute(e.itemDataQ)||o.getAttribute(e.itemDataInitQ)||o.querySelector(e.itemQuestionEl)?.innerText||o.querySelector(e.itemQuestionEl)?.textContent);if(!c||t&&c!==n(t))return[];let g=o.classList.contains(e.expandedClass)||o.querySelector(e.clickTarget)?.getAttribute("aria-expanded")==="true",w=o.querySelector(e.answerContainer),p=w?.querySelector(e.aiAnswerBody)||(w?.matches(e.aiAnswerBody)?w:null)||w?.querySelector(e.answerBody)||(w?.matches(e.answerBody)?w:null),M=p||w,y=r(M,M,!p),T=/^(?:an error has occurred(?:[.!…]\s*)?(?:please try again later[.!…]?)?|loading|please wait|try again|something went wrong)[.!…\s]*$/i.test(y),O=[...Array.from((M||o).querySelectorAll("a[href]")),...Array.from(w?.querySelectorAll("a[href]")||[]),...Array.from(o.querySelectorAll(e.aiCitation+","+e.aiSourceCard))],x=!T&&(g&&y.length>=10||y.length>30&&O.some(N=>/^https?:\/\//i.test(N.href))),b=M?.matches(e.aiAnswerBody)&&M.closest(".hICk5e[data-collapsed]")?M:null,G=b&&Array.from(b.querySelectorAll('[hidden], [aria-hidden="true"], [style]')).some(N=>{if(!s(N)||!n(N.textContent))return!1;let D=N.closest('button, [role="button"]');if(D&&!u(D,b)||N.closest('[data-artifact-type="map"], .AQisZb, '+e.aiSourceCard+","+e.sourceCard+","+e.citationBadge))return!1;let C=N.closest("[data-xpm-copy-root][data-xpm-math-type]");return d(C,b)&&(N.closest("svg")?.parentElement===C||N.closest("math")?.parentElement?.parentElement===C)?!1:!h(N,b)||s(N,!0)}),F=b&&!G?b:null,P=Array.from(w?.querySelectorAll(e.answerControl)||[]),v=x?P.flatMap((N,D)=>{if(!i(N,F))return[];for(let C=N;C&&C!==w;C=C.parentElement)if(s(C)||l(C))return[];return[D]}):[],W=new Map;if(x)for(let N of O){if(!/^https?:\/\//i.test(N.href)||N.closest('[data-artifact-type="map"]'))continue;let D=N.closest(e.sourceCard),C=D?n(D.querySelector(e.sourceDescription)?.textContent):"",L=(D?n(D.querySelector(e.sourceCardTitle)?.textContent):"")||a(N.getAttribute("aria-label"))||n(N.querySelector("h3")?.textContent)||n(N.textContent),m=W.get(N.href);W.set(N.href,{title:D&&L?L:m?.title||L,rawHref:N.href,...C||m?.description?{description:C||m?.description}:{}})}let f=[...W.values()],k=x&&n(o.querySelector(e.sourceTitle)?.textContent)||void 0,K=x&&n(o.querySelector(e.sourceSite)?.textContent)||void 0;return k||=f.find(N=>N.title.length>2)?.title||f[0]?.title||void 0,[{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:c,answer:x?y:void 0,sourceTitle:k,sourceSite:K,sources:f,...v.length||x&&G||o.getAttribute("data-mcp-answer-expansion")==="pending"?{answerExpansionIncomplete:!0}:{},itemIndex:U,expanded:g,answerControls:v,...v.some(N=>P[N]?.getAttribute("data-mcp-answer-expansion")==="pending")?{answerControlPending:!0}:{}}]})}async function Te(e,t,n,a){let i=Math.min(n.deadlineMs??1/0,Date.now()+1e4),s=()=>Math.max(0,i-Date.now()),l=n.dispatchClick??(U=>U()),d=async()=>(await e.evaluate(a,{selectors:n.selectors,onlyQuestion:t}))[0],S=await d(),u=async(U,c)=>n.signal?.aborted||s()<=0?!1:e.evaluate(({selectors:g,question:w,operation:p,controlIndex:M})=>{let y=G=>(G??"").replace(/\u00a0/g," ").replace(/\s+/g," ").trim(),T=Array.from(document.querySelectorAll(g.item)).find(G=>y(G.getAttribute(g.itemDataQ)||G.getAttribute(g.itemDataInitQ)||G.querySelector(g.itemQuestionEl)?.textContent)===y(w));if(!T)return!1;if(p==="clear")return T.removeAttribute("data-mcp-answer-expansion"),!0;let O=Array.from(T.querySelector(g.answerContainer)?.querySelectorAll(g.answerControl)||[]),x=O.filter(G=>G.getAttribute("data-mcp-answer-expansion")==="pending");if(p==="confirmed")return x.length>1?!1:(x[0]?.setAttribute("data-mcp-answer-expansion","confirmed"),!0);let b=M===void 0?void 0:O[M];return!b||x.length||b.matches(":disabled")||b.closest('[aria-disabled="true"]')?!1:(b.setAttribute("data-mcp-answer-expansion","pending"),b.setAttribute("data-mcp-answer-expansion-for",encodeURIComponent(w)),T.setAttribute("data-mcp-answer-expansion","pending"),!0)},{selectors:n.selectors,question:t,operation:U,controlIndex:c}).catch(()=>!1);async function h(U,c){let g=Date.now()+U.budgetMs,w,p=null,M=U.beforeAnswer;for(;Date.now()<g;){if(await new Promise(y=>window.setTimeout(y,Math.min(150,g-Date.now()))),w=c({selectors:U.selectors,onlyQuestion:U.onlyQuestion})[0],!w)return{acknowledged:!1,clearMarker:!1};if(w.answer!==M&&(M=w.answer,p=Date.now()),!w.answerControls.length&&w.answer){p??=Date.now();let y=w.answer!==U.beforeAnswer?300:1e3;if(Date.now()-p>=y)return{state:w,acknowledged:!0,clearMarker:!0}}else if(w.answerControls.length&&(w.answer!==U.beforeAnswer||!w.answerControlPending)&&(p??=Date.now(),Date.now()-p>=300))return{state:w,acknowledged:!0,clearMarker:!1}}return{state:w,acknowledged:!1,clearMarker:!1}}let r=new Function("input",`return (${h.toString()})(input, (${a.toString()}));`),o=async U=>{if(n.signal?.aborted||s()<=0)return!1;let c,g=new Promise(w=>{c=()=>w(void 0),n.signal?.addEventListener("abort",c,{once:!0})});try{let w=e.evaluate(r,{selectors:n.selectors,onlyQuestion:t,beforeAnswer:U,budgetMs:Math.min(2500,s())}),p=await Promise.race([w,g]);return!p||n.signal?.aborted||s()<=0?!1:(S=p.state,p.acknowledged&&(p.clearMarker?await u("clear"):!0))}finally{c&&n.signal?.removeEventListener("abort",c)}};if(S?.answerExpansionIncomplete&&!S.answerControls.length){await o(S.answer);return}for(let U=0;S?.answerControls.length&&U<8;U+=1){if(n.signal?.aborted||s()<=0)return;let c=S.answer,g=!1;try{if(S=await d(),!S?.answerControls.length)return;c=S.answer;let p=e.locator(n.selectors.item).nth(S.itemIndex);if(!S.expanded){if(n.allowOuterReopen===!1||(await l(async()=>{n.signal?.aborted||s()<=0||await p.locator(n.selectors.clickTarget).first().click({force:!0,noWaitAfter:!0,timeout:Math.min(1200,s())})}),s()<=0||n.signal?.aborted)||(await e.waitForTimeout(Math.min(250,s())),S=await d(),!S?.answerControls.length))return;c=S.answer}if(n.signal?.aborted||s()<=0)return;let M=S;await l(async()=>{if(n.signal?.aborted||s()<=0)return;let y=await u("pending",M.answerControls[0]);g=!0,y&&!n.signal?.aborted&&s()>0&&await e.locator(`[data-mcp-answer-expansion="pending"][data-mcp-answer-expansion-for="${encodeURIComponent(t)}"]`).first().click({force:!0,noWaitAfter:!0,timeout:Math.min(1200,s())}).catch(()=>{})})}catch{}if(!g||n.signal?.aborted||s()<=0||!await o(c)||!S?.answerControls.length||!await u("confirmed"))return}}async function Rn(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(P){return P?(P.innerText??P.textContent??"").trim():""}function s(P){if(!P)return!1;let v=P.replace(/\s+/g," ").trim();return v.length>=16&&v.split(" ").filter(Boolean).length>=2}function l(P){let v=P.querySelector(t.aio.heading);if(i(v)==="AI Overview")return!0;let W=P.querySelector(t.aio.header);return!!i(W).split(/\n|\s{2,}/).some(f=>f.trim()==="AI Overview")}function d(){let v=Array.from(document.querySelectorAll(t.aio.root)).find(l);if(v)return v;if(t.aio.legacyRoot){let f=document.querySelector(t.aio.legacyRoot);if(f&&l(f))return f}let W=document.querySelectorAll(`${t.aio.heading}, h1, h2, h3, [role="heading"]`);for(let f of W){if(i(f)!=="AI Overview")continue;let k=f.parentElement;for(let K=0;K<8&&k;K++){if(k.matches(t.aio.root)||k.querySelector(t.aio.controller)||k.querySelector(t.aio.contentSubtree))return k;k=k.parentElement}return f.parentElement}return null}function S(P){if(!P)return null;let v=P.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(D=>D.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(P.getBoundingClientRect?.().width||960))}px`,W.style.opacity="0",W.style.pointerEvents="none",W.append(v),document.body.append(W);let f=v.innerText||v.textContent||"";W.remove();let k=f.replace(/\r/g,"").replace(/[ \t]+\n/g,`
|
|
21710
|
+
Zwolle,Louisiana,United States`,dn={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 Ue={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 he=null,Sn=null;function fa(){if(he)return;let e=new Map,t=new Map;for(let n of rn.split(`
|
|
21711
|
+
`)){let a=n.trim();if(!a)continue;let i=a.toLowerCase();e.has(i)||e.set(i,a);let s=i.split(",",1)[0],l=t.get(s);l?l.push(a):t.set(s,[a])}for(let n of Object.values(dn)){let a=String(n).toLowerCase();e.has(a)||e.set(a,String(n))}he=e,Sn=t}function Na(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 Un(e){let t=Buffer.from(e,"utf8");return`w+${Buffer.concat([Buffer.from([8,2,16,32,34]),Buffer.from(Na(t.length)),t]).toString("base64")}`}function ln(){return{canonical:null,matched:!1,source:"unresolved",ambiguousCandidates:0}}function St(e,t){return{canonical:e,matched:!0,source:t,ambiguousCandidates:0}}function ue(e){let t=e.toLowerCase().trim();if(!t)return ln();if(gt[t])return St(gt[t],"alias");fa();let n=he,a=Sn,i=n.get(t);if(i)return St(i,"exact");let s=n.get(`${t},united states`);if(s)return St(s,"state-or-country");let l=t.split(",");if(l.length>=2){let r=l[0].trim(),o=l.slice(1).join(",").trim(),U=Ue[o.toUpperCase()]??o,c=n.get(`${r},${U.toLowerCase()},united states`);if(c)return St(c,"city-state")}let d=t.match(/^(.*?)[\s,]+([a-z]{2})$/);if(d){let r=Ue[d[2].toUpperCase()];if(r){let o=n.get(`${d[1].trim()},${r.toLowerCase()},united states`);if(o)return St(o,"city-state")}}let S=a.get(t);if(S?.length===1)return St(S[0],"city-unique");if(S&&S.length>1)return{canonical:null,matched:!1,source:"unresolved",ambiguousCandidates:S.length};let u=l[0].trim();if(u!==t&>[u])return St(gt[u],"alias-partial");let h=t.replace(/\s+[a-z]{2}$/,"").trim();return h!==t&>[h]?St(gt[h],"alias-partial"):ln()}function hn(e){return ue(e).canonical??e}var un={alabama:"AL",alaska:"AK",arizona:"AZ",arkansas:"AR",california:"CA",colorado:"CO",connecticut:"CT",delaware:"DE",florida:"FL",georgia:"GA",hawaii:"HI",idaho:"ID",illinois:"IL",indiana:"IN",iowa:"IA",kansas:"KS",kentucky:"KY",louisiana:"LA",maine:"ME",maryland:"MD",massachusetts:"MA",michigan:"MI",minnesota:"MN",mississippi:"MS",missouri:"MO",montana:"MT",nebraska:"NE",nevada:"NV","new hampshire":"NH","new jersey":"NJ","new mexico":"NM","new york":"NY","north carolina":"NC","north dakota":"ND",ohio:"OH",oklahoma:"OK",oregon:"OR",pennsylvania:"PA","rhode island":"RI","south carolina":"SC","south dakota":"SD",tennessee:"TN",texas:"TX",utah:"UT",vermont:"VT",virginia:"VA",washington:"WA","west virginia":"WV",wisconsin:"WI",wyoming:"WY"},Ta={"atlanta|GA":"30303","austin|TX":"78701","baltimore|MD":"21201","boston|MA":"02108","boulder|CO":"80302","charlotte|NC":"28202","chicago|IL":"60601","colorado_springs|CO":"80903","columbus|OH":"43215","dallas|TX":"75201","denver|CO":"80202","detroit|MI":"48226","fort_collins|CO":"80524","fort_worth|TX":"76102","houston|TX":"77002","indianapolis|IN":"46204","jacksonville|FL":"32202","las_vegas|NV":"89101","los_angeles|CA":"90012","louisville|KY":"40202","loveland|CO":"80537","memphis|TN":"38103","miami|FL":"33131","minneapolis|MN":"55401","nashville|TN":"37203","new_york|NY":"10001","orlando|FL":"32801","philadelphia|PA":"19103","phoenix|AZ":"85004","portland|OR":"97205","raleigh|NC":"27601","richmond|VA":"23219","sacramento|CA":"95814","salt_lake_city|UT":"84101","san_antonio|TX":"78205","san_diego|CA":"92101","san_francisco|CA":"94103","san_jose|CA":"95113","seattle|WA":"98101"};function Pa(e){return e?e.slice(-6):null}function X(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:Pa(n),target:a,error:i,disposable:s}}}function ba(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function Ia(e){return e.trim().toLowerCase().replace(/\./g,"").replace(/\s+/g," ")}function Wa(e){if(!e)return!0;let t=Ia(e);return t==="united states"||t==="united states of america"||t==="usa"||t==="us"}function we(e){let t=e.trim();if(/^[A-Za-z]{2}$/.test(t)){let n=t.toUpperCase();return Object.values(un).includes(n)?n:null}return un[ba(t)]??null}function Aa(e){let n=e.normalize("NFKD").replace(/[^\x00-\x7F]/g,"").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean),a=n.join("_"),i=n.join("");return Array.from(new Set([a,i].filter(Boolean)))}function ht(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 xa(e){return`mcp-serp-residential-us-zip-${e}`}function cn(e,t){if(!e||t.toLowerCase()!=="us")return null;let n=hn(e),a=n.split(",").map(u=>u.trim()).filter(Boolean);if(a.length>1&&Wa(a[a.length-1])&&(a=a.slice(0,-1)),a.length===1){let u=we(a[0]);return u?{canonicalLocation:n,level:"state",country:"US",state:u,city:"",cityCandidates:[],proxyName:ht("US",u),config:{country:"US",state:u}}:null}let[i="",s=""]=a;if(!i||!s)return null;let l=we(s);if(!l)return null;let d=Aa(i),S=d[0];return S?{canonicalLocation:n,level:"city",country:"US",state:l,city:S,cityCandidates:d,proxyName:ht("US",l,S),config:{country:"US",state:l,city:S}}:null}function Oa(e){return`${e.city}|${e.state}`}function wn(e,t){return t&&/^\d{5}$/.test(t)?t:Ta[Oa(e)]??null}function gn(e,t){return{...e,level:"zip",zip:t,proxyName:xa(t),config:{country:e.country,state:e.state,zip:t}}}function ce(e,t){return{...e,proxyName:t}}function ye(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 La(e,t){return e.find(n=>n.type==="residential"&&n.status!=="unavailable"&&!!n.id&&(n.name===t.proxyName||ye(n.config,t,t.level==="city"?t.city:void 0)))??null}function Ba(e,t){for(let n of t.cityCandidates){let a=ht(t.country,t.state,n),i=e.find(s=>s.type==="residential"&&s.status!=="unavailable"&&!!s.id&&(s.name===a||ye(s.config,t,n)));if(i)return i}return null}function $t(e){return{...e,level:"state",proxyName:ht(e.country,e.state),config:{country:e.country,state:e.state}}}function Ha(e,t){let n=ht(t.country,t.state);return e.find(a=>a.type==="residential"&&a.status!=="unavailable"&&!!a.id&&(a.name===n||ye(a.config,t)))??null}function Fa(e,t){return $t(e)}function Ut(e){return e instanceof Error?e.message:String(e)}function Ra(e,t,n){let a=[],i=wn(e,t);if(i){let l=gn(e,i);a.push(ce(l,Lt(l.proxyName,n)))}for(let l of e.cityCandidates){let d={...e,level:"city",city:l,proxyName:ht(e.country,e.state,l),config:{country:e.country,state:e.state,city:l}};a.push(ce(d,Lt(d.proxyName,n)))}let s=$t(e);return a.push(ce(s,Lt(s.proxyName,n))),a}async function ge(e,t,n){if(e.backupOnExhaustion&&n.length>0&&e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey&&zt())try{let a=await jt(e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,{attemptIndex:e.attemptIndex});return X("backup_custom",e.proxyMode,a,t,null,!0)}catch(a){n.push(`backup: ${Se(Ut(a))}`)}return X("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,t,n.join(" | "))}async function Is(e){if(!e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey||!zt())return null;try{let t=await jt(e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,{attemptIndex:e.attemptIndex});return X("backup_custom",e.proxyMode,t,null,null,!0)}catch{return null}}async function Da(e,t,n){let a=[];for(let i of Ra(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 X("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=$t(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 X("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 ge(t,n,a)}async function yn(e,t){if(!e||!t)return;await new ot({apiKey:e}).proxies.delete(t)}async function Ws(e){let t=we(e.state);if(!t)throw new Error("A valid US state is required for a mobile Maps proxy");let n=new ot({apiKey:e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey}),a=cn(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 X("mobile_created","configured",i.id,a,null,!0)}async function pn(e){if(e.proxyMode==="none")return X("disabled",e.proxyMode,void 0,null,null);if(e.proxyMode==="configured")return X("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,null,null);let t=cn(e.location,e.gl);if(!t||!e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey)return X("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 ot({apiKey:e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey});try{let a=e.attemptIndex??0;if(e.fresh)return await Da(n,e,t);if(a>=1){let h=Fa(t,a),r=[];try{let o=await n.proxies.create({type:"residential",name:h.proxyName,config:h.config});if(o.id)return X("location_created",e.proxyMode,o.id,h,null);r.push(`${h.state}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(o){r.push(`${h.state}: ${Ut(o)}`)}return ge(e,h,r)}let i=[];for await(let h of await n.proxies.list())i.push(h);let s=wn(t,e.proxyZip),l=[];if(s){let h=gn(t,s),r=La(i,h);if(r?.id)return X("location_reused",e.proxyMode,r.id,h,null);try{let o=await n.proxies.create({type:"residential",name:h.proxyName,config:{country:h.country,zip:s}});if(o.id)return X("location_created",e.proxyMode,o.id,h,null);l.push(`${s}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(o){l.push(`${s}: ${Ut(o)}`)}}let d=Ba(i,t);if(d?.id)return X("location_reused",e.proxyMode,d.id,t,l.join(" | ")||null);for(let h of t.cityCandidates)try{let r=await n.proxies.create({type:"residential",name:ht(t.country,t.state,h),config:{country:t.country,state:t.state,city:h}});if(r.id)return X("location_created",e.proxyMode,r.id,{...t,level:"city",city:h,proxyName:ht(t.country,t.state,h),config:{country:t.country,state:t.state,city:h}},null);l.push(`${h}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(r){l.push(`${h}: ${Ut(r)}`)}let S=$t(t),u=Ha(i,S);if(u?.id)return X("location_reused",e.proxyMode,u.id,S,l.join(" | "));try{let h=await n.proxies.create({type:"residential",name:S.proxyName,config:S.config});if(h.id)return X("location_created",e.proxyMode,h.id,S,l.join(" | "));l.push(`${S.state}: \u004b\u0065\u0072\u006e\u0065\u006c did not return a proxy id`)}catch(h){l.push(`${S.state}: ${Ut(h)}`)}return ge(e,t,l)}catch(a){return X("configured_fallback",e.proxyMode,e.configured\u004b\u0065\u0072\u006e\u0065\u006cProxyId,t,Ut(a))}}function pe(){return process.env.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_BROWSER_WSS?.trim()||null}function mn(){return process.env.SERP_BROWSER_PROVIDER?.trim().toLowerCase()==="\u006b\u0065\u0072\u006e\u0065\u006c"?!1:!!pe()}import{chromium as fe}from"playwright-extra";import za from"puppeteer-extra-plugin-stealth";import{chromium as ja}from"playwright";var tt={paaItem:".related-question-pair",captchaMarker:'#captcha-form, #recaptcha, form[action*="/sorry/"], .g-recaptcha, [data-sitekey]'},Bt={container:'div[jscontroller="HWk0Gf"]',sectionHeading:'.mgAbYb[role="heading"]',item:"a.rIRoqf"},Ht={udm:"39",item:"a.rIRoqf",durationPattern:/^\d+:\d+$/,platforms:["YouTube","TikTok","Instagram","Facebook","X"]},kn={section:".ULSxyf",item:"a.KYg7td.INpicf",title:".hyYc0c",source:".K4ETW"},Cn={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"},Mn={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"},vn={root:'[data-hveid="CAUQAA"]',wrapper:".Fgyi2e",citations:'.Fgyi2e [data-hveid] a[jsname="pxBnId"]'},fn={result:".wHYlTd.tF2Cxc",title:"h3.LC20lb",siteName:".VuuXrf",cite:"cite.tjvcx",snippet:".VwiC3b",redditCite:"cite.qLRx3b",ratingWrap:".Y0A0hc",ratingValue:".yi40Hd",reviewCount:".RDApEe"},Nn={headingText:"Businesses",card:".w7Dbne",name:".OSrXXb",ratingValue:".yi40Hd",reviewCount:".RDApEe"},Tn="2026-05-07",Os={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 Qt(e,t,n,a){let i,s=!1,l,d=()=>{},S=()=>a?.reason instanceof DOMException&&a.reason.name==="TimeoutError"?a.reason:new at,u=()=>d(S()),h=new Promise((o,U)=>{d=U}),r=async o=>{let U;try{await Promise.race([o.close().catch(()=>{}),new Promise(c=>{U=setTimeout(c,2e3)})])}finally{U&&clearTimeout(U)}};if(a?.aborted)throw S();a?.addEventListener("abort",u,{once:!0}),l=setTimeout(()=>d(new DOMException("Optional pagination timed out","TimeoutError")),3e4);try{return await Promise.race([(async()=>{let o=await e.newPage();if(s)throw await r(o),new at;if(i=o,await t(o),s)throw new at;return n(o)})(),h])}finally{s=!0,l&&clearTimeout(l),a?.removeEventListener("abort",u),i&&await r(i)}}var Ga=/\b(?:HeadlessChrome|Chrome|Chromium|Firefox)\/\d+|\bVersion\/\d+.*\bSafari\//;async function me(e){try{let t=await e.evaluate(()=>navigator.userAgent);return typeof t=="string"&&Ga.test(t)?t:null}catch{return null}}async function ke(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 me(n)}catch{return null}finally{t&&await t.close().catch(()=>{})}}function Fs(e,t){return t?{...e,userAgent:t}:e}function Pn(e){let{headless:t,viewport:n,userAgent:a,user_agent:i,...s}=e;return s}async function bn(e,t={}){return t.blockServiceWorkers?e.newContext({viewport:null,serviceWorkers:"block"}):e.contexts()[0]??await e.newContext({viewport:null})}async function In(e){return e.pages()[0]??await e.newPage()}function Zt(e={}){let t=e.nowMs??Date.now(),n=Math.max(0,e.waitMs??3e4);return Math.min(e.deadlineMs??1/0,t+n)}var Es=Zt({nowMs:0});async function Wn(e){let t=Zt(e),n=async()=>{if(e.signal?.aborted)throw Ot(e.signal);let i=t-Date.now();if(i<=0)return!0;let s;try{return await $(Promise.race([e.observeChallenge(),new Promise(l=>{s=setTimeout(()=>l(!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 $(new Promise(s=>{i=setTimeout(s,Math.min(500,t-Date.now()))}),e.signal)}finally{i&&clearTimeout(i)}if(e.signal?.aborted)throw Ot(e.signal);if(Date.now()>t)break;a=await n()}return a}var Ea=`#search h3, #rso h3, #search .related-question-pair, #rso .related-question-pair, #search ${Bt.item}, #rso ${Bt.item}, #search .isv-r, #rso .isv-r`,Va=75e3,Ya=3e3;async function Ce(e,t){if(t.signal?.aborted)throw new at;let n=Math.min(Date.now()+Va,t.deadlineMs===void 0?1/0:t.deadlineMs-Ya);if(n<=Date.now())throw new nt("Google search navigation has no remaining time");let a=_e(Math.max(1,n-Date.now()),t.signal),i=!1,s,l=async()=>{if(!await $(An(e),a))return!1;if(i=!0,s??=Zt({deadlineMs:n}),await Wn({solverEnabled:t.solverEnabled,deadlineMs:s,signal:a,observeChallenge:()=>An(e)}))throw new j("Google challenge did not clear within the remaining browser time.");return!0};try{await _a(e,{params:Ka(t),deadlineMs:n,signal:a},l,Ja);let d=()=>$(qa(e,{query:t.query,deadlineMs:n,signal:a,readySelector:Ea},l),a);if(await d(),t.purpose==="paa"){let S=Math.min(n,Date.now()+4e3);await $(e.waitForSelector(tt.paaItem,{state:"visible",timeout:Math.max(1,S-Date.now())}).catch(()=>null),a);for(let u=1;u<=6&&Date.now()<n&&(await l(),!await $(e.locator(tt.paaItem).count(),a));u+=1)await $(e.evaluate(h=>{window.scrollTo(0,document.body.scrollHeight*h)},u/6),a),await $(new Promise(h=>setTimeout(h,Math.min(400,n-Date.now()))),a)}for(;Date.now()<n;){await d();let S=await $(e.locator(tt.paaItem).count(),a)>0;if(!await l())return{hasPaa:S,challengeObserved:i}}throw new nt("Google search results did not reach a readable state")}catch(d){throw t.signal?.aborted?new at:d instanceof j||d instanceof nt?d:d instanceof Error&&d.message==="Google search results did not reach a readable state"?new nt(d.message):d 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(d.message)?new nt(d.message):d instanceof Error&&["Google homepage did not expose a visible search box","Google search form did not expose a visible Search button"].includes(d.message)?new nt(d.message):new nt(a.aborted?"Google search navigation timed out before results were ready":"Google homepage search interaction failed")}}async function An(e){if(/google\.[^/]+\/sorry(?:\/|\?|$)/i.test(e.url())||await e.locator(tt.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 Ka(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 Ja(e,t={}){let n=t.deadlineMs??Date.now()+1e4,a=async(d,S,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,o,U=new Promise((c,g)=>{r=setTimeout(()=>g(new Error(`Google search ${d} timed out`)),h),t.signal&&(o=()=>{let w=new Error("Google search navigation aborted");w.name="AbortError",g(w)},t.signal.addEventListener("abort",o,{once:!0}))});try{return await Promise.race([S(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 ${d} failed`)}finally{r&&clearTimeout(r),o&&t.signal?.removeEventListener("abort",o)}},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(d=>{let S=new RegExp(d,"i");return/^consent\.google\./i.test(window.location.hostname)||!!document.querySelector("#W0wltc")||Array.from(document.querySelectorAll('button, [role="button"]')).some(u=>S.test(u.textContent?.trim()??""))},i.source),2e3))return!1;let l=e.locator("#W0wltc").or(e.getByRole("button",{name:i}));for(let d=0,S=await a("consent inspection",()=>l.count(),2e3);d<S;d+=1){let u=l.nth(d);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 _a(e,t,n,a){let i=async(U,c,g=8e3)=>{let w=Math.min(g,t.deadlineMs-Date.now());if(t.signal?.aborted){let T=new Error("Google search navigation aborted");throw T.name="AbortError",T}if(w<=0)throw new Error("Google search navigation deadline exhausted");let p,M,y=new Promise((T,O)=>{p=setTimeout(()=>O(new Error(`Google search ${U} timed out`)),w),t.signal&&(M=()=>{let x=new Error("Google search navigation aborted");x.name="AbortError",O(x)},t.signal.addEventListener("abort",M,{once:!0}))});try{return await Promise.race([c(w),y])}catch{if(t.signal?.aborted){let O=new Error("Google search navigation aborted");throw O.name="AbortError",O}throw new Error(`Google search ${U} failed`)}finally{p&&clearTimeout(p),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 l='textarea[name="q"], input[name="q"]';await i("search box readiness",U=>e.waitForSelector(l,{state:"visible",timeout:U}));let d=e.locator(l),S;for(let U=0,c=await i("search box inspection",()=>d.count());U<c;U+=1)if(await i("search box inspection",()=>d.nth(U).isVisible())){S=d.nth(U);break}if(!S)throw new Error("Google homepage did not expose a visible search box");let u=S;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[w,p]of Object.entries(c)){if(w==="q")continue;let M=Array.from(U.querySelectorAll("input")).filter(y=>y.name===w);for(let y of M)y.value=p,y.disabled=!1;if(M.length===0){let y=document.createElement("input");y.type="hidden",y.name=w,y.value=p,U.appendChild(y)}}let g=new URL(U.action,location.href);for(let w of Object.keys(c))g.searchParams.delete(w);U.action=g.toString()},t.params));let r=h.locator('input[name="btnK"], button[name="btnK"], button[type="submit"]'),o=!1;for(let U=0,c=await i("search button inspection",()=>r.count());U<c;U+=1){let g=r.nth(U);if(await i("search button inspection",()=>g.isVisible())){await i("search submit",w=>g.click({timeout:w,noWaitAfter:!0})),o=!0;break}}if(!o)throw new Error("Google search form did not expose a visible Search button");await n(),await s(),await n()}async function qa(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 l=!1;try{let S=new URL(e.url());l=/(^|\.)google\.[a-z.]+$/i.test(S.hostname)&&S.pathname==="/search"&&S.searchParams.get("q")===t.query}catch{}if(l){let S=await e.waitForSelector(a,{state:"visible",timeout:Math.min(500,Math.max(1,i-Date.now()))}).catch(()=>null),u=S?!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(S||u){if(await n()===!0)continue;return}}if(t.signal?.aborted)throw new Error("Google search navigation aborted");let d=Math.min(200,i-Date.now(),t.deadlineMs-Date.now());d>0&&await e.waitForTimeout(d)}throw new Error("Google search results did not reach a readable state")}fe.use(za());var $a=180,Qa=3e3,Za=5e3,Xa='#search, #rso, a[href] h3, [data-snhf], [role="main"]';function Me(e,t){return e?Math.max(1,Math.min(t,e-Date.now())):t}function ti(e,t){let n=process.env[e];if(!n)return t;let a=Number(n);return Number.isInteger(a)&&a>0?a:t}function ve(e){return e?e.slice(-6):null}function xn(e,t){let n=(t??process.env.SERP_REDIRECT_BASE)?.trim().replace(/\/+$/,"");return n?`${n}/g/${Buffer.from(e,"utf8").toString("base64url")}`:e}function ei(e){return e?/united states|u\.?s\.?a?\.?|^us$/i.test(e.trim()):!1}function Tt(e){return e instanceof Error?e.message:String(e)}function ni(e){return/\b409\b|conflict|already exists/i.test(Tt(e))}function ai(e){return/\b404\b|not[ _-]?found|already (?:gone|deleted|closed)|does not exist/i.test(Tt(e))}async function ii(e,t){try{await e.profiles.create({name:t})}catch(n){if(!ni(n))throw n}}function On(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 yt(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 si(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 l=new URL(/^https?:\/\//i.test(t)?t:`https://${t}`);if(l.hostname.replace(/^www\./,"").replace(/^m\./,"").toLowerCase()!=="youtube.com")throw new Error("channel URL must be on youtube.com");let S=l.pathname.split("/").filter(Boolean),u=S[0]??"",h=S[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 Xt=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 nt("\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 ot({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):ti("\u004b\u0045\u0052\u004e\u0045\u004c_BROWSER_TIMEOUT_SECONDS",$a),l=Math.min(s,600);t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName&&t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges===!0&&await ii(this.\u006b\u0065\u0072\u006e\u0065\u006cClient,t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName);let d=Yt();this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=null,this.last\u004b\u0065\u0072\u006e\u0065\u006cBillingMode="headful",d?.headlessSentOut&&(d.headlessSentOut.value=this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent);let S=await this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.create(Pn({stealth:t.\u006b\u0065\u0072\u006e\u0065\u006cStealth===!0,timeout_seconds:l,...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=S.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 S.stealth=="boolean"?S.stealth:null,this.\u006b\u0065\u0072\u006e\u0065\u006cSolverEnabled=t.\u006b\u0065\u0072\u006e\u0065\u006cStealth===!0&&S.stealth!==!1,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed=typeof S.proxy_id=="string"?!!S.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 yt(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(o){u=!1,h=Tt(o)}let r={sessionId:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,proxyMode:n,requestedProxyIdPresent:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,requestedProxyIdSuffix:ve(t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId),createdProxyIdPresent:typeof S.proxy_id=="string"?!!S.proxy_id:null,createdProxyIdSuffix:ve(S.proxy_id),retrievedProxyIdPresent:null,retrievedProxyIdSuffix:null,retrievedProxyIdMatchesRequested:null,defaultProxyDisabled:u,defaultProxyDisableError:h,proxyResolution:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution??null,timeoutSeconds:l,stealth:typeof S.stealth=="boolean"?S.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:l,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 ja.connectOverCDP(S.cdp_ws_url),this.context=await bn(this.browser),this.page=await In(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 o=this.debugSnapshot.networkLocation?.country??null;if(!ei(o))throw new j(`Non-US egress (${o??"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 fe.launchPersistentContext(t.profileDir,{...i,...On(t)}),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage(),this.debugSnapshot.context.userAgent=await me(this.page);else{this.browser=await fe.launch(i);let s=await ke(this.browser);this.debugSnapshot.context.userAgent=s,this.context=await this.browser.newContext(On(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 yt(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=ve(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=Tt(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 d=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 d.org=="string"?d.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 yt(n.goto("https://ipapi.co/json/",{waitUntil:"domcontentloaded",timeout:7e3}),8e3,"browser network location navigation");let s=await n.locator("body").innerText({timeout:2e3}),l=JSON.parse(s);return{source:"ipapi.co",ip:typeof l.ip=="string"?l.ip:null,city:typeof l.city=="string"?l.city:null,region:typeof l.region=="string"?l.region:null,country:typeof l.country_name=="string"?l.country_name:typeof l.country=="string"?l.country:null,org:typeof l.org=="string"?l.org:null,timezone:typeof l.timezone=="string"?l.timezone:null,error:null}}catch(a){return t(Tt(a))}finally{await n?.close().catch(()=>{})}}async loadJsonInDebugPage(t,n){try{await yt(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 Qt(this.context,async()=>{},t,n)}async navigateToSERP(t,n,a,i,s){let l=new URLSearchParams({q:t,gl:a,hl:i,pws:"0"});s?.tbs&&l.set("tbs",s.tbs),n&&l.set("uule",n);let d="https://www.google.com/search?"+l.toString(),S=xn(d),u=s?.debug?{requestedUrl:d,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 o=await Ce(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,d,{hasPaa:o.hasPaa,captchaDetected:o.challengeObserved===!0},r),{hasPaa:o.hasPaa}}catch(o){throw await this.updateSerpNavigationDebug(u,d,{hasPaa:null,captchaDetected:o instanceof j?!0:null},r),o}}try{await this.page.goto(S,{waitUntil:"domcontentloaded",timeout:Me(s?.deadlineMs,s?.purpose==="serp"?8e3:45e3)})}catch(r){await this.updateSerpNavigationDebug(u,d,{hasPaa:null,captchaDetected:null});let o=await this.captureDiagnostics(d);throw new nt(`page.goto failed: ${r.message} | ${o}`)}if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(u,d,{hasPaa:!1,captchaDetected:!0}),new j(this.captchaMessage());if(s?.purpose==="serp"){await this.page.waitForSelector(Xa,{timeout:Me(s.deadlineMs,1500)}).catch(()=>null);let r=await this.page.locator(tt.paaItem).count().catch(()=>0)>0;return await this.updateSerpNavigationDebug(u,d,{hasPaa:r,captchaDetected:!1}),{hasPaa:r}}if(await this.page.waitForSelector(tt.paaItem,{timeout:Me(s?.deadlineMs,4e3)}).catch(()=>null))return await this.updateSerpNavigationDebug(u,d,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(u,d,{hasPaa:!1,captchaDetected:!0}),new j(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(tt.paaItem).count()>0)return await this.updateSerpNavigationDebug(u,d,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};return await this.updateSerpNavigationDebug(u,d,{hasPaa:!1,captchaDetected:!1}),{hasPaa:!1}}async isSerpChallengeVisible(){if(!this.page)return!1;if(await this.page.locator(tt.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 l=Math.min(1e3,i?.deadlineMs===void 0?1e3:i.deadlineMs-Date.now());if(i&&(i.signal?.aborted||l<=0))return;let d=Promise.all([this.page.title().catch(()=>""),this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,500)).catch(()=>"")]),[S,u]=i?await $(yt(d,l,"\u004b\u0065\u0072\u006e\u0065\u006c navigation debug"),i.signal):await d;t.title=S,t.bodySnippet=u,t.captchaDetected=a.captchaDetected??/recaptcha|unusual traffic|are you a robot/i.test(u)}catch(s){t.bodySnippet=`debug capture failed: ${Tt(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),l=/recaptcha|unusual traffic|are you a robot/i.test(i),d=[s?"CONSENT_WALL":"",l?"BOT_CHALLENGE":"",n!==t?"REDIRECTED":""].filter(Boolean).join(",");return`intended=${t} | final=${n} | title="${a}" | flags=[${d}] | 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.":Ee}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 Ce(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?xn(t,n):t;try{if(await this.page.goto(a,{waitUntil:"domcontentloaded",timeout:45e3}),/google\.[^/]+\/search\?/i.test(t)&&await this.isSerpChallengeVisible())throw new j(this.captchaMessage())}catch(i){if(i instanceof j)throw i;let s=await this.captureDiagnostics(t);throw new nt(`page.goto failed: ${i.message} | ${s}`)}}async navigateToChannel(t){let n=si(t);try{await this.page.goto(n,{waitUntil:"networkidle",timeout:3e4})}catch(a){let i=await this.captureDiagnostics(n);throw new nt(`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,l=this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed,d=this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource,S=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=yt(a.browsers.deleteByID(n),Za,`\u004b\u0065\u0072\u006e\u0065\u006c session ${n} delete`),o=yt(t.close(),Qa,`\u004b\u0065\u0072\u006e\u0065\u006c browser ${n} close`),[U,c]=await Promise.allSettled([r,o]);this.last\u004b\u0065\u0072\u006e\u0065\u006cClosedAtMs=Date.now(),i!=null&&Je({\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,source:"browser_driver",stealth:s,headlessSent:u,proxyUsed:l,proxySource:d,proxyType:S,openedAtMs:i,closedAtMs:this.last\u004b\u0065\u0072\u006e\u0065\u006cClosedAtMs});let g=U.status==="rejected"&&ai(U.reason),w={\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!0,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:U.status==="fulfilled"||g,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError: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:h.provider,providerSessionId:h.providerSessionId,providerDisconnectObserved:!1,providerDisconnectMessage:null};return U.status==="rejected"&&!g?(console.warn(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_failed",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n,message:w.\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:w.browserCloseError})),console.warn(`\u004b\u0065\u0072\u006e\u0065\u006c browser close failed for ${n}:`,c.reason)),w}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 oi}from"playwright";var ri=new Set(["image","media","font","stylesheet","ping"]),di=["doubleclick.net","googleadservices.com","googlesyndication.com","google-analytics.com"],li='#search, #rso, a[href] h3, [data-snhf], [role="main"]',Si=3e4,Ln=1500,Ui=3e3,hi=new Set(["https://www.google.com","https://www.gstatic.com","https://www.recaptcha.net","https://recaptcha.net"]);function te(e){return e.origin==="https://www.google.com"&&/^\/sorry(?:\/|$)/.test(e.pathname)}function ui(e,t){if(te(e)||hi.has(e.origin)&&/^\/recaptcha(?:\/|$)/.test(e.pathname))return!0;try{return te(new URL(t))}catch{return!1}}function pt(e,t){return e?Math.max(1,Math.min(t,e-Date.now())):t}async function ci(e,t,n){let a=Math.min(Date.now()+Ui,n??1/0);if(Date.now()>=a)return!1;let i=e.request(),s=new AbortController;t.add(s);let l=new Promise((u,h)=>{s.signal.addEventListener("abort",()=>h(s.signal.reason),{once:!0})}),d=setTimeout(()=>{s.abort(new DOMException("Controller asset transfer timed out","TimeoutError"))},Math.max(0,a-Date.now())),S=!1;try{let u=i.headers();if(s.signal.aborted||Date.now()>=a)return!1;let h=await Promise.race([fetch(i.url(),{method:i.method(),signal:s.signal,redirect:"error",headers:{accept:u.accept??"*/*","accept-language":u["accept-language"]??"en-US,en;q=0.9","user-agent":u["user-agent"]??"Mozilla/5.0"},body:i.method()==="GET"||i.method()==="HEAD"?void 0:i.postData()}),l]);if(!h.ok||s.signal.aborted||Date.now()>=a)return!1;let r=Buffer.from(await Promise.race([h.arrayBuffer(),l]));if(s.signal.aborted||Date.now()>=a)return!1;let o={status:h.status,contentType:h.headers.get("content-type")??"application/octet-stream",headers:{"cache-control":"public, max-age=3600"},body:r};return clearTimeout(d),S=!0,await e.fulfill(o),!0}catch{return S}finally{clearTimeout(d),t.delete(s),s.abort()}}var ee=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;controllerAssetTransfers=new Set;operationDeadlineMs;observeDisconnect(t,n){this.closing||this.disconnectObservation||(this.disconnectObservation=re(t,n))}async launch(t){if(this.page)return;this.operationDeadlineMs=t.operationDeadlineMs,this.closing=!1,this.providerSessionId=null,this.disconnectObservation=null;let n=pe();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 oi.connectOverCDP(n,{timeout:pt(t.operationDeadlineMs,Si)})}catch(s){let l=(s instanceof Error?s.message:String(s)).replaceAll(n,"[redacted endpoint]");throw Re(l)&&(this.connectionStarted=!1),new Error(lt(l)??"\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=l=>l),typeof s.__publicField!="function"&&(s.__publicField=(l,d,S)=>(l[d]=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 i=await this.cdpSession.send("Browser.getSessionId");this.providerSessionId=tn(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=>{if(this.closing)return;let a=n.request(),i=a.resourceType(),s;try{s=new URL(a.url())}catch{await n.continue();return}if(s.origin==="https://www.google.com"&&(s.pathname==="/sgasync"||/^\/async(?:\/|$)/.test(s.pathname))||ui(s,t.url())){await n.continue();return}let d=s.hostname.toLowerCase();if(!((s.origin==="https://www.google.com"||s.origin==="https://www.gstatic.com")&&(s.pathname.includes("/shared_dict/")||i==="script")&&await ci(n,this.controllerAssetTransfers,this.operationDeadlineMs))&&!this.closing){if(ri.has(i)&&!(i==="image"&&this.resourcePolicy.allowImages)&&!(i==="stylesheet"&&this.resourcePolicy.allowStylesheets)){await n.abort("blockedbyclient");return}if(di.some(u=>d===u||d.endsWith(`.${u}`))){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 Qt(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 l=()=>{if(s?.signal?.aborted)throw Ot(s.signal);if(s?.deadlineMs!=null&&Date.now()>=s.deadlineMs)throw new DOMException("Google navigation exceeded the work deadline","TimeoutError")};l();let d=new URLSearchParams({q:t,gl:a,hl:i,pws:"0"});if(s?.tbs&&d.set("tbs",s.tbs),n&&d.set("uule",n),await $(this.page.goto(`https://www.google.com/search?${d}`,{waitUntil:"domcontentloaded",timeout:pt(s?.deadlineMs,s?.purpose==="serp"?12e4:45e3)}),s?.signal),l(),te(new URL(this.page.url()))&&this.cdpSession){let h=this.cdpSession,r,o=await $(Promise.race([h.send("Captcha.solve",{detectTimeout:pt(s?.deadlineMs,3e4)}).catch(()=>null),new Promise(U=>{r=setTimeout(()=>U(null),pt(s?.deadlineMs,75e3))})]),s?.signal).finally(()=>{r&&clearTimeout(r)});l(),o?.status==="solve_finished"&&(await $(this.page.waitForURL(U=>U.origin==="https://www.google.com"&&U.pathname==="/search",{timeout:pt(s?.deadlineMs,25e3)}).catch(()=>{}),s?.signal),l())}if(s?.purpose==="serp")return await $(this.page.waitForSelector(li,{timeout:pt(s.deadlineMs,8e3)}).catch(()=>null),s.signal),l(),{hasPaa:await $(this.page.locator(tt.paaItem).count().catch(()=>0),s.signal)>0};if(te(new URL(this.page.url())))throw new j("Google SERP returned a CAPTCHA \u2014 retrying with a fresh session.");let S=await $(this.page.evaluate(h=>!!document.querySelector(h),tt.paaItem).catch(()=>!1),s?.signal);if(l(),S)return{hasPaa:!0};let u=!!await $(this.page.waitForSelector(tt.paaItem,{state:"attached",timeout:pt(s?.deadlineMs,8e3)}).catch(()=>null),s?.signal);return l(),{hasPaa:u}}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;for(let d of this.controllerAssetTransfers)d.abort(new DOMException("Browser is closing","AbortError"));let t=en(this.getProviderSessionMetadata()),n=!1,a=null,i=null,s=null,l=async(d,S)=>{let u;try{await Promise.race([d(),new Promise((h,r)=>{u=setTimeout(()=>r(new Error(`${S} acknowledgement exceeded ${Ln}ms`)),Ln)})])}finally{u&&clearTimeout(u)}};if(this.connectionStarted)if(!this.browser)a="Browser connection outcome is unknown; no remote termination receipt";else{try{await l(async()=>{let d=this.cdpSession??(this.context&&this.page?await this.context.newCDPSession(this.page):null);if(!d)throw new Error("Remote browser termination channel is unavailable");await d.send("Browser.close")},"Remote browser close"),n=!0}catch(d){a=lt(d instanceof Error?d.message:String(d))??"Remote browser termination is unconfirmed",this.disconnectObservation??=re("browser_close_error",a)}try{await l(()=>this.browser.close(),"Local browser disconnect"),i=!0}catch(d){i=!1,s=lt(d instanceof Error?d.message:String(d))??"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 Bn(e,t){return e.plannedProvider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?new ee({nativeGoogleAssets:t?.nativeGoogleAssets}):new Xt}var q={container:".eJH8qe.adDDi",dataInitq:"[data-initq]",item:tt.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:tt.captchaMarker};var Ne={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"},wi=[...Object.keys(Ne).map(e=>e.replace(/\s+/g,"\\s+")),...Object.values(Ne)].join("|"),gi=new RegExp(`\\b([A-Z][A-Za-z]+(?:[\\s.-][A-Z][A-Za-z]+){0,4}),?\\s+(${wi})\\b`,"gi");function Fn(e){if(!e)return null;let t=e.trim();return/^[A-Z]{2}$/i.test(t)?t.toUpperCase():Ne[t.toLowerCase()]??null}function Rn(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 yi(e){if(!e)return null;let[t="",n=""]=e.split(",").map(a=>a.trim());return{city:Rn(t),regionCode:Fn(n),canonicalLocation:e}}function pi(e,t,n,a){let i=Rn(t),s=Fn(n);if(!i||!s)return;let l=`${i.toLowerCase()}|${s}`,d=e.get(l);if(d){d.count++,d.examples.length<3&&!d.examples.includes(a)&&d.examples.push(a);return}e.set(l,{city:i,regionCode:s,count:1,examples:[a]})}function mi(e){try{return decodeURIComponent(e)}catch{}try{return decodeURIComponent(e.replace(/%(?![0-9a-fA-F]{2})/g,"%25"))}catch{return e}}function Hn(e,t){let n=mi(t).replace(/[+/|_-]+/g," ");for(let a of n.matchAll(gi))pi(e,a[1]??"",a[2]??"",n.slice(0,180))}function Ft(e,t,n){let a=yi(e),i=new Map;for(let d of t)Hn(i,[d.title,d.snippet??"",d.cite??"",d.url].join(" "));for(let d of n)Hn(i,[d.name,...d.metadata,d.websiteUrl??"",d.directionsUrl??""].join(" "));let s=Array.from(i.values()).sort((d,S)=>S.count-d.count||d.city.localeCompare(S.city)).slice(0,8);return a?s.length===0?{status:"unknown",expected:a,candidates:[]}:{status:s.some(d=>d.city.toLowerCase()===a.city.toLowerCase()&&(a.regionCode==null||d.regionCode===a.regionCode))?"matched":"mismatch",expected:a,candidates:s}:{status:"not_requested",expected:null,candidates:s}}var ki=/^(?: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,Ci=/^(?:AI Overview|View all|Show more|Show less|Related Links|Ask anything in AI Mode|AI can make mistakes)[.!…\s]*$/i;function Te(e){return e.replace(/\u00a0/g," ").replace(/\s+/g," ").trim()}function Rt(e,t){if(!e)return;let n=Te(e.split(/\r?\n/).filter(i=>!Ci.test(Te(i))).join(`
|
|
21712
|
+
`)),a=t?Te(t):"";return a&&n.toLowerCase().startsWith(a.toLowerCase())&&(n=n.slice(a.length).trim()),!n||ki.test(n)?void 0:n}function mt({selectors:e,onlyQuestion:t}){let n=o=>(o??"").replace(/\u00a0/g," ").replace(/\s+/g," ").trim(),a=o=>n(o).replace(/\s*\(\+\d+\)\s*-\s*View related links.*$/i,"").replace(/\s*(?:[-.]\s*)?Opens in new tab[.!]?$/i,"").trim(),i=(o,U)=>{if(o.matches(e.clickTarget)||o.getAttribute("aria-expanded")==="true")return!1;let c=o.closest(".biJ8pb")?.closest(".hICk5e[data-collapsed]");if(c&&(c.getAttribute("data-collapsed")!=="1"||U?.closest(".hICk5e[data-collapsed]")===c))return!1;let g=o.getAttribute("href");return g&&!/^(?:#|javascript:void\(0\);?$)/i.test(g)||o.closest(e.aiSourceCard+","+e.sourceCard)?!1:[o.getAttribute("aria-label"),o.textContent].map(n).some(p=>/^(?:(?:show|read|see) more(?: (?:AI Overview|(?:of )?(?:this |the )?answer))?|continue reading|expand(?: (?:this |the )?answer)?)(?:[.!…]|\s*[▼⌄+])?$/i.test(p))},s=(o,U=!1)=>o.hasAttribute("hidden")||o.getAttribute("aria-hidden")==="true"&&!U||/(?:display\s*:\s*none|visibility\s*:\s*hidden)/i.test(o.getAttribute("style")??""),l=o=>{let U=o.ownerDocument.defaultView?.getComputedStyle(o);return U?.display==="none"||U?.visibility==="hidden"},d=(o,U)=>!U?.matches(e.aiAnswerBody)||!U.closest(".hICk5e[data-collapsed]")||!o?.matches("span.mTEjhd > span.dteT0b > div[data-xpm-copy-root][data-xpm-math-type]")||!o.querySelector(":scope > div > math > semantics")?"":n(o.querySelector(':scope > img[data-xpm-latex][role="presentation"][aria-hidden="true"]')?.getAttribute("data-xpm-latex")),S=(o,U)=>{let c=o?.closest('div.Q9iar.bliT4d.KfKEse.xRMEde[role="list"]');return!!(U?.matches(e.aiAnswerBody)&&U.closest(".hICk5e[data-collapsed]")&&c&&U.contains(c)&&o?.matches('div.Q9iar.BPUOre.bliT4d.KfKEse.xRMEde[role="listitem"]')&&o.querySelector(":scope > div.Q9iar.BPUOre.ua6Thd.bliT4d.KfKEse.xRMEde"))},u=(o,U)=>{if(!U?.matches(e.aiAnswerBody)||!U.closest(".hICk5e[data-collapsed]")||!o.matches('span.jAOkJc[role="button"]')||!o.parentElement?.matches("u.wfWfIf.fxyaSe")||!o.parentElement.parentElement?.matches("span.iNqyIf"))return!1;let c=o.firstElementChild;return!!(c?.matches("span.iNqyIf")&&o.children.length===1&&n(o.textContent)===n(c.textContent))},h=(o,U)=>{if(!U?.matches(e.aiAnswerBody)||!U.closest(".hICk5e[data-collapsed]"))return!1;if(o.matches("li.Z1qcYe, div.WYczDe, span.iNqyIf, ol.T9WCjf.qkgVBf")||S(o,U)||o.matches("strong.rQesXe.MPyX")&&o.closest("div.n6owBd.awi2gc")&&S(o.closest('[role="listitem"]'),U))return!0;if(o.closest("span.iNqyIf")){if(o.matches("strong.rQesXe.MPyX"))return!0;let g=o.matches("span")?o.querySelector(":scope > a.H23r4e[href]"):null;if(g&&/^(?:https?:\/\/|\/goto\?url=|\/url\?)/i.test(g.getAttribute("href")??"")&&o.children.length===1&&n(o.textContent)===n(g.textContent)&&o.parentElement?.matches("span")&&/display\s*:\s*contents/i.test(o.parentElement.getAttribute("style")??""))return!0}if(!o.matches("div.tYHU1b"))return!1;let c=o.querySelector(":scope > div.ID94bb[id]");return c?Array.from(o.querySelectorAll('[role="button"][aria-expanded="true"][aria-controls]')).some(g=>{if(g.closest(".tYHU1b")!==o||g.getAttribute("aria-controls")!==c.id||n(g.textContent)!=="Show less")return!1;for(let w=g;w&&w!==o;w=w.parentElement)if(s(w)||l(w))return!1;return!0}):!1},r=(o,U,c)=>{if(!o||o!==U&&(s(o,h(o,U))||o.matches('style,script,noscript,button,[data-artifact-type="map"]')||o.matches('[role="button"]')&&!o.matches(e.answerEntity)&&!u(o,U)||o.matches(e.aiSourceCard+","+e.sourceCard+","+e.citationBadge)||c&&(o.matches("cite,"+e.sourceSite)||o.matches("a[href]")&&o.querySelector("h3"))))return"";let g=d(o,U);if(g)return g;let w=[];for(let p of o.childNodes)p.nodeType===Node.TEXT_NODE?w.push(p.textContent??""):p.nodeType===Node.ELEMENT_NODE&&w.push(r(p,U,c));return n(w.join(" "))};return Array.from(document.querySelectorAll(e.item)).flatMap((o,U)=>{let c=n(o.getAttribute(e.itemDataQ)||o.getAttribute(e.itemDataInitQ)||o.querySelector(e.itemQuestionEl)?.innerText||o.querySelector(e.itemQuestionEl)?.textContent);if(!c||t&&c!==n(t))return[];let g=o.classList.contains(e.expandedClass)||o.querySelector(e.clickTarget)?.getAttribute("aria-expanded")==="true",w=o.querySelector(e.answerContainer),p=w?.querySelector(e.aiAnswerBody)||(w?.matches(e.aiAnswerBody)?w:null)||w?.querySelector(e.answerBody)||(w?.matches(e.answerBody)?w:null),M=p||w,y=r(M,M,!p),T=/^(?:an error has occurred(?:[.!…]\s*)?(?:please try again later[.!…]?)?|loading|please wait|try again|something went wrong)[.!…\s]*$/i.test(y),O=[...Array.from((M||o).querySelectorAll("a[href]")),...Array.from(w?.querySelectorAll("a[href]")||[]),...Array.from(o.querySelectorAll(e.aiCitation+","+e.aiSourceCard))],x=!T&&(g&&y.length>=10||y.length>30&&O.some(N=>/^https?:\/\//i.test(N.href))),b=M?.matches(e.aiAnswerBody)&&M.closest(".hICk5e[data-collapsed]")?M:null,G=b&&Array.from(b.querySelectorAll('[hidden], [aria-hidden="true"], [style]')).some(N=>{if(!s(N)||!n(N.textContent))return!1;let D=N.closest('button, [role="button"]');if(D&&!u(D,b)||N.closest('[data-artifact-type="map"], .AQisZb, '+e.aiSourceCard+","+e.sourceCard+","+e.citationBadge))return!1;let C=N.closest("[data-xpm-copy-root][data-xpm-math-type]");return d(C,b)&&(N.closest("svg")?.parentElement===C||N.closest("math")?.parentElement?.parentElement===C)?!1:!h(N,b)||s(N,!0)}),F=b&&!G?b:null,P=Array.from(w?.querySelectorAll(e.answerControl)||[]),v=x?P.flatMap((N,D)=>{if(!i(N,F))return[];for(let C=N;C&&C!==w;C=C.parentElement)if(s(C)||l(C))return[];return[D]}):[],W=new Map;if(x)for(let N of O){if(!/^https?:\/\//i.test(N.href)||N.closest('[data-artifact-type="map"]'))continue;let D=N.closest(e.sourceCard),C=D?n(D.querySelector(e.sourceDescription)?.textContent):"",L=(D?n(D.querySelector(e.sourceCardTitle)?.textContent):"")||a(N.getAttribute("aria-label"))||n(N.querySelector("h3")?.textContent)||n(N.textContent),m=W.get(N.href);W.set(N.href,{title:D&&L?L:m?.title||L,rawHref:N.href,...C||m?.description?{description:C||m?.description}:{}})}let f=[...W.values()],k=x&&n(o.querySelector(e.sourceTitle)?.textContent)||void 0,K=x&&n(o.querySelector(e.sourceSite)?.textContent)||void 0;return k||=f.find(N=>N.title.length>2)?.title||f[0]?.title||void 0,[{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:c,answer:x?y:void 0,sourceTitle:k,sourceSite:K,sources:f,...v.length||x&&G||o.getAttribute("data-mcp-answer-expansion")==="pending"?{answerExpansionIncomplete:!0}:{},itemIndex:U,expanded:g,answerControls:v,...v.some(N=>P[N]?.getAttribute("data-mcp-answer-expansion")==="pending")?{answerControlPending:!0}:{}}]})}async function Pe(e,t,n,a){let i=Math.min(n.deadlineMs??1/0,Date.now()+1e4),s=()=>Math.max(0,i-Date.now()),l=n.dispatchClick??(U=>U()),d=async()=>(await e.evaluate(a,{selectors:n.selectors,onlyQuestion:t}))[0],S=await d(),u=async(U,c)=>n.signal?.aborted||s()<=0?!1:e.evaluate(({selectors:g,question:w,operation:p,controlIndex:M})=>{let y=G=>(G??"").replace(/\u00a0/g," ").replace(/\s+/g," ").trim(),T=Array.from(document.querySelectorAll(g.item)).find(G=>y(G.getAttribute(g.itemDataQ)||G.getAttribute(g.itemDataInitQ)||G.querySelector(g.itemQuestionEl)?.textContent)===y(w));if(!T)return!1;if(p==="clear")return T.removeAttribute("data-mcp-answer-expansion"),!0;let O=Array.from(T.querySelector(g.answerContainer)?.querySelectorAll(g.answerControl)||[]),x=O.filter(G=>G.getAttribute("data-mcp-answer-expansion")==="pending");if(p==="confirmed")return x.length>1?!1:(x[0]?.setAttribute("data-mcp-answer-expansion","confirmed"),!0);let b=M===void 0?void 0:O[M];return!b||x.length||b.matches(":disabled")||b.closest('[aria-disabled="true"]')?!1:(b.setAttribute("data-mcp-answer-expansion","pending"),b.setAttribute("data-mcp-answer-expansion-for",encodeURIComponent(w)),T.setAttribute("data-mcp-answer-expansion","pending"),!0)},{selectors:n.selectors,question:t,operation:U,controlIndex:c}).catch(()=>!1);async function h(U,c){let g=Date.now()+U.budgetMs,w,p=null,M=U.beforeAnswer;for(;Date.now()<g;){if(await new Promise(y=>window.setTimeout(y,Math.min(150,g-Date.now()))),w=c({selectors:U.selectors,onlyQuestion:U.onlyQuestion})[0],!w)return{acknowledged:!1,clearMarker:!1};if(w.answer!==M&&(M=w.answer,p=Date.now()),!w.answerControls.length&&w.answer){p??=Date.now();let y=w.answer!==U.beforeAnswer?300:1e3;if(Date.now()-p>=y)return{state:w,acknowledged:!0,clearMarker:!0}}else if(w.answerControls.length&&(w.answer!==U.beforeAnswer||!w.answerControlPending)&&(p??=Date.now(),Date.now()-p>=300))return{state:w,acknowledged:!0,clearMarker:!1}}return{state:w,acknowledged:!1,clearMarker:!1}}let r=new Function("input",`return (${h.toString()})(input, (${a.toString()}));`),o=async U=>{if(n.signal?.aborted||s()<=0)return!1;let c,g=new Promise(w=>{c=()=>w(void 0),n.signal?.addEventListener("abort",c,{once:!0})});try{let w=e.evaluate(r,{selectors:n.selectors,onlyQuestion:t,beforeAnswer:U,budgetMs:Math.min(2500,s())}),p=await Promise.race([w,g]);return!p||n.signal?.aborted||s()<=0?!1:(S=p.state,p.acknowledged&&(p.clearMarker?await u("clear"):!0))}finally{c&&n.signal?.removeEventListener("abort",c)}};if(S?.answerExpansionIncomplete&&!S.answerControls.length){await o(S.answer);return}for(let U=0;S?.answerControls.length&&U<8;U+=1){if(n.signal?.aborted||s()<=0)return;let c=S.answer,g=!1;try{if(S=await d(),!S?.answerControls.length)return;c=S.answer;let p=e.locator(n.selectors.item).nth(S.itemIndex);if(!S.expanded){if(n.allowOuterReopen===!1||(await l(async()=>{n.signal?.aborted||s()<=0||await p.locator(n.selectors.clickTarget).first().click({force:!0,noWaitAfter:!0,timeout:Math.min(1200,s())})}),s()<=0||n.signal?.aborted)||(await e.waitForTimeout(Math.min(250,s())),S=await d(),!S?.answerControls.length))return;c=S.answer}if(n.signal?.aborted||s()<=0)return;let M=S;await l(async()=>{if(n.signal?.aborted||s()<=0)return;let y=await u("pending",M.answerControls[0]);g=!0,y&&!n.signal?.aborted&&s()>0&&await e.locator(`[data-mcp-answer-expansion="pending"][data-mcp-answer-expansion-for="${encodeURIComponent(t)}"]`).first().click({force:!0,noWaitAfter:!0,timeout:Math.min(1200,s())}).catch(()=>{})})}catch{}if(!g||n.signal?.aborted||s()<=0||!await o(c)||!S?.answerControls.length||!await u("confirmed"))return}}async function Dn(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(P){return P?(P.innerText??P.textContent??"").trim():""}function s(P){if(!P)return!1;let v=P.replace(/\s+/g," ").trim();return v.length>=16&&v.split(" ").filter(Boolean).length>=2}function l(P){let v=P.querySelector(t.aio.heading);if(i(v)==="AI Overview")return!0;let W=P.querySelector(t.aio.header);return!!i(W).split(/\n|\s{2,}/).some(f=>f.trim()==="AI Overview")}function d(){let v=Array.from(document.querySelectorAll(t.aio.root)).find(l);if(v)return v;if(t.aio.legacyRoot){let f=document.querySelector(t.aio.legacyRoot);if(f&&l(f))return f}let W=document.querySelectorAll(`${t.aio.heading}, h1, h2, h3, [role="heading"]`);for(let f of W){if(i(f)!=="AI Overview")continue;let k=f.parentElement;for(let K=0;K<8&&k;K++){if(k.matches(t.aio.root)||k.querySelector(t.aio.controller)||k.querySelector(t.aio.contentSubtree))return k;k=k.parentElement}return f.parentElement}return null}function S(P){if(!P)return null;let v=P.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(D=>D.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(P.getBoundingClientRect?.().width||960))}px`,W.style.opacity="0",W.style.pointerEvents="none",W.append(v),document.body.append(W);let f=v.innerText||v.textContent||"";W.remove();let k=f.replace(/\r/g,"").replace(/[ \t]+\n/g,`
|
|
21707
21713
|
`).replace(/\n[ \t]+/g,`
|
|
21708
21714
|
`).replace(/\n{3,}/g,`
|
|
21709
21715
|
|
|
@@ -21712,11 +21718,11 @@ Zwolle,Louisiana,United States`,rn={ad:"Andorra",ae:"United Arab Emirates",af:"A
|
|
|
21712
21718
|
`).replace(/\n{3,}/g,`
|
|
21713
21719
|
|
|
21714
21720
|
`).trim();return!N||/not available|try again|can't generate/i.test(N)?null:N}function u(P){if(!P||P.startsWith("javascript:"))return null;try{let v=new URL(P,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(P){if(!P)return[];let v=new Set,W=[];for(let f of Array.from(P.querySelectorAll("a[href]"))){let k=u(f.getAttribute("href")??"");if(!k||v.has(k.rawHref))continue;v.add(k.rawHref);let K="";try{K=new URL(k.href).hostname.replace(/^www\./,"")}catch{}W.push({text:i(f)||K||k.href,href:k.href,rawHref:k.rawHref})}return W}async function r(P){let v=P.querySelector(t.aio.showMoreButton);if(!v||v.getAttribute("aria-expanded")!=="false")return!1;v.click();let W=t.expandWaitMs??1500;return W>0&&await new Promise(f=>setTimeout(f,W)),!0}let o=d(),U=null,c=[],g=!1,w=!1,p=[];if(o){g=await r(o);let P=o.querySelector(t.aio.controller),v=o.querySelector(t.aio.contentSubtree),W=o.querySelector(t.aio.showMoreButton);w=P?.getAttribute("data-trnct")==="false"||W?.getAttribute("aria-expanded")==="true"||!W,U=S(v??P??o),p=(U??"").split(`
|
|
21715
|
-
`).map(f=>f.trim()).filter(f=>/^\d+\.\s+.+/.test(f)),c=h(o)}let M=document.querySelector(t.aim.root),y=a==="aim"&&!!M,T=M?.closest(t.aim.wrapper)??M,O=y?S(T):null,x=y&&s(O),b=x?O:null,G=x?h(T):[],F=!!o&&s(U);return{surface:a,aiOverview:{detected:F,text:F?U:null,citations:F?c:[],expanded:F?g:!1,fullyExpanded:F?w:!1,sections:F?p:[]},aiMode:{detected:x&&b!==null,text:b,citations:G}}}import{createHash as Ci}from"crypto";var Gn=8e3,En=3e3,Vn=1e4,Mi=8;function ut(e){return/(^|\.)google\.(?:com|[a-z]{2,3}(?:\.[a-z]{2})?)$/i.test(e)}function Dt(e){if(!e||e.length>Gn)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 vi(e,t){if(!e||e.length>Gn||/^javascript:/i.test(e))return null;try{let n=new URL(e,t);return Dt(n.href)}catch{return null}}function Rt(e){let t=Dt(e);return!t||t.protocol!=="https:"||!ut(t.hostname)||t.pathname!=="/goto"?null:t.searchParams.get("url")?t:null}function Pe(e){if(e.linkType!=="google_goto_redirect"||e.resolutionStatus!=="resolved"||!Rt(e.rawUrl)||!e.resolvedUrl)return!1;let t=Dt(e.resolvedUrl);return!!(t&&!ut(t.hostname)&&t.href===e.resolvedUrl&&e.url===t.href)}function kt(e){let t=e.normalize("NFKC").toLocaleLowerCase("en-US").replace(/[^\p{L}\p{N}\s]/gu,"").replace(/\s+/g," ").trim();return`paa_${Ci("sha256").update(t).digest("hex").slice(0,16)}`}function Ct(e,t){let n=vi(e,t);if(!n)return null;let a=n.href;if(!ut(n.hostname))return{url:a,rawUrl:a,resolvedUrl:a,linkType:"plain",resolutionStatus:"not_needed"};if(n.pathname==="/url"){let i=Dt(n.searchParams.get("q")??n.searchParams.get("url")??"");return!i||ut(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 Rt(e)?.searchParams.get("url")??null}function Yn(e,t){try{let n=new URL(e),a=Dt(new URL(t,n).href);return!a||ut(a.hostname)?null:(!a.hash&&n.hash&&(a.hash=n.hash),a.href)}catch{return null}}async function Kn(e,t={}){let n=[...new Set([...e].flatMap(r=>Rt(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 l=Math.max(1,t.timeoutMs??En),d=Date.now()+Math.max(1,t.totalBudgetMs??Vn),S=Math.max(1,Math.min(16,Math.floor(t.concurrency??Mi))),u=0,h=async()=>{for(;u<n.length;){let r=n[u++],o=Rt(r),U=o?.searchParams.get("url");if(!o||!U){a.set(r,{rawUrl:r,resolvedUrl:null,resolutionStatus:"rejected"});continue}o.hash="";let c=o.href;for(let g=0;g<2;g++){let w=d-Date.now();if(w<=0)return;let p=new AbortController,M=setTimeout(()=>p.abort(),Math.min(l,w)),y;try{y=await s(c,{method:"GET",redirect:"manual",headers:{accept:"*/*","user-agent":"Mozilla/5.0"},signal:p.signal})}catch{break}finally{clearTimeout(M)}if(y.status<300||y.status>=400)break;let T=y.headers.get("location");if(!T)break;let O=Yn(r,T);if(O){a.set(r,{rawUrl:r,resolvedUrl:O,resolutionStatus:"resolved"});break}let x;try{x=new URL(T,c)}catch{a.set(r,{rawUrl:r,resolvedUrl:null,resolutionStatus:"rejected"});break}if(!ut(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(S,n.length)},()=>h())),{resolutions:[...a.values()],nonGoogleRequestsObserved:0}}function Dn(e,t){try{return new URL(e.resolvedUrl??e.url).hostname.replace(/^www\./,"")}catch{return t}}async function Jn(e,t={}){let n=[],a=r=>{for(let o of r)n.push(o),a(o.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:o,...U})=>({...U,url:o})),...(e.aiMode?.citations??[]).map(({text:r,href:o,...U})=>({...U,url:o}))],s=new Map(i.filter(r=>!!r?.rawUrl).map(r=>[r.rawUrl,r])),l=[...s.values()].filter(r=>r.linkType==="google_goto_redirect"&&r.resolutionStatus!=="resolved").map(r=>r.rawUrl);if(l.length>0){let r=await Kn(l,t);for(let o of r.resolutions){let U=s.get(o.rawUrl);U&&s.set(o.rawUrl,o.resolutionStatus==="resolved"&&o.resolvedUrl?{...U,url:o.resolvedUrl,resolvedUrl:o.resolvedUrl,resolutionStatus:"resolved"}:{...U,resolutionStatus:o.resolutionStatus})}}let d=r=>({...r,...s.get(r.rawUrl)??r}),S=r=>r.map(o=>{let U=d(o);return{...U,site:Dn(U,o.site)}});for(let r of e.flat){r.sources=S(r.sources??[]);let o=r.sources[0];r.source_title=o?.title??r.source_title,r.source_site=o?.site??r.source_site,r.source_cite=o?.url??r.source_cite}for(let r of n){r.sources=S(r.sources??[]);let o=r.sources[0];r.sourceTitle=o?.title??r.sourceTitle,r.sourceSite=o?.site??r.sourceSite,r.sourceCite=o?.url??r.sourceCite}for(let r=0;r<(e.organicResults?.length??0);r++){let o=d(e.organicResults[r]);e.organicResults[r]={...o,domain:Dn(o,e.organicResults[r].domain)??""}}let u=r=>{let o=d({url:r.href,rawUrl:r.rawUrl,resolvedUrl:r.resolvedUrl,linkType:r.linkType,resolutionStatus:r.resolutionStatus}),{url:U,...c}=o;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,o)=>r+o.sources.length,0),aiOverviewLabelValidated:e.aiOverview?.detected??!1},e}async function _n(e,t,n={}){let a=new Map;for(let o of t){let U=a.get(o.rawUrl);U&&Pe(U)||a.set(o.rawUrl,o.linkType==="google_goto_redirect"&&!Pe(o)?{...o,url:o.rawUrl,resolvedUrl:null,resolutionStatus:"unresolved"}:o)}let i=[...a.values()].filter(o=>o.linkType==="google_goto_redirect"&&!Pe(o));if(i.length===0)return a;let s=Date.now()+(n.totalBudgetMs??Vn),l=await Kn(i.map(o=>o.rawUrl),n);for(let o of l.resolutions){let U=a.get(o.rawUrl);U&&a.set(o.rawUrl,o.resolutionStatus==="resolved"&&o.resolvedUrl?{...U,url:o.resolvedUrl,resolvedUrl:o.resolvedUrl,resolutionStatus:"resolved"}:{...U,resolutionStatus:o.resolutionStatus})}let d=i.filter(o=>a.get(o.rawUrl)?.resolutionStatus==="unresolved");if(d.length===0||n.browserFallback===!1||Date.now()>=s)return n.onNetworkAudit?.({nonGoogleRequestsObserved:0}),a;let S=n.timeoutMs??En,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 o=>{let U=o.request().url();try{ut(new URL(U).hostname)||(r+=1)}catch{}let c=be(U);if(!h||c!==h.token){await o.abort("blockedbyclient").catch(()=>{});return}let g=h;try{let w=await o.fetch({maxRedirects:0,timeout:g.timeoutMs});g.location=w.headers().location??null}finally{await o.abort("blockedbyclient").catch(()=>{}),g.finish()}});for(let o of d){let U=s-Date.now();if(U<=0)break;let c=Rt(o.rawUrl),g=c?.searchParams.get("url");if(!c||!g){a.set(o.rawUrl,{...o,resolutionStatus:"rejected"});continue}let w=Math.min(S,U);c.hash="";let p=c.href,M=!1;for(let y=0;y<2;y++){let T,O=new Promise(P=>{T=P}),x=`mcp-goto-${Math.random().toString(36).slice(2)}`;h={token:g,timeoutMs:w,location:null,finish:T},await u.evaluate(({url:P,id:v})=>{let W=document.createElement("iframe");W.id=v,W.hidden=!0,W.src=P,document.body.append(W)},{url:p,id:x}).catch(()=>null),await Promise.race([O,new Promise(P=>setTimeout(P,w))]);let b=h.location;if(h=null,await u.evaluate(P=>document.getElementById(P)?.remove(),x).catch(()=>null),!b)break;let G=Yn(o.rawUrl,b);if(G){a.set(o.rawUrl,{...o,url:G,resolvedUrl:G,resolutionStatus:"resolved"});break}let F;try{F=new URL(b,p)}catch{M=!0;break}if(!ut(F.hostname)||be(F.href)!==g){M=!0;break}p=F.href}M&&a.get(o.rawUrl)?.resolutionStatus!=="resolved"&&a.set(o.rawUrl,{...o,resolutionStatus:"rejected"})}}finally{h=null,await u.close().catch(()=>{}),n.onNetworkAudit?.({nonGoogleRequestsObserved:r})}return a}async function qn(e){let t=Lt;return e.evaluate(n=>{let a=[],i=Array.from(document.querySelectorAll(n.container));for(let s of i){let S=(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 o=h.textContent?.trim()??"",U=o.indexOf("YouTube");if(U===-1)continue;let c=o.slice(0,U).trim(),w=o.slice(U+7).replace(/^[·\s·]+/,"").match(/^([^·\n]+)/),p=w?w[1].trim():"";c&&a.push({type:S,title:c,channel:p,platform:"YouTube",duration:"",url:r})}}return a},t)}async function zn(e){let t=mn;return e.evaluate(n=>{let a=[],s=Array.from(document.querySelectorAll(n.section)).find(d=>d.textContent?.includes("Discussions"));if(!s)return a;let l=Array.from(s.querySelectorAll(n.item));for(let d of l){let S=d.href;if(!S)continue;let u=d.querySelector(n.title),h=d.querySelector(n.source),r=u?.textContent?.trim()??"",o=h?.textContent?.trim()??"";r&&a.push({title:r,source:o,url:S})}return a},t)}async function jn(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 l=new Set,d=[],S=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 S){let o=r.href;if(!o||!u.some(c=>o.includes(c)))continue;let U=r.textContent?.trim()??"";h.has(o)||h.set(o,[]),h.get(o).push(U)}for(let[r,o]of h.entries()){if(l.has(r))continue;l.add(r);let U=o.find(M=>/^\d+:\d+$/.test(M))??"",c=o.find(M=>!/^\d+:\d+$/.test(M)&&M.length>5)??"";if(!c)continue;let g=c,w="",p="";for(let M of s.platforms){let y=-1,T=0;for(;;){let F=c.indexOf(M,T);if(F===-1)break;y=F,T=F+1}if(y===-1)continue;let O=c.slice(y+M.length);if(!(/^[\s·]/.test(O)||O.trim()===""))continue;g=c.slice(0,y).trim(),w=M;let b=O.replace(/^[\s·]+/,""),G=b.indexOf("\xB7");p=(G===-1?b:b.slice(0,G)).trim();break}g&&d.push({title:g,channel:p,platform:w,duration:U,url:r})}return d},a)).map(s=>({type:"short_video",...s}))}async function $n(e){let t=kn;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 l=i.querySelector(n.cardLink)?.href??"",d=i.querySelector(n.titleH1)?.textContent?.trim(),S=i.querySelector(n.titleDiv)?.textContent?.trim(),u=d??S??"",h=i.querySelector(n.source)?.textContent?.trim()??"",o=i.querySelector(n.platformBadge)?.textContent?.trim()??"",U=i.querySelector(n.ytChannel)?.textContent?.trim()??"",c=i.querySelector(n.ytDate)?.textContent?.trim()??"",g=i.querySelector(n.authorNote)?.textContent?.trim()??null,w=i.querySelector(n.popularCommentLabel),p=null;if(w){let k=w.nextSibling;for(;k;){let K=k.textContent?.trim();if(K){p=K;break}k=k.nextSibling}}let M=Array.from(i.querySelectorAll("span")),y=M.find(k=>/^\d+:\d+$/.test(k.textContent?.trim()??""))?.textContent?.trim()??null,O=M.map(k=>k.textContent?.trim()??"").filter(k=>/\d/.test(k)&&(k.includes("comment")||k.includes("reaction")||k.includes("view")||k.includes("like")||k.includes("share")))[0]??"",x=M.map(k=>k.textContent?.trim()??"").filter(k=>/\d+ (day|week|month|year|hour)s? ago|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/.test(k)),b=c||(x[0]??""),G=o||(U?"YouTube":""),F=U||h,P="unknown",v=G.toLowerCase(),W=F.toLowerCase(),f=h.toLowerCase();return v.includes("reddit")||W.startsWith("r/")?P="reddit":v.includes("facebook")||f.includes("facebook")?P="facebook":v.includes("instagram")||f.includes("instagram")?P="instagram":v.includes("tiktok")||f.includes("tiktok")?P="tiktok":v.includes("youtube")||U?P="youtube":P="news",{type:P,title:u,url:l,source:F,platform:G,popularComment:p,engagement:O,date:b,duration:y,authorNote:g}}):[]},t)}async function Qn(e){let t=vn,n=await e.evaluate(i=>{let s=[],l=0;return document.querySelectorAll(i.result).forEach(d=>{let S=d.querySelector(i.title);if(!S)return;let u=S.textContent?.trim()??"",r=S.closest("a")?.href??"";if(!u||!r)return;l++;let o=d.querySelector(i.cite)?.textContent?.trim()??null,U=d.querySelector(i.snippet)?.textContent?.trim()??null,c=!!d.querySelector(i.redditCite),g=d.querySelector(i.ratingWrap),w=g?{value:g.querySelector(i.ratingValue)?.textContent?.trim()??"",count:g.querySelector(i.reviewCount)?.textContent?.trim()??""}:null,p="";try{p=new URL(r).hostname.replace(/^www\./,"")}catch{p=d.querySelector(i.siteName)?.textContent?.trim()??""}s.push({position:l,title:u,url:r,domain:p,cite:o,snippet:U,isRedditStyle:c,inlineRating:w})}),s},t),a=typeof e.url=="function"?e.url():"https://www.google.com/";return n.flatMap(i=>{let s=Ct(i.url,a);if(!s)return[];let l=i.domain;try{l=new URL(s.resolvedUrl??s.rawUrl).hostname.replace(/^www\./,"")}catch{}return[{...i,...s,domain:l}]})}async function Zn(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,l)=>{let d=s.querySelector(n.name)?.textContent?.trim()??"";if(!d)return;let S=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 w of Array.from(s.querySelectorAll("a[href]"))){let p=w.href.match(/[?&]cid=(\d+)/);if(p){r=p[1];break}let M=w.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 o=[];s.querySelectorAll("div, span").forEach(w=>{let p=Array.from(w.childNodes).filter(M=>M.nodeType===3).map(M=>M.textContent?.trim()??"").filter(M=>M.length>1&&M.length<120).join(" ");p&&!o.includes(p)&&o.push(p)});let U=Array.from(s.querySelectorAll("a[href]")),c=U.find(w=>w.href.includes("google.com/maps"))?.href??null,g=U.find(w=>!w.href.includes("google.com")&&w.href.startsWith("http"))?.href??null;a.push({position:l+1,name:d,cid:r,rating:S,reviewCount:h,metadata:o,websiteUrl:g,directionsUrl:c})}),a},t)}async function Xn(e){return e.evaluate(()=>{let t=new Set,n=new Set,a=new Set,i=new Map;function s(d){let S=[".OSrXXb",".dbg0pd",".tzt0oe",'[role="heading"]',"h3"];for(let u of S){let h=d.querySelector(u);if(h?.textContent?.trim())return h.textContent.trim()}return""}document.querySelectorAll('[id^="pv-/g/"]').forEach(d=>{let S=d.getAttribute("id");if(!S)return;let u=S.replace("pv-","");t.add(u);let h=s(d),o=d.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;o&&n.add(o),h&&i.set(u,{name:h,kgId:u,cid:o,gcid:null})}),document.querySelectorAll("[data-mid]").forEach(d=>{let S=d.getAttribute("data-mid");if(S?.startsWith("/g/")&&(t.add(S),!i.has(S))){let u=s(d);u&&i.set(S,{name:u,kgId:S,cid:null,gcid:null})}}),document.querySelectorAll(".w7Dbne").forEach(d=>{let u=d.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;if(!u)return;n.add(u);let h=d.querySelector(".OSrXXb")?.textContent?.trim()??"";if(!h)return;let r=d.querySelector('[id^="pv-/g/"]'),o=r?r.getAttribute("id").replace("pv-",""):null,U=o??`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:o,cid:u,gcid:null})}),document.querySelectorAll("a[data-cid]").forEach(d=>{let S=d.getAttribute("data-cid");if(!S)return;if(n.add(S),![...i.values()].some(h=>h.cid===S)){let h=d.parentElement,r="";for(let o=0;o<8&&h;o++){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:${S}`,{name:r,kgId:null,cid:S,gcid:null})}});let l=Array.from(document.querySelectorAll("script:not([src])")).map(d=>d.textContent??"").filter(d=>d.length>1e4).join(`
|
|
21716
|
-
`);for(let d of l.matchAll(/\/g\/[a-zA-Z0-9_-]{5,20}/g))t.add(d[0]);for(let d of l.matchAll(/gcid:[a-zA-Z0-9_]+/g))a.add(d[0]);for(let d of l.matchAll(/0x[0-9a-f]+:0x([0-9a-f]+)/gi))try{n.add(BigInt("0x"+d[1]).toString())}catch{}return{entities:[...i.values()],kgIds:[...t],cids:[...n],gcids:[...a]}})}function ta(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(),l=a.find(d=>d.name.toLowerCase().trim()===s);l?l.cid||(l.cid=i.cid):a.find(d=>d.cid===i.cid)||a.push({name:i.name,kgId:null,cid:i.cid,gcid:null})}return{...e,entities:a,cids:[...n]}}var ea=String.raw`^(?:an error has occurred(?:[.!…]\s*)?(?:please try again later[.!…]?)?|loading|please wait|try again|something went wrong)[.!…\s]*$`,Ni=700,Ti=1e3,na=1400,aa=2e3,Pi=4,ia=250,ee=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 l=i.resolutionStatus==="resolved"&&s.resolutionStatus!=="resolved"?i:s,d=i.description?.trim()&&!s.description?.trim()?i:s.description?.trim()?s:l;a.set(i.rawUrl,{...l,title:d.title??l.title??s.title??i.title,site:l.site??s.site??i.site,...(d.description??s.description??i.description)!==void 0?{description:d.description??s.description??i.description}:{}})}return[...a.values()]}normalizeAICitations(t,n){let a=new Set;return n.flatMap(i=>{let s=Ct(i.rawHref??i.href,t);if(!s||a.has(s.rawUrl))return[];a.add(s.rawUrl);let{url:l,...d}=s;return[{...d,text:i.text,href:l}]})}async resolveMaterialLinks(t,n,a,i,s){let l=Date.now(),d=[...n.flatMap(c=>c.sources??[]),...a,...i.citations.map(({text:c,href:g,...w})=>({...w,url:g})),...s.citations.map(({text:c,href:g,...w})=>({...w,url:g}))],S=new Map(d.map(c=>[c.rawUrl,c])),u=0,h=await _n(t,d,{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 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=r(a[c]);if(g.resolvedUrl)try{g.domain=new URL(g.resolvedUrl).hostname.replace(/^www\./,"")}catch{}a[c]=g}let o=c=>{let g=r({url:c.href,rawUrl:c.rawUrl,resolvedUrl:c.resolvedUrl,linkType:c.linkType,resolutionStatus:c.resolutionStatus}),{url:w,...p}=g;return{...p,text:c.text,href:w}};i.citations=i.citations.map(o),s.citations=s.citations.map(o);let U=[...h.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:i.detected},this.phaseTimings.linkResolutionMs=(this.phaseTimings.linkResolutionMs??0)+(Date.now()-l)}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 at}async throwIfCaptcha(t,n){if(await t.locator(q.captchaMarker).count().catch(()=>0)>0)throw new j(`${n} returned a CAPTCHA \u2014 retrying with a fresh session.`)}async extractVisibleItems(t,n){let a=await t.evaluate(mt,{selectors:q,onlyQuestion:n}),i=typeof t.url=="function"?t.url():"https://www.google.com/";return this.mapPaaDomRecords(a,i)}mapPaaDomRecords(t,n){return t.flatMap(a=>{let i=[],s=new Set;for(let u of a.sources){let h=Ct(u.rawHref,n);if(!h||s.has(h.rawUrl))continue;s.add(h.rawUrl);let r=a.sourceSite??null;try{r||=new URL(h.resolvedUrl??h.rawUrl).hostname.replace(/^www\./,"")}catch{}i.push({...h,title:u.title||a.sourceTitle||null,site:r,...u.description?{description:u.description}:{}})}let l=i[0],d={questionId:kt(a.question),googleLinkId:a.googleLinkId,googleEvidenceId:a.googleEvidenceId,question:a.question,answer:Ft(a.answer,a.question),sourceTitle:l?.title??a.sourceTitle,sourceSite:l?.site??a.sourceSite,sourceCite:l?.url,sources:i,...a.answerExpansionIncomplete?{answerExpansionIncomplete:!0}:{}},S=nn.safeParse(d);return S.success?[S.data]:(console.warn("[PAAExtractor] item parse failed:",a.question,S.error.issues[0]?.message),[])})}jitteredDelayMs(t,n){return t+Math.floor(Math.random()*(n-t+1))}async clickItem(t,n){try{await t.locator(`${q.item}[data-q="${n}"], ${q.item}[data-initq="${n}"]`).first().click()}catch{}}toFlatRow(t,n,a,i){return{seed_query:i,question_id:t.questionId??kt(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(d=>this.normalizeQuestion(d.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},l=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 l&&(this.collectedRows[a]=s),l}async emitProgress(t){if(!this.onPaaProgress||this.collectedRows.length===0&&!this.checkpointMaterial)return;let n={sequence:++this.progressSequence,observedAt:new Date().toISOString(),clickedQuestions:[...this.clickedQuestions],phase:t,records:this.collectedRows.map(a=>({...a})),lifecycle:{...this.paaLifecycle},...this.checkpointMaterial?{material:structuredClone(this.checkpointMaterial)}:{},interactions:this.interactionObservations.map(a=>({...a,confirmationSignals:[...a.confirmationSignals]}))};try{await this.onPaaProgress(n)}catch(a){console.warn(JSON.stringify({event:"paa_progress_sink_failed",sequence:n.sequence,phase:n.phase,message:a instanceof Error?a.message:String(a)}))}}getPartialResult(){let t=this.partialContext;if(!t||this.collectedRows.length===0&&!this.checkpointMaterial)return null;let n=this.collectedRows.map(S=>({...S})),a=this.checkpointMaterial,i=t.questionsOnly?0:n.filter(S=>!S.answer?.trim()).length,s=t.questionsOnly?0:n.filter(S=>(S.sources??[]).length===0).length,l=t.questionsOnly?0:n.filter(S=>S.answerExpansionIncomplete).length,d={seed:t.seed,totalQuestions:n.length,maxDepthReached:n.reduce((S,u)=>Math.max(S,u.depth),0),durationMs:Date.now()-t.startMs,errorCount:0};return{seed:t.seed,location:t.location,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(t.startMs),completionStatus:"paa_found",problem:null,...a?.pagination?{pagination:{...a.pagination}}:{},resultQuality:"partial",degradedResult:!1,retryRecommended:!0,paaLifecycle:{...this.paaLifecycle,questionsFound:n.length,targetStatus:n.length>=(t.maxQuestions??0)?"met":"not_met",discoveryStatus:"interrupted",materialStatus:i>0||s>0||l>0?"partial":"complete",completionReason:"The browser attempt ended before frontier exhaustion could be proven."},completeness:{...this.completeness,paaWithoutAnswer:i,paaWithoutSource:s,paaIncompleteAnswers:l,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 i=new Set,s=new Set,l=[];this.clickedQuestions=new Set,this.interactionObservations=[];let d=new Set,S=new Map,u=new Set,h=new Set,r=new Map,o=new Set,U=2,c=3,g=0,w=Promise.resolve(),p=v=>{let W=w.then(()=>{if(this.throwIfAborted(a),n.softDeadlineMs&&Date.now()>=n.softDeadlineMs)throw new ft("The execution deadline arrived before the next PAA interaction.");return v()});return w=W.then(()=>{},()=>{}),W},M={sel:q.item,dataQ:q.itemDataQ,dataInitQ:q.itemDataInitQ,questionEl:q.itemQuestionEl,answerSel:q.answerContainer,expandedClass:q.expandedClass,clickTarget:q.clickTarget,answerPlaceholderPattern:ea,questionsOnly:n.questionsOnly},y=()=>t.evaluate(({sel:v,dataQ:W,dataInitQ:f,questionEl:k,expandedClass:K,clickTarget:N,answerSel:D,answerPlaceholderPattern:C,questionsOnly:L})=>{let m=I=>{if(!I)return"";let R=[];for(let H of I.childNodes){if(H.nodeType===Node.TEXT_NODE){let z=H.textContent?.trim();z&&R.push(z);continue}if(H.nodeType!==Node.ELEMENT_NODE)continue;let J=H;if(J.tagName==="STYLE"||J.tagName==="SCRIPT"||J.getAttribute("aria-hidden")==="true")continue;let B=m(J);B&&R.push(B)}return R.join(" ").replace(/\s+/g," ").trim()};return Array.from(document.querySelectorAll(v)).map((I,R)=>{let H=m(I.querySelector(D)).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(K)||I.querySelector(N)?.getAttribute("aria-expanded")==="true",B=H.length>=10&&!new RegExp(C,"i").test(H);return{q:(I.getAttribute(W)||I.getAttribute(f)||I.querySelector(k)?.innerText?.trim()||"").replace(/\s+/g," ").trim(),done:J&&(L||B),expanded:J,index:R,answerReady:B,sourceCount:B?I.querySelector(D)?.querySelectorAll("a[href]").length??0:0}}).filter(I=>I.q)},M),T=async(v,W,f,k,K,N,D)=>{let C=Date.now(),L={id:`${D}:${kt(v)}:${N}`,questionId:kt(v),question:v,batchNumber:D,controlAttempt:N,observedAt:new Date(C).toISOString(),beforeQuestionCount:W,expandedBefore:k},m=f>=0?t.locator(M.sel).nth(f).locator(M.clickTarget):null,I=null,R=await p(async()=>(C=Date.now(),L.observedAt=new Date(C).toISOString(),m?(k&&(await m.click({timeout:aa,force:!0,noWaitAfter:!0}),await t.waitForTimeout(120)),await m.click({timeout:aa,force:!0,noWaitAfter:!0}),!0):!1)).catch(B=>(I=B instanceof Error&&(B.name==="TimeoutError"||/timeout/i.test(B.message))?"click_ack_timeout":"click_failed",!1)),H=Date.now()-C,J={...L,dispatched:R,outcome:R?"unconfirmed":"dispatch_failed",confirmationSignals:[],confirmationCheckpointMs:null,confirmedAtMs:null,dispatchDurationMs:H,totalDurationMs:H,afterQuestionCount:W,newQuestionCount:0,expandedAfter:k,answerObserved:!1,sourceCount:0,errorCode:f<0?"control_missing":I};return{clickStartedMs:C,dispatched:R,confirmed:!1,hadMaterialBefore:K,observation:J}},O=async v=>{let W=null,f=v.filter(k=>k.dispatched||k.observation.errorCode==="click_ack_timeout");for(let k of[Ni,Ti,na]){if(!f.length)break;let K=Math.min(...f.map(C=>C.clickStartedMs+k-Date.now()));K>0&&await t.waitForTimeout(K);let N=n.questionsOnly?await y().catch(()=>null):await t.evaluate(mt,{selectors:q}).catch(()=>null);N&&!n.questionsOnly&&(W=N);let D=N?.length;for(let C of f){let L=C.observation;if(N){let m=n.questionsOnly?N.find(B=>B.q===L.question):N.find(B=>B.question===L.question),I=!1,R=0;if(m)if("q"in m)I=m.answerReady,R=m.sourceCount;else{let B=Ft(m.answer,m.question);I=!!(B&&B.length>=10&&!new RegExp(ea,"i").test(B)),R=I?m.sources.length:0}L.afterQuestionCount=D??L.beforeQuestionCount,L.newQuestionCount=Math.max(0,L.afterQuestionCount-L.beforeQuestionCount),L.expandedAfter=m?.expanded??!1,L.answerObserved=I,L.sourceCount=I?R:0,L.confirmationSignals=[...L.expandedAfter?["expanded"]:[],...I?["answer"]:[],...L.sourceCount>0?["source"]:[],...L.newQuestionCount>0?["question_growth"]:[]];let H=!!(m?.expanded&&!L.expandedBefore);((I||L.sourceCount>0)&&(!C.hadMaterialBefore||C.dispatched||H)||L.newQuestionCount>0&&(C.dispatched||H))&&(C.confirmed=!0,L.outcome="confirmed",L.confirmationCheckpointMs=k,L.confirmedAtMs=Date.now()-C.clickStartedMs),C.dispatched&&(L.errorCode=C.confirmed?null:m?"confirmation_timeout":"control_missing")}L.totalDurationMs=Date.now()-C.clickStartedMs}f=f.filter(C=>!C.confirmed&&Date.now()-C.clickStartedMs<na)}for(let k of v)k.dispatched&&!k.confirmed&&k.observation.errorCode===null&&(k.observation.errorCode="confirmation_timeout");return W},x=null,b=0;t:for(;;){if(n.softDeadlineMs&&Date.now()>=n.softDeadlineMs)throw this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"interrupted",completionReason:"The execution deadline arrived before frontier exhaustion could be proven."},new ft(this.paaLifecycle.completionReason);this.throwIfAborted(a);let v=n.questionsOnly?null:x??await t.evaluate(mt,{selectors:q});x=null;let W=typeof t.url=="function"?t.url():"https://www.google.com/",f=v?v.map(m=>{let I=!!Ft(m.answer,m.question),R=I&&!m.answerExpansionIncomplete&&m.sources.some(H=>!!Ct(H.rawHref,W));return{q:m.question,done:R||m.expanded&&I,answerReady:I,expanded:m.expanded,index:m.itemIndex}}):await y(),k=!1;for(let m of f)s.has(m.q)||(s.add(m.q),l.push(m.q),l.length<=n.maxQuestions&&(k=this.upsertCollectedRow(this.toFlatRow({questionId:kt(m.q),googleLinkId:null,googleEvidenceId:null,question:m.q,sources:[]},1,null,n.query))||k)),m.done&&(u.has(m.q)||h.delete(m.q),u.add(m.q));if(this.paaLifecycle={...this.paaLifecycle,questionsFound:Math.min(l.length,n.maxQuestions),targetStatus:l.length>=n.maxQuestions?"met":"not_met",knownQuestions:l.length,processedQuestions:u.size,failedInteractions:h.size,visibleControls:f.length},k&&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 m=!1,I=new Set(l.slice(0,n.maxQuestions)),R=this.mapPaaDomRecords(v??[],W),H=R.filter(B=>I.has(B.question)&&B.answerExpansionIncomplete&&!o.has(B.question)),J;await Promise.allSettled(H.map(async B=>{o.add(B.question);try{await Te(t,B.question,{selectors:q,deadlineMs:n.softDeadlineMs,signal:a,allowOuterReopen:!d.has(B.question),dispatchClick:p},mt)}catch(z){J??={reason:z}}})),H.length&&(R=await this.extractVisibleItems(t).catch(B=>{if(J)return R;throw B}));for(let B of R){if(!I.has(B.question))continue;let z=r.get(B.question),Y={...B,answer:B.answer||z?.answer,answerExpansionIncomplete:B.answer?B.answerExpansionIncomplete:z?.answerExpansionIncomplete,sourceTitle:B.sourceTitle??z?.sourceTitle,sourceSite:B.sourceSite??z?.sourceSite,sourceCite:B.sourceCite??z?.sourceCite,sources:this.mergePaaSources(z?.sources,B.sources)};r.set(B.question,Y),m=this.upsertCollectedRow(this.toFlatRow(Y,1,null,n.query))||m}if(m&&await this.emitProgress("answer_captured"),J)throw J.reason;if([...I].every(B=>{let z=r.get(B);return!!(z?.answer?.trim()&&z.sources.length>0&&!z.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 K=new Set(l.slice(0,n.maxQuestions)),N=f.filter(m=>K.has(m.q)&&(!m.done||s.size<n.maxQuestions&&!this.clickedQuestions.has(m.q))&&(S.get(m.q)??0)<U&&!d.has(m.q)),D=N.slice(-Pi);if(this.paaLifecycle={...this.paaLifecycle,eligibleControls:N.length},D.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 m=new Set(f.map(R=>R.q)),I=l.slice(0,n.maxQuestions).filter(R=>h.has(R)||!u.has(R)&&!m.has(R));if(I.length>0)throw this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"interrupted",failedInteractions:new Set([...h,...I]).size,completionReason:"At least one known PAA control failed or disappeared before it could be confirmed."},await this.emitProgress("expansion_finished"),new ft(this.paaLifecycle.completionReason);for(let R=1;R<=c;R++){this.throwIfAborted(a),await this.throwIfCaptcha(t,"Google PAA exhaustion confirmation"),await t.mouse.wheel(0,320);let H=await t.waitForFunction(({sel:B,min:z})=>document.querySelectorAll(B).length>z,{sel:q.item,min:f.length},{timeout:1500,polling:100}).catch(()=>null);if(this.paaLifecycle={...this.paaLifecycle,noGrowthConfirmations:R},H||(await y()).some(B=>!s.has(B.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"),g+=1;for(let m of D){if(this.reporter.onDepth(++b),(S.get(m.q)??0)>0){let I=this.paaLifecycle.retryBreakdown.controlRetries+1;this.paaLifecycle={...this.paaLifecycle,automaticRetries:I+this.paaLifecycle.retryBreakdown.browserRetries+this.paaLifecycle.retryBreakdown.runtimeRecoveries,retryBreakdown:{...this.paaLifecycle.retryBreakdown,controlRetries:I}}}S.set(m.q,(S.get(m.q)??0)+1)}let C=[];for(let m of D)C.push({target:m,result:await T(m.q,f.length,m.index,m.expanded,m.answerReady,S.get(m.q)??1,g)});let L=await O(C.map(({result:m})=>m));for(let{target:m,result:I}of C)(I.dispatched||I.confirmed)&&this.clickedQuestions.add(m.q),this.interactionObservations.push(I.observation);if(this.interactionObservations.length>ia&&this.interactionObservations.splice(0,this.interactionObservations.length-ia),!n.questionsOnly){let m=new Set(D.map(R=>R.q)),I=L??await t.evaluate(mt,{selectors:q});for(let R of this.mapPaaDomRecords(I,typeof t.url=="function"?t.url():"https://www.google.com/"))m.has(R.question)&&(r.set(R.question,R),this.upsertCollectedRow(this.toFlatRow(R,1,null,n.query))&&await this.emitProgress("answer_captured"));l.length>=n.maxQuestions&&l.slice(0,n.maxQuestions).every(R=>{let H=I.find(J=>J.question===R);return!!(H&&Ft(H.answer,H.question)&&!H.answerExpansionIncomplete&&H.sources.some(J=>Ct(J.rawHref,W)))})&&(x=I)}for(let{target:m,result:I}of C){I.observation.errorCode==="click_ack_timeout"&&d.add(m.q);let R=r.get(m.q);I.confirmed||R?.answer?.trim()&&(!I.hadMaterialBefore||I.dispatched)?(u.add(m.q),h.delete(m.q)):(I.observation.errorCode==="click_ack_timeout"||(S.get(m.q)??0)>=U)&&(h.add(m.q),d.add(m.q))}this.paaLifecycle={...this.paaLifecycle,processedQuestions:u.size,failedInteractions:h.size,noGrowthConfirmations:0,dispatchedInteractions:this.interactionObservations.filter(m=>m.dispatched).length,confirmedInteractions:this.interactionObservations.filter(m=>m.outcome==="confirmed").length,unconfirmedInteractions:this.interactionObservations.filter(m=>m.outcome!=="confirmed").length},await this.emitProgress("click_observed")}let G=n.questionsOnly?new Map:new Map(r);n.questionsOnly||await this.fillIncompleteItems(t,l,G,n,d,a);let F=[];for(let v of l){if(F.length>=n.maxQuestions)break;let W=this.normalizeQuestion(v);if(i.has(W))continue;i.add(W);let f=G.get(v);if(f){let k=this.toFlatRow(f,1,null,n.query);this.upsertCollectedRow(k),F.push(k),this.reporter.onQuestion({questionId:f.questionId,googleLinkId:f.googleLinkId,googleEvidenceId:f.googleEvidenceId,question:f.question,answer:f.answer??null,sourceTitle:f.sourceTitle??null,sourceSite:f.sourceSite??null,sourceCite:f.sourceCite??null,sources:f.sources,...f.answerExpansionIncomplete?{answerExpansionIncomplete:!0}:{},depth:1,parentQuestion:null,children:[]})}else{let k=this.toFlatRow({questionId:kt(v),googleLinkId:null,googleEvidenceId:null,question:v,answer:void 0,sourceTitle:void 0,sourceSite:void 0,sourceCite:void 0,sources:[]},1,null,n.query);this.upsertCollectedRow(k),F.push(k)}}this.completeness.paaWithoutAnswer=n.questionsOnly?0:F.filter(v=>!v.answer).length,this.completeness.paaWithoutSource=n.questionsOnly?0:F.filter(v=>(v.sources??[]).length===0).length,this.completeness.paaIncompleteAnswers=n.questionsOnly?0:F.filter(v=>v.answerExpansionIncomplete).length,this.completeness.paaRequested=n.maxQuestions,this.completeness.paaReturned=F.length,this.completeness.paaUnique=i.size;let P=!n.questionsOnly&&(this.completeness.paaWithoutAnswer>0||this.completeness.paaWithoutSource>0||this.completeness.paaIncompleteAnswers>0);return this.paaLifecycle={...this.paaLifecycle,questionsFound:F.length,targetStatus:F.length>=n.maxQuestions?"met":"not_met",materialStatus:P?"partial":"complete",processedQuestions:u.size,failedInteractions:h.size},await this.emitProgress("fill_incomplete"),await this.emitProgress("expansion_finished"),F}async fillIncompleteItems(t,n,a,i,s,l){let d=new Set(n.slice(0,i.maxQuestions)),S=r=>!r?.answer||(r.sources??[]).length===0||!!r.answerExpansionIncomplete,u=new Set([...d].filter(r=>S(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 o=(await this.extractVisibleItems(t,r))[0];if(o?.answerExpansionIncomplete&&(await Te(t,r,{selectors:q,deadlineMs:i.softDeadlineMs,signal:l,allowOuterReopen:!s?.has(r)},mt),o=(await this.extractVisibleItems(t,r))[0]),!o)continue;let U=a.get(r);a.set(r,{...o,answer:o.answer||U?.answer,answerExpansionIncomplete:o.answer?o.answerExpansionIncomplete:U?.answerExpansionIncomplete,sourceTitle:o.sourceTitle??U?.sourceTitle,sourceSite:o.sourceSite??U?.sourceSite,sourceCite:o.sourceCite??U?.sourceCite,sources:this.mergePaaSources(U?.sources,o.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=`${q.item}:not(.${q.expandedClass}) ${q.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 qn(t)}extractForums(t){return zn(t)}extractShortVideos(t,n){return jn(t,n,(a,i)=>this.throwIfCaptcha(a,i))}extractWhatPeopleSaying(t){return $n(t)}extractOrganicResults(t){return Qn(t)}extractLocalPack(t){return Zn(t)}extractEntityIds(t){return Xn(t)}mergeLocalPackIntoEntities(t,n){return ta(t,n)}async extractAISurfaces(t,n){let a=await t.evaluate(Rn,{aio:Cn,aim:Mn,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 l=this.aioShareUrlEarly??await this.captureAIOverviewShareUrl(t,n).catch(()=>null);return this.completeness.aioShareCaptured=l!==null,{...s,aiOverview:{...s.aiOverview,shareUrl:l}}}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(l=>(l.textContent||"").trim()==="AI Overview");for(let l of s){let d=l;for(let S=0;S<8&&d;S++){let u=d.querySelector('[aria-label="Share"]');if(u)return u.scrollIntoView({block:"center"}),u.click(),!0;d=d.parentElement}}return!1}).catch(()=>!1))return null;let i=null;try{i=await(await t.waitForFunction(()=>{let l=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT);for(;l.nextNode();){let d=(l.currentNode.textContent||"").match(/https:\/\/share\.google\/aimode\/\S+/);if(d)return d[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 l={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,l)}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()),l=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}},d=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(!d)return{organic:[],status:"unavailable",failureCode:"missing_next"};if(!l(d))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"),!l(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 S=await this.driver.withTemporaryPage(async u=>{if(await u.route("**/*",async h=>{let r=h.request();r.isNavigationRequest()&&r.frame()===u.mainFrame()&&!l(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(d,s).href,{waitUntil:"domcontentloaded",timeout:2e4}),this.throwIfAborted(a),await this.throwIfCaptcha(u,"Google SERP page 2"),!l(u.url()))throw i="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(s){if(this.throwIfAborted(a),s instanceof at)throw s;return{organic:[],status:"failed",failureCode:i??(s instanceof j?"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.phaseTimings={},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},l=0,d=[];try{this.throwIfAborted(n);let S=Date.now();await this.driver.launch(s),this.phaseTimings.providerConnectMs=Date.now()-S;let u=this.driver.getProviderSessionMetadata();if(u?.providerSessionId&&this.onProviderSession)try{await this.onProviderSession(u)}catch(Y){console.warn(JSON.stringify({event:"paa_provider_session_sink_failed",provider:u.provider,message:Y instanceof Error?Y.message:String(Y)}))}this.throwIfAborted(n);let h=t.location?he(t.location):null,r=t.location?h?.canonical??t.location:null,o=r?Sn(r):null,U=t,c=t.includeAllSerpFeatures,g=c||t.includeLocalPack,w=c||t.includeForums,p=c||t.includeVideos,M=c||t.includeAiOverview,y=c||t.includeWhatPeopleSaying,T={surface:"web",aiOverview:{detected:!1,text:null,citations:[]},aiMode:{detected:!1,text:null,citations:[]}},O=Date.now(),{hasPaa:x}=await this.driver.navigateToSERP(U.query,o,t.gl,t.hl,{...se(t.recency)?{tbs:se(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()-O,this.throwIfAborted(n);let b=this.driver.getPage();if(await this.throwIfCaptcha(b,"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 Y=Date.now(),E=x?await this.runBFS(b,U,n):[];this.phaseTimings.paaExpansionMs=Date.now()-Y,await this.resolveMaterialLinks(b,E,[],T.aiOverview,T.aiMode);let it={seed:U.query,totalQuestions:E.length,maxDepthReached:E.reduce((st,It)=>Math.max(st,It.depth),0),durationMs:Date.now()-a,errorCount:l};return this.reporter.onComplete(it),{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,o,void 0,h)}:{}},totalQuestions:E.length,surface:"web",aiOverview:{detected:!1,text:null,citations:[]},aiMode:{detected:!1,text:null,citations:[]},whatPeopleSaying:[],tree:this.buildTree(E,U.query),flat:E,videos:[],forums:[],organicResults:[],localPack:[],entityIds:{entities:[],kgIds:[],cids:[],gcids:[]},stats:it}}if(M&&(this.aioShareUrlEarly=await this.captureAIOverviewShareUrl(b,t).catch(()=>null)),t.serpOnly){let Y=Date.now(),[E,it,st]=await Promise.all([this.extractOrganicResults(b),g?this.extractLocalPack(b):Promise.resolve([]),this.extractEntityIds(b)]),It=this.mergeLocalPackIntoEntities(st,it),V=M?await this.extractAISurfaces(b,t):T;this.phaseTimings.serpParseMs=Date.now()-Y;let Mt=t.debug?Ht(r,E,it):void 0,rt=E,Wt={requestedPages:(t.pages??1)>=2?2:1,capturedPages:1,page2Status:(t.pages??1)>=2?"not_attempted":"not_requested",page1OrganicCount:E.length,page2OrganicCount:0};if((t.pages??1)>=2){let Z=await this.captureSecondOrganicPage(b,U,n);rt=[...E,...Z.organic],Wt={...Wt,capturedPages:Z.status==="captured"?2:1,page2Status:Z.status,page2OrganicCount:Z.organic.length,...Z.failureCode?{failureCode:Z.failureCode}:{}},t.debug&&(Mt=Ht(r,rt,it))}await this.resolveMaterialLinks(b,[],rt,V.aiOverview,V.aiMode);let Q={seed:U.query,totalQuestions:0,maxDepthReached:0,durationMs:Date.now()-a,errorCount:l};return this.reporter.onComplete(Q),{seed:U.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"serp_only",problem:null,pagination:Wt,completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(U,r,o,Mt,h)}:{}},totalQuestions:0,surface:V.surface,aiOverview:V.aiOverview,aiMode:V.aiMode,whatPeopleSaying:[],tree:[],flat:[],videos:[],forums:[],organicResults:rt,localPack:it,entityIds:It,stats:Q}}let[G,F,P,v,W,f]=await Promise.all([p?this.extractVideos(b):Promise.resolve([]),w?this.extractForums(b):Promise.resolve([]),y?this.extractWhatPeopleSaying(b):Promise.resolve([]),this.extractEntityIds(b),this.extractOrganicResults(b),g?this.extractLocalPack(b):Promise.resolve([])]),k=this.mergeLocalPackIntoEntities(v,f),K=t.debug?Ht(r,W,f):void 0;this.reporter.onVideos(G),this.reporter.onForums(F);let N=M?await this.extractAISurfaces(b,t):T,D={requestedPages:(t.pages??1)>=2?2:1,capturedPages:1,page2Status:(t.pages??1)>=2?"not_attempted":"not_requested",page1OrganicCount:W.length,page2OrganicCount:0},C=W;if(this.checkpointMaterial={surface:N.surface,aiOverview:N.aiOverview,aiMode:N.aiMode,whatPeopleSaying:P,videos:G,forums:F,organicResults:C,localPack:f,entityIds:k,pagination:D},await this.emitProgress("serp_captured"),D.requestedPages===2){let Y=await this.captureSecondOrganicPage(b,U,n);C=[...W,...Y.organic],D={...D,capturedPages:Y.status==="captured"?2:1,page2Status:Y.status,page2OrganicCount:Y.organic.length,...Y.failureCode?{failureCode:Y.failureCode}:{}},this.checkpointMaterial={...this.checkpointMaterial,organicResults:C,pagination:D},await this.emitProgress("serp_captured"),await this.resolveMaterialLinks(b,[],C,N.aiOverview,N.aiMode),this.checkpointMaterial={...this.checkpointMaterial,organicResults:C},await this.emitProgress("serp_captured")}let L=t.debug?Ht(r,C,f):K;if(!x){await this.resolveMaterialLinks(b,[],C,N.aiOverview,N.aiMode),this.checkpointMaterial={...this.checkpointMaterial,organicResults:C},await this.emitProgress("serp_captured");let Y={seed:U.query,totalQuestions:0,maxDepthReached:0,durationMs:Date.now()-a,errorCount:l};return this.reporter.onComplete(Y),{seed:U.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"no_paa",noPaaObserved:!0,problem:null,pagination:D,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(U,r,o,L,h)}:{}},totalQuestions:0,surface:N.surface,aiOverview:N.aiOverview,aiMode:N.aiMode,whatPeopleSaying:P,tree:[],flat:[],videos:G,forums:F,organicResults:C,localPack:f,entityIds:k,stats:Y}}let m=Date.now(),I=await this.runBFS(b,U,n);this.phaseTimings.paaExpansionMs=Date.now()-m,this.throwIfAborted(n);let R=new URLSearchParams({q:U.query,gl:t.gl,hl:t.hl,pws:"0",udm:Bt.udm});o&&R.set("uule",o);let H=[];if(t.includeShortVideos===!0||t.includeShortVideos!==!1&&(p||c))try{H=await this.extractShortVideos(b,"https://www.google.com/search?"+R.toString())}catch(Y){if(!(Y instanceof j))throw Y;l++,d.push({code:"short_videos_captcha_skipped",surface:"short_videos",message:Y.message,retryable:!0})}this.reporter.onVideos(H),await this.resolveMaterialLinks(b,I,C,N.aiOverview,N.aiMode),this.checkpointMaterial={...this.checkpointMaterial,surface:N.surface,aiOverview:N.aiOverview,aiMode:N.aiMode,videos:[...G,...H],organicResults:C},await this.emitProgress("expansion_finished");let J=[...G,...H],B=this.buildTree(I,U.query),z={seed:U.query,totalQuestions:I.length,maxDepthReached:I.reduce((Y,E)=>Math.max(Y,E.depth),0),durationMs:Date.now()-a,errorCount:l};return this.reporter.onComplete(z),{seed:U.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"paa_found",problem:null,pagination:D,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...d.length>0?{warnings:d}:{},...t.debug?{debug:this.buildHarvestDebugSnapshot(U,r,o,L,h)}:{}},totalQuestions:I.length,surface:N.surface,aiOverview:N.aiOverview,aiMode:N.aiMode,whatPeopleSaying:P,tree:B,flat:I,videos:J,forums:F,organicResults:C,localPack:f,entityIds:k,stats:z}}catch(S){throw l++,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}}};var ne=class{onQuestion(t){process.stdout.write(JSON.stringify({event:"question",depth:t.depth,question:t.question})+`
|
|
21721
|
+
`).map(f=>f.trim()).filter(f=>/^\d+\.\s+.+/.test(f)),c=h(o)}let M=document.querySelector(t.aim.root),y=a==="aim"&&!!M,T=M?.closest(t.aim.wrapper)??M,O=y?S(T):null,x=y&&s(O),b=x?O:null,G=x?h(T):[],F=!!o&&s(U);return{surface:a,aiOverview:{detected:F,text:F?U:null,citations:F?c:[],expanded:F?g:!1,fullyExpanded:F?w:!1,sections:F?p:[]},aiMode:{detected:x&&b!==null,text:b,citations:G}}}import{createHash as Mi}from"crypto";var En=8e3,Vn=3e3,Yn=1e4,vi=8;function ut(e){return/(^|\.)google\.(?:com|[a-z]{2,3}(?:\.[a-z]{2})?)$/i.test(e)}function Gt(e){if(!e||e.length>En)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 fi(e,t){if(!e||e.length>En||/^javascript:/i.test(e))return null;try{let n=new URL(e,t);return Gt(n.href)}catch{return null}}function Dt(e){let t=Gt(e);return!t||t.protocol!=="https:"||!ut(t.hostname)||t.pathname!=="/goto"?null:t.searchParams.get("url")?t:null}function be(e){if(e.linkType!=="google_goto_redirect"||e.resolutionStatus!=="resolved"||!Dt(e.rawUrl)||!e.resolvedUrl)return!1;let t=Gt(e.resolvedUrl);return!!(t&&!ut(t.hostname)&&t.href===e.resolvedUrl&&e.url===t.href)}function kt(e){let t=e.normalize("NFKC").toLocaleLowerCase("en-US").replace(/[^\p{L}\p{N}\s]/gu,"").replace(/\s+/g," ").trim();return`paa_${Mi("sha256").update(t).digest("hex").slice(0,16)}`}function Ct(e,t){let n=fi(e,t);if(!n)return null;let a=n.href;if(!ut(n.hostname))return{url:a,rawUrl:a,resolvedUrl:a,linkType:"plain",resolutionStatus:"not_needed"};if(n.pathname==="/url"){let i=Gt(n.searchParams.get("q")??n.searchParams.get("url")??"");return!i||ut(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 Ie(e){return Dt(e)?.searchParams.get("url")??null}function Kn(e,t){try{let n=new URL(e),a=Gt(new URL(t,n).href);return!a||ut(a.hostname)?null:(!a.hash&&n.hash&&(a.hash=n.hash),a.href)}catch{return null}}async function Jn(e,t={}){let n=[...new Set([...e].flatMap(r=>Dt(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 l=Math.max(1,t.timeoutMs??Vn),d=Date.now()+Math.max(1,t.totalBudgetMs??Yn),S=Math.max(1,Math.min(16,Math.floor(t.concurrency??vi))),u=0,h=async()=>{for(;u<n.length;){let r=n[u++],o=Dt(r),U=o?.searchParams.get("url");if(!o||!U){a.set(r,{rawUrl:r,resolvedUrl:null,resolutionStatus:"rejected"});continue}o.hash="";let c=o.href;for(let g=0;g<2;g++){let w=d-Date.now();if(w<=0)return;let p=new AbortController,M=setTimeout(()=>p.abort(),Math.min(l,w)),y;try{y=await s(c,{method:"GET",redirect:"manual",headers:{accept:"*/*","user-agent":"Mozilla/5.0"},signal:p.signal})}catch{break}finally{clearTimeout(M)}if(y.status<300||y.status>=400)break;let T=y.headers.get("location");if(!T)break;let O=Kn(r,T);if(O){a.set(r,{rawUrl:r,resolvedUrl:O,resolutionStatus:"resolved"});break}let x;try{x=new URL(T,c)}catch{a.set(r,{rawUrl:r,resolvedUrl:null,resolutionStatus:"rejected"});break}if(!ut(x.hostname)||Ie(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(S,n.length)},()=>h())),{resolutions:[...a.values()],nonGoogleRequestsObserved:0}}function Gn(e,t){try{return new URL(e.resolvedUrl??e.url).hostname.replace(/^www\./,"")}catch{return t}}async function _n(e,t={}){let n=[],a=r=>{for(let o of r)n.push(o),a(o.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:o,...U})=>({...U,url:o})),...(e.aiMode?.citations??[]).map(({text:r,href:o,...U})=>({...U,url:o}))],s=new Map(i.filter(r=>!!r?.rawUrl).map(r=>[r.rawUrl,r])),l=[...s.values()].filter(r=>r.linkType==="google_goto_redirect"&&r.resolutionStatus!=="resolved").map(r=>r.rawUrl);if(l.length>0){let r=await Jn(l,t);for(let o of r.resolutions){let U=s.get(o.rawUrl);U&&s.set(o.rawUrl,o.resolutionStatus==="resolved"&&o.resolvedUrl?{...U,url:o.resolvedUrl,resolvedUrl:o.resolvedUrl,resolutionStatus:"resolved"}:{...U,resolutionStatus:o.resolutionStatus})}}let d=r=>({...r,...s.get(r.rawUrl)??r}),S=r=>r.map(o=>{let U=d(o);return{...U,site:Gn(U,o.site)}});for(let r of e.flat){r.sources=S(r.sources??[]);let o=r.sources[0];r.source_title=o?.title??r.source_title,r.source_site=o?.site??r.source_site,r.source_cite=o?.url??r.source_cite}for(let r of n){r.sources=S(r.sources??[]);let o=r.sources[0];r.sourceTitle=o?.title??r.sourceTitle,r.sourceSite=o?.site??r.sourceSite,r.sourceCite=o?.url??r.sourceCite}for(let r=0;r<(e.organicResults?.length??0);r++){let o=d(e.organicResults[r]);e.organicResults[r]={...o,domain:Gn(o,e.organicResults[r].domain)??""}}let u=r=>{let o=d({url:r.href,rawUrl:r.rawUrl,resolvedUrl:r.resolvedUrl,linkType:r.linkType,resolutionStatus:r.resolutionStatus}),{url:U,...c}=o;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,o)=>r+o.sources.length,0),aiOverviewLabelValidated:e.aiOverview?.detected??!1},e}async function qn(e,t,n={}){let a=new Map;for(let o of t){let U=a.get(o.rawUrl);U&&be(U)||a.set(o.rawUrl,o.linkType==="google_goto_redirect"&&!be(o)?{...o,url:o.rawUrl,resolvedUrl:null,resolutionStatus:"unresolved"}:o)}let i=[...a.values()].filter(o=>o.linkType==="google_goto_redirect"&&!be(o));if(i.length===0)return a;let s=Date.now()+(n.totalBudgetMs??Yn),l=await Jn(i.map(o=>o.rawUrl),n);for(let o of l.resolutions){let U=a.get(o.rawUrl);U&&a.set(o.rawUrl,o.resolutionStatus==="resolved"&&o.resolvedUrl?{...U,url:o.resolvedUrl,resolvedUrl:o.resolvedUrl,resolutionStatus:"resolved"}:{...U,resolutionStatus:o.resolutionStatus})}let d=i.filter(o=>a.get(o.rawUrl)?.resolutionStatus==="unresolved");if(d.length===0||n.browserFallback===!1||Date.now()>=s)return n.onNetworkAudit?.({nonGoogleRequestsObserved:0}),a;let S=n.timeoutMs??Vn,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 o=>{let U=o.request().url();try{ut(new URL(U).hostname)||(r+=1)}catch{}let c=Ie(U);if(!h||c!==h.token){await o.abort("blockedbyclient").catch(()=>{});return}let g=h;try{let w=await o.fetch({maxRedirects:0,timeout:g.timeoutMs});g.location=w.headers().location??null}finally{await o.abort("blockedbyclient").catch(()=>{}),g.finish()}});for(let o of d){let U=s-Date.now();if(U<=0)break;let c=Dt(o.rawUrl),g=c?.searchParams.get("url");if(!c||!g){a.set(o.rawUrl,{...o,resolutionStatus:"rejected"});continue}let w=Math.min(S,U);c.hash="";let p=c.href,M=!1;for(let y=0;y<2;y++){let T,O=new Promise(P=>{T=P}),x=`mcp-goto-${Math.random().toString(36).slice(2)}`;h={token:g,timeoutMs:w,location:null,finish:T},await u.evaluate(({url:P,id:v})=>{let W=document.createElement("iframe");W.id=v,W.hidden=!0,W.src=P,document.body.append(W)},{url:p,id:x}).catch(()=>null),await Promise.race([O,new Promise(P=>setTimeout(P,w))]);let b=h.location;if(h=null,await u.evaluate(P=>document.getElementById(P)?.remove(),x).catch(()=>null),!b)break;let G=Kn(o.rawUrl,b);if(G){a.set(o.rawUrl,{...o,url:G,resolvedUrl:G,resolutionStatus:"resolved"});break}let F;try{F=new URL(b,p)}catch{M=!0;break}if(!ut(F.hostname)||Ie(F.href)!==g){M=!0;break}p=F.href}M&&a.get(o.rawUrl)?.resolutionStatus!=="resolved"&&a.set(o.rawUrl,{...o,resolutionStatus:"rejected"})}}finally{h=null,await u.close().catch(()=>{}),n.onNetworkAudit?.({nonGoogleRequestsObserved:r})}return a}async function zn(e){let t=Bt;return e.evaluate(n=>{let a=[],i=Array.from(document.querySelectorAll(n.container));for(let s of i){let S=(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 o=h.textContent?.trim()??"",U=o.indexOf("YouTube");if(U===-1)continue;let c=o.slice(0,U).trim(),w=o.slice(U+7).replace(/^[·\s·]+/,"").match(/^([^·\n]+)/),p=w?w[1].trim():"";c&&a.push({type:S,title:c,channel:p,platform:"YouTube",duration:"",url:r})}}return a},t)}async function jn(e){let t=kn;return e.evaluate(n=>{let a=[],s=Array.from(document.querySelectorAll(n.section)).find(d=>d.textContent?.includes("Discussions"));if(!s)return a;let l=Array.from(s.querySelectorAll(n.item));for(let d of l){let S=d.href;if(!S)continue;let u=d.querySelector(n.title),h=d.querySelector(n.source),r=u?.textContent?.trim()??"",o=h?.textContent?.trim()??"";r&&a.push({title:r,source:o,url:S})}return a},t)}async function $n(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:Ht.item,platforms:[...Ht.platforms]};return(await e.evaluate(s=>{let l=new Set,d=[],S=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 S){let o=r.href;if(!o||!u.some(c=>o.includes(c)))continue;let U=r.textContent?.trim()??"";h.has(o)||h.set(o,[]),h.get(o).push(U)}for(let[r,o]of h.entries()){if(l.has(r))continue;l.add(r);let U=o.find(M=>/^\d+:\d+$/.test(M))??"",c=o.find(M=>!/^\d+:\d+$/.test(M)&&M.length>5)??"";if(!c)continue;let g=c,w="",p="";for(let M of s.platforms){let y=-1,T=0;for(;;){let F=c.indexOf(M,T);if(F===-1)break;y=F,T=F+1}if(y===-1)continue;let O=c.slice(y+M.length);if(!(/^[\s·]/.test(O)||O.trim()===""))continue;g=c.slice(0,y).trim(),w=M;let b=O.replace(/^[\s·]+/,""),G=b.indexOf("\xB7");p=(G===-1?b:b.slice(0,G)).trim();break}g&&d.push({title:g,channel:p,platform:w,duration:U,url:r})}return d},a)).map(s=>({type:"short_video",...s}))}async function Qn(e){let t=Cn;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 l=i.querySelector(n.cardLink)?.href??"",d=i.querySelector(n.titleH1)?.textContent?.trim(),S=i.querySelector(n.titleDiv)?.textContent?.trim(),u=d??S??"",h=i.querySelector(n.source)?.textContent?.trim()??"",o=i.querySelector(n.platformBadge)?.textContent?.trim()??"",U=i.querySelector(n.ytChannel)?.textContent?.trim()??"",c=i.querySelector(n.ytDate)?.textContent?.trim()??"",g=i.querySelector(n.authorNote)?.textContent?.trim()??null,w=i.querySelector(n.popularCommentLabel),p=null;if(w){let k=w.nextSibling;for(;k;){let K=k.textContent?.trim();if(K){p=K;break}k=k.nextSibling}}let M=Array.from(i.querySelectorAll("span")),y=M.find(k=>/^\d+:\d+$/.test(k.textContent?.trim()??""))?.textContent?.trim()??null,O=M.map(k=>k.textContent?.trim()??"").filter(k=>/\d/.test(k)&&(k.includes("comment")||k.includes("reaction")||k.includes("view")||k.includes("like")||k.includes("share")))[0]??"",x=M.map(k=>k.textContent?.trim()??"").filter(k=>/\d+ (day|week|month|year|hour)s? ago|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/.test(k)),b=c||(x[0]??""),G=o||(U?"YouTube":""),F=U||h,P="unknown",v=G.toLowerCase(),W=F.toLowerCase(),f=h.toLowerCase();return v.includes("reddit")||W.startsWith("r/")?P="reddit":v.includes("facebook")||f.includes("facebook")?P="facebook":v.includes("instagram")||f.includes("instagram")?P="instagram":v.includes("tiktok")||f.includes("tiktok")?P="tiktok":v.includes("youtube")||U?P="youtube":P="news",{type:P,title:u,url:l,source:F,platform:G,popularComment:p,engagement:O,date:b,duration:y,authorNote:g}}):[]},t)}async function Zn(e){let t=fn,n=await e.evaluate(i=>{let s=[],l=0;return document.querySelectorAll(i.result).forEach(d=>{let S=d.querySelector(i.title);if(!S)return;let u=S.textContent?.trim()??"",r=S.closest("a")?.href??"";if(!u||!r)return;l++;let o=d.querySelector(i.cite)?.textContent?.trim()??null,U=d.querySelector(i.snippet)?.textContent?.trim()??null,c=!!d.querySelector(i.redditCite),g=d.querySelector(i.ratingWrap),w=g?{value:g.querySelector(i.ratingValue)?.textContent?.trim()??"",count:g.querySelector(i.reviewCount)?.textContent?.trim()??""}:null,p="";try{p=new URL(r).hostname.replace(/^www\./,"")}catch{p=d.querySelector(i.siteName)?.textContent?.trim()??""}s.push({position:l,title:u,url:r,domain:p,cite:o,snippet:U,isRedditStyle:c,inlineRating:w})}),s},t),a=typeof e.url=="function"?e.url():"https://www.google.com/";return n.flatMap(i=>{let s=Ct(i.url,a);if(!s)return[];let l=i.domain;try{l=new URL(s.resolvedUrl??s.rawUrl).hostname.replace(/^www\./,"")}catch{}return[{...i,...s,domain:l}]})}async function Xn(e){let t=Nn;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,l)=>{let d=s.querySelector(n.name)?.textContent?.trim()??"";if(!d)return;let S=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 w of Array.from(s.querySelectorAll("a[href]"))){let p=w.href.match(/[?&]cid=(\d+)/);if(p){r=p[1];break}let M=w.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 o=[];s.querySelectorAll("div, span").forEach(w=>{let p=Array.from(w.childNodes).filter(M=>M.nodeType===3).map(M=>M.textContent?.trim()??"").filter(M=>M.length>1&&M.length<120).join(" ");p&&!o.includes(p)&&o.push(p)});let U=Array.from(s.querySelectorAll("a[href]")),c=U.find(w=>w.href.includes("google.com/maps"))?.href??null,g=U.find(w=>!w.href.includes("google.com")&&w.href.startsWith("http"))?.href??null;a.push({position:l+1,name:d,cid:r,rating:S,reviewCount:h,metadata:o,websiteUrl:g,directionsUrl:c})}),a},t)}async function ta(e){return e.evaluate(()=>{let t=new Set,n=new Set,a=new Set,i=new Map;function s(d){let S=[".OSrXXb",".dbg0pd",".tzt0oe",'[role="heading"]',"h3"];for(let u of S){let h=d.querySelector(u);if(h?.textContent?.trim())return h.textContent.trim()}return""}document.querySelectorAll('[id^="pv-/g/"]').forEach(d=>{let S=d.getAttribute("id");if(!S)return;let u=S.replace("pv-","");t.add(u);let h=s(d),o=d.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;o&&n.add(o),h&&i.set(u,{name:h,kgId:u,cid:o,gcid:null})}),document.querySelectorAll("[data-mid]").forEach(d=>{let S=d.getAttribute("data-mid");if(S?.startsWith("/g/")&&(t.add(S),!i.has(S))){let u=s(d);u&&i.set(S,{name:u,kgId:S,cid:null,gcid:null})}}),document.querySelectorAll(".w7Dbne").forEach(d=>{let u=d.querySelector("a[data-cid]")?.getAttribute("data-cid")??null;if(!u)return;n.add(u);let h=d.querySelector(".OSrXXb")?.textContent?.trim()??"";if(!h)return;let r=d.querySelector('[id^="pv-/g/"]'),o=r?r.getAttribute("id").replace("pv-",""):null,U=o??`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:o,cid:u,gcid:null})}),document.querySelectorAll("a[data-cid]").forEach(d=>{let S=d.getAttribute("data-cid");if(!S)return;if(n.add(S),![...i.values()].some(h=>h.cid===S)){let h=d.parentElement,r="";for(let o=0;o<8&&h;o++){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:${S}`,{name:r,kgId:null,cid:S,gcid:null})}});let l=Array.from(document.querySelectorAll("script:not([src])")).map(d=>d.textContent??"").filter(d=>d.length>1e4).join(`
|
|
21722
|
+
`);for(let d of l.matchAll(/\/g\/[a-zA-Z0-9_-]{5,20}/g))t.add(d[0]);for(let d of l.matchAll(/gcid:[a-zA-Z0-9_]+/g))a.add(d[0]);for(let d of l.matchAll(/0x[0-9a-f]+:0x([0-9a-f]+)/gi))try{n.add(BigInt("0x"+d[1]).toString())}catch{}return{entities:[...i.values()],kgIds:[...t],cids:[...n],gcids:[...a]}})}function ea(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(),l=a.find(d=>d.name.toLowerCase().trim()===s);l?l.cid||(l.cid=i.cid):a.find(d=>d.cid===i.cid)||a.push({name:i.name,kgId:null,cid:i.cid,gcid:null})}return{...e,entities:a,cids:[...n]}}var na=String.raw`^(?:an error has occurred(?:[.!…]\s*)?(?:please try again later[.!…]?)?|loading|please wait|try again|something went wrong)[.!…\s]*$`,Ti=700,Pi=1e3,aa=1400,ia=2e3,bi=4,sa=250,ne=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 l=i.resolutionStatus==="resolved"&&s.resolutionStatus!=="resolved"?i:s,d=i.description?.trim()&&!s.description?.trim()?i:s.description?.trim()?s:l;a.set(i.rawUrl,{...l,title:d.title??l.title??s.title??i.title,site:l.site??s.site??i.site,...(d.description??s.description??i.description)!==void 0?{description:d.description??s.description??i.description}:{}})}return[...a.values()]}normalizeAICitations(t,n){let a=new Set;return n.flatMap(i=>{let s=Ct(i.rawHref??i.href,t);if(!s||a.has(s.rawUrl))return[];a.add(s.rawUrl);let{url:l,...d}=s;return[{...d,text:i.text,href:l}]})}async resolveMaterialLinks(t,n,a,i,s){let l=Date.now(),d=[...n.flatMap(c=>c.sources??[]),...a,...i.citations.map(({text:c,href:g,...w})=>({...w,url:g})),...s.citations.map(({text:c,href:g,...w})=>({...w,url:g}))],S=new Map(d.map(c=>[c.rawUrl,c])),u=0,h=await qn(t,d,{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 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=r(a[c]);if(g.resolvedUrl)try{g.domain=new URL(g.resolvedUrl).hostname.replace(/^www\./,"")}catch{}a[c]=g}let o=c=>{let g=r({url:c.href,rawUrl:c.rawUrl,resolvedUrl:c.resolvedUrl,linkType:c.linkType,resolutionStatus:c.resolutionStatus}),{url:w,...p}=g;return{...p,text:c.text,href:w}};i.citations=i.citations.map(o),s.citations=s.citations.map(o);let U=[...h.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:i.detected},this.phaseTimings.linkResolutionMs=(this.phaseTimings.linkResolutionMs??0)+(Date.now()-l)}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 at}async throwIfCaptcha(t,n){if(await t.locator(q.captchaMarker).count().catch(()=>0)>0)throw new j(`${n} returned a CAPTCHA \u2014 retrying with a fresh session.`)}async extractVisibleItems(t,n){let a=await t.evaluate(mt,{selectors:q,onlyQuestion:n}),i=typeof t.url=="function"?t.url():"https://www.google.com/";return this.mapPaaDomRecords(a,i)}mapPaaDomRecords(t,n){return t.flatMap(a=>{let i=[],s=new Set;for(let u of a.sources){let h=Ct(u.rawHref,n);if(!h||s.has(h.rawUrl))continue;s.add(h.rawUrl);let r=a.sourceSite??null;try{r||=new URL(h.resolvedUrl??h.rawUrl).hostname.replace(/^www\./,"")}catch{}i.push({...h,title:u.title||a.sourceTitle||null,site:r,...u.description?{description:u.description}:{}})}let l=i[0],d={questionId:kt(a.question),googleLinkId:a.googleLinkId,googleEvidenceId:a.googleEvidenceId,question:a.question,answer:Rt(a.answer,a.question),sourceTitle:l?.title??a.sourceTitle,sourceSite:l?.site??a.sourceSite,sourceCite:l?.url,sources:i,...a.answerExpansionIncomplete?{answerExpansionIncomplete:!0}:{}},S=an.safeParse(d);return S.success?[S.data]:(console.warn("[PAAExtractor] item parse failed:",a.question,S.error.issues[0]?.message),[])})}jitteredDelayMs(t,n){return t+Math.floor(Math.random()*(n-t+1))}async clickItem(t,n){try{await t.locator(`${q.item}[data-q="${n}"], ${q.item}[data-initq="${n}"]`).first().click()}catch{}}toFlatRow(t,n,a,i){return{seed_query:i,question_id:t.questionId??kt(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(d=>this.normalizeQuestion(d.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},l=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 l&&(this.collectedRows[a]=s),l}async emitProgress(t){if(!this.onPaaProgress||this.collectedRows.length===0&&!this.checkpointMaterial)return;let n={sequence:++this.progressSequence,observedAt:new Date().toISOString(),clickedQuestions:[...this.clickedQuestions],phase:t,records:this.collectedRows.map(a=>({...a})),lifecycle:{...this.paaLifecycle},...this.checkpointMaterial?{material:structuredClone(this.checkpointMaterial)}:{},interactions:this.interactionObservations.map(a=>({...a,confirmationSignals:[...a.confirmationSignals]}))};try{await this.onPaaProgress(n)}catch(a){console.warn(JSON.stringify({event:"paa_progress_sink_failed",sequence:n.sequence,phase:n.phase,message:a instanceof Error?a.message:String(a)}))}}getPartialResult(){let t=this.partialContext;if(!t||this.collectedRows.length===0&&!this.checkpointMaterial)return null;let n=this.collectedRows.map(S=>({...S})),a=this.checkpointMaterial,i=t.questionsOnly?0:n.filter(S=>!S.answer?.trim()).length,s=t.questionsOnly?0:n.filter(S=>(S.sources??[]).length===0).length,l=t.questionsOnly?0:n.filter(S=>S.answerExpansionIncomplete).length,d={seed:t.seed,totalQuestions:n.length,maxDepthReached:n.reduce((S,u)=>Math.max(S,u.depth),0),durationMs:Date.now()-t.startMs,errorCount:0};return{seed:t.seed,location:t.location,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(t.startMs),completionStatus:"paa_found",problem:null,...a?.pagination?{pagination:{...a.pagination}}:{},resultQuality:"partial",degradedResult:!1,retryRecommended:!0,paaLifecycle:{...this.paaLifecycle,questionsFound:n.length,targetStatus:n.length>=(t.maxQuestions??0)?"met":"not_met",discoveryStatus:"interrupted",materialStatus:i>0||s>0||l>0?"partial":"complete",completionReason:"The browser attempt ended before frontier exhaustion could be proven."},completeness:{...this.completeness,paaWithoutAnswer:i,paaWithoutSource:s,paaIncompleteAnswers:l,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 i=new Set,s=new Set,l=[];this.clickedQuestions=new Set,this.interactionObservations=[];let d=new Set,S=new Map,u=new Set,h=new Set,r=new Map,o=new Set,U=2,c=3,g=0,w=Promise.resolve(),p=v=>{let W=w.then(()=>{if(this.throwIfAborted(a),n.softDeadlineMs&&Date.now()>=n.softDeadlineMs)throw new ft("The execution deadline arrived before the next PAA interaction.");return v()});return w=W.then(()=>{},()=>{}),W},M={sel:q.item,dataQ:q.itemDataQ,dataInitQ:q.itemDataInitQ,questionEl:q.itemQuestionEl,answerSel:q.answerContainer,expandedClass:q.expandedClass,clickTarget:q.clickTarget,answerPlaceholderPattern:na,questionsOnly:n.questionsOnly},y=()=>t.evaluate(({sel:v,dataQ:W,dataInitQ:f,questionEl:k,expandedClass:K,clickTarget:N,answerSel:D,answerPlaceholderPattern:C,questionsOnly:L})=>{let m=I=>{if(!I)return"";let R=[];for(let H of I.childNodes){if(H.nodeType===Node.TEXT_NODE){let z=H.textContent?.trim();z&&R.push(z);continue}if(H.nodeType!==Node.ELEMENT_NODE)continue;let J=H;if(J.tagName==="STYLE"||J.tagName==="SCRIPT"||J.getAttribute("aria-hidden")==="true")continue;let B=m(J);B&&R.push(B)}return R.join(" ").replace(/\s+/g," ").trim()};return Array.from(document.querySelectorAll(v)).map((I,R)=>{let H=m(I.querySelector(D)).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(K)||I.querySelector(N)?.getAttribute("aria-expanded")==="true",B=H.length>=10&&!new RegExp(C,"i").test(H);return{q:(I.getAttribute(W)||I.getAttribute(f)||I.querySelector(k)?.innerText?.trim()||"").replace(/\s+/g," ").trim(),done:J&&(L||B),expanded:J,index:R,answerReady:B,sourceCount:B?I.querySelector(D)?.querySelectorAll("a[href]").length??0:0}}).filter(I=>I.q)},M),T=async(v,W,f,k,K,N,D)=>{let C=Date.now(),L={id:`${D}:${kt(v)}:${N}`,questionId:kt(v),question:v,batchNumber:D,controlAttempt:N,observedAt:new Date(C).toISOString(),beforeQuestionCount:W,expandedBefore:k},m=f>=0?t.locator(M.sel).nth(f).locator(M.clickTarget):null,I=null,R=await p(async()=>(C=Date.now(),L.observedAt=new Date(C).toISOString(),m?(k&&(await m.click({timeout:ia,force:!0,noWaitAfter:!0}),await t.waitForTimeout(120)),await m.click({timeout:ia,force:!0,noWaitAfter:!0}),!0):!1)).catch(B=>(I=B instanceof Error&&(B.name==="TimeoutError"||/timeout/i.test(B.message))?"click_ack_timeout":"click_failed",!1)),H=Date.now()-C,J={...L,dispatched:R,outcome:R?"unconfirmed":"dispatch_failed",confirmationSignals:[],confirmationCheckpointMs:null,confirmedAtMs:null,dispatchDurationMs:H,totalDurationMs:H,afterQuestionCount:W,newQuestionCount:0,expandedAfter:k,answerObserved:!1,sourceCount:0,errorCode:f<0?"control_missing":I};return{clickStartedMs:C,dispatched:R,confirmed:!1,hadMaterialBefore:K,observation:J}},O=async v=>{let W=null,f=v.filter(k=>k.dispatched||k.observation.errorCode==="click_ack_timeout");for(let k of[Ti,Pi,aa]){if(!f.length)break;let K=Math.min(...f.map(C=>C.clickStartedMs+k-Date.now()));K>0&&await t.waitForTimeout(K);let N=n.questionsOnly?await y().catch(()=>null):await t.evaluate(mt,{selectors:q}).catch(()=>null);N&&!n.questionsOnly&&(W=N);let D=N?.length;for(let C of f){let L=C.observation;if(N){let m=n.questionsOnly?N.find(B=>B.q===L.question):N.find(B=>B.question===L.question),I=!1,R=0;if(m)if("q"in m)I=m.answerReady,R=m.sourceCount;else{let B=Rt(m.answer,m.question);I=!!(B&&B.length>=10&&!new RegExp(na,"i").test(B)),R=I?m.sources.length:0}L.afterQuestionCount=D??L.beforeQuestionCount,L.newQuestionCount=Math.max(0,L.afterQuestionCount-L.beforeQuestionCount),L.expandedAfter=m?.expanded??!1,L.answerObserved=I,L.sourceCount=I?R:0,L.confirmationSignals=[...L.expandedAfter?["expanded"]:[],...I?["answer"]:[],...L.sourceCount>0?["source"]:[],...L.newQuestionCount>0?["question_growth"]:[]];let H=!!(m?.expanded&&!L.expandedBefore);((I||L.sourceCount>0)&&(!C.hadMaterialBefore||C.dispatched||H)||L.newQuestionCount>0&&(C.dispatched||H))&&(C.confirmed=!0,L.outcome="confirmed",L.confirmationCheckpointMs=k,L.confirmedAtMs=Date.now()-C.clickStartedMs),C.dispatched&&(L.errorCode=C.confirmed?null:m?"confirmation_timeout":"control_missing")}L.totalDurationMs=Date.now()-C.clickStartedMs}f=f.filter(C=>!C.confirmed&&Date.now()-C.clickStartedMs<aa)}for(let k of v)k.dispatched&&!k.confirmed&&k.observation.errorCode===null&&(k.observation.errorCode="confirmation_timeout");return W},x=null,b=0;t:for(;;){if(n.softDeadlineMs&&Date.now()>=n.softDeadlineMs)throw this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"interrupted",completionReason:"The execution deadline arrived before frontier exhaustion could be proven."},new ft(this.paaLifecycle.completionReason);this.throwIfAborted(a);let v=n.questionsOnly?null:x??await t.evaluate(mt,{selectors:q});x=null;let W=typeof t.url=="function"?t.url():"https://www.google.com/",f=v?v.map(m=>{let I=!!Rt(m.answer,m.question),R=I&&!m.answerExpansionIncomplete&&m.sources.some(H=>!!Ct(H.rawHref,W));return{q:m.question,done:R||m.expanded&&I,answerReady:I,expanded:m.expanded,index:m.itemIndex}}):await y(),k=!1;for(let m of f)s.has(m.q)||(s.add(m.q),l.push(m.q),l.length<=n.maxQuestions&&(k=this.upsertCollectedRow(this.toFlatRow({questionId:kt(m.q),googleLinkId:null,googleEvidenceId:null,question:m.q,sources:[]},1,null,n.query))||k)),m.done&&(u.has(m.q)||h.delete(m.q),u.add(m.q));if(this.paaLifecycle={...this.paaLifecycle,questionsFound:Math.min(l.length,n.maxQuestions),targetStatus:l.length>=n.maxQuestions?"met":"not_met",knownQuestions:l.length,processedQuestions:u.size,failedInteractions:h.size,visibleControls:f.length},k&&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 m=!1,I=new Set(l.slice(0,n.maxQuestions)),R=this.mapPaaDomRecords(v??[],W),H=R.filter(B=>I.has(B.question)&&B.answerExpansionIncomplete&&!o.has(B.question)),J;await Promise.allSettled(H.map(async B=>{o.add(B.question);try{await Pe(t,B.question,{selectors:q,deadlineMs:n.softDeadlineMs,signal:a,allowOuterReopen:!d.has(B.question),dispatchClick:p},mt)}catch(z){J??={reason:z}}})),H.length&&(R=await this.extractVisibleItems(t).catch(B=>{if(J)return R;throw B}));for(let B of R){if(!I.has(B.question))continue;let z=r.get(B.question),Y={...B,answer:B.answer||z?.answer,answerExpansionIncomplete:B.answer?B.answerExpansionIncomplete:z?.answerExpansionIncomplete,sourceTitle:B.sourceTitle??z?.sourceTitle,sourceSite:B.sourceSite??z?.sourceSite,sourceCite:B.sourceCite??z?.sourceCite,sources:this.mergePaaSources(z?.sources,B.sources)};r.set(B.question,Y),m=this.upsertCollectedRow(this.toFlatRow(Y,1,null,n.query))||m}if(m&&await this.emitProgress("answer_captured"),J)throw J.reason;if([...I].every(B=>{let z=r.get(B);return!!(z?.answer?.trim()&&z.sources.length>0&&!z.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 K=new Set(l.slice(0,n.maxQuestions)),N=f.filter(m=>K.has(m.q)&&(!m.done||s.size<n.maxQuestions&&!this.clickedQuestions.has(m.q))&&(S.get(m.q)??0)<U&&!d.has(m.q)),D=N.slice(-bi);if(this.paaLifecycle={...this.paaLifecycle,eligibleControls:N.length},D.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 m=new Set(f.map(R=>R.q)),I=l.slice(0,n.maxQuestions).filter(R=>h.has(R)||!u.has(R)&&!m.has(R));if(I.length>0)throw this.paaLifecycle={...this.paaLifecycle,discoveryStatus:"interrupted",failedInteractions:new Set([...h,...I]).size,completionReason:"At least one known PAA control failed or disappeared before it could be confirmed."},await this.emitProgress("expansion_finished"),new ft(this.paaLifecycle.completionReason);for(let R=1;R<=c;R++){this.throwIfAborted(a),await this.throwIfCaptcha(t,"Google PAA exhaustion confirmation"),await t.mouse.wheel(0,320);let H=await t.waitForFunction(({sel:B,min:z})=>document.querySelectorAll(B).length>z,{sel:q.item,min:f.length},{timeout:1500,polling:100}).catch(()=>null);if(this.paaLifecycle={...this.paaLifecycle,noGrowthConfirmations:R},H||(await y()).some(B=>!s.has(B.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"),g+=1;for(let m of D){if(this.reporter.onDepth(++b),(S.get(m.q)??0)>0){let I=this.paaLifecycle.retryBreakdown.controlRetries+1;this.paaLifecycle={...this.paaLifecycle,automaticRetries:I+this.paaLifecycle.retryBreakdown.browserRetries+this.paaLifecycle.retryBreakdown.runtimeRecoveries,retryBreakdown:{...this.paaLifecycle.retryBreakdown,controlRetries:I}}}S.set(m.q,(S.get(m.q)??0)+1)}let C=[];for(let m of D)C.push({target:m,result:await T(m.q,f.length,m.index,m.expanded,m.answerReady,S.get(m.q)??1,g)});let L=await O(C.map(({result:m})=>m));for(let{target:m,result:I}of C)(I.dispatched||I.confirmed)&&this.clickedQuestions.add(m.q),this.interactionObservations.push(I.observation);if(this.interactionObservations.length>sa&&this.interactionObservations.splice(0,this.interactionObservations.length-sa),!n.questionsOnly){let m=new Set(D.map(R=>R.q)),I=L??await t.evaluate(mt,{selectors:q});for(let R of this.mapPaaDomRecords(I,typeof t.url=="function"?t.url():"https://www.google.com/"))m.has(R.question)&&(r.set(R.question,R),this.upsertCollectedRow(this.toFlatRow(R,1,null,n.query))&&await this.emitProgress("answer_captured"));l.length>=n.maxQuestions&&l.slice(0,n.maxQuestions).every(R=>{let H=I.find(J=>J.question===R);return!!(H&&Rt(H.answer,H.question)&&!H.answerExpansionIncomplete&&H.sources.some(J=>Ct(J.rawHref,W)))})&&(x=I)}for(let{target:m,result:I}of C){I.observation.errorCode==="click_ack_timeout"&&d.add(m.q);let R=r.get(m.q);I.confirmed||R?.answer?.trim()&&(!I.hadMaterialBefore||I.dispatched)?(u.add(m.q),h.delete(m.q)):(I.observation.errorCode==="click_ack_timeout"||(S.get(m.q)??0)>=U)&&(h.add(m.q),d.add(m.q))}this.paaLifecycle={...this.paaLifecycle,processedQuestions:u.size,failedInteractions:h.size,noGrowthConfirmations:0,dispatchedInteractions:this.interactionObservations.filter(m=>m.dispatched).length,confirmedInteractions:this.interactionObservations.filter(m=>m.outcome==="confirmed").length,unconfirmedInteractions:this.interactionObservations.filter(m=>m.outcome!=="confirmed").length},await this.emitProgress("click_observed")}let G=n.questionsOnly?new Map:new Map(r);n.questionsOnly||await this.fillIncompleteItems(t,l,G,n,d,a);let F=[];for(let v of l){if(F.length>=n.maxQuestions)break;let W=this.normalizeQuestion(v);if(i.has(W))continue;i.add(W);let f=G.get(v);if(f){let k=this.toFlatRow(f,1,null,n.query);this.upsertCollectedRow(k),F.push(k),this.reporter.onQuestion({questionId:f.questionId,googleLinkId:f.googleLinkId,googleEvidenceId:f.googleEvidenceId,question:f.question,answer:f.answer??null,sourceTitle:f.sourceTitle??null,sourceSite:f.sourceSite??null,sourceCite:f.sourceCite??null,sources:f.sources,...f.answerExpansionIncomplete?{answerExpansionIncomplete:!0}:{},depth:1,parentQuestion:null,children:[]})}else{let k=this.toFlatRow({questionId:kt(v),googleLinkId:null,googleEvidenceId:null,question:v,answer:void 0,sourceTitle:void 0,sourceSite:void 0,sourceCite:void 0,sources:[]},1,null,n.query);this.upsertCollectedRow(k),F.push(k)}}this.completeness.paaWithoutAnswer=n.questionsOnly?0:F.filter(v=>!v.answer).length,this.completeness.paaWithoutSource=n.questionsOnly?0:F.filter(v=>(v.sources??[]).length===0).length,this.completeness.paaIncompleteAnswers=n.questionsOnly?0:F.filter(v=>v.answerExpansionIncomplete).length,this.completeness.paaRequested=n.maxQuestions,this.completeness.paaReturned=F.length,this.completeness.paaUnique=i.size;let P=!n.questionsOnly&&(this.completeness.paaWithoutAnswer>0||this.completeness.paaWithoutSource>0||this.completeness.paaIncompleteAnswers>0);return this.paaLifecycle={...this.paaLifecycle,questionsFound:F.length,targetStatus:F.length>=n.maxQuestions?"met":"not_met",materialStatus:P?"partial":"complete",processedQuestions:u.size,failedInteractions:h.size},await this.emitProgress("fill_incomplete"),await this.emitProgress("expansion_finished"),F}async fillIncompleteItems(t,n,a,i,s,l){let d=new Set(n.slice(0,i.maxQuestions)),S=r=>!r?.answer||(r.sources??[]).length===0||!!r.answerExpansionIncomplete,u=new Set([...d].filter(r=>S(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 o=(await this.extractVisibleItems(t,r))[0];if(o?.answerExpansionIncomplete&&(await Pe(t,r,{selectors:q,deadlineMs:i.softDeadlineMs,signal:l,allowOuterReopen:!s?.has(r)},mt),o=(await this.extractVisibleItems(t,r))[0]),!o)continue;let U=a.get(r);a.set(r,{...o,answer:o.answer||U?.answer,answerExpansionIncomplete:o.answer?o.answerExpansionIncomplete:U?.answerExpansionIncomplete,sourceTitle:o.sourceTitle??U?.sourceTitle,sourceSite:o.sourceSite??U?.sourceSite,sourceCite:o.sourceCite??U?.sourceCite,sources:this.mergePaaSources(U?.sources,o.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=`${q.item}:not(.${q.expandedClass}) ${q.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 zn(t)}extractForums(t){return jn(t)}extractShortVideos(t,n){return $n(t,n,(a,i)=>this.throwIfCaptcha(a,i))}extractWhatPeopleSaying(t){return Qn(t)}extractOrganicResults(t){return Zn(t)}extractLocalPack(t){return Xn(t)}extractEntityIds(t){return ta(t)}mergeLocalPackIntoEntities(t,n){return ea(t,n)}async extractAISurfaces(t,n){let a=await t.evaluate(Dn,{aio:Mn,aim:vn,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 l=this.aioShareUrlEarly??await this.captureAIOverviewShareUrl(t,n).catch(()=>null);return this.completeness.aioShareCaptured=l!==null,{...s,aiOverview:{...s.aiOverview,shareUrl:l}}}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(l=>(l.textContent||"").trim()==="AI Overview");for(let l of s){let d=l;for(let S=0;S<8&&d;S++){let u=d.querySelector('[aria-label="Share"]');if(u)return u.scrollIntoView({block:"center"}),u.click(),!0;d=d.parentElement}}return!1}).catch(()=>!1))return null;let i=null;try{i=await(await t.waitForFunction(()=>{let l=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT);for(;l.nextNode();){let d=(l.currentNode.textContent||"").match(/https:\/\/share\.google\/aimode\/\S+/);if(d)return d[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 l={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,l)}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()),l=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}},d=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(!d)return{organic:[],status:"unavailable",failureCode:"missing_next"};if(!l(d))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"),!l(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 S=await this.driver.withTemporaryPage(async u=>{if(await u.route("**/*",async h=>{let r=h.request();r.isNavigationRequest()&&r.frame()===u.mainFrame()&&!l(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(d,s).href,{waitUntil:"domcontentloaded",timeout:2e4}),this.throwIfAborted(a),await this.throwIfCaptcha(u,"Google SERP page 2"),!l(u.url()))throw i="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(s){if(this.throwIfAborted(a),s instanceof at)throw s;return{organic:[],status:"failed",failureCode:i??(s instanceof j?"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.phaseTimings={},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},l=0,d=[];try{this.throwIfAborted(n);let S=Date.now();await this.driver.launch(s),this.phaseTimings.providerConnectMs=Date.now()-S;let u=this.driver.getProviderSessionMetadata();if(u?.providerSessionId&&this.onProviderSession)try{await this.onProviderSession(u)}catch(Y){console.warn(JSON.stringify({event:"paa_provider_session_sink_failed",provider:u.provider,message:Y instanceof Error?Y.message:String(Y)}))}this.throwIfAborted(n);let h=t.location?ue(t.location):null,r=t.location?h?.canonical??t.location:null,o=r?Un(r):null,U=t,c=t.includeAllSerpFeatures,g=c||t.includeLocalPack,w=c||t.includeForums,p=c||t.includeVideos,M=c||t.includeAiOverview,y=c||t.includeWhatPeopleSaying,T={surface:"web",aiOverview:{detected:!1,text:null,citations:[]},aiMode:{detected:!1,text:null,citations:[]}},O=Date.now(),{hasPaa:x}=await this.driver.navigateToSERP(U.query,o,t.gl,t.hl,{...oe(t.recency)?{tbs:oe(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()-O,this.throwIfAborted(n);let b=this.driver.getPage();if(await this.throwIfCaptcha(b,"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 Y=Date.now(),E=x?await this.runBFS(b,U,n):[];this.phaseTimings.paaExpansionMs=Date.now()-Y,await this.resolveMaterialLinks(b,E,[],T.aiOverview,T.aiMode);let it={seed:U.query,totalQuestions:E.length,maxDepthReached:E.reduce((st,It)=>Math.max(st,It.depth),0),durationMs:Date.now()-a,errorCount:l};return this.reporter.onComplete(it),{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,o,void 0,h)}:{}},totalQuestions:E.length,surface:"web",aiOverview:{detected:!1,text:null,citations:[]},aiMode:{detected:!1,text:null,citations:[]},whatPeopleSaying:[],tree:this.buildTree(E,U.query),flat:E,videos:[],forums:[],organicResults:[],localPack:[],entityIds:{entities:[],kgIds:[],cids:[],gcids:[]},stats:it}}if(M&&(this.aioShareUrlEarly=await this.captureAIOverviewShareUrl(b,t).catch(()=>null)),t.serpOnly){let Y=Date.now(),[E,it,st]=await Promise.all([this.extractOrganicResults(b),g?this.extractLocalPack(b):Promise.resolve([]),this.extractEntityIds(b)]),It=this.mergeLocalPackIntoEntities(st,it),V=M?await this.extractAISurfaces(b,t):T;this.phaseTimings.serpParseMs=Date.now()-Y;let Mt=t.debug?Ft(r,E,it):void 0,rt=E,Wt={requestedPages:(t.pages??1)>=2?2:1,capturedPages:1,page2Status:(t.pages??1)>=2?"not_attempted":"not_requested",page1OrganicCount:E.length,page2OrganicCount:0};if((t.pages??1)>=2){let Z=await this.captureSecondOrganicPage(b,U,n);rt=[...E,...Z.organic],Wt={...Wt,capturedPages:Z.status==="captured"?2:1,page2Status:Z.status,page2OrganicCount:Z.organic.length,...Z.failureCode?{failureCode:Z.failureCode}:{}},t.debug&&(Mt=Ft(r,rt,it))}await this.resolveMaterialLinks(b,[],rt,V.aiOverview,V.aiMode);let Q={seed:U.query,totalQuestions:0,maxDepthReached:0,durationMs:Date.now()-a,errorCount:l};return this.reporter.onComplete(Q),{seed:U.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"serp_only",problem:null,pagination:Wt,completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(U,r,o,Mt,h)}:{}},totalQuestions:0,surface:V.surface,aiOverview:V.aiOverview,aiMode:V.aiMode,whatPeopleSaying:[],tree:[],flat:[],videos:[],forums:[],organicResults:rt,localPack:it,entityIds:It,stats:Q}}let[G,F,P,v,W,f]=await Promise.all([p?this.extractVideos(b):Promise.resolve([]),w?this.extractForums(b):Promise.resolve([]),y?this.extractWhatPeopleSaying(b):Promise.resolve([]),this.extractEntityIds(b),this.extractOrganicResults(b),g?this.extractLocalPack(b):Promise.resolve([])]),k=this.mergeLocalPackIntoEntities(v,f),K=t.debug?Ft(r,W,f):void 0;this.reporter.onVideos(G),this.reporter.onForums(F);let N=M?await this.extractAISurfaces(b,t):T,D={requestedPages:(t.pages??1)>=2?2:1,capturedPages:1,page2Status:(t.pages??1)>=2?"not_attempted":"not_requested",page1OrganicCount:W.length,page2OrganicCount:0},C=W;if(this.checkpointMaterial={surface:N.surface,aiOverview:N.aiOverview,aiMode:N.aiMode,whatPeopleSaying:P,videos:G,forums:F,organicResults:C,localPack:f,entityIds:k,pagination:D},await this.emitProgress("serp_captured"),D.requestedPages===2){let Y=await this.captureSecondOrganicPage(b,U,n);C=[...W,...Y.organic],D={...D,capturedPages:Y.status==="captured"?2:1,page2Status:Y.status,page2OrganicCount:Y.organic.length,...Y.failureCode?{failureCode:Y.failureCode}:{}},this.checkpointMaterial={...this.checkpointMaterial,organicResults:C,pagination:D},await this.emitProgress("serp_captured"),await this.resolveMaterialLinks(b,[],C,N.aiOverview,N.aiMode),this.checkpointMaterial={...this.checkpointMaterial,organicResults:C},await this.emitProgress("serp_captured")}let L=t.debug?Ft(r,C,f):K;if(!x){await this.resolveMaterialLinks(b,[],C,N.aiOverview,N.aiMode),this.checkpointMaterial={...this.checkpointMaterial,organicResults:C},await this.emitProgress("serp_captured");let Y={seed:U.query,totalQuestions:0,maxDepthReached:0,durationMs:Date.now()-a,errorCount:l};return this.reporter.onComplete(Y),{seed:U.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"no_paa",noPaaObserved:!0,problem:null,pagination:D,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...t.debug?{debug:this.buildHarvestDebugSnapshot(U,r,o,L,h)}:{}},totalQuestions:0,surface:N.surface,aiOverview:N.aiOverview,aiMode:N.aiMode,whatPeopleSaying:P,tree:[],flat:[],videos:G,forums:F,organicResults:C,localPack:f,entityIds:k,stats:Y}}let m=Date.now(),I=await this.runBFS(b,U,n);this.phaseTimings.paaExpansionMs=Date.now()-m,this.throwIfAborted(n);let R=new URLSearchParams({q:U.query,gl:t.gl,hl:t.hl,pws:"0",udm:Ht.udm});o&&R.set("uule",o);let H=[];if(t.includeShortVideos===!0||t.includeShortVideos!==!1&&(p||c))try{H=await this.extractShortVideos(b,"https://www.google.com/search?"+R.toString())}catch(Y){if(!(Y instanceof j))throw Y;l++,d.push({code:"short_videos_captcha_skipped",surface:"short_videos",message:Y.message,retryable:!0})}this.reporter.onVideos(H),await this.resolveMaterialLinks(b,I,C,N.aiOverview,N.aiMode),this.checkpointMaterial={...this.checkpointMaterial,surface:N.surface,aiOverview:N.aiOverview,aiMode:N.aiMode,videos:[...G,...H],organicResults:C},await this.emitProgress("expansion_finished");let J=[...G,...H],B=this.buildTree(I,U.query),z={seed:U.query,totalQuestions:I.length,maxDepthReached:I.reduce((Y,E)=>Math.max(Y,E.depth),0),durationMs:Date.now()-a,errorCount:l};return this.reporter.onComplete(z),{seed:U.query,location:t.location??null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:this.currentPhaseTimings(a),completionStatus:"paa_found",problem:null,pagination:D,paaLifecycle:{...this.paaLifecycle},completeness:{...this.completeness},links:{...this.linkDiagnostics},...d.length>0?{warnings:d}:{},...t.debug?{debug:this.buildHarvestDebugSnapshot(U,r,o,L,h)}:{}},totalQuestions:I.length,surface:N.surface,aiOverview:N.aiOverview,aiMode:N.aiMode,whatPeopleSaying:P,tree:B,flat:I,videos:J,forums:F,organicResults:C,localPack:f,entityIds:k,stats:z}}catch(S){throw l++,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}}};var ae=class{onQuestion(t){process.stdout.write(JSON.stringify({event:"question",depth:t.depth,question:t.question})+`
|
|
21717
21723
|
`)}onDepth(t){process.stdout.write(JSON.stringify({event:"depth",depth:t})+`
|
|
21718
21724
|
`)}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})+`
|
|
21719
21725
|
`)}onForums(t){for(let n of t)process.stdout.write(JSON.stringify({event:"forum",title:n.title,source:n.source,url:n.url})+`
|
|
21720
21726
|
`)}onComplete(t){process.stdout.write(JSON.stringify({event:"complete",...t})+`
|
|
21721
21727
|
`)}onError(t){process.stderr.write(JSON.stringify({event:"error",type:t.constructor.name,message:t.message})+`
|
|
21722
|
-
`)}};function ae(e){return e.reason instanceof DOMException&&e.reason.name==="TimeoutError"?e.reason:new at}async function bi(e){let t=await e.evaluate(n=>{let a=n,i=Array.from(document.querySelectorAll(a.item)),s=i.map(S=>S.querySelector(a.clickTarget)).filter(S=>S!=null),l=S=>{let u=S.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 o=document.elementFromPoint(h,r);return o!=null&&o!==S&&!S.contains(o)&&!o.contains(S)},d=Array.from(document.querySelectorAll("body *")).filter(S=>{let u=window.getComputedStyle(S);if(u.position!=="fixed"&&u.position!=="sticky")return!1;let h=S.getBoundingClientRect();return h.width*h.height>=window.innerWidth*window.innerHeight*.15&&u.visibility!=="hidden"&&u.display!=="none"});return{itemCount:i.length,expandedItemCount:i.filter(S=>S.classList.contains(a.expandedClass)||S.querySelector(a.clickTarget)?.getAttribute("aria-expanded")==="true").length,answeredItemCount:i.filter(S=>(S.querySelector(a.answerContainer)?.textContent?.trim().length??0)>=10).length,sourcedItemCount:i.filter(S=>S.querySelector(`${a.answerContainer} a[href]`)!=null).length,clickTargetCount:s.length,clickTargetsWithButtonRole:s.filter(S=>S.getAttribute("role")==="button"||S.tagName==="BUTTON").length,clickTargetsWithExpandedState:s.filter(S=>S.hasAttribute("aria-expanded")).length,clickTargetsOffscreen:s.filter(S=>{let u=S.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(l).length,fixedOrStickyOverlayCount:d.length}},{item:q.item,answerContainer:q.answerContainer,clickTarget:q.clickTarget,expandedClass:q.expandedClass});return{capturedAt:new Date().toISOString(),...t,selectorVersion:Nn}}function Pt(e){if(e instanceof dt)return"error";if(e instanceof j)return"captcha";if(e instanceof Vt)return"location_mismatch";if(e instanceof at)return"request_aborted";if(e instanceof ft)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":Ii(t)?"proxy_tunnel_failed":Wi(t)?"proxy_unavailable":/timeout|timed out|Timeout \d+ms exceeded|deadline/i.test(t)?"timeout":"error"}function Ii(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 Wi(e){return/proxy unavailable|proxy_unavailable|connection_test_failed|did not return a proxy id|configured fallback/i.test(e)}async function Ie(e,t,n,a,i,s,l){let d=Ln(t,{nativeGoogleAssets:e.serpOnly}),S=l?$e(d,l.execution,l.permit,t.plannedProvider):d,u=new ne,h=new ee(S,u,a,i);if(n?.aborted)return{result:null,error:ae(n),cleanup:await S.close(),debug:null};let r,o=n?new Promise((y,T)=>{r=()=>T(ae(n)),n.addEventListener("abort",r,{once:!0})}):null,U=null,c=null,g,w=null,p=!1,M;try{M=h.extract(e,n),M.then(()=>{p=!0},()=>{p=!0}),U=await(o?Promise.race([M,o]):M)}catch(y){c=y}finally{if(n&&r&&n.removeEventListener("abort",r),s){let y;try{let T=bi(S);T.catch(()=>{});let O=await Promise.race([T,new Promise((x,b)=>{y=setTimeout(()=>b(new DOMException("PAA DOM evidence timed out","TimeoutError")),2e3)})]);await s(O)}catch(T){console.warn(JSON.stringify({event:"paa_dom_evidence_failed",message:T instanceof Error?T.message:String(T)}))}finally{y&&clearTimeout(y)}}w=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:S.getDebugSnapshot()}:null);try{g=await S.close()}catch(y){g={\u006b\u0065\u0072\u006e\u0065\u006cSessionId:S.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:y instanceof Error?y.message:String(y),physicalOutcome:"unknown"}}if(M&&!p){let y;try{await Promise.race([M.then(()=>{},()=>{}),new Promise(T=>{y=setTimeout(T,2e3)})])}finally{y&&clearTimeout(y)}}g.extractionDrained=p,p||(g.physicalOutcome="unknown")}if(c){let y=Pt(c),T=y==="timeout"||y==="request_aborted"||y==="browser_session_interrupted"?y:null,O=null;if(T)try{O=typeof h.getPartialResult=="function"?h.getPartialResult():null}catch{O=null}return O&&T?(O.diagnostics={...O.diagnostics,interruption:{code:T,reasonSource:"client_runtime",message:c instanceof Error?c.message:String(c)}},{result:O,error:c,cleanup:g,debug:w,salvagedFrom:c}):{result:null,error:c,cleanup:g,debug:w}}return{result:U,error:null,cleanup:g,debug:w}}function sa(e){return e.diagnostics.degradedResult?"degraded_result":e.diagnostics?.completionStatus??(e.totalQuestions>0?"paa_found":"no_paa")}function Ai(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 We(e,t,n){let a=Ai(e),i=(e.diagnostics.warnings?.length??0)>0,s=new Set(e.flat.map(w=>w.question.toLowerCase().replace(/[^\w\s]/g,"").replace(/\s+/g," ").trim())).size,l=n?0:e.flat.filter(w=>!w.answer?.trim()).length,d=n?0:e.flat.filter(w=>!w.source_cite?.trim()).length,S=n?0:e.flat.filter(w=>w.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,o=r==="interrupted"||r==="recovery_exhausted",U=h&&(s<t&&r!=="frontier_exhausted"||l>0||d>0||S>0||!!e.diagnostics.interruption||o),c=u?"complete":h&&s>0?U||i?"partial":"complete":a?i?"partial":"complete":"degraded",g=c==="degraded";return e.diagnostics={...e.diagnostics,resultQuality:c,degradedResult:g,degradationReasons:g?["empty_primary_serp"]:[],retryRecommended:g||c==="partial"&&(U||e.diagnostics.warnings?.some(w=>w.retryable)===!0),completeness:{paaWithoutAnswer:l,paaWithoutSource:d,paaIncompleteAnswers:S,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:l>0||d>0||S>0?"partial":"complete"}}:{}},e}function Ae(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 oa(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 xe(e,t){if(t||!e.diagnostics.debug)return e;let n={...e.diagnostics};return delete n.debug,{...e,diagnostics:n}}async function Oe(e,t){let n=t==null?3e3:t-Date.now();if(n<=0)return e;try{return await Jn(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 Le=2,xi=2,Oi=3e3;function Li(e){if(!e||typeof e!="object")return;let t=e.signal;if(t instanceof AbortSignal)return t}function Bi(e){if(!e||typeof e!="object")return;let t=e.onAttemptEvent;return typeof t=="function"?t:void 0}function Hi(e){if(!e||typeof e!="object")return;let t=e.onPaaProgress;return typeof t=="function"?t:void 0}function Fi(e){if(!e||typeof e!="object")return;let t=e.onPaaDomEvidence;return typeof t=="function"?t:void 0}async function bt(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 ct(e){return e instanceof Error?e.message:String(e)}function Ri(e){return e==="location"?xi:Le}function ra(e){return e==="captcha"||e==="proxy_tunnel_failed"||e==="proxy_unavailable"}function da(e){return e==="browser_session_interrupted"}function Di(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 Gi(e,t){return t==="location"&&e.diagnostics.debug?.locationEvidence?.status==="mismatch"}function la(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 Ei(e,t){if(!t)return!0;if(!e)return!1;try{return await gn(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:ct(n)})),!1}}async function ur(e){let t=typeof e=="object"&&e!==null?e:{},n=Li(e),a=en(e),i=Bi(e),s=Hi(e),l=Fi(e),d=t.forceManagedSerp===!0,S=t.force\u004b\u0065\u0072\u006e\u0065\u006cSerp===!0,u=_e({forceManagedSerp:d,force\u004b\u0065\u0072\u006e\u0065\u006cSerp:S}),h=t.proxyMode,r=h==="location"||h==="none"||h==="configured"?h:Et,o=typeof t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey=="string"?t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey.trim():Fe(),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:o,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"},g=typeof t.debug=="boolean"?t.debug:!1,w=r==="location"&&!!c.location,p=t.maxAttempts,M=typeof p=="number"&&Number.isInteger(p)&&p>=1?Math.min(Le,p):Ri(r),y=Math.min(Le,M),T=typeof t.softDeadlineMs=="number"?t.softDeadlineMs:null,O=new _t,x=null,b=r,G=0,F=()=>T==null||T-Date.now()>=Oi;for(let P=0;P<y;P++){let v=P+1,W=Date.now(),f=!0,k,K=!1,N=n,D;try{if(N?.aborted)throw ae(N);let C=Je({intent:u,\u0062\u0072\u0069\u0067\u0068\u0074\u0044\u0061\u0074\u0061Available:pn(),\u006b\u0065\u0072\u006e\u0065\u006cFallbackAvailable:!!o,persistent\u004b\u0065\u0072\u006e\u0065\u006cIdentityRequested:!!(t.serpIdentity||t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName),retryIndex:P,priorTerminalReason:x==null?null:Pt(x),softDeadlineMs:T}),L=de.parse({...t,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:o,proxyMode:b,debug:g||w});a&&(k=await a.prepare(C.plannedProvider,v),D=a.watch(k,n),N=D.signal);let m=C.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 bt(i,{type:"started",attemptNumber:v,maxAttempts:y,method:m,provider:m==="\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:C.reasonCode,planTimeoutMs:C.timeoutMs,retryKind:v===1?null:C.attemptKind==="provider_fallback"?"provider_fallback":"same_method",retryReason:v===1||x==null?null:Pt(x),query:L.query,location:L.location??null,maxQuestions:L.maxQuestions,startedAt:new Date(W).toISOString()}),C.plannedProvider==="\u006b\u0065\u0072\u006e\u0065\u006c"&&(f=!1,a&&k&&await a.start(k,"proxy"));let I=C.plannedProvider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?null:await yn({...c,proxyMode:b,attemptIndex:P,fresh:b==="location"});if(C.plannedProvider==="\u006b\u0065\u0072\u006e\u0065\u006c"&&!I)throw new Error("\u004b\u0065\u0072\u006e\u0065\u006c proxy resolution did not produce an execution plan");a&&k&&C.plannedProvider==="\u006b\u0065\u0072\u006e\u0065\u006c"&&await a.resource(k,"proxy",I?.disposableProxyId??null);let R={...t,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:o,...I?{\u006b\u0065\u0072\u006e\u0065\u006cProxyId:I.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution:I.resolution}:{},proxyMode:b,keepDefaultProxy:P>0,softDeadlineMs:T==null?void 0:W+C.timeoutMs,debug:g||w};b==="none"&&(R.\u006b\u0065\u0072\u006e\u0065\u006cProxyId=void 0);let H=de.parse(R);console.info(JSON.stringify({event:"harvest_attempt_started",attempt_number:v,max_attempts:y,query:H.query,location:H.location??null,max_questions:H.maxQuestions}));let J=Yt(),B=null,z=async Q=>{Jt(Q.provider)!==C.plannedProvider&&(B=new dt(C.plannedProvider,Q.provider)),await bt(i,{type:"provider_session_started",attemptNumber:v,maxAttempts:y,provider:Q.provider,providerSessionId:Q.providerSessionId,billingMode:Q.billingMode,observedAt:new Date().toISOString()})},Y=J?.harvestBrowserMode==="headless-test"&&process.env[Ee]==="true";f=!1;let E=J?await Ve({...J,forceHeadless:Y,forceHeadful:!Y},()=>Ie(H,C,N,s,z,l,a&&k?{execution:a,permit:k}:void 0)):await Ie(H,C,N,s,z,l,a&&k?{execution:a,permit:k}:void 0),it=await Ei(o,I?.disposableProxyId);if(E.cleanup.disposableProxyDeleted=it,a&&k){let Q=await re(a,k,E.cleanup,I?.disposableProxyId??null);K=!0,D?.stop(),f=Q.state!=="unknown"&&la(E.cleanup)&&it}else f=la(E.cleanup)&⁢if(E.error||B){let Q=B??E.error,Z=Pt(Q);(Z==="captcha"||Z==="proxy_tunnel_failed")&&b==="location"&&(G++,G>=2&&(b="none"));let At=!E.result&&f&&!N?.aborted&&P<y-1&&F()&&(Z==="captcha"||da(Z)||r==="location"&&ra(Z));if(Z==="captcha"?console.warn(JSON.stringify({event:"harvest_attempt_captcha",attempt_number:v,max_attempts:y,message:ct(Q),will_retry:At})):At&&console.warn(JSON.stringify({event:"harvest_attempt_proxy_retry",attempt_number:v,max_attempts:y,outcome:Z,message:ct(Q),will_retry:At})),await bt(i,{type:"finished",attemptNumber:v,maxAttempts:y,outcome:Z,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:E.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:E.result?.totalQuestions??0,durationMs:Date.now()-W,error:ct(Q),willRetry:At,cleanup:E.cleanup,debug:E.debug,completedAt:new Date().toISOString()}),x=Q,At)continue;if(E.result&&!B){let Sa=await Oe(E.result,T);return Ae(We(xe(Sa,g),H.maxQuestions,H.questionsOnly),P,C.attemptKind==="provider_fallback"?1:0)}break}let st=E.result;if(!st)throw new Error("Harvest attempt completed without a result");if(Gi(st,r)){let Q=new Vt(Di(st)),Z=f&&!N?.aborted&&P<y-1&&F();if(console.warn(JSON.stringify({event:"harvest_attempt_location_mismatch",attempt_number:v,max_attempts:y,message:Q.message,will_retry:Z})),await bt(i,{type:"finished",attemptNumber:v,maxAttempts:y,outcome:"location_mismatch",\u006b\u0065\u0072\u006e\u0065\u006cSessionId:E.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:st.totalQuestions,durationMs:Date.now()-W,error:Q.message,willRetry:Z,cleanup:E.cleanup,debug:E.debug,completedAt:new Date().toISOString()}),x=Q,Z)continue;break}let It=await Oe(st,T),V=Ae(We(xe(It,g),H.maxQuestions,H.questionsOnly),P,C.attemptKind==="provider_fallback"?1:0),Mt=sa(V),rt=Mt==="degraded_result"&&f&&!N?.aborted&&P<y-1&&F(),Wt=Mt==="degraded_result"?oa(V):null;if(rt&&console.warn(JSON.stringify({event:"harvest_attempt_degraded_result",attempt_number:v,max_attempts:y,degradation_reasons:V.diagnostics.degradationReasons,will_retry:!0})),await bt(i,{type:"finished",attemptNumber:v,maxAttempts:y,outcome:Mt,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:E.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:V.totalQuestions,durationMs:Date.now()-W,error:Wt,willRetry:rt,cleanup:E.cleanup,debug:E.debug,completedAt:new Date().toISOString()}),rt)continue;return(H.format==="json"||H.format==="both")&&await O.writeJSON(V,H.outputDir),(H.format==="csv"||H.format==="both")&&await Promise.all([O.writeCSV(V.flat,H.outputDir),V.videos.length>0?O.writeVideoCSV(V.videos,V.seed,H.outputDir):Promise.resolve(""),V.forums.length>0?O.writeForumCSV(V.forums,V.seed,H.outputDir):Promise.resolve(""),V.aiOverview.detected?O.writeAIOverviewCSV(V.aiOverview.citations,V.aiOverview.text,V.seed,H.outputDir):Promise.resolve(""),V.aiMode.detected?O.writeAIModeCSV(V.aiMode.citations,V.aiMode.text,V.seed,H.outputDir):Promise.resolve(""),V.whatPeopleSaying.length>0?O.writeWhatPeopleSayingCSV(V.whatPeopleSaying,V.seed,H.outputDir):Promise.resolve("")]),V}catch(C){a&&k&&!K&&(f=!1,await re(a,k,{\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:ct(C),physicalOutcome:"unknown",extractionDrained:!0,disposableProxyDeleted:!1}).catch(()=>{}));let L=Pt(C);(L==="captcha"||L==="proxy_tunnel_failed")&&b==="location"&&(G++,G>=2&&(b="none"));let m=f&&!N?.aborted&&P<y-1&&F()&&(L==="captcha"||da(L)||r==="location"&&ra(L));if(L==="captcha"?console.warn(JSON.stringify({event:"harvest_attempt_captcha",attempt_number:v,max_attempts:y,message:ct(C),will_retry:m})):m&&console.warn(JSON.stringify({event:"harvest_attempt_proxy_retry",attempt_number:v,max_attempts:y,outcome:L,message:ct(C),will_retry:m})),await bt(i,{type:"finished",attemptNumber:v,maxAttempts:y,outcome:L,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,questionCount:0,durationMs:Date.now()-W,error:ct(C),willRetry:m,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=C,m)continue;if(L==="captcha")break;throw C}finally{D?.stop()}}throw x&&!(x instanceof j)?x:(console.warn(JSON.stringify({event:"harvest_captcha_exhausted",max_attempts:y,session_kind:o?"\u006b\u0065\u0072\u006e\u0065\u006c":"local"})),new j(Ge(`CAPTCHA on all ${y} fresh sessions. Try again in a few minutes.`)))}export{lt as a,ze as b,_ as c,Qi as d,Zi as e,Xi as f,ts as g,us as h,qt as i,cs as j,ws as k,Sn as l,he as m,ce as n,Ps as o,gn as p,bs as q,yn as r,ye as s,pn as t,As as u,pe as v,me as w,Bs as x,Tn as y,Pn as z,bn as A,Qt as B,In as C,Ka as D,An as E,ii as F,Zt as G,te as H,kt as I,Ct as J,ur as K};
|
|
21728
|
+
`)}};function ie(e){return e.reason instanceof DOMException&&e.reason.name==="TimeoutError"?e.reason:new at}async function Ii(e){let t=await e.evaluate(n=>{let a=n,i=Array.from(document.querySelectorAll(a.item)),s=i.map(S=>S.querySelector(a.clickTarget)).filter(S=>S!=null),l=S=>{let u=S.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 o=document.elementFromPoint(h,r);return o!=null&&o!==S&&!S.contains(o)&&!o.contains(S)},d=Array.from(document.querySelectorAll("body *")).filter(S=>{let u=window.getComputedStyle(S);if(u.position!=="fixed"&&u.position!=="sticky")return!1;let h=S.getBoundingClientRect();return h.width*h.height>=window.innerWidth*window.innerHeight*.15&&u.visibility!=="hidden"&&u.display!=="none"});return{itemCount:i.length,expandedItemCount:i.filter(S=>S.classList.contains(a.expandedClass)||S.querySelector(a.clickTarget)?.getAttribute("aria-expanded")==="true").length,answeredItemCount:i.filter(S=>(S.querySelector(a.answerContainer)?.textContent?.trim().length??0)>=10).length,sourcedItemCount:i.filter(S=>S.querySelector(`${a.answerContainer} a[href]`)!=null).length,clickTargetCount:s.length,clickTargetsWithButtonRole:s.filter(S=>S.getAttribute("role")==="button"||S.tagName==="BUTTON").length,clickTargetsWithExpandedState:s.filter(S=>S.hasAttribute("aria-expanded")).length,clickTargetsOffscreen:s.filter(S=>{let u=S.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(l).length,fixedOrStickyOverlayCount:d.length}},{item:q.item,answerContainer:q.answerContainer,clickTarget:q.clickTarget,expandedClass:q.expandedClass});return{capturedAt:new Date().toISOString(),...t,selectorVersion:Tn}}function Pt(e){if(e instanceof dt)return"error";if(e instanceof j)return"captcha";if(e instanceof Vt)return"location_mismatch";if(e instanceof at)return"request_aborted";if(e instanceof ft)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":Wi(t)?"proxy_tunnel_failed":Ai(t)?"proxy_unavailable":/timeout|timed out|Timeout \d+ms exceeded|deadline/i.test(t)?"timeout":"error"}function Wi(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 Ai(e){return/proxy unavailable|proxy_unavailable|connection_test_failed|did not return a proxy id|configured fallback/i.test(e)}async function We(e,t,n,a,i,s,l){let d=Bn(t,{nativeGoogleAssets:e.serpOnly}),S=l?nn(d,l.execution,l.permit,t.plannedProvider):d,u=new ae,h=new ne(S,u,a,i);if(n?.aborted)return{result:null,error:ie(n),cleanup:await S.close(),debug:null};let r,o=n?new Promise((y,T)=>{r=()=>T(ie(n)),n.addEventListener("abort",r,{once:!0})}):null,U=null,c=null,g,w=null,p=!1,M;try{M=h.extract(e,n),M.then(()=>{p=!0},()=>{p=!0}),U=await(o?Promise.race([M,o]):M)}catch(y){c=y}finally{if(n&&r&&n.removeEventListener("abort",r),s){let y;try{let T=Ii(S);T.catch(()=>{});let O=await Promise.race([T,new Promise((x,b)=>{y=setTimeout(()=>b(new DOMException("PAA DOM evidence timed out","TimeoutError")),2e3)})]);await s(O)}catch(T){console.warn(JSON.stringify({event:"paa_dom_evidence_failed",message:T instanceof Error?T.message:String(T)}))}finally{y&&clearTimeout(y)}}w=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:S.getDebugSnapshot()}:null);try{g=await S.close()}catch(y){g={\u006b\u0065\u0072\u006e\u0065\u006cSessionId:S.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:y instanceof Error?y.message:String(y),physicalOutcome:"unknown"}}if(M&&!p){let y;try{await Promise.race([M.then(()=>{},()=>{}),new Promise(T=>{y=setTimeout(T,2e3)})])}finally{y&&clearTimeout(y)}}g.extractionDrained=p,p||(g.physicalOutcome="unknown")}if(c){let y=Pt(c),T=y==="timeout"||y==="request_aborted"||y==="browser_session_interrupted"?y:null,O=null;if(T)try{O=typeof h.getPartialResult=="function"?h.getPartialResult():null}catch{O=null}return O&&T?(O.diagnostics={...O.diagnostics,interruption:{code:T,reasonSource:"client_runtime",message:c instanceof Error?c.message:String(c)}},{result:O,error:c,cleanup:g,debug:w,salvagedFrom:c}):{result:null,error:c,cleanup:g,debug:w}}return{result:U,error:null,cleanup:g,debug:w}}function oa(e){return e.diagnostics.degradedResult?"degraded_result":e.diagnostics?.completionStatus??(e.totalQuestions>0?"paa_found":"no_paa")}function xi(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 Ae(e,t,n){let a=xi(e),i=(e.diagnostics.warnings?.length??0)>0,s=new Set(e.flat.map(w=>w.question.toLowerCase().replace(/[^\w\s]/g,"").replace(/\s+/g," ").trim())).size,l=n?0:e.flat.filter(w=>!w.answer?.trim()).length,d=n?0:e.flat.filter(w=>!w.source_cite?.trim()).length,S=n?0:e.flat.filter(w=>w.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,o=r==="interrupted"||r==="recovery_exhausted",U=h&&(s<t&&r!=="frontier_exhausted"||l>0||d>0||S>0||!!e.diagnostics.interruption||o),c=u?"complete":h&&s>0?U||i?"partial":"complete":a?i?"partial":"complete":"degraded",g=c==="degraded";return e.diagnostics={...e.diagnostics,resultQuality:c,degradedResult:g,degradationReasons:g?["empty_primary_serp"]:[],retryRecommended:g||c==="partial"&&(U||e.diagnostics.warnings?.some(w=>w.retryable)===!0),completeness:{paaWithoutAnswer:l,paaWithoutSource:d,paaIncompleteAnswers:S,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:l>0||d>0||S>0?"partial":"complete"}}:{}},e}function xe(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 ra(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 Oe(e,t){if(t||!e.diagnostics.debug)return e;let n={...e.diagnostics};return delete n.debug,{...e,diagnostics:n}}async function Le(e,t){let n=t==null?3e3:t-Date.now();if(n<=0)return e;try{return await _n(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 Be=2,Oi=2,Li=3e3;function Bi(e){if(!e||typeof e!="object")return;let t=e.signal;if(t instanceof AbortSignal)return t}function Hi(e){if(!e||typeof e!="object")return;let t=e.onAttemptEvent;return typeof t=="function"?t:void 0}function Fi(e){if(!e||typeof e!="object")return;let t=e.onPaaProgress;return typeof t=="function"?t:void 0}function Ri(e){if(!e||typeof e!="object")return;let t=e.onPaaDomEvidence;return typeof t=="function"?t:void 0}async function bt(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 ct(e){return e instanceof Error?e.message:String(e)}function Di(e){return e==="location"?Oi:Be}function da(e){return e==="captcha"||e==="proxy_tunnel_failed"||e==="proxy_unavailable"}function la(e){return e==="browser_session_interrupted"}function Gi(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 Ei(e,t){return t==="location"&&e.diagnostics.debug?.locationEvidence?.status==="mismatch"}function Sa(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 Vi(e,t){if(!t)return!0;if(!e)return!1;try{return await yn(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:ct(n)})),!1}}async function gr(e){let t=typeof e=="object"&&e!==null?e:{},n=Bi(e),a=$e(e),i=Hi(e),s=Fi(e),l=Ri(e),d=t.forceManagedSerp===!0,S=t.force\u004b\u0065\u0072\u006e\u0065\u006cSerp===!0,u=Ze({forceManagedSerp:d,force\u004b\u0065\u0072\u006e\u0065\u006cSerp:S}),h=t.proxyMode,r=h==="location"||h==="none"||h==="configured"?h:Et,o=typeof t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey=="string"?t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey.trim():De(),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:o,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"},g=typeof t.debug=="boolean"?t.debug:!1,w=r==="location"&&!!c.location,p=t.maxAttempts,M=typeof p=="number"&&Number.isInteger(p)&&p>=1?Math.min(Be,p):Di(r),y=Math.min(Be,M),T=typeof t.softDeadlineMs=="number"?t.softDeadlineMs:null,O=new qt,x=null,b=r,G=0,F=()=>T==null||T-Date.now()>=Li;for(let P=0;P<y;P++){let v=P+1,W=Date.now(),f=!0,k,K=!1,N=n,D;try{if(N?.aborted)throw ie(N);let C=Qe({intent:u,\u0062\u0072\u0069\u0067\u0068\u0074\u0044\u0061\u0074\u0061Available:mn(),\u006b\u0065\u0072\u006e\u0065\u006cFallbackAvailable:!!o,persistent\u004b\u0065\u0072\u006e\u0065\u006cIdentityRequested:!!(t.serpIdentity||t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName),retryIndex:P,priorTerminalReason:x==null?null:Pt(x),softDeadlineMs:T}),L=le.parse({...t,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:o,proxyMode:b,debug:g||w});a&&(k=await a.prepare(C.plannedProvider,v),D=a.watch(k,n),N=D.signal);let m=C.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 bt(i,{type:"started",attemptNumber:v,maxAttempts:y,method:m,provider:m==="\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:C.reasonCode,planTimeoutMs:C.timeoutMs,retryKind:v===1?null:C.attemptKind==="provider_fallback"?"provider_fallback":"same_method",retryReason:v===1||x==null?null:Pt(x),query:L.query,location:L.location??null,maxQuestions:L.maxQuestions,startedAt:new Date(W).toISOString()}),C.plannedProvider==="\u006b\u0065\u0072\u006e\u0065\u006c"&&(f=!1,a&&k&&await a.start(k,"proxy"));let I=C.plannedProvider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?null:await pn({...c,proxyMode:b,attemptIndex:P,fresh:b==="location"});if(C.plannedProvider==="\u006b\u0065\u0072\u006e\u0065\u006c"&&!I)throw new Error("\u004b\u0065\u0072\u006e\u0065\u006c proxy resolution did not produce an execution plan");a&&k&&C.plannedProvider==="\u006b\u0065\u0072\u006e\u0065\u006c"&&await a.resource(k,"proxy",I?.disposableProxyId??null);let R={...t,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:o,...I?{\u006b\u0065\u0072\u006e\u0065\u006cProxyId:I.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution:I.resolution}:{},proxyMode:b,keepDefaultProxy:P>0,softDeadlineMs:T==null?void 0:W+C.timeoutMs,debug:g||w};b==="none"&&(R.\u006b\u0065\u0072\u006e\u0065\u006cProxyId=void 0);let H=le.parse(R);console.info(JSON.stringify({event:"harvest_attempt_started",attempt_number:v,max_attempts:y,query:H.query,location:H.location??null,max_questions:H.maxQuestions}));let J=Yt(),B=null,z=async Q=>{_t(Q.provider)!==C.plannedProvider&&(B=new dt(C.plannedProvider,Q.provider)),await bt(i,{type:"provider_session_started",attemptNumber:v,maxAttempts:y,provider:Q.provider,providerSessionId:Q.providerSessionId,billingMode:Q.billingMode,observedAt:new Date().toISOString()})},Y=J?.harvestBrowserMode==="headless-test"&&process.env[Ye]==="true";f=!1;let E=J?await Ke({...J,forceHeadless:Y,forceHeadful:!Y},()=>We(H,C,N,s,z,l,a&&k?{execution:a,permit:k}:void 0)):await We(H,C,N,s,z,l,a&&k?{execution:a,permit:k}:void 0),it=await Vi(o,I?.disposableProxyId);if(E.cleanup.disposableProxyDeleted=it,a&&k){let Q=await de(a,k,E.cleanup,I?.disposableProxyId??null);K=!0,D?.stop(),f=Q.state!=="unknown"&&Sa(E.cleanup)&&it}else f=Sa(E.cleanup)&⁢if(E.error||B){let Q=B??E.error,Z=Pt(Q);(Z==="captcha"||Z==="proxy_tunnel_failed")&&b==="location"&&(G++,G>=2&&(b="none"));let At=!E.result&&f&&!N?.aborted&&P<y-1&&F()&&(Z==="captcha"||la(Z)||r==="location"&&da(Z));if(Z==="captcha"?console.warn(JSON.stringify({event:"harvest_attempt_captcha",attempt_number:v,max_attempts:y,message:ct(Q),will_retry:At})):At&&console.warn(JSON.stringify({event:"harvest_attempt_proxy_retry",attempt_number:v,max_attempts:y,outcome:Z,message:ct(Q),will_retry:At})),await bt(i,{type:"finished",attemptNumber:v,maxAttempts:y,outcome:Z,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:E.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:E.result?.totalQuestions??0,durationMs:Date.now()-W,error:ct(Q),willRetry:At,cleanup:E.cleanup,debug:E.debug,completedAt:new Date().toISOString()}),x=Q,At)continue;if(E.result&&!B){let Ua=await Le(E.result,T);return xe(Ae(Oe(Ua,g),H.maxQuestions,H.questionsOnly),P,C.attemptKind==="provider_fallback"?1:0)}break}let st=E.result;if(!st)throw new Error("Harvest attempt completed without a result");if(Ei(st,r)){let Q=new Vt(Gi(st)),Z=f&&!N?.aborted&&P<y-1&&F();if(console.warn(JSON.stringify({event:"harvest_attempt_location_mismatch",attempt_number:v,max_attempts:y,message:Q.message,will_retry:Z})),await bt(i,{type:"finished",attemptNumber:v,maxAttempts:y,outcome:"location_mismatch",\u006b\u0065\u0072\u006e\u0065\u006cSessionId:E.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:st.totalQuestions,durationMs:Date.now()-W,error:Q.message,willRetry:Z,cleanup:E.cleanup,debug:E.debug,completedAt:new Date().toISOString()}),x=Q,Z)continue;break}let It=await Le(st,T),V=xe(Ae(Oe(It,g),H.maxQuestions,H.questionsOnly),P,C.attemptKind==="provider_fallback"?1:0),Mt=oa(V),rt=Mt==="degraded_result"&&f&&!N?.aborted&&P<y-1&&F(),Wt=Mt==="degraded_result"?ra(V):null;if(rt&&console.warn(JSON.stringify({event:"harvest_attempt_degraded_result",attempt_number:v,max_attempts:y,degradation_reasons:V.diagnostics.degradationReasons,will_retry:!0})),await bt(i,{type:"finished",attemptNumber:v,maxAttempts:y,outcome:Mt,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:E.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:V.totalQuestions,durationMs:Date.now()-W,error:Wt,willRetry:rt,cleanup:E.cleanup,debug:E.debug,completedAt:new Date().toISOString()}),rt)continue;return(H.format==="json"||H.format==="both")&&await O.writeJSON(V,H.outputDir),(H.format==="csv"||H.format==="both")&&await Promise.all([O.writeCSV(V.flat,H.outputDir),V.videos.length>0?O.writeVideoCSV(V.videos,V.seed,H.outputDir):Promise.resolve(""),V.forums.length>0?O.writeForumCSV(V.forums,V.seed,H.outputDir):Promise.resolve(""),V.aiOverview.detected?O.writeAIOverviewCSV(V.aiOverview.citations,V.aiOverview.text,V.seed,H.outputDir):Promise.resolve(""),V.aiMode.detected?O.writeAIModeCSV(V.aiMode.citations,V.aiMode.text,V.seed,H.outputDir):Promise.resolve(""),V.whatPeopleSaying.length>0?O.writeWhatPeopleSayingCSV(V.whatPeopleSaying,V.seed,H.outputDir):Promise.resolve("")]),V}catch(C){a&&k&&!K&&(f=!1,await de(a,k,{\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:ct(C),physicalOutcome:"unknown",extractionDrained:!0,disposableProxyDeleted:!1}).catch(()=>{}));let L=Pt(C);(L==="captcha"||L==="proxy_tunnel_failed")&&b==="location"&&(G++,G>=2&&(b="none"));let m=f&&!N?.aborted&&P<y-1&&F()&&(L==="captcha"||la(L)||r==="location"&&da(L));if(L==="captcha"?console.warn(JSON.stringify({event:"harvest_attempt_captcha",attempt_number:v,max_attempts:y,message:ct(C),will_retry:m})):m&&console.warn(JSON.stringify({event:"harvest_attempt_proxy_retry",attempt_number:v,max_attempts:y,outcome:L,message:ct(C),will_retry:m})),await bt(i,{type:"finished",attemptNumber:v,maxAttempts:y,outcome:L,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,questionCount:0,durationMs:Date.now()-W,error:ct(C),willRetry:m,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=C,m)continue;if(L==="captcha")break;throw C}finally{D?.stop()}}throw x&&!(x instanceof j)?x:(console.warn(JSON.stringify({event:"harvest_captcha_exhausted",max_attempts:y,session_kind:o?"\u006b\u0065\u0072\u006e\u0065\u006c":"local"})),new j(Ve(`CAPTCHA on all ${y} fresh sessions. Try again in a few minutes.`)))}export{lt as a,tn as b,_ as c,qi as d,zi as e,ji as f,$i as g,Qi as h,ws as i,zt as j,gs as k,ys as l,Un as m,ue as n,we as o,Is as p,yn as q,Ws as r,pn as s,pe as t,mn as u,Os as v,me as w,ke as x,Fs as y,Pn as z,bn as A,In as B,Zt as C,Wn as D,Ja as E,xn as F,si as G,Xt as H,ee as I,kt as J,Ct as K,gr as L};
|