mcp-scraper 0.96.0 → 0.96.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +28 -1
  2. package/README.md +3 -1
  3. package/dist/{actions-YCMJY3PF.js → actions-R4EJDLRO.js} +1 -1
  4. package/dist/bin/api-server.js +1 -1
  5. package/dist/bin/mcp-scraper-cli.js +1 -1
  6. package/dist/bin/mcp-scraper-core.js +1 -1
  7. package/dist/bin/mcp-scraper-install.js +1 -1
  8. package/dist/bin/mcp-stdio-server.js +1 -1
  9. package/dist/bin/paa-harvest.js +1 -1
  10. package/dist/{bundle-TTJP6DHU.js → bundle-FCXZMIRB.js} +1 -1
  11. package/dist/chunk-2OKQVTQ5.js +173 -0
  12. package/dist/{chunk-ZPQNY5TI.js → chunk-5LYINW7Z.js} +8 -1
  13. package/dist/{chunk-R5LJL6IR.js → chunk-6BD75VKS.js} +30 -37
  14. package/dist/{chunk-VAC3SQ5T.js → chunk-6K7ZJYQW.js} +3 -3
  15. package/dist/chunk-7H6YWD2L.js +1 -0
  16. package/dist/{chunk-6SNOUSSZ.js → chunk-7WPCGRD7.js} +1 -1
  17. package/dist/{chunk-DGAW7FD7.js → chunk-BPKTUCV7.js} +1 -1
  18. package/dist/{chunk-QWE7VKIX.js → chunk-CORWWDHL.js} +1 -1
  19. package/dist/{chunk-LFRAA3MY.js → chunk-DTVKZU5X.js} +1 -1
  20. package/dist/{chunk-HJIOH7HF.js → chunk-H6MODA7W.js} +2 -2
  21. package/dist/{chunk-JAV5V3JT.js → chunk-HVQZRQRJ.js} +19 -19
  22. package/dist/chunk-JHT6A4U6.js +11 -0
  23. package/dist/{chunk-ARSQZCTJ.js → chunk-KUEMW76G.js} +255 -245
  24. package/dist/{chunk-SNJR5N36.js → chunk-RYX4FJVH.js} +1 -1
  25. package/dist/{chunk-JW4GDY7S.js → chunk-SE4VKLEC.js} +1 -1
  26. package/dist/{chunk-TPN25AFZ.js → chunk-SFUOSJ3A.js} +1 -1
  27. package/dist/{chunk-GVYGAZV7.js → chunk-UXNR3K6I.js} +1 -1
  28. package/dist/{chunk-FRXKMOXI.js → chunk-ZTMQEDIB.js} +1 -1
  29. package/dist/{dispatch-3HY4735M.js → dispatch-P7IY75LH.js} +1 -1
  30. package/dist/index.cjs +36 -36
  31. package/dist/index.d.cts +3 -0
  32. package/dist/index.d.ts +3 -0
  33. package/dist/index.js +1 -1
  34. package/dist/{queue-HUP2GNXF.js → queue-AC4XKD6Z.js} +1 -1
  35. package/dist/{reconciliation-ANXNJWME.js → reconciliation-UZUZ6B74.js} +1 -1
  36. package/dist/{server-VQU6S24A.js → server-AEEE7E3C.js} +600 -600
  37. package/dist/{settlement-6CCE2PDH.js → settlement-6CS4JZTY.js} +1 -1
  38. package/dist/{worker-5G5BK23B.js → worker-HHUU2ECG.js} +1 -1
  39. package/package.json +1 -1
  40. package/dist/chunk-2PRH4Z3N.js +0 -181
  41. package/dist/chunk-7UHDOIUE.js +0 -1
  42. package/dist/chunk-OB6E6UTD.js +0 -1
@@ -1 +1 @@
1
- import{b as a,c as b}from"./chunk-DGAW7FD7.js";import"./chunk-R5LJL6IR.js";import"./chunk-6SNOUSSZ.js";import"./chunk-KXJCGV3H.js";import"./chunk-QWE7VKIX.js";import"./chunk-ZPQNY5TI.js";import"./chunk-HUNSEGUN.js";import"./chunk-SEZETSB3.js";import"./chunk-SDQW7IJN.js";import"./chunk-C7MGJUTU.js";import"./chunk-4ZVO6GX4.js";import"./chunk-WNUXMPVX.js";import"./chunk-WP3QS4CJ.js";import"./chunk-OILOHQNL.js";import"./chunk-HNNYXMSI.js";export{a as settleExtractJobCharge,b as settleTerminalExtractJob};
1
+ import{b as a,c as b}from"./chunk-BPKTUCV7.js";import"./chunk-6BD75VKS.js";import"./chunk-7WPCGRD7.js";import"./chunk-KXJCGV3H.js";import"./chunk-CORWWDHL.js";import"./chunk-5LYINW7Z.js";import"./chunk-HUNSEGUN.js";import"./chunk-SEZETSB3.js";import"./chunk-SDQW7IJN.js";import"./chunk-C7MGJUTU.js";import"./chunk-4ZVO6GX4.js";import"./chunk-WNUXMPVX.js";import"./chunk-WP3QS4CJ.js";import"./chunk-OILOHQNL.js";import"./chunk-HNNYXMSI.js";export{a as settleExtractJobCharge,b as settleTerminalExtractJob};
@@ -1 +1 @@
1
- import{U as a,V as b,W as c}from"./chunk-2PRH4Z3N.js";import"./chunk-R5LJL6IR.js";import"./chunk-U4WIJZCX.js";import"./chunk-JAV5V3JT.js";import"./chunk-M5QHXNFZ.js";import"./chunk-OB6E6UTD.js";import"./chunk-63VWBMYR.js";import"./chunk-ZPQNY5TI.js";import"./chunk-7SR7MEU5.js";import"./chunk-HUNSEGUN.js";import"./chunk-B4ZKPLSP.js";import"./chunk-VVSHZV5S.js";import"./chunk-C7MGJUTU.js";import"./chunk-4ZVO6GX4.js";import"./chunk-WNUXMPVX.js";import"./chunk-6N5EC7ZO.js";import"./chunk-B3JRL45T.js";import"./chunk-HNNYXMSI.js";export{b as drainQueue,c as startWorker,a as tickOnce};
1
+ import{N as a,O as b,P as c}from"./chunk-2OKQVTQ5.js";import"./chunk-6BD75VKS.js";import"./chunk-U4WIJZCX.js";import"./chunk-HVQZRQRJ.js";import"./chunk-M5QHXNFZ.js";import"./chunk-JHT6A4U6.js";import"./chunk-63VWBMYR.js";import"./chunk-5LYINW7Z.js";import"./chunk-7SR7MEU5.js";import"./chunk-HUNSEGUN.js";import"./chunk-B4ZKPLSP.js";import"./chunk-VVSHZV5S.js";import"./chunk-C7MGJUTU.js";import"./chunk-4ZVO6GX4.js";import"./chunk-WNUXMPVX.js";import"./chunk-6N5EC7ZO.js";import"./chunk-B3JRL45T.js";import"./chunk-HNNYXMSI.js";export{b as drainQueue,c as startWorker,a as tickOnce};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-scraper",
3
- "version": "0.96.0",
3
+ "version": "0.96.2",
4
4
  "description": "MCP server for MCP Scraper web intelligence tools",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -1,181 +0,0 @@
1
- import{c as Fe,d as ir,g as dt,h as ar,i as lr,j as ur,k as dr}from"./chunk-R5LJL6IR.js";import{a as fr}from"./chunk-U4WIJZCX.js";import{J as He,c as Ft,d as Ee,e as te,f as $t,k as Xt,l as Qt,s as er}from"./chunk-JAV5V3JT.js";import{b as nr,c as sr,d as ae,e as ct,f as le,g as ue,h as We}from"./chunk-OB6E6UTD.js";import{a as ie,b as Ae,c as S,e as yr}from"./chunk-63VWBMYR.js";import{c as cr,g as pr}from"./chunk-ZPQNY5TI.js";import{b as ne,d as se,e as K,f as V,g as gr,j as X,p as _r}from"./chunk-7SR7MEU5.js";import{d as $e,e as Ue,f as Je,g as we,h as re,k as Se,m as oe,o as Ge,r as Be,s as T}from"./chunk-HUNSEGUN.js";import{b as Ut,c as Jt,d as Gt}from"./chunk-B4ZKPLSP.js";import{a as tr,b as rr,c as or}from"./chunk-VVSHZV5S.js";import{b as ut,d as Bt,e as Wt,g as F,h as z,j as zt,m as Kt,o as Vt}from"./chunk-C7MGJUTU.js";import{b as Yt,c as Zt}from"./chunk-4ZVO6GX4.js";import{a as m}from"./chunk-WNUXMPVX.js";import{b as mr}from"./chunk-B3JRL45T.js";import{c as O,d as b,f as ve}from"./chunk-HNNYXMSI.js";var In="strftime('%Y-%m-%dT%H:%M:%fZ','now')",ze="julianday('now')";var pt="(json_extract(options,'$.executionOwner')='direct' AND json_extract(options,'$.serpOnly') IS NOT 1)",mt=`NOT COALESCE(${pt},0) AND json_extract(options,'$.syncExecutionProtocol') IS NOT 1 AND json_extract(options,'$.queueExecutionProtocol') IS NULL`,kn=`${pt} AND julianday(json_extract(options,'$.paaLeaseExpiresAt')) > ${ze}`,Dn=`${pt} AND (
2
- (json_extract(options,'$.paaLeaseExpiresAt') IS NOT NULL AND COALESCE(julianday(json_extract(options,'$.paaLeaseExpiresAt')),0) <= ${ze})
3
- OR (json_extract(options,'$.paaLeaseExpiresAt') IS NULL AND julianday(started_at) <= julianday('now','-15 minutes'))
4
- )`;function Pn(e){return{jobId:e.id,userId:e.user_id,leaseToken:typeof e.options.paaLeaseToken=="string"?e.options.paaLeaseToken:null,recoveryCount:Number(e.options.paaRecoveryCount??0),resultJson:e.result==null?null:JSON.stringify(e.result)}}function On(e,t){return!t||t.jobId!==e||!Number.isSafeInteger(t.userId)||t.userId<=0||!Number.isSafeInteger(t.recoveryCount)||t.recoveryCount<0||t.leaseToken!==null&&(typeof t.leaseToken!="string"||t.leaseToken.length===0)?{sql:"0",args:[]}:{sql:`user_id=? AND json_extract(options,'$.paaLeaseToken') IS ?
5
- AND COALESCE(json_extract(options,'$.paaRecoveryCount'),0)=? AND json(result) IS json(?)`,args:[t.userId,t.leaseToken,t.recoveryCount,t.resultJson]}}function Tn(e,t,r){let o={userId:e.user_id,tool:"harvest_paa",jobId:e.id,sql:"0",args:[]},n=e.options.requestFingerprint;if(e.options.executionProtocol!==1||e.options.executionOwner!=="direct"||e.options.serpOnly===!0||typeof n!="string"||!/^[a-f0-9]{64}$/.test(n)||!t||r.userId!==e.user_id||r.key!==e.options.billingDebitKey||r.amountMc!==e.options.billingHoldMc)return o;let i=Fe(r);return{...o,sql:`EXISTS (SELECT 1 FROM jobs j WHERE j.id=? AND j.user_id=? AND j.query=? AND j.status='running'
6
- AND json_extract(j.options,'$.executionOwner')='direct' AND json_extract(j.options,'$.serpOnly') IS NOT 1
7
- AND json_extract(j.options,'$.executionProtocol')=1 AND json_extract(j.options,'$.requestFingerprint')=?
8
- AND json_extract(j.options,'$.paaLeaseToken')=?
9
- AND julianday(json_extract(j.options,'$.paaLeaseExpiresAt')) > ${ze}
10
- AND json_extract(j.options,'$.billingDebitKey')=? AND json_extract(j.options,'$.billingHoldMc')=?
11
- AND json_extract(j.options,'$.billingSettledAt') IS NULL AND (${i.sql}))`,args:[e.id,e.user_id,e.query,n,t,r.key,r.amountMc,...i.args]}}import{randomUUID as qo}from"crypto";async function $n(e,t,r){let o=qo();return await m().execute({sql:"INSERT INTO jobs (id, user_id, query, options, status, started_at) VALUES (?, ?, ?, ?, 'running', datetime('now'))",args:[o,e,t,JSON.stringify(r)]}),o}async function Un(e,t,r,o){let n=await m().execute({sql:`INSERT INTO jobs (id, user_id, query, options, status, started_at)
12
- VALUES (?, ?, ?, ?, 'running', datetime('now'))
13
- ON CONFLICT(id) DO NOTHING`,args:[e,t,r,JSON.stringify(o)]}),i=await S(e,t);if(!i)throw new Error(`getOrCreateRunningJob: row missing immediately after insert/lookup for ${e}`);return{job:i,created:n.rowsAffected===1}}async function Jn(e,t,r){await m().execute({sql:`UPDATE jobs
14
- SET status = 'running', started_at = COALESCE(started_at, datetime('now'))
15
- WHERE id = ? AND status = 'pending'
16
- AND json_extract(options, '$.executionOwner') = ?
17
- AND json_extract(options, '$.jobKind') = ?`,args:[e,t,r]});let o=await S(e);if(!(!o||o.options.executionOwner!==t||o.options.jobKind!==r))return o}async function Gn(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await m().execute({sql:`SELECT * FROM jobs
18
- WHERE status = 'pending'
19
- AND json_extract(options, '$.executionOwner') = 'inngest'
20
- AND json_extract(options, '$.jobKind') = 'extract_url'
21
- AND json_extract(options, '$.billingDebitKey') IS NOT NULL
22
- AND created_at <= datetime('now', '-30 seconds')
23
- AND datetime(COALESCE(json_extract(options, '$.extractUrlLastDispatchAt'), '1970-01-01')) <= datetime('now', '-30 seconds')
24
- ORDER BY created_at
25
- LIMIT ?`,args:[t]})).rows.map(o=>Ae(ie(o)))}async function Bn(e,t){return(await m().execute({sql:`UPDATE jobs
26
- SET options = json_set(options,
27
- '$.extractUrlDispatchAttempts', COALESCE(json_extract(options, '$.extractUrlDispatchAttempts'), 0) + 1,
28
- '$.extractUrlLastDispatchAt', ?,
29
- '$.extractUrlLastDispatchError', ?)
30
- WHERE id = ? AND status = 'pending'
31
- AND json_extract(options, '$.executionOwner') = 'inngest'
32
- AND json_extract(options, '$.jobKind') = 'extract_url'`,args:[new Date().toISOString(),t??null,e]})).rowsAffected===1}async function Wn(e){return(await m().execute({sql:"SELECT * FROM jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[e]})).rows.map(r=>Ae(ie(r)))}async function br(){let e=m(),t=await e.execute(`
33
- SELECT * FROM jobs
34
- WHERE status = 'pending'
35
- AND COALESCE(json_extract(options, '$.executionOwner'), 'cron') NOT IN ('direct', 'inngest')
36
- AND json_extract(options,'$.queueExecutionProtocol') IS NOT 0
37
- ORDER BY created_at
38
- LIMIT 1
39
- `),r=t.rows[0]?ie(t.rows[0]):void 0;return r?(await e.execute({sql:"UPDATE jobs SET status = 'running', started_at = datetime('now') WHERE id = ? AND status = 'pending'",args:[r.id]})).rowsAffected===0?void 0:{...r,status:"running"}:void 0}async function zn(e,t){await m().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now') WHERE id = ? AND ${mt}`,args:[JSON.stringify(t),e]})}async function Kn(e,t,r){await m().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now') WHERE id = ? AND ${mt}`,args:[t,Bt(r),e]})}async function Yn(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await m().execute({sql:`SELECT * FROM jobs
40
- WHERE status IN ('done', 'failed', 'cancelled')
41
- AND json_extract(options, '$.executionOwner') IN ('direct', 'inngest')
42
- AND json_extract(options, '$.billingDebitKey') IS NOT NULL
43
- AND CAST(json_extract(options, '$.billingHoldMc') AS INTEGER) > 0
44
- AND json_extract(options, '$.billingSettledAt') IS NULL
45
- ORDER BY completed_at DESC
46
- LIMIT ?`,args:[t]})).rows.map(o=>Ae(ie(o)))}async function hr(e,t=25,r="1"){if(!/^[a-z_]+$/.test(e)||!r.trim()||r.length>8192)throw Error("Invalid intent selection");return(await m().execute({sql:`SELECT r.id,r.user_id,r.job_id FROM operation_runs r
47
- JOIN operation_executions e ON e.run_id=r.id
48
- WHERE r.tool=? AND r.status='running' AND e.phase='claimed'
49
- AND e.expires_at_ms <= CAST(strftime('%s','now') AS INTEGER)*1000
50
- AND json_extract(r.normalized_flags_json,'$._storeGateRequired') IS 1 AND (${r})
51
- ORDER BY r.started_at LIMIT ?`,args:[e,Math.max(1,Math.min(100,Math.floor(t)))]})).rows.map(n=>({runId:String(n.id),userId:Number(n.user_id),jobId:String(n.job_id)}))}import{request as $o}from"https";import{HttpsProxyAgent as Uo}from"https-proxy-agent";var Ke={source:"https://\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061.com/users/zone/premium_domains",retrievedAt:"2026-09-23T20:14:30.483Z",includedStatuses:["premium","remove_candidate"],domains:["advanceautoparts.com","affitto.it","agoda.cn","albertsons.com","allpeople.com","autozone.com","bestbuy.com","bestwestern.com","billiger.de","bottlerover.com","carousell.com","carousell.com.hk","carousell.com.my","carousell.ph","carousell.sg","carsales.com.au","cdiscount.com","chewy.com","costco.com","cvs.com","despegar.com.mx","dickssportinggoods.com","dynos.es","emaxme.com","familytreenow.com","feuvert.fr","flooranddecor.com","foodlion.com","footlocker.co.uk","footlocker.com","giantfoodstores.com","gopuff.com","gplay.bg","hermes.com","hyatt.com","idealo.de","immobilienscout24.de","ingatlan.com","instacart.com","intersport.fr","joann.com","kroger.com","lazada.co.id","lazada.co.th","lazada.com.my","lazada.com.ph","lazada.sg","lazada.vn","lowes.ca","lowes.com","mcmaster.com","mediamarkt.de","mediamarkt.es","medline.com","mscdirect.com","napaonline.com","nofrills.ca","peoplefinders.com","platt.com","publicdatausa.com","realcanadiansuperstore.ca","realestate.com.au","restaurantguru.com","searchpeoplefree.com","shopee.cl","shopee.co.id","shopee.co.th","shopee.com.br","shopee.com.co","shopee.com.mx","shopee.com.my","shopee.ph","shopee.sg","shopee.tw","shopee.vn","similarweb.com","skyscanner.co.kr","skyscanner.net","stopandshop.com","target.com","temu.com","ticketmaster.com","totalwine.com","tractorsupply.com","walmart.com.mx","wayfair.com","weismarkets.com","wizzair.com","worten.pt"]};var rs=Ke.source,os=Ke.retrievedAt,Lo=new Set(Ke.domains);function Ie(e){let t=new URL(e).hostname.toLowerCase().replace(/\.$/,"");for(let r of Lo)if(t===r||t.endsWith(`.${r}`))return"premium";return"standard"}function Re(e){for(let t of["providerProduct","billingTier","billableEvent","unitType","source","policyVersion","effectiveAt"])if(!e[t]?.trim())throw new Error(`Provider rate ${t} is required`);if(!Number.isSafeInteger(e.numeratorUsdNanos)||e.numeratorUsdNanos<0)throw new Error("Provider rate numerator must be a non-negative safe integer");if(!Number.isSafeInteger(e.denominatorUnits)||e.denominatorUnits<1)throw new Error("Provider rate denominator must be a positive safe integer");if(Number.isNaN(Date.parse(e.effectiveAt)))throw new Error("Provider rate effectiveAt must be a date");return e}function Ve(e,t){if(Re(e),!Number.isSafeInteger(t)||t<0)throw new Error("Billable units must be a non-negative safe integer");let r=BigInt(e.numeratorUsdNanos)*BigInt(t),o=BigInt(e.denominatorUnits),n=(r*2n+o)/(o*2n);if(n>BigInt(Number.MAX_SAFE_INTEGER))throw new Error("Provider amount exceeds safe integer range");return Number(n)}function Ho(){return Re({providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_api",billingTier:"payg",billableEvent:"successful_delivery",unitType:"request",numeratorUsdNanos:15e8,denominatorUnits:1e3,source:"owner_confirmed_2026-09-24;docs/decisions/2026-08-11-preserve-questions-only-paa-while-evaluating-serp-api.md",policyVersion:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061-serp-payg-2026-09-24",effectiveAt:"2026-08-11T00:00:00Z"})}function vr(e=process.env){let t=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_CONTRACT_USD_PER_1000?.trim(),r=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_RATE_SOURCE?.trim(),o=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_RATE_POLICY_VERSION?.trim(),n=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_RATE_EFFECTIVE_AT?.trim();if(!t&&!r&&!o&&!n)return Ho();if(!t||!r||!o||!n)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP contract rate requires amount, source, policy version, and effective date");let i=Number(t);if(!Number.isFinite(i)||i<0)throw new Error("Invalid \u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP contract amount");return Re({providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_api",billingTier:"payg",billableEvent:"successful_delivery",unitType:"request",numeratorUsdNanos:Math.round(i*1e9),denominatorUnits:1e3,source:r,policyVersion:o,effectiveAt:n})}function Fo(e){return Re({providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser_api",billingTier:e,billableEvent:"transferred_byte",unitType:"byte",numeratorUsdNanos:8e9,denominatorUnits:1e9,source:"owner_confirmed_2026-10-12",policyVersion:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061-browser-account-2026-10-12",effectiveAt:"2026-10-12T00:00:00Z"})}function is(e){return Fo(Ie(e))}function Er(){return Re({providerProduct:"apify_google_serp_scraperlink",billingTier:"store_pay_per_event",billableEvent:"serp_page",unitType:"page",numeratorUsdNanos:5e8,denominatorUnits:1e3,source:"https://apify.com/scraperlink/google-search-results-serp-scraper",policyVersion:"scraperlink-listing-2026-09-24",effectiveAt:"2026-09-24T00:00:00Z"})}var Jo="https://api.\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061.com/request",Go=8e3,Bo="brd.superproxy.io",Wo="44445",zo=10*1024*1024;async function Ko(e,t){let r=new URL(`http://${t.host}:${t.port}`);r.username=t.username,r.password=t.password;let o=new Uo(r);try{return await new Promise((n,i)=>{let s=$o(e,{agent:o,headers:{"x-unblock-data-format":"parsed"},rejectUnauthorized:!1,signal:t.signal},a=>{let l=[],u=0;a.on("data",d=>{let c=Buffer.isBuffer(d)?d:Buffer.from(d);if(u+=c.length,u>zo){s.destroy(new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP response exceeded the maximum size"));return}l.push(c)}),a.on("end",()=>n({ok:(a.statusCode??500)>=200&&(a.statusCode??500)<300,status:a.statusCode??500,rawText:Buffer.concat(l).toString("utf8"),providerRequestId:typeof a.headers["x-response-id"]=="string"?a.headers["x-response-id"]:typeof a.headers["x-request-id"]=="string"?a.headers["x-request-id"]:null}))});s.on("error",()=>i(new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 native SERP request failed"))),s.end()})}finally{o.destroy()}}function Or(e){let t=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_USERNAME?.trim(),r=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PASSWORD?.trim();if(t||r){if(!t||!r)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP requires both \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_USERNAME and \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PASSWORD");if(/[\u0000-\u001f\u007f]/.test(t+r))throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP native credentials contain invalid control characters");return{method:"native",username:t,password:r}}let o=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_API_KEY?.trim(),n=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_ZONE?.trim();if(!o||!n)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP requires \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_API_KEY and \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_ZONE, or complete native SERP proxy credentials; \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_API_KEY is not used for SERP");if(/\s|[\u0000-\u001f\u007f]/.test(o)||!/^[a-zA-Z0-9_-]+$/.test(n))throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API key or zone has an invalid format");return{method:"rest",apiKey:o,zone:n}}function Ze(e=process.env){try{return Or(e),!0}catch{return!1}}function f(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)?e:null}function $(e){return Array.isArray(e)?e:[]}function _t(e){return typeof e=="string"&&e.trim()?e.trim():null}function N(e){return typeof e=="number"&&Number.isFinite(e)?e:typeof e=="string"&&e.trim()&&Number.isFinite(Number(e))?Number(e):null}function y(e,t){for(let r of t){let o=_t(e[r]);if(o)return o}return null}function ce(e){try{return new URL(e).hostname.replace(/^www\./,"")}catch{return""}}function Tr(e){return{rawUrl:e,resolvedUrl:e,linkType:"plain",resolutionStatus:"not_needed"}}function Vo(e){let t=e;if(typeof t=="string")try{t=JSON.parse(t)}catch{throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API returned invalid JSON")}let r=f(t);if(!r)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API returned an invalid payload");if(typeof r.body=="string")try{let n=JSON.parse(r.body);if(f(n))return f(n)}catch{}let o=f(r.body);return o?f(o.result)??f(o.data)??o:f(r.result)??f(r.data)??r}function pe(e,t){for(let o of t){let n=$(e[o]);if(n.length)return n}let r=f(e.results);if(r)for(let o of t){let n=$(r[o]);if(n.length)return n}return[]}function de(e,t){let r=[e,f(e.results)].filter(o=>!!o);for(let o of r)for(let n of t)if(Object.prototype.hasOwnProperty.call(o,n))return{observed:!0,rawShapeValid:Array.isArray(o[n]),rawCount:$(o[n]).length};return{observed:!1,rawShapeValid:!1,rawCount:0}}function gt(e,t){let r=[e,f(e.results)].filter(o=>!!o);for(let o of r)for(let n of t){if(!Object.prototype.hasOwnProperty.call(o,n))continue;let i=f(o[n]);return{observed:!0,rawShapeValid:i!==null,rawCount:i&&Object.keys(i).length>0?1:0}}return{observed:!1,rawShapeValid:!1,rawCount:0}}function wr(e){return pe(e,["organic","organic_results","organicResults"]).flatMap((t,r)=>{let o=f(t);if(!o)return[];let n=y(o,["link","url","href"]),i=y(o,["title","name"]);if(!n||!i)return[];let s=f(o.rating)??f(o.inline_rating);return[{position:Math.max(1,Math.trunc(N(o.global_rank)??N(o.rank)??N(o.position)??r+1)),title:i,url:n,...Tr(n),domain:ce(n),cite:y(o,["display_link","displayLink","cite"]),snippet:y(o,["description","snippet","text"]),isRedditStyle:ce(n)==="reddit.com",inlineRating:s?{value:String(s.value??s.rating??""),count:String(s.count??s.reviews??"")}:null}]}).sort((t,r)=>t.position-r.position)}function Sr(e){return pe(e,["snack_pack","local","local_results","local_pack","localPack"]).flatMap((t,r)=>{let o=f(t);if(!o)return[];let n=y(o,["title","name"]);if(!n)return[];let i=$(o.extensions??o.metadata).map(_t).filter(s=>!!s);return[{position:Math.max(1,Math.trunc(N(o.global_rank)??N(o.rank)??N(o.position)??r+1)),name:n,cid:y(o,["cid"]),rating:y(o,["rating"])??(N(o.rating)!=null?String(N(o.rating)):null),reviewCount:y(o,["reviews_cnt","reviews","review_count","reviewCount"])??(N(o.reviews_cnt)!=null?String(N(o.reviews_cnt)):N(o.reviews)!=null?String(N(o.reviews)):null),metadata:i,websiteUrl:y(o,["website","website_url","link"]),directionsUrl:y(o,["directions","directions_url"])}]})}function Cr(e){let t=f(e);return $(t?.citations??t?.sources??t?.references).flatMap(r=>{let o=f(r);if(!o)return[];let n=y(o,["link","url","href"]);return n?[{text:y(o,["title","text","name"])??ce(n),href:n,...Tr(n)}]:[]})}function Ye(e,t=0){if(t>4)return[];if(Array.isArray(e))return e.flatMap(i=>Ye(i,t+1));let r=f(e);if(!r)return[];let o=y(r,["snippet","text","answer"]),n=Ye(r.texts??r.list??r.items,t+1);return[...o?[o]:[],...n]}function Ar(e,t){if(!t)return{detected:!1,text:null,citations:[]};let r=f(e.ai_overview)??f(e.aiOverview)??f(e.overview);if(!r)return{detected:!1,text:null,citations:[]};let o=y(r,["text","answer","description"])??(Ye(r.texts).join(`
52
-
53
- `).slice(0,5e4)||null),n=Cr(r);return{detected:!!(o||n.length),text:o,citations:n}}function Ir(e,t){if(!t)return{detected:!1,text:null,citations:[]};let r=f(e.ai_mode)??f(e.aiMode);if(!r)return{detected:!1,text:null,citations:[]};let o=y(r,["text","answer","description"])??(Ye(r.texts).join(`
54
-
55
- `).slice(0,5e4)||null),n=Cr(r);return{detected:!!(o||n.length),text:o,citations:n}}function Rr(e,t){return t?[...pe(e,["videos","video_results"]),...pe(e,["short_videos","shorts"])].flatMap(r=>{let o=f(r);if(!o)return[];let n=y(o,["link","url"]),i=y(o,["title","name"]);return!n||!i?[]:[{type:"video",title:i,channel:y(o,["channel","source"])??"",platform:ce(n),duration:y(o,["duration"])??"",url:n}]}):[]}function Nr(e,t){if(!t)return[];let r=f(e.forums);return[...pe(e,["discussions","forums","forum_results"]),...$(r?.items)].flatMap(o=>{let n=f(o);if(!n)return[];let i=y(n,["link","url"]),s=y(n,["title","name"]);return!i||!s?[]:[{title:s,source:y(n,["source"])??ce(i),url:i}]})}function xr(e,t){return t?pe(e,["what_people_are_saying","whatPeopleSaying"]).flatMap(r=>{let o=f(r);if(!o)return[];let n=y(o,["link","url"]),i=y(o,["title","name"]);if(!n||!i)return[];let s=y(o,["platform","source"])??ce(n),a=s.toLowerCase();return[{type:a.includes("reddit")?"reddit":a.includes("facebook")?"facebook":a.includes("instagram")?"instagram":a.includes("tiktok")?"tiktok":a.includes("youtube")?"youtube":a.includes("news")?"news":"unknown",title:i,url:n,source:s,platform:s,popularComment:y(o,["comment","popular_comment"]),engagement:y(o,["engagement"])??"",date:y(o,["date"])??"",duration:y(o,["duration"]),authorNote:y(o,["author_note"])}]}):[]}var Xo={featuredSnippets:["featured_snippets","featured_snippet","featuredSnippet"],knowledgePanel:["knowledge","knowledge_graph","knowledgeGraph"],topStories:["top_stories","topStories"],news:["news","news_results"],images:["images","image_results"],shopping:["shopping","shopping_results"],relatedSearches:["related","related_searches","relatedSearches"],recipes:["recipes","recipe_results"],jobs:["jobs","job_results"],topAds:["top_ads"],bottomAds:["bottom_ads"],topProducts:["top_pla"],bottomProducts:["bottom_pla"],jackpotProducts:["jackpot_pla"],shortVideos:["short_videos","shorts"],localMap:["snack_pack_map"],flights:["flights"],hotels:["hotels_selection"],popularProducts:["popular_products"],weather:["weather"],currencyExchange:["currency_exchange"],latestPosts:["latest_posts"],perspectives:["perspectives"],navigation:["navigation"],chips:["chips"],spelling:["spelling"]};function Xe(e,t){for(let r of[e,f(e.results)])if(r){for(let o of t)if(Object.prototype.hasOwnProperty.call(r,o))return{observed:!0,value:r[o]}}return{observed:!1,value:null}}function Qe(e,t,r){return e?t==null||Array.isArray(t)&&t.length===0?"observed_absent":Array.isArray(t)?r>0?"observed_present":"incomplete":f(t)?r>0?"observed_present":Object.keys(f(t)).length===0?"observed_absent":"incomplete":"incomplete":"unknown"}function Qo(e,t){let r={},o=[["localPack",["snack_pack","local","local_results","local_pack","localPack"],t.localPack],["forums",["discussions","forums","forum_results"],t.forums],["videos",["videos","video_results","short_videos","shorts"],t.videos],["aiOverview",["ai_overview","aiOverview","overview"],t.aiOverview],["whatPeopleSaying",["what_people_are_saying","whatPeopleSaying"],t.whatPeopleSaying],["entityIds",["knowledge","knowledge_graph","knowledgeGraph"],t.entityIds]];for(let[l,u,d]of o){let c=Xe(e,u);r[l]=Qe(c.observed,c.value,d)}let n=Xe(e,["ai_mode","aiMode"]);r.aiMode=Qe(n.observed,n.value,t.aiMode);let i=Xe(e,["people_also_ask","peopleAlsoAsk","related_questions","paa"]),s=$(i.value).slice(0,30).flatMap(l=>{let u=f(l);if(!u)return[];let d=y(u,["question","title"]);return d?[{question:d.slice(0,1e3),answer:y(u,["answer","snippet","text"])?.slice(0,1e4)??null,url:y(u,["link","url"])??null}]:[]});r.paaPreview=Qe(i.observed,i.value,s.length);let a=[];for(let[l,u]of Object.entries(Xo)){let d=Xe(e,u);if(!d.observed)continue;let c=f(d.value),h=(Array.isArray(d.value)?d.value:c&&(Array.isArray(c.items)||Array.isArray(c.posts))?[...$(c.items),...$(c.posts)]:[d.value]).slice(0,20).flatMap(_=>{let E=f(_);if(!E)return[];let x=y(E,["title","name","heading"]),L=y(E,["link","url","website"]),J=y(E,["description","snippet","text","summary","story"]);return!x&&!L&&!J?[]:[{title:x?.slice(0,1e3)??null,url:L,description:J?.slice(0,1e4)??null,position:N(E.global_rank)??N(E.rank)??N(E.position)??null}]});r[l]=Qe(d.observed,d.value,h.length);let v=Object.fromEntries(Object.entries(c??{}).slice(0,30).flatMap(([_,E])=>/^[a-zA-Z0-9_]{1,80}$/.test(_)&&(E===null||["string","number","boolean"].includes(typeof E))?[[_,typeof E=="string"?E.slice(0,2e3):E]]:[]));a.push({name:l,attributes:v,items:h})}return{status:r,paaPreview:s,additional:a}}function kr(e,t){let r=new Set,o=new Set(t.map(s=>s.cid).filter(s=>!!s)),n=new Set,i=(s,a=0)=>{if(a>6||s==null)return;if(Array.isArray(s)){for(let u of s)i(u,a+1);return}let l=f(s);if(l)for(let[u,d]of Object.entries(l)){let c=u.toLowerCase().replace(/[^a-z]/g,""),p=_t(d);p&&(c==="kgid"||c==="kgmid"||c==="mid")?r.add(p):p&&c==="cid"?o.add(p):p&&c==="gcid"?n.add(p):typeof d=="object"&&i(d,a+1)}};return i(e),{entities:[],kgIds:[...r],cids:[...o],gcids:[...n]}}function Dr(e,t){let r=e instanceof Error?e.message:String(e);return t.aborted||/timeout|timed out/i.test(r)?"timeout":/captcha|recaptcha|unusual traffic|google\.com\/sorry|blocked/i.test(r)?"captcha":/invalid (?:json|payload)/i.test(r)?"invalid_payload":"provider_error"}function Pr(e){return e==="invalid_payload"?"invalid_payload":e==="captcha"?"serp_readiness":e==="timeout"||e==="provider_error"?"provider_transport":"pagination"}async function ft(e,t=process.env,r=fetch,o=Ko,n){if(e.pages!==1)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP supports one page only; use Apify for two pages");let i=Or(t),s=i.method==="native",a=Date.now(),l=Zt(),u=null,d=e.location?Qt(e.location):null;if(e.location&&!d?.canonical)throw new ae("query_integrity","location_unresolved",`SERP location could not be resolved without changing the query (candidates: ${d?.ambiguousCandidates??0})`);let c=d?.canonical?Xt(d.canonical):null,p=AbortSignal.timeout(e.includeAllSerpFeatures?33e3:Go),h=e.signal?AbortSignal.any([e.signal,p]):p,v=1,_=[],E=[],x=0,L=async g=>{let P=Date.now(),R=s?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_native_proxy":"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_rest",C=null,G=null,fe=!1,ye=!1,ee=null,be=null;if(l?.operationRunId&&(g===1||u))try{C=await ne({runId:l.operationRunId,attemptNumber:n?n.attemptNumber+g-1:g,method:R,provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",...g===2?{parentAttemptId:u,edgeKind:"next_phase"}:n?{parentAttemptId:n.parentAttemptId,edgeKind:"provider_fallback",retryKind:"provider_fallback"}:{},normalizedFlags:{page:g,device:e.device,hasLocation:!!e.location}}),g===1&&(u=C),G=(await K({attemptId:C,provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_api",accountScope:l.operationAccountScope??"production-default",method:R,providerStatus:"started"})).id}catch(A){throw console.warn(JSON.stringify({event:"direct_serp_telemetry_start_failed",page:g,message:A instanceof Error?A.message:String(A)})),A}let k=new URLSearchParams({q:e.query,gl:e.gl,hl:e.hl,pws:"0",num:"10",...g===2?{start:"10"}:{}}),Le=Ut(e.recency);Le&&k.set("tbs",Le),e.device==="mobile"&&k.set("brd_mobile","1"),(e.includeAiOverview||e.includeAllSerpFeatures)&&k.set("brd_ai_overview","2"),c&&k.set("uule",c),s&&k.set("brd_json","1"),x+=1;let H;try{if(i.method==="native"){let D=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_HOST?.trim()||Bo,he=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PORT?.trim()||Wo;H=await o(`https://www.google.com/search?${k}`,{username:i.username,password:i.password,host:D,port:he,signal:h})}else{let D=await r(Jo,{method:"POST",headers:{Authorization:`Bearer ${i.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({zone:i.zone,url:`https://www.google.com/search?${k}`,format:"json",data_format:"parsed"}),signal:h});H={ok:D.ok,status:D.status,rawText:await D.text(),providerRequestId:D.headers.get("x-response-id")??D.headers.get("x-request-id")}}if(be=`http_${H.status}`,G&&H.providerRequestId&&await V(G,H.providerRequestId),!H.ok)throw new Error(`\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API failed with HTTP ${H.status}`);fe=!0;let A;try{A=Vo(JSON.parse(H.rawText))}catch(D){let he=D instanceof Error&&D.message!=="Unexpected end of JSON input"?D.message:"\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API returned invalid JSON";throw new ae("invalid_payload","invalid_provider_payload",he)}let w=wr(A);return _.push({page:g,attempted:!0,captured:w.length>0,resultCount:w.length,requestOffset:g===2?10:0,providerRequestIdObserved:!!H.providerRequestId,...w.length===0?{failureCode:"empty_page"}:{}}),ye=!0,A}catch(A){ee=A;let w=Dr(A,h);if(_.some(he=>he.page===g)||_.push({page:g,attempted:!0,captured:!1,resultCount:0,requestOffset:g===2?10:0,providerRequestIdObserved:!1,failureCode:w}),g===2)throw A;let D=A instanceof ae?A.stage:Pr(w);throw A instanceof ae?A:new ae(D,w,A instanceof Error?A.message:String(A))}finally{let A=null;if(G&&fe)try{let w=vr(t);await X({receiptId:G,costState:"measured",units:1,unitType:"request",amountUsdNanos:Ve(w,1),rateSource:w.source,providerProduct:w.providerProduct,billingTier:w.billingTier,billableEvent:w.billableEvent,measurementSource:"provider_http_delivery",rateNumerator:w.numeratorUsdNanos,rateDenominator:w.denominatorUnits,ratePolicyVersion:w.policyVersion,rateEffectiveAt:w.effectiveAt,providerStatus:be??"delivered",providerDurationMs:Date.now()-P})}catch(w){console.warn(JSON.stringify({event:"direct_serp_receipt_finalize_failed",page:g,message:w instanceof Error?w.message:String(w)})),A=w}if(C&&await se({attemptId:C,status:ye?"succeeded":h.aborted?"timed_out":"failed",errorCode:ee?Dr(ee,h):null,durationMs:Date.now()-P}).catch(w=>console.warn(JSON.stringify({event:"direct_serp_attempt_finish_failed",page:g,message:w instanceof Error?w.message:String(w)}))),A)throw A}};try{E.push({page:1,payload:await L(1)})}catch(g){throw g}let J=null;if(v===2)try{E.push({page:2,payload:await L(2)})}catch(g){J=g}let st=Date.now()-a,Te=Date.now(),I=E[0].payload,Ce=E.flatMap(({page:g,payload:P})=>wr(P).map(R=>({...R,position:g===2&&R.position<=10?R.position+10:R.position,sourcePage:g}))).filter((g,P,R)=>R.findIndex(C=>ct(C.url)===ct(g.url))===P),je=e.includeLocalPack||e.includeAllSerpFeatures,W=je?Sr(I):[],_e=de(I,["snack_pack","local","local_results","local_pack","localPack"]),Do=ue({requested:je,moduleObserved:_e.observed,rawCount:_e.rawCount,mappedCount:W.length,rawShapeValid:_e.rawShapeValid}),kt=e.includeAiOverview||e.includeAllSerpFeatures,Dt=Ar(I,kt),Pt=e.includeForums||e.includeAllSerpFeatures,Ot=Nr(I,Pt),Tt=e.includeVideos||e.includeAllSerpFeatures,Ct=Rr(I,Tt),jt=e.includeWhatPeopleSaying||e.includeAllSerpFeatures,qt=xr(I,jt),it=f(I.forums),at=it&&Array.isArray(it.items)?{observed:!0,rawCount:it.items.length,rawShapeValid:!0}:de(I,["discussions","forums","forum_results"]),lt=de(I,["videos","video_results","short_videos","shorts"]),Mt={localPack:Do,forums:ue({requested:Pt,moduleObserved:at.observed,rawCount:at.rawCount,mappedCount:Ot.length,rawShapeValid:at.rawShapeValid}),videos:ue({requested:Tt,moduleObserved:lt.observed,rawCount:lt.rawCount,mappedCount:Ct.length,rawShapeValid:lt.rawShapeValid}),aiOverview:ue({requested:kt,moduleObserved:gt(I,["ai_overview","aiOverview","overview"]).observed,rawCount:gt(I,["ai_overview","aiOverview","overview"]).rawCount,mappedCount:Dt.detected?1:0,rawShapeValid:gt(I,["ai_overview","aiOverview","overview"]).rawShapeValid}),whatPeopleSaying:ue({requested:jt,moduleObserved:de(I,["what_people_are_saying","whatPeopleSaying"]).observed,rawCount:de(I,["what_people_are_saying","whatPeopleSaying"]).rawCount,mappedCount:qt.length,rawShapeValid:de(I,["what_people_are_saying","whatPeopleSaying"]).rawShapeValid})},Po=le(1,_),Oo=_.find(g=>g.page===1)?.resultCount??0,qe=_.find(g=>g.page===2)?.resultCount??0,To=We({query:e.query,finalQuery:e.query,canonicalLocation:d?.canonical??null,locationResolutionSource:d?.source??"not_requested",locationAmbiguousCandidates:d?.ambiguousCandidates??0,uule:c,outboundProviderMethod:s?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_native_proxy":"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_rest"}),Me=J?Pr(_.find(g=>g.page===2)?.failureCode??"provider_error"):Object.values(Mt).some(g=>g==="incomplete"||g==="unknown")?"optional_feature_parsing":null,Co={pagination:{...Po,providerRequestCount:x},features:Mt,queryIntegrity:To,failureStage:Me},Lt=e.includeAllSerpFeatures?(()=>{let g=E.map(({page:P,payload:R})=>{let C=Sr(R),G=Nr(R,!0),fe=Rr(R,!0),ye=xr(R,!0),ee=Ar(R,!0),be=Ir(R,!0),k=kr(R,C),Le=Qo(R,{localPack:C.length,forums:G.length,videos:fe.length,aiOverview:ee.detected?1:0,aiMode:be.detected?1:0,whatPeopleSaying:ye.length,entityIds:k.entities.length+k.kgIds.length+k.cids.length+k.gcids.length});return{page:P,...Le,localPack:C,forums:G,videos:fe,whatPeopleSaying:ye,aiOverview:ee,aiMode:be,entityIds:k}});return{status:g[0].status,paaPreview:g.flatMap(P=>P.paaPreview),additional:g.flatMap(P=>P.additional),pages:g}})():void 0,jo=new Date().toISOString(),Ht=Date.now()-a;return{seed:e.query,location:e.location??null,extractedAt:jo,diagnostics:{phaseTimings:{providerConnectMs:st,serpParseMs:Date.now()-Te,totalServerMs:Ht},pagination:{requestedPages:v,capturedPages:v===2&&qe>0?2:1,page2Status:v===2?qe>0?"captured":"failed":"not_requested",page1OrganicCount:Oo,page2OrganicCount:qe,...v===2&&qe===0?{failureCode:_.find(g=>g.page===2)?.failureCode==="captcha"?"captcha":_.find(g=>g.page===2)?.failureCode==="timeout"?"timeout":"empty_page"}:{}},completionStatus:"serp_only",problem:null,resultQuality:Me?"partial":"complete",degradedResult:!!Me,degradationReasons:[],retryRecommended:!!Me,serpCompleteness:Co},totalQuestions:0,surface:"web",aiOverview:Dt,aiMode:Ir(I,e.includeAllSerpFeatures),...Lt?{fullSerpFeatures:Lt}:{},whatPeopleSaying:qt,tree:[],flat:[],videos:Ct,forums:Ot,organicResults:Ce,localPack:W,entityIds:kr(I,W),stats:{seed:e.query,totalQuestions:0,maxDepthReached:0,durationMs:Ht,errorCount:0}}}var Yo="scraperlink~google-search-results-serp-scraper",Ne="https://api.apify.com/v2";var q=class extends Error{constructor(r,o=null,n=!1,i=null){super(r);this.runId=o;this.retrySafe=n;this.terminalStatus=i;this.name="ApifyGoogleRunError"}runId;retrySafe;terminalStatus};function xe(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:null}function ke(e){return typeof e=="string"&&e.trim()?e.trim():null}function Zo(e){try{return["http:","https:"].includes(new URL(e).protocol)}catch{return!1}}function en(e){if(typeof e!="string")return e;try{return JSON.parse(e)}catch{throw new Error("Apify searchResults is not valid JSON")}}function jr(e,t){if(!Array.isArray(e)||e.length===0)throw new Error("Apify dataset contains no search results");let r=[];for(let[i,s]of e.entries()){let a=xe(s);if(!a)throw new Error("Apify dataset contains an invalid row");let l=en(a.searchResults??a),u=xe(l),d=Array.isArray(l)?l:Array.isArray(u?.results)?u.results:Array.isArray(u?.organicResults)?u.organicResults:Array.isArray(u?.organic)?u.organic:u&&(u.position!==void 0||u.title!==void 0)?[u]:null;if(!d)throw new Error("Apify dataset search result shape is unsupported");let c=Number(a.page_number??u?.page_number??i+1);if(!Number.isInteger(c)||c<1||c>t)throw new Error("Apify dataset has an unexpected page number");r.push(...d.map(p=>({row:p,page:c})))}let o=r.map(({row:i,page:s},a)=>{let l=xe(i),u=l?.position,d=ke(l?.title),c=ke(l?.url??l?.link);if(!l||!d||!c||!Zo(c)||u!==void 0&&(!Number.isInteger(u)||u<1))throw new Error(`Apify search result ${a+1} is missing a valid position, URL, or title`);let p=ke(l.description??l.snippet),h=typeof u=="number"?u:a%10+1;return{position:s>1&&h<=10?h+(s-1)*10:h,url:c,title:d,description:p}});if(o.length>t*10)throw new Error("Apify returned more results than requested");let n={page1:o.filter(i=>i.position<=10).length,page2:o.filter(i=>i.position>10).length};if(n.page1===0)throw new Error("Apify did not return the first result page");return{results:o,pageResultCounts:n}}async function et(e,t,r,o){let n=await r(e,{headers:{Authorization:`Bearer ${t}`},signal:o});if(!n.ok)throw new Error(`Apify API returned HTTP ${n.status}`);return n.json()}function yt(e){let t=xe(xe(e)?.data),r=ke(t?.id),o=ke(t?.status);if(!r||!o)throw new Error("Apify returned an invalid run receipt");return{id:r,status:o}}async function tn(e,t=fetch){let r=performance.now(),o=AbortSignal.timeout(9e4),n=e.signal?AbortSignal.any([e.signal,o]):o,i=e.runId,s=!1,a=null;try{if(!/^[A-Za-z0-9]+$/.test(i))throw new Error("Invalid Apify run ID");let l=yt(await et(`${Ne}/actor-runs/${i}?waitForFinish=30`,e.token,t,n));for(;["READY","RUNNING","TIMING-OUT","ABORTING"].includes(l.status);)l=yt(await et(`${Ne}/actor-runs/${i}?waitForFinish=30`,e.token,t,n));if(s=!0,a=l.status,l.status!=="SUCCEEDED")throw new Error(`Apify run ended with status ${l.status}`);let u=e.pages??1,d=await et(`${Ne}/actor-runs/${i}/dataset/items?format=json`,e.token,t,n);return{query:e.query,...jr(d,u),requestedPages:u,runId:i,elapsedMs:Math.round(performance.now()-r)}}catch(l){throw new q(l instanceof Error?l.message:String(l),i,s,a)}}async function qr(e,t,r=fetch){let o=performance.now(),n=e.query.trim(),i=e.pages??1;if(!n||n.includes(`
56
- `))throw new Error("Apify search requires one nonempty query");if(i!==1&&i!==2)throw new Error("Apify search supports one or two pages");let s=t.token.trim();if(!s)throw new Error("Apify API token is required");let a=t.maxChargeUsd??.01;if(!Number.isFinite(a)||a<=0)throw new Error("Invalid Apify charge cap");let l=AbortSignal.timeout(9e4),u=e.signal?AbortSignal.any([e.signal,l]):l,d=`${Ne}/actors/${Yo}/runs?maxTotalChargeUsd=${a}&restartOnError=false&waitForFinish=30`,c=null,p=!1,h=null;try{let v=await r(d,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({keyword:n,limit:i===2?"20":"10",page:1,proxy_location:"us",include_merged:!1}),signal:u});if(!v.ok)throw new Error(`Apify run start returned HTTP ${v.status}`);let _=yt(await v.json());if(c=_.id,p=!["READY","RUNNING","TIMING-OUT","ABORTING"].includes(_.status),p&&(h=_.status),_.status!=="SUCCEEDED"&&_.status!=="READY"&&_.status!=="RUNNING")throw new Error(`Apify run ended with status ${_.status}`);if(_.status==="SUCCEEDED"){let x=await et(`${Ne}/actor-runs/${c}/dataset/items?format=json`,s,r,u);return{query:n,...jr(x,i),requestedPages:i,runId:c,elapsedMs:Math.round(performance.now()-o)}}return{...await tn({runId:c,query:n,token:s,pages:i,signal:u},r),elapsedMs:Math.round(performance.now()-o)}}catch(v){throw v instanceof q?v:new q(v instanceof Error?v.message:String(v),c,p,h)}}var Mr="apify_google_serp",Lr="apify",rn="apify_google_serp_scraperlink";async function Hr(e,t,r,o){let n=Er();await X({receiptId:e,costState:"estimated",units:t,unitType:n.unitType,amountUsdNanos:Ve(n,t),rateSource:n.source,providerProduct:n.providerProduct,billingTier:n.billingTier,billableEvent:n.billableEvent,measurementSource:"actor_run_succeeded",rateNumerator:n.numeratorUsdNanos,rateDenominator:n.denominatorUnits,ratePolicyVersion:n.policyVersion,rateEffectiveAt:n.effectiveAt,providerStatus:o,providerDurationMs:r})}async function Fr(e){let t=performance.now(),r=await ne({runId:e.operationRunId,attemptNumber:e.attemptNumber,method:Mr,provider:Lr,parentAttemptId:e.parentAttemptId,edgeKind:e.edgeKind,retryKind:e.retryKind,normalizedFlags:{page:1,pages:e.options.pages??1,proxyLocation:"us"}}),o=await K({attemptId:r,provider:Lr,providerProduct:rn,billingTier:"store_pay_per_event",accountScope:e.accountScope,method:Mr,providerStatus:"before_actor_start"}),n=null,i=null;try{return n=await qr(e.options,{token:e.token},e.fetchImpl),await V(o.id,n.runId),await Hr(o.id,n.requestedPages,n.elapsedMs,"succeeded_estimated"),{...n,attemptId:r}}catch(s){throw i=s,n?Object.assign(new q("Apify cost tracking failed after run completion",n.runId),{attemptId:r}):(s instanceof q&&s.runId&&(await V(o.id,s.runId),s.terminalStatus==="SUCCEEDED"?await Hr(o.id,e.options.pages??1,Math.round(performance.now()-t),"succeeded_dataset_unavailable"):await gr({receiptId:o.id,units:e.options.pages??1,unitType:"page",providerStatus:"run_outcome_or_cost_pending"})),Object.assign(s instanceof Error?s:new Error(String(s)),{attemptId:r}))}finally{await se({attemptId:r,status:i?e.options.signal?.aborted?"timed_out":"failed":"succeeded",errorCode:i?"apify_search_failed":null,durationMs:Math.round(performance.now()-t)})}}function $r(e,t=e.requestedPages){let r=e.results.map(s=>{let a=new URL(s.url).hostname.replace(/^www\./,"");return{position:s.position,title:s.title,url:s.url,rawUrl:s.url,resolvedUrl:s.url,linkType:"plain",resolutionStatus:"not_needed",domain:a,cite:null,snippet:s.description,isRedditStyle:a==="reddit.com",inlineRating:null}}),o=t===2&&e.pageResultCounts.page2>0?2:1,n=t===2&&o===1,i=le(t,[{page:1,attempted:!0,captured:!0,resultCount:e.pageResultCounts.page1,requestOffset:0,providerRequestIdObserved:!0},...t===2?[{page:2,attempted:!0,captured:!n,resultCount:e.pageResultCounts.page2,requestOffset:10,providerRequestIdObserved:!0,...n?{failureCode:"empty_page"}:{}}]:[]]);return{seed:e.query,location:null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:{providerConnectMs:e.elapsedMs,totalServerMs:e.elapsedMs},pagination:{requestedPages:t,capturedPages:o,page2Status:t===2?n?"failed":"captured":"not_requested",page1OrganicCount:e.pageResultCounts.page1,page2OrganicCount:e.pageResultCounts.page2},completionStatus:"serp_only",problem:null,resultQuality:n?"partial":"complete",degradedResult:n,degradationReasons:n?["page_two_missing"]:[],retryRecommended:!1,serpCompleteness:{pagination:i,features:{localPack:"not_requested",forums:"not_requested",videos:"not_requested",aiOverview:"not_requested",whatPeopleSaying:"not_requested"},queryIntegrity:We({query:e.query,finalQuery:e.query,locationResolutionSource:"not_requested",outboundProviderMethod:"default_search"}),failureStage:null}},totalQuestions:0,surface:"web",aiOverview:{detected:!1,text:null,citations:[],shareUrl:null},aiMode:{detected:!1,text:null,citations:[]},whatPeopleSaying:[],tree:[],flat:[],videos:[],forums:[],organicResults:r,localPack:[],entityIds:{entities:[],kgIds:[],cids:[],gcids:[]},stats:{seed:e.query,totalQuestions:0,maxDepthReached:0,durationMs:e.elapsedMs,errorCount:0}}}var on=12e3;function Jr(e){return e.recency?er():e.mode==="full"&&e.pages===1?Ze():!!e.token||Ze()}async function bt(e){if(e.signal.throwIfAborted(),e.recency)return nn(e);if(e.mode==="full")return sn(e);if(!e.token)return Ur(e);let t=performance.now(),r;for(let o=1;o<=2;o++){let n=AbortSignal.any([e.signal,AbortSignal.timeout(on)]),i=e.pages;try{let s=await Fr({options:{query:e.query,pages:i,signal:n},token:e.token,operationRunId:e.operationRunId,accountScope:e.accountScope,attemptNumber:o,...r?{parentAttemptId:r,edgeKind:"same_method_retry",retryKind:"same_method"}:{}});console.info(JSON.stringify({event:"serp_provider_succeeded",provider:"apify",operationRunId:e.operationRunId,attemptNumber:o,durationMs:s.elapsedMs,resultCount:s.results.length,requestedPages:e.pages,providerRequestedPages:s.requestedPages,deliveredPages:s.pageResultCounts.page2>0?2:1,runId:s.runId}));let a=$r(s,e.pages);return a.stats.durationMs=Math.round(performance.now()-t),a.diagnostics.phaseTimings&&(a.diagnostics.phaseTimings.totalServerMs=a.stats.durationMs),{result:a,mode:"light",deliveryProvider:"apify",deliveredPages:s.pageResultCounts.page2>0?2:1}}catch(s){r=s&&typeof s=="object"&&"attemptId"in s?String(s.attemptId):void 0;let a=s instanceof q?s:null;if(console.warn(JSON.stringify({event:"serp_provider_failed",provider:"apify",operationRunId:e.operationRunId,attemptNumber:o,runId:a?.runId??null,requestedPages:e.pages,attemptPages:i,retrySafe:a?.retrySafe===!0,error:s instanceof Error?s.message:String(s)})),e.signal.aborted||!r||a?.retrySafe!==!0)throw s}}return Ur(e,r)}async function Ur(e,t){if(e.signal.throwIfAborted(),!Ze())throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API fallback is not configured; set \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_API_KEY and \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_ZONE, or the SERP proxy username and password");let r=performance.now(),o={query:e.query,gl:"us",hl:"en",device:"desktop",pages:1,includeAllSerpFeatures:!1,includeLocalPack:!1,includeForums:!1,includeVideos:!1,includeAiOverview:!1,includeWhatPeopleSaying:!1,signal:e.signal};console.info(JSON.stringify({event:"serp_provider_fallback",provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",operationRunId:e.operationRunId,attemptNumber:3,requestedPages:e.pages,providerRequestedPages:1}));try{let n=await ft(o,process.env,fetch,void 0,t?{attemptNumber:3,parentAttemptId:t}:void 0);if(n.organicResults.length===0)throw new Error("Search returned no organic results");if(e.pages===2){n.diagnostics.pagination={requestedPages:2,capturedPages:1,page2Status:"unavailable",page1OrganicCount:n.organicResults.length,page2OrganicCount:0},n.diagnostics.resultQuality="partial",n.diagnostics.degradedResult=!0,n.diagnostics.degradationReasons=[...new Set([...n.diagnostics.degradationReasons??[],"page_two_missing"])],n.diagnostics.retryRecommended=!1;let i=n.diagnostics;i.serpCompleteness&&(i.serpCompleteness.pagination=le(2,i.serpCompleteness.pagination.evidence.filter(s=>s.page===1)),i.serpCompleteness.failureStage="pagination")}return n.stats.durationMs=Math.round(performance.now()-r),n.diagnostics.phaseTimings&&(n.diagnostics.phaseTimings.totalServerMs=n.stats.durationMs),console.info(JSON.stringify({event:"serp_provider_succeeded",provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",operationRunId:e.operationRunId,attemptNumber:3,durationMs:n.stats.durationMs,resultCount:n.organicResults.length,requestedPages:e.pages,providerRequestedPages:1,deliveredPages:1,resultQuality:n.diagnostics.resultQuality})),{result:n,mode:"light",deliveryProvider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",deliveredPages:1}}catch(n){throw console.warn(JSON.stringify({event:"serp_provider_failed",provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",operationRunId:e.operationRunId,attemptNumber:3,error:n instanceof Error?n.message:String(n)})),n}}async function nn(e){let t=await He({...e.physicalFactory?{physicalExecution:await e.physicalFactory()}:{},query:e.query,gl:"us",hl:"en",device:"desktop",pages:e.pages,recency:e.recency,serpOnly:!0,forceManagedSerp:!0,maxAttempts:2,proxyMode:"none",maxQuestions:1,depth:1,headless:!0,format:"json",outputDir:"/tmp/paa-output-api",softDeadlineMs:Date.now()+23e4,signal:e.signal,onAttemptEvent:e.onAttemptEvent});if(t.organicResults.length===0)throw new Error("Search returned no organic results");let r=t.diagnostics.pagination?.capturedPages===2?2:1;if(e.pages===2&&r===1&&(t.diagnostics.resultQuality="partial",t.diagnostics.degradedResult=!0,t.diagnostics.degradationReasons=["page_two_missing"],t.diagnostics.retryRecommended=!0),e.mode==="full"){let o=Object.fromEntries(["localPack","forums","videos","aiOverview","aiMode","whatPeopleSaying","entityIds","paaPreview","topStories"].map(n=>[n,"unsupported"]));t.fullSerpFeatures={status:o,paaPreview:[],additional:[],pages:[]}}return{result:t,mode:e.mode==="full"?"full":"light",deliveryProvider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",deliveredPages:r}}async function sn(e){if(e.pages===2){let t=await bt({...e,mode:"light",pages:2}),r=Object.fromEntries(["localPack","forums","videos","aiOverview","aiMode","whatPeopleSaying","entityIds","paaPreview","topStories"].map(n=>[n,"unsupported"]));t.result.fullSerpFeatures={status:r,paaPreview:[],additional:[],pages:[]};let o=t.result.diagnostics;return o.serpCompleteness&&(o.serpCompleteness.features={localPack:"unsupported",forums:"unsupported",videos:"unsupported",aiOverview:"unsupported",whatPeopleSaying:"unsupported"}),{...t,mode:"full"}}return an({...e,mode:"full"})}async function an(e){let t=performance.now(),r=e.mode==="full",o={query:e.query,gl:"us",hl:"en",device:"desktop",pages:1,...e.recency?{recency:e.recency}:{},includeAllSerpFeatures:r,includeLocalPack:r,includeForums:r,includeVideos:r,includeAiOverview:r,includeWhatPeopleSaying:r,signal:e.signal},n=await ft(o);if(n.organicResults.length===0)throw new Error("Search returned no organic results");return n.stats.durationMs=Math.round(performance.now()-t),n.diagnostics.phaseTimings&&(n.diagnostics.phaseTimings.totalServerMs=n.stats.durationMs),{result:n,mode:r?"full":"light",deliveryProvider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",deliveredPages:n.diagnostics.pagination?.capturedPages===2?2:1}}import{randomUUID as so}from"crypto";var Gr="2026-10-10-operation-final-settlements.1";async function Br(e){let t=async()=>{let[r,o,n]=await Promise.all([e.execute("SELECT sql FROM sqlite_master WHERE name='operation_final_settlements'"),e.execute("PRAGMA index_info(operation_final_settlement_key)"),e.execute({sql:"SELECT 1 FROM schema_migrations WHERE version=?",args:[Gr]})]),i=String(r.rows[0]?.sql??"").replace(/\s+/g," ");return n.rows.length===1&&o.rows.map(s=>s.name).join(",")==="debit_key"&&i.includes("run_id TEXT NOT NULL REFERENCES operation_runs(id)")&&i.includes("user_id INTEGER NOT NULL CHECK (user_id > 0)")&&i.includes("final_amount_mc INTEGER NOT NULL CHECK (final_amount_mc >= 0)")&&i.includes("receipt_json TEXT NOT NULL CHECK (json_valid(receipt_json))")};if(!await t()){try{await e.batch([`CREATE TABLE IF NOT EXISTS operation_final_settlements (
57
- id TEXT NOT NULL PRIMARY KEY,
58
- run_id TEXT NOT NULL REFERENCES operation_runs(id),
59
- user_id INTEGER NOT NULL CHECK (user_id > 0),
60
- debit_key TEXT NOT NULL REFERENCES operation_debit_plans(debit_key),
61
- final_amount_mc INTEGER NOT NULL CHECK (final_amount_mc >= 0),
62
- refund_operation TEXT NOT NULL,source_surface TEXT NOT NULL,
63
- receipt_json TEXT NOT NULL CHECK (json_valid(receipt_json)),
64
- created_at TEXT NOT NULL DEFAULT (datetime('now'))
65
- )`,"CREATE UNIQUE INDEX IF NOT EXISTS operation_final_settlement_key ON operation_final_settlements(debit_key)",{sql:"INSERT OR IGNORE INTO schema_migrations(version) VALUES (?)",args:[Gr]}],"write")}catch(r){if(!await t().catch(()=>!1))throw r}if(!await t())throw Error("Final settlement schema is incomplete")}}var ln="(CAST(strftime('%s','now') AS INTEGER)*1000)";async function Wr(e){let{claim:t,gate:r}=e;if(ve({userId:t.userId,tool:r.tool,jobId:r.jobId},r),!Number.isSafeInteger(e.amountMc)||e.amountMc<0||!e.key||!e.refundOperation||!e.sourceSurface)throw Error("Invalid final settlement input");let o=b({key:e.key,amountMc:e.amountMc,refundOperation:e.refundOperation,sourceSurface:e.sourceSurface,material:e.material});if(Buffer.byteLength(o)>16*1024*1024)throw Error("Final settlement material exceeds budget");let n=m();await Br(n),await te({userId:t.userId,runId:t.runId});let i=$t(t.userId,r.jobId),s="settlement:"+O(`${t.runId}\0${e.key}`),a=`EXISTS(SELECT 1 FROM operation_runs r JOIN operation_executions x ON x.run_id=r.id
66
- WHERE r.id=? AND r.user_id=? AND r.tool=? AND r.job_id=? AND r.status=? AND x.claim_token=? AND x.phase=? AND x.expires_at_ms>${ln}) AND (${r.sql}) AND (${i.sql})`,l=[t.runId,t.userId,r.tool,r.jobId,e.recovery?"unknown":"running",t.token,e.recovery?"unknown":"effects_started",...r.args,...i.args];try{await n.execute({sql:`INSERT OR IGNORE INTO operation_final_settlements(id,run_id,user_id,debit_key,final_amount_mc,refund_operation,source_surface,receipt_json)
67
- SELECT ?,?,?,?,?,?,?,? WHERE (${a}) AND EXISTS(SELECT 1 FROM operation_debit_plans p JOIN billing_debits d ON d.idempotency_key=p.debit_key
68
- WHERE p.run_id=? AND p.debit_key=? AND p.refund_operation=? AND p.source_surface=? AND d.user_id=? AND d.status='applied' AND ?>=0 AND ?<=p.amount_mc)`,args:[s,t.runId,t.userId,e.key,e.amountMc,e.refundOperation,e.sourceSurface,o,...l,t.runId,e.key,e.refundOperation,e.sourceSurface,t.userId,e.amountMc,e.amountMc]})}catch{}let u=(await n.execute({sql:`SELECT s.* FROM operation_final_settlements s WHERE s.id=? AND s.run_id=? AND s.user_id=? AND (${a})`,args:[s,t.runId,t.userId,...l]})).rows[0];if(!u||u.receipt_json!==o)throw Error("final_settlement_plan_unknown_or_conflicting");return{...t,mode:e.recovery?"compensate":"execute",settlementPlanId:s}}function tt(e){return{...e,sql:`EXISTS(SELECT 1 FROM operation_final_settlements s JOIN billing_events b ON b.user_id=s.user_id
69
- WHERE s.run_id=? AND s.user_id=? AND s.debit_key=? AND b.billing_class='wallet_hold_settlement' AND b.status='settled'
70
- AND b.source_surface=s.source_surface AND b.amount_mc=s.final_amount_mc AND json_extract(b.metadata,'$.debitIdempotencyKey')=s.debit_key
71
- AND json_extract(b.metadata,'$.refundOperation')=s.refund_operation)`,args:[e.runId,e.userId,e.key]}}var zr="2026-10-10-outbound-delivery.1";async function rt(e){let t=async()=>{let r=(await e.execute("SELECT sql FROM sqlite_master WHERE name='outbound_deliveries'")).rows[0],o=(await e.execute({sql:"SELECT 1 FROM schema_migrations WHERE version=?",args:[zr]})).rows,n=String(r?.sql??"").replace(/\s+/g," "),i=(await e.execute("PRAGMA index_info(outbound_delivery_job)")).rows.map(s=>s.name).join(",");return o.length===1&&i==="job_id,user_id"&&n.includes("request_json TEXT NOT NULL CHECK (json_valid(request_json))")&&n.includes("expires_at_ms INTEGER NOT NULL")&&n.includes("'accepted','unknown','expired','unavailable'")};if(!await t()){try{await e.batch([`CREATE TABLE IF NOT EXISTS outbound_deliveries (
72
- id TEXT NOT NULL PRIMARY KEY,user_id INTEGER NOT NULL CHECK (user_id > 0),job_id TEXT NOT NULL,
73
- parent_run_id TEXT NOT NULL REFERENCES operation_runs(id),request_json TEXT NOT NULL CHECK (json_valid(request_json)),
74
- state TEXT NOT NULL CHECK (state IN ('requested','frozen','sending','accepted','unknown','expired','unavailable')),
75
- expires_at_ms INTEGER NOT NULL,payload_json TEXT CHECK (payload_json IS NULL OR json_valid(payload_json)),payload_sha256 TEXT,
76
- send_nonce TEXT,send_token TEXT,http_status INTEGER,receipt_json TEXT CHECK (receipt_json IS NULL OR json_valid(receipt_json)),
77
- created_at TEXT NOT NULL DEFAULT (datetime('now')),updated_at TEXT NOT NULL DEFAULT (datetime('now'))
78
- )`,"CREATE UNIQUE INDEX IF NOT EXISTS outbound_delivery_job ON outbound_deliveries(job_id,user_id)",{sql:"INSERT OR IGNORE INTO schema_migrations(version) VALUES (?)",args:[zr]}],"write")}catch(r){if(!await t().catch(()=>!1))throw r}if(!await t())throw Error("Delivery schema is incomplete")}}var Q=class extends Error{};var me="(CAST(strftime('%s','now') AS INTEGER)*1000)",De=e=>`delivery:${e}`,Y=e=>b(e);async function j(e,t){let r=m();await rt(r);let o=(await r.execute({sql:`SELECT *,${me} AS now_ms FROM outbound_deliveries WHERE id=? AND user_id=?`,args:[e,t]})).rows[0];if(!o)return null;let n=JSON.parse(String(o.request_json));if(n.id!==e||n.userId!==t||n.jobId!==o.job_id||n.parentRunId!==o.parent_run_id)throw Error("Delivery request conflicts");return{...n,state:String(o.state),expiresAtMs:Number(o.expires_at_ms),nowMs:Number(o.now_ms),payloadJson:o.payload_json==null?null:String(o.payload_json),payloadSha256:o.payload_sha256==null?null:String(o.payload_sha256),sendNonce:o.send_nonce==null?null:String(o.send_nonce),sendToken:o.send_token==null?null:String(o.send_token),httpStatus:o.http_status==null?null:Number(o.http_status),receiptJson:o.receipt_json==null?null:String(o.receipt_json)}}async function Kr(e,t,r){if(ve({userId:e.userId,tool:r.tool,jobId:e.jobId},r),!e.id||!e.url||!["paa-direct","paa-queue"].includes(e.profile)||!Number.isSafeInteger(e.userId)||e.userId<=0||t.runId!==e.parentRunId||t.userId!==e.userId||!/^[a-f0-9]{64}$/.test(e.fingerprint))throw Error("Invalid delivery request");let o=m();await rt(o);let n;try{await o.execute({sql:`INSERT OR IGNORE INTO outbound_deliveries(id,user_id,job_id,parent_run_id,request_json,state,expires_at_ms)
79
- SELECT ?,?,?,?,?,'requested',${me}+? WHERE (${r.sql}) AND EXISTS(SELECT 1 FROM operation_runs r JOIN operation_executions x ON x.run_id=r.id
80
- WHERE r.id=? AND r.user_id=? AND r.tool=? AND r.job_id=? AND r.status='running' AND x.phase='claimed' AND x.claim_token=? AND x.expires_at_ms>${me})`,args:[e.id,e.userId,e.jobId,e.parentRunId,Y(e),864e5,...r.args,t.runId,t.userId,r.tool,r.jobId,t.token]})}catch(s){n=s}let i=await j(e.id,e.userId);if(!i||Y(U(i))!==Y(e))throw n??Error("Delivery request receipt is unavailable or conflicting");return i}function U(e){return{id:e.id,userId:e.userId,jobId:e.jobId,parentRunId:e.parentRunId,url:e.url,profile:e.profile,fingerprint:e.fingerprint}}async function Vr(e,t,r){let o;try{o=b(t)}catch{throw new Q("Delivery payload cannot be serialized")}let n=O(o);if(Buffer.byteLength(o)>16777216)throw new Q("Delivery payload exceeds budget");ve({userId:e.userId,tool:r.tool,jobId:e.jobId},r);let i;try{await m().execute({sql:`UPDATE outbound_deliveries SET state='frozen',payload_json=?,payload_sha256=?,updated_at=datetime('now') WHERE id=? AND user_id=? AND request_json=? AND state='requested' AND expires_at_ms>${me} AND (${r.sql})`,args:[o,n,e.id,e.userId,Y(U(e)),...r.args]})}catch(a){i=a}let s=await j(e.id,e.userId);if(!s||s.payloadJson!==o||s.payloadSha256!==n)throw i??Error("Delivery payload receipt is unavailable or conflicting");return s}function Pe(e,t,r,o){return{userId:e.userId,tool:"paa_callback",jobId:e.jobId,sql:`(${t.sql}) AND EXISTS(SELECT 1 FROM outbound_deliveries d WHERE d.id=? AND d.user_id=? AND d.request_json=? AND d.state=? AND d.payload_json=? AND d.payload_sha256=? ${r==="accepted"?"":`AND d.expires_at_ms>${me}`} ${o?"AND d.send_nonce=?":""})`,args:[...t.args,e.id,e.userId,Y(U(e)),r,e.payloadJson,e.payloadSha256,...o?[o]:[]]}}async function Xr(e,t,r,o){let n=Pe(e,o,"frozen"),i=oe(t,{tool:n.tool,jobId:e.jobId}),s;try{await m().execute({sql:`UPDATE outbound_deliveries SET state='sending',send_nonce=?,send_token=?,updated_at=datetime('now') WHERE id=? AND user_id=? AND state='frozen' AND (${n.sql}) AND (${i.sql})`,args:[r,t.token,e.id,e.userId,...n.args,...i.args]})}catch(l){s=l}let a=await j(e.id,e.userId);if(!a||a.state!=="sending"||a.sendNonce!==r||a.sendToken!==t.token||a.payloadSha256!==e.payloadSha256)throw s??Error("Delivery send permission is unavailable");return a}async function Qr(e,t,r){let o=Pe(e,r,"sending",e.sendNonce),n=oe(t,{tool:o.tool,jobId:e.jobId});return(await m().execute({sql:`SELECT 1 WHERE (${o.sql}) AND (${n.sql})`,args:[...o.args,...n.args]})).rows.length===1}async function Yr(e,t){if(!e.sendNonce||!e.sendToken||!e.payloadSha256||t<200||t>=300)throw Error("Invalid endpoint acceptance");let r=b({deliveryId:e.id,idempotencyKey:e.id,payloadSha256:e.payloadSha256,httpStatus:t}),o=m(),n;try{await o.execute({sql:`UPDATE outbound_deliveries SET state='accepted',http_status=?,receipt_json=?,updated_at=datetime('now') WHERE id=? AND user_id=? AND state IN ('sending','unknown') AND send_nonce=? AND send_token=? AND payload_sha256=? AND request_json=?
81
- AND EXISTS(SELECT 1 FROM operation_runs WHERE id=? AND user_id=? AND tool='paa_callback' AND job_id=?)`,args:[t,r,e.id,e.userId,e.sendNonce,e.sendToken,e.payloadSha256,Y(U(e)),De(e.id),e.userId,e.jobId]})}catch(s){n=s}let i=await j(e.id,e.userId);if(!i||i.state!=="accepted"||i.receiptJson!==r)throw n??Error("Endpoint acceptance receipt is unavailable");return i}async function ht(e){await m().execute({sql:"UPDATE outbound_deliveries SET state='unknown',updated_at=datetime('now') WHERE id=? AND user_id=? AND request_json=? AND state='frozen' AND send_nonce IS NULL AND EXISTS(SELECT 1 FROM operation_executions x JOIN operation_runs o ON o.id=x.run_id WHERE o.id=? AND o.user_id=? AND o.tool='paa_callback' AND o.job_id=? AND x.phase IN ('effects_started','unknown'))",args:[e.id,e.userId,Y(U(e)),De(e.id),e.userId,e.jobId]})}async function Zr(e){await m().execute({sql:"UPDATE outbound_deliveries SET state='unknown',updated_at=datetime('now') WHERE id=? AND user_id=? AND state='sending' AND send_nonce=?",args:[e.id,e.userId,e.sendNonce]})}async function ot(e,t,r){await m().execute({sql:`UPDATE outbound_deliveries SET state=?,updated_at=datetime('now') WHERE id=? AND user_id=? AND state IN ('requested','frozen') AND send_nonce IS NULL ${t==="expired"?`AND expires_at_ms<=${me}`:""} ${r?`AND (${r.sql})`:""}`,args:[t,e.id,e.userId,...r?r.args:[]]})}async function M(e){let t=e.state==="sending"?"unknown":e.state;return await m().execute({sql:"UPDATE jobs SET options=json_set(options,'$.callbackDeliveryState',?,'$.callbackDeliveryId',?,'$.callbackDeliveryExpiresAtMs',?) WHERE id=? AND user_id=? AND callback_url=? AND json_extract(options,'$.callbackDeliveryProtocol')=1",args:[t,e.id,e.expiresAtMs,e.jobId,e.userId,e.url]}).catch(()=>{}),{state:t,deliveryId:e.id,expiresAtMs:e.expiresAtMs,...e.httpStatus?{httpStatus:e.httpStatus}:{}}}async function eo(e=25){let t=m();return await rt(t),(await t.execute({sql:"SELECT d.id,d.user_id,d.job_id FROM outbound_deliveries d JOIN jobs j ON j.id=d.job_id AND j.user_id=d.user_id WHERE (d.state IN ('requested','frozen') OR (d.state='accepted' AND EXISTS(SELECT 1 FROM operation_executions x WHERE x.run_id='delivery:'||d.id AND x.phase<>'published'))) AND j.status IN ('done','failed','cancelled') AND json_extract(j.options,'$.executionState')='finalized' ORDER BY d.created_at LIMIT ?",args:[Math.max(1,Math.min(100,Math.floor(e)))]})).rows.map(r=>({id:String(r.id),userId:Number(r.user_id),jobId:String(r.job_id)}))}function vt(e){if(!e.callback_url||e.options.callbackDeliveryProtocol!==1)return null;let t=e.options.executionProtocol===1&&e.options.directCompletionProtocol===1&&e.options.executionOwner==="direct",r=e.options.queueExecutionProtocol===1&&e.options.executionOwner==="cron";if(!t&&!r)throw Error("Callback parent profile is unavailable");return{id:`paa-callback:${e.id}`,userId:e.user_id,jobId:e.id,parentRunId:t?`paa-execution:${e.id}`:`harvest:${e.id}`,url:e.callback_url,profile:t?"paa-direct":"paa-queue",fingerprint:String(e.options.requestFingerprint)}}async function to(e,t,r){let o=vt(e);o&&await Kr(o,t,{...r,sql:`(${r.sql}) AND EXISTS(SELECT 1 FROM jobs WHERE id=? AND user_id=? AND callback_url=? AND json_extract(options,'$.callbackDeliveryProtocol')=1 AND json_extract(options,'$.requestFingerprint')=?)`,args:[...r.args,e.id,e.user_id,e.callback_url,o.fingerprint]})}function ro(e,t){let r=vt(e);return r?{...t,sql:`(${t.sql}) AND EXISTS(SELECT 1 FROM outbound_deliveries WHERE id=? AND user_id=? AND request_json=? AND state='requested')`,args:[...t.args,r.id,r.userId,b(r)]}:t}async function oo(e,t){let r=await S(e,t);if(!r?.callback_url)return{kind:"none"};let o=vt(r);if(!o)return{kind:"unavailable"};let n=await j(o.id,r.user_id);if(!n||b(U(n))!==b(o))return{kind:"unavailable"};if(!["done","failed","cancelled"].includes(r.status)||r.options.executionState!=="finalized"||r.options.holdState!=="settled"||!r.options.syncCapturedAt)return{kind:"pending",record:n};let i=await T(o.parentRunId,r.user_id,o.profile==="paa-direct"?"harvest_paa":"search_serp",r.id);if(!i||i.phase!=="published")return{kind:"pending",record:n};let s=o.profile==="paa-direct"?i.flags:i.flags.intent;if(!s||s.callbackUrl!==o.url||s.requestFingerprint!==o.fingerprint||s.userId!==r.user_id||s.jobId!==r.id||r.query!==s.options?.query||b(Object.fromEntries(Object.keys(s.options).map(p=>[p,r.options[p]])))!==b(s.options)||s.hold?.userId!==r.user_id||s.hold.key!==r.options.billingDebitKey||s.hold.amountMc!==r.options.billingHoldMc||r.status!==r.options.syncTerminalStatus||r.options.syncFinalAmountMc!==r.options.billingFinalAmountMc)return{kind:"unavailable"};if(r.options.syncRequiresPhysicalReceipt===1&&(await Ee(o.parentRunId,r.user_id)).length===0)return{kind:"pending",record:n};if(await te({runId:o.parentRunId,userId:r.user_id}))return{kind:"pending",record:n};let a=O(b({result:r.result,error:r.publicError,httpStatus:r.options.syncHttpStatus,requiresPhysical:r.options.syncRequiresPhysicalReceipt})),l={jobId:r.id,requestFingerprint:s.requestFingerprint,captureSha256:a,status:r.status},u=b({...l,amountMc:Number(r.options.syncFinalAmountMc),physicalOutcome:"terminated"}),d=tt({userId:r.user_id,jobId:r.id,tool:o.profile==="paa-direct"?"harvest_paa":"search_serp",runId:o.parentRunId,key:s.hold.key}),c={...d,sql:`(${d.sql}) AND EXISTS(SELECT 1 FROM jobs j JOIN operation_runs r ON r.job_id=j.id AND r.user_id=j.user_id JOIN operation_executions x ON x.run_id=r.id JOIN operation_final_settlements s ON s.run_id=r.id AND s.user_id=r.user_id
82
- WHERE j.id=? AND j.user_id=? AND r.id=? AND x.phase='published' AND r.status=x.result_status AND x.result_json=? AND j.status=?
83
- AND j.callback_url=? AND json_extract(j.options,'$.requestFingerprint')=? AND r.request_fingerprint=? AND j.query=json_extract(r.normalized_flags_json,?)
84
- AND NOT EXISTS(SELECT 1 FROM json_each(r.normalized_flags_json,?) v WHERE NOT EXISTS(SELECT 1 FROM json_each(j.options) actual WHERE actual.key=v.key AND actual.type=v.type AND actual.value IS v.value))
85
- AND json_extract(j.options,'$.callbackDeliveryProtocol')=1 AND json_extract(j.options,'$.executionState')='finalized' AND json_extract(j.options,'$.holdState')='settled'
86
- AND json_extract(j.options,'$.syncFinalAmountMc')=? AND json_extract(j.options,'$.billingFinalAmountMc')=? AND json_extract(j.options,'$.syncTerminalStatus')=? AND json(j.result) IS json(?) AND j.public_error_json IS ?
87
- AND s.debit_key=? AND s.final_amount_mc=? AND json_extract(s.receipt_json,'$.material.captureSha256')=?)`,args:[...d.args,r.id,r.user_id,o.parentRunId,u,r.status,o.url,o.fingerprint,i.fingerprint,o.profile==="paa-direct"?"$.options.query":"$.intent.options.query",o.profile==="paa-direct"?"$.options":"$.intent.options",Number(r.options.syncFinalAmountMc),Number(r.options.syncFinalAmountMc),r.status,r.result==null?null:b(r.result),r.publicError==null?null:JSON.stringify(r.publicError),s.hold.key,Number(r.options.syncFinalAmountMc),a]};return{kind:"ready",job:r,record:n,domain:c}}var Z=e=>`harvest:${e}`,io=e=>e.profile==="direct"?"executionProtocol":e.profile==="queue"?"queueExecutionProtocol":"syncExecutionProtocol";function ge(e,t="'running'"){let r=b(e.options),o=Object.keys(JSON.parse(r)).sort();if(o.some(n=>!/^[a-zA-Z][a-zA-Z0-9]*$/.test(n)))throw Error("Invalid synchronous option key");return{userId:e.userId,tool:e.tool,jobId:e.jobId,sql:`EXISTS(SELECT 1 FROM jobs j WHERE j.id=? AND j.user_id=? AND j.status IN (${t}) AND json_extract(j.options,'$.${io(e)}')=1 AND j.query=? AND j.callback_url IS ? ${e.profile==="direct"?"AND json_extract(j.options,'$.executionOwner')='direct' AND json_extract(j.options,'$.directCompletionProtocol')=1 AND json_extract(j.options,'$.paaLeaseToken')=? AND json_extract(j.options,'$.executionRunId')=?":e.profile==="queue"?"AND json_extract(j.options,'$.executionOwner')='cron'":""} AND json_extract(j.options,'$.requestFingerprint')=? AND json_extract(j.options,'$.billingHoldMc')=? ${o.map(()=>"AND json_extract(j.options,?) IS json_extract(?,?)").join(" ")})`,args:[e.jobId,e.userId,String(e.options.query),e.callbackUrl??null,...e.profile==="direct"?[e.recordToken,`paa-execution:${e.jobId}`]:[],e.requestFingerprint,e.hold.amountMc,...o.flatMap(n=>[`$.${n}`,r,`$.${n}`])]}}function wt(e){let t=JSON.parse(b(e));if(!t.jobId||!Number.isSafeInteger(t.userId)||t.userId<=0||!["harvest_paa","search_serp"].includes(t.tool)||!Number.isSafeInteger(t.deadlineAt)||!Number.isSafeInteger(t.hold.amountMc)||t.hold.amountMc<=0||t.hold.userId!==t.userId||t.hold.key!==(t.profile==="queue"?`serp-search:${t.jobId}:hold`:`harvest-sync:${t.jobId}:charge`)||!/^[a-f0-9]{64}$/.test(t.requestFingerprint)||!t.refundOperation||!t.sourceSurface)throw Error("Invalid synchronous funded intent");if(t.profile==="queue"&&(t.tool!=="search_serp"||t.options.serpOnly!==!0||t.deadlineAt!==0||!Number.isSafeInteger(t.budgetMs)||t.budgetMs<1e3||t.budgetMs>36e5||t.hold.operation!=="serp"||t.refundOperation!=="serp_refund"||t.sourceSurface!=="serp_search"||t.hold.description!==`SERP search: ${t.options.query}`.slice(0,500)))throw Error("Invalid queued compatibility intent");return t}async function ao(e){let t=await T(Z(e.id),e.user_id,e.options.serpOnly===!0?"search_serp":"harvest_paa",e.id);if(!t||t.flags.syncExecutionProtocol!==1||!t.flags.intent)return null;let r=wt(t.flags.intent);if((r.profile==="queue"?e.options.queueExecutionProtocol:e.options.syncExecutionProtocol)!==1||r.jobId!==e.id||r.userId!==e.user_id||t.fingerprint!==r.requestFingerprint)throw Error("Synchronous intent receipt conflicts");return r}async function B(e,t="held"){return{status:503,headers:{"Retry-After":"2"},body:{job_id:e.id,status:"running",saved_status:e.status,...z({errorCode:"response_lost",retryable:!0,chargeStatus:t==="held"?"refund_pending":void 0,details:{retry_guidance:"Retry this exact request with the same idempotencyKey or read the returned job. Saved content and settlement resume without another acquisition."}}),executionState:"unknown",hold_state:t,status_tool:e.options.queueExecutionProtocol===1?"harvest_paa_status":e.options.serpOnly===!0?"search_serp":"harvest_paa_status",...e.result?{result:e.result}:{}}}}async function cn(e,t){await m().execute({sql:`UPDATE jobs SET options=json_set(options,'$.executionState','unknown','$.holdState',CASE WHEN json_extract(options,'$.billingSettledAt') IS NOT NULL THEN 'settled' ELSE 'held' END) WHERE id=? AND user_id=? AND json_extract(options,'$.${io(e)}')=1 AND EXISTS(SELECT 1 FROM operation_executions x WHERE x.run_id=? AND x.claim_token=?)`,args:[e.jobId,e.userId,t.runId,t.token]})}async function no(e,t,r,o,n,i=null,s=200,a=!0){if(!Number.isSafeInteger(o)||o<0||o>e.hold.amountMc)throw Error("Invalid captured synchronous charge");let l=r==null?null:b(r),u=i==null?null:JSON.stringify(i),d=ge(e),c;try{await m().execute({sql:`UPDATE jobs SET result=?,public_error_json=?,options=json_set(options,'$.syncCapturedAt',datetime('now'),'$.syncFinalAmountMc',?,'$.syncTerminalStatus',?,'$.syncHttpStatus',?,'$.syncRequiresPhysicalReceipt',?)
88
- WHERE id=? AND user_id=? AND json_extract(options,'$.syncCapturedAt') IS NULL AND (${d.sql})
89
- AND EXISTS(SELECT 1 FROM operation_runs r JOIN operation_executions x ON x.run_id=r.id WHERE r.id=? AND r.user_id=? AND x.claim_token=? AND x.phase IN ('effects_started','unknown') AND r.status IN ('running','unknown'))`,args:[l,u,o,n,s,a?1:0,e.jobId,e.userId,...d.args,t.runId,t.userId,t.token]})}catch(h){c=h}let p=await S(e.jobId,e.userId);if(!p?.options.syncCapturedAt||b({result:p.result})!==b({result:r==null?null:JSON.parse(l)})||p.options.syncFinalAmountMc!==o||p.options.syncTerminalStatus!==n||b({error:p.publicError})!==b({error:Wt(i)})||p.options.syncHttpStatus!==s||p.options.syncRequiresPhysicalReceipt!==(a?1:0))throw c??Error("synchronous_capture_receipt_unknown_or_conflicting");return p}async function nt(e,t){return{status:t?200:Number(e.options.syncHttpStatus??200),body:{job_id:e.id,status:e.status,...e.result?{result:e.result}:{},...e.publicError?{...e.publicError,error:e.publicError.message,...e.options.holdState==="settled"&&e.options.billingFinalAmountMc===0?{charge_status:"refunded"}:{}}:{},...t?{replayed:!0}:{}}}}async function Et(e,t,r,o=!1){let n=await S(e.jobId,e.userId);if(!n?.options.syncCapturedAt)throw Error("Synchronous capture is not known");if(n.options.syncRequiresPhysicalReceipt===1&&(await Ee(t.runId,t.userId)).length===0)throw Error("synchronous_physical_receipt_missing");if(await te({userId:e.userId,runId:t.runId}))throw Error("synchronous_physical_outcome_unknown");let i=Number(n.options.syncFinalAmountMc),s=String(n.options.syncTerminalStatus);if(!["done","failed","cancelled"].includes(s))throw Error("Invalid synchronous terminal receipt");let a={jobId:n.id,requestFingerprint:e.requestFingerprint,captureSha256:O(b({result:n.result,error:n.publicError,httpStatus:n.options.syncHttpStatus,requiresPhysical:n.options.syncRequiresPhysicalReceipt})),status:s},l=ge(e,"'running','done','failed','cancelled'"),u={...l,sql:`(${l.sql}) AND EXISTS(SELECT 1 FROM jobs WHERE id=? AND user_id=? AND json_extract(options,'$.syncCapturedAt') IS NOT NULL AND json_extract(options,'$.syncFinalAmountMc')=? AND json_extract(options,'$.syncTerminalStatus')=? AND json(result) IS json(?) AND public_error_json IS ? AND json_extract(options,'$.syncHttpStatus')=? AND json_extract(options,'$.syncRequiresPhysicalReceipt')=?)`,args:[...l.args,n.id,n.user_id,i,s,n.result==null?null:b(n.result),n.publicError==null?null:JSON.stringify(n.publicError),Number(n.options.syncHttpStatus),Number(n.options.syncRequiresPhysicalReceipt)]},d=await Wr({claim:t,recovery:r,gate:u,key:e.hold.key,amountMc:i,refundOperation:e.refundOperation,sourceSurface:e.sourceSurface,material:a});if((await dr(e.userId,e.hold.key,e.sourceSurface)??await lr(e.userId,e.hold.key,i,e.refundOperation,"Synchronous harvest settlement",e.sourceSurface,d)).final_amount_mc!==i)throw Error("Synchronous settlement receipt conflicts");let p=tt({userId:n.user_id,tool:e.tool,jobId:n.id,runId:t.runId,key:e.hold.key}),h=oe(t,{tool:e.tool,jobId:n.id,recovery:r}),v;try{await m().execute({sql:`UPDATE jobs SET status=?,completed_at=COALESCE(completed_at,datetime('now')),options=json_set(options,'$.executionState','finalized','$.holdState','settled','$.physicalOutcome','terminated','$.billingSettledAt',COALESCE(json_extract(options,'$.billingSettledAt'),datetime('now')),'$.billingFinalAmountMc',?${e.profile==="direct"?",'$.billedMc',?":""}) WHERE id=? AND user_id=? AND (${u.sql}) AND (${h.sql}) AND (${p.sql})`,args:[s,i,...e.profile==="direct"?[i]:[],n.id,n.user_id,...u.args,...h.args,...p.args]})}catch(L){v=L}let _=await S(n.id,n.user_id);if(!_||_.status!==s||_.options.billingFinalAmountMc!==i||_.options.holdState!=="settled"||b({result:_.result})!==b({result:n.result}))throw v??Error("synchronous_publication_receipt_unknown");let E={status:r?"unknown":s==="done"?"succeeded":s,json:b({...a,amountMc:i,physicalOutcome:"terminated"})};if(!(r?await Je(t,E,p):await Ue(t,E)))throw Error("Synchronous execution receipt publication unknown");return nt(_,o)}async function St(e){if(e.options.syncExecutionProtocol!==1&&e.options.queueExecutionProtocol!==1)return null;let t=await ao(e);if(!t)return e.options.queueExecutionProtocol===1||await Ge(Z(e.id),e.user_id)?B(e,"unconfirmed"):null;let r=await T(Z(e.id),e.user_id,t.tool,e.id);if(r?.phase==="published"&&e.options.holdState==="settled")return nt(e,!0);if(r?.phase==="claimed"&&r.expiresAtMs<=r.nowMs&&e.status==="running"&&!e.options.syncCapturedAt)return null;if(r?.phase==="claimed"||r?.phase==="effects_started"&&r.expiresAtMs>r.nowMs)return{status:409,headers:{"Retry-After":"2"},body:{job_id:e.id,error:"This request is already running under the supplied Idempotency-Key.",errorCode:"idempotency_in_progress",retryable:!0,...e.result?{result:e.result}:{}}};let o=await $e(Z(e.id),e.user_id);if(!o)return B(e);try{return await Et(t,o,!0,!0)}catch{return B(await S(e.id,e.user_id)??e,e.options.holdState==="settled"?"settled":"held")}}async function lo(e,t,r=!0){let o=await dt(t.userId,t.hold.key);if(!o||o.status!=="applied"){if(!r)throw Error("Original applied hold is unavailable");let n=await ar(t.userId,t.hold.amountMc,t.hold.operation,t.hold.description,t.hold.key);if(!n.ok)return{status:402,body:{job_id:t.jobId,error:"Insufficient balance",error_code:"insufficient_balance",balance_mc:n.balance_mc,required_mc:t.hold.amountMc}}}return await ur(e,{hold:t.hold,label:t.profile==="queue"?"original-queue-hold":"original-sync-hold",refundOperation:t.refundOperation,sourceSurface:t.sourceSurface,tool:t.tool,jobId:t.jobId}),null}async function uo(e,t,r){let o=wt(e),n,i=!1,s=!1,a=!1,l=await S(o.jobId,o.userId);try{let u=await ao(l);if(u){if(u.requestFingerprint!==o.requestFingerprint)throw Error("Synchronous request conflicts");o=u}else if(o.profile==="queue"||await Ge(Z(o.jobId),o.userId)||(await dt(o.userId,o.hold.key))?.status==="applied")return B(l,"unconfirmed");if(o.profile!=="queue"&&Date.now()>=o.deadlineAt)return B(l,"unconfirmed");let d=await Se({id:Z(o.jobId),userId:o.userId,ownerScope:`user:${o.userId}`,tool:o.tool,jobId:o.jobId,idempotencyKey:`job:${o.jobId}`,requestFingerprint:o.requestFingerprint,normalizedFlags:{syncExecutionProtocol:1,intent:o}},so(),Math.min(36e5,Math.max(1e3,(o.profile==="queue"?o.budgetMs:o.deadlineAt-Date.now())+3e4)),ge(o));if(d.kind!=="claimed")return B(l,"unconfirmed");n=d.claim;let c=await lo(n,o);if(c)return c;let p=ge(o),h=Fe(o.hold),v=await S(o.jobId,o.userId),_=ro(v,{...p,sql:`(${p.sql}) AND (${h.sql})`,args:[...p.args,...h.args]});if(!await Be(n,_))throw Error("Synchronous effect start unknown");if(i=!0,o.profile==="queue"){let Te=oe(n,{tool:o.tool,jobId:o.jobId}),I=ge(o),Ce;try{await m().execute({sql:`UPDATE jobs SET options=json_set(options,'$.compatDeadlineAt',CAST(strftime('%s','now') AS INTEGER)*1000+?) WHERE id=? AND user_id=? AND json_extract(options,'$.compatDeadlineAt') IS NULL AND (${I.sql}) AND (${Te.sql})`,args:[o.budgetMs,o.jobId,o.userId,...I.args,...Te.args]})}catch(_e){Ce=_e}let je=await S(o.jobId,o.userId),W=Number(je?.options.compatDeadlineAt);if(!Number.isSafeInteger(W)||W<=Date.now())throw Ce??Error("Queued deadline unavailable or expired");o={...o,deadlineAt:W}}let E=0,x=n,L={claim:n,deadlineAt:o.deadlineAt,physicalFactory:async()=>Ft({claim:x,gate:_,deadlineAt:o.deadlineAt,scope:`sync-browser-${++E}`,profile:"customer-funded"})},J=await t(L);a=!0,await no(o,n,J.result,J.amountMc,"done",null,200,o.options.serpOnly!==!0||E>0);let st=await Et(o,n,!1);return s=!0,st}catch(u){if(n&&i){if(!(await S(o.jobId,o.userId))?.options.syncCapturedAt&&!a){let c=await Ee(n.runId,n.userId).catch(()=>[]);if(c.length>0&&c.every(p=>p.state==="terminated"||p.state==="not_started")){let p=r(u);try{await no(o,n,null,0,p.terminalStatus==="cancelled"?"cancelled":"failed",p.publicError,p.httpStatus);let h=await Et(o,n,!1);return s=!0,h}catch{}}}await re(n).catch(()=>{}),await cn(o,n).catch(()=>{})}return B(await S(o.jobId,o.userId)??l)}finally{n&&!i&&await we(n).catch(()=>{}),n&&i&&!s&&await re(n).catch(()=>{})}}async function At(e,t=!0){let r=wt(e);if(r.profile!=="queue")throw Error("Queue profile required");let o=!1,n=Z(r.jobId),i=await S(r.jobId,r.userId),s=async()=>({kind:"unknown",reply:i?await B(i):{status:503,body:{job_id:r.jobId,status:"pending",executionState:"unknown",hold_state:o?"held":"unconfirmed",status_tool:"harvest_paa_status",...z({errorCode:"response_lost",retryable:!0})}}});if(i&&i.options.queueExecutionProtocol!==1)return s();let a=await T(n,r.userId,r.tool,r.jobId);if(a){if(a.flags.syncExecutionProtocol!==1||b({intent:a.flags.intent})!==b({intent:r}))return s();if(["effects_started","unknown","published"].includes(a.phase)){if(!i)return s();let d=await St(i);if(d&&d.status!==200)return{kind:"unknown",reply:d};let c=await S(r.jobId,r.userId);return c?{kind:"ready",job:c,replayed:!0}:s()}}else if(i||await Ge(n,r.userId))return s();let l={userId:r.userId,tool:r.tool,jobId:r.jobId,sql:"EXISTS(SELECT 1 FROM users WHERE id=? AND active=1)",args:[r.userId]},u;try{let d=await Se({id:n,userId:r.userId,ownerScope:`user:${r.userId}`,tool:r.tool,jobId:r.jobId,idempotencyKey:`job:${r.jobId}`,requestFingerprint:r.requestFingerprint,normalizedFlags:{syncExecutionProtocol:1,intent:r}},so(),45e3,l);if(d.kind!=="claimed")return s();u=d.claim;let c=await lo(u,r,t);if(c)return{kind:"unfunded",reply:c};if(o=!0,!i&&(await yr(r.jobId,r.userId,String(r.options.query),{...r.options,executionOwner:"cron",queueExecutionProtocol:1,...r.callbackUrl?{callbackDeliveryProtocol:1}:{},billingHoldMc:r.hold.amountMc,billingDebitKey:r.hold.key,requestFingerprint:r.requestFingerprint},r.callbackUrl??void 0)).kind==="unknown")return s();let p=ge(r,"'pending','running','done','failed','cancelled'"),h=(await m().execute({sql:`SELECT 1 WHERE (${p.sql})`,args:p.args})).rows.length>0,v=await S(r.jobId,r.userId);return h&&v&&await to(v,u,p),h&&v?{kind:"ready",job:v,replayed:!!(i||a)}:s()}catch{return s()}finally{u&&await we(u).catch(()=>{})}}function co(e){let t=JSON.parse(b(e.options)),r=t.serpOnly===!0&&!t.serpIdentity;return{profile:"queue",jobId:e.jobId,userId:e.userId,tool:"search_serp",requestFingerprint:e.requestFingerprint,options:t,callbackUrl:e.callbackUrl??null,deadlineAt:0,budgetMs:Jt(Number(t.maxQuestions??30),!0,t.mode,t.pages,!!t.recency,r).serverMs,hold:{userId:e.userId,key:`serp-search:${e.jobId}:hold`,amountMc:e.amountMc,operation:"serp",description:`SERP search: ${t.query}`.slice(0,500)},refundOperation:"serp_refund",sourceSurface:"serp_search"}}var Ai=e=>At(co(e));async function pn(e,t){let r;try{r=await T(`harvest:${t}`,e,"search_serp",t)}catch{return{kind:"unknown",reply:{status:503,body:{job_id:t,status:"pending",executionState:"unknown",hold_state:"unconfirmed",status_tool:"harvest_paa_status",...z({errorCode:"response_lost",retryable:!0})}}}}return r?.flags.syncExecutionProtocol!==1||r.flags.intent?.profile!=="queue"?null:At(r.flags.intent,!1)}async function po(){for(let t of await hr("search_serp",1,`json_extract(r.normalized_flags_json,'$.intent.profile')='queue' AND (EXISTS(SELECT 1 FROM (SELECT r.user_id AS user_id,json_extract(r.normalized_flags_json,'$.intent') AS normalized_flags_json) saved WHERE ${ir("saved.user_id","json_extract(saved.normalized_flags_json,'$.hold.key')")}))`))await S(t.jobId,t.userId)||await pn(t.userId,t.jobId);let e=(await m().execute(`SELECT j.id,j.user_id FROM jobs j JOIN operation_runs r ON r.id='harvest:'||j.id AND r.user_id=j.user_id JOIN operation_executions x ON x.run_id=r.id
90
- WHERE json_extract(j.options,'$.queueExecutionProtocol')=1 AND x.phase IN ('effects_started','unknown') AND x.expires_at_ms<=CAST(strftime('%s','now') AS INTEGER)*1000
91
- ORDER BY j.created_at LIMIT 1`)).rows[0];return e?S(String(e.id),Number(e.user_id)):void 0}async function mo(e,t){if(e.options.queueExecutionProtocol!==1)return await m().execute({sql:"UPDATE jobs SET options=json_set(options,'$.queueExecutionProtocol',0,'$.executionState','unknown','$.holdState','unconfirmed') WHERE id=? AND user_id=? AND json_extract(options,'$.queueExecutionProtocol') IS NULL",args:[e.id,e.user_id]}),{completed:!1,replayed:!1,reply:null};let r=await St(e);if(r)return{completed:(await S(e.id,e.user_id))?.options.executionState==="finalized"&&r.status===200,replayed:!0,reply:r};let o=e.options,n=Object.fromEntries(Object.entries(o).filter(([l])=>!["executionOwner","queueExecutionProtocol","billingHoldMc","billingDebitKey","requestFingerprint","compatDeadlineAt","executionState","holdState"].includes(l))),i=co({jobId:e.id,userId:e.user_id,options:n,requestFingerprint:String(o.requestFingerprint),amountMc:Number(o.billingHoldMc),callbackUrl:e.callback_url}),s=await uo(i,async l=>{let u={value:null},d=o.serpOnly===!0&&!o.serpIdentity,c=`harvest:${e.id}`,p=null,h=AbortSignal.timeout(Math.max(0,l.deadlineAt-Date.now()));if(d&&!Jr({pages:o.pages===2?2:1,recency:o.recency==="week"||o.recency==="month"?o.recency:void 0,mode:o.mode,token:t.apifyToken}))throw Error("Search providers are not configured");let v=await t.withCostContext({op:"serp",userId:e.user_id,headlessSentOut:u,operationRunId:c,operationAccountScope:"production-default"},async()=>d?bt({query:String(o.query??e.query),pages:o.pages===2?2:1,mode:o.mode,recency:o.recency==="week"||o.recency==="month"?o.recency:void 0,token:t.apifyToken,operationRunId:c,accountScope:"production-default",signal:h,onAttemptEvent:t.onAttemptEvent,physicalFactory:l.physicalFactory}).then(x=>(p=x,x.result)):He({...o,physicalExecution:await l.physicalFactory(),\u006b\u0065\u0072\u006e\u0065\u006cApiKey:t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,headless:!0,format:"json",outputDir:"/tmp/paa-output-api",signal:h,onAttemptEvent:t.onAttemptEvent}));if(d&&!p)throw Error("Search provider billing receipt is missing");let _=p,E=d?pr(_.deliveredPages,_.deliveryProvider):cr(u.value);return{result:v,amountMc:Math.min(Number(o.billingHoldMc),E)}},t.classifyFailure);return{completed:(await S(e.id,e.user_id))?.options.executionState==="finalized"&&!!(s.body.status&&["done","failed","cancelled"].includes(String(s.body.status))),replayed:!1,reply:s}}import{randomUUID as mn}from"crypto";function Oe(e){return e==null?null:Number(e)===1}function go(e){if(e==null)return null;try{return JSON.parse(String(e))}catch{return null}}function _o(e){return{id:String(e.id),job_id:String(e.job_id),user_id:Number(e.user_id),attempt_number:Number(e.attempt_number),max_attempts:Number(e.max_attempts),query:String(e.query),location:e.location!=null?String(e.location):null,max_questions:Number(e.max_questions),status:String(e.status),outcome:e.outcome!=null?String(e.outcome):null,\u006b\u0065\u0072\u006e\u0065\u006c_session_id:e.\u006b\u0065\u0072\u006e\u0065\u006c_session_id!=null?String(e.\u006b\u0065\u0072\u006e\u0065\u006c_session_id):null,question_count:e.question_count!=null?Number(e.question_count):null,duration_ms:e.duration_ms!=null?Number(e.duration_ms):null,error:e.error!=null?String(e.error):null,will_retry:Oe(e.will_retry),\u006b\u0065\u0072\u006e\u0065\u006c_delete_started:Number(e.\u006b\u0065\u0072\u006e\u0065\u006c_delete_started??0)===1,\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded:Oe(e.\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded),\u006b\u0065\u0072\u006e\u0065\u006c_delete_error:e.\u006b\u0065\u0072\u006e\u0065\u006c_delete_error!=null?String(e.\u006b\u0065\u0072\u006e\u0065\u006c_delete_error):null,browser_close_succeeded:Oe(e.browser_close_succeeded),browser_close_error:e.browser_close_error!=null?String(e.browser_close_error):null,browser_provider:e.browser_provider!=null?String(e.browser_provider):null,provider_session_id:e.provider_session_id!=null?String(e.provider_session_id):null,provider_session_observed_at:e.provider_session_observed_at!=null?String(e.provider_session_observed_at):null,provider_lookup_status:e.provider_lookup_status!=null?String(e.provider_lookup_status):null,provider_status:e.provider_status!=null?String(e.provider_status):null,provider_error_code:e.provider_error_code!=null?String(e.provider_error_code):null,provider_error_message:e.provider_error_message!=null?String(e.provider_error_message):null,provider_reason_source:e.provider_reason_source!=null?String(e.provider_reason_source):null,provider_duration_ms:e.provider_duration_ms!=null?Number(e.provider_duration_ms):null,provider_bandwidth_bytes:e.provider_bandwidth_bytes!=null?Number(e.provider_bandwidth_bytes):null,provider_captcha:Oe(e.provider_captcha),provider_checked_at:e.provider_checked_at!=null?String(e.provider_checked_at):null,provider_detail:go(e.provider_detail_json),provider_disconnect_observed:Oe(e.provider_disconnect_observed),provider_disconnect_message:e.provider_disconnect_message!=null?String(e.provider_disconnect_message):null,debug:go(e.debug_json),created_at:String(e.created_at),completed_at:e.completed_at!=null?String(e.completed_at):null}}async function fo(e){await m().execute({sql:`
92
- INSERT INTO harvest_attempts (
93
- id, job_id, user_id, attempt_number, max_attempts, query, location, max_questions, status, created_at
94
- )
95
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'running', ?)
96
- ON CONFLICT(job_id, attempt_number) DO NOTHING
97
- `,args:[mn(),e.jobId,e.userId,e.attemptNumber,e.maxAttempts,e.query,e.location,e.maxQuestions,e.startedAt]})}async function yo(e){return(await m().execute({sql:`
98
- UPDATE harvest_attempts SET
99
- browser_provider = ?,
100
- provider_session_id = ?,
101
- provider_session_observed_at = COALESCE(provider_session_observed_at, ?),
102
- provider_lookup_status = CASE
103
- WHEN provider_lookup_status = 'complete' THEN provider_lookup_status
104
- ELSE 'pending'
105
- END
106
- WHERE job_id = ? AND attempt_number = ? AND status = 'running'
107
- `,args:[e.browserProvider,e.providerSessionId,e.observedAt,e.jobId,e.attemptNumber]})).rowsAffected===1}async function bo(e){await m().execute({sql:`
108
- UPDATE harvest_attempts SET
109
- status = 'finished',
110
- outcome = ?,
111
- \u006b\u0065\u0072\u006e\u0065\u006c_session_id = ?,
112
- question_count = ?,
113
- duration_ms = ?,
114
- error = ?,
115
- will_retry = ?,
116
- \u006b\u0065\u0072\u006e\u0065\u006c_delete_started = ?,
117
- \u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded = ?,
118
- \u006b\u0065\u0072\u006e\u0065\u006c_delete_error = ?,
119
- browser_close_succeeded = ?,
120
- browser_close_error = ?,
121
- browser_provider = COALESCE(browser_provider, ?),
122
- provider_session_id = COALESCE(provider_session_id, ?),
123
- provider_lookup_status = CASE
124
- WHEN provider_lookup_status = 'complete' THEN provider_lookup_status
125
- ELSE COALESCE(?, provider_lookup_status)
126
- END,
127
- provider_status = COALESCE(provider_status, ?),
128
- provider_error_code = CASE
129
- WHEN provider_reason_source = 'provider_session_api' THEN provider_error_code
130
- ELSE COALESCE(?, provider_error_code)
131
- END,
132
- provider_error_message = CASE
133
- WHEN provider_reason_source = 'provider_session_api' THEN provider_error_message
134
- ELSE COALESCE(?, provider_error_message)
135
- END,
136
- provider_reason_source = CASE
137
- WHEN provider_reason_source = 'provider_session_api' THEN provider_reason_source
138
- ELSE COALESCE(?, provider_reason_source)
139
- END,
140
- provider_duration_ms = COALESCE(provider_duration_ms, ?),
141
- provider_bandwidth_bytes = COALESCE(provider_bandwidth_bytes, ?),
142
- provider_captcha = COALESCE(provider_captcha, ?),
143
- provider_checked_at = COALESCE(provider_checked_at, ?),
144
- provider_detail_json = COALESCE(provider_detail_json, ?),
145
- provider_disconnect_observed = COALESCE(provider_disconnect_observed, ?),
146
- provider_disconnect_message = COALESCE(provider_disconnect_message, ?),
147
- debug_json = ?,
148
- completed_at = ?
149
- WHERE job_id = ? AND attempt_number = ?
150
- `,args:[e.outcome,e.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,e.questionCount,e.durationMs,e.error,e.willRetry?1:0,e.\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted?1:0,e.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded==null?null:e.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded?1:0,e.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError,e.browserCloseSucceeded==null?null:e.browserCloseSucceeded?1:0,e.browserCloseError,e.browserProvider??null,e.providerSessionId??null,e.providerLookupStatus??null,e.providerStatus??null,e.providerErrorCode??null,e.providerErrorMessage??null,e.providerReasonSource??null,e.providerDurationMs??null,e.providerBandwidthBytes??null,e.providerCaptcha==null?null:e.providerCaptcha?1:0,e.providerCheckedAt??null,e.providerDetail==null?null:ho(e.providerDetail),e.providerDisconnectObserved==null?null:e.providerDisconnectObserved?1:0,e.providerDisconnectMessage??null,e.debug==null?null:JSON.stringify(e.debug),e.completedAt,e.jobId,e.attemptNumber]})}function ho(e,t=4096){let r=JSON.stringify(e);return r.length<=t?r:JSON.stringify({truncated:!0})}async function xi(e){return(await m().execute({sql:`
151
- UPDATE harvest_attempts SET
152
- provider_lookup_status = ?,
153
- provider_status = ?,
154
- provider_error_code = ?,
155
- provider_error_message = ?,
156
- provider_reason_source = ?,
157
- provider_duration_ms = ?,
158
- provider_bandwidth_bytes = ?,
159
- provider_captcha = ?,
160
- provider_checked_at = ?,
161
- provider_detail_json = ?
162
- WHERE id = ?
163
- AND job_id = ?
164
- AND user_id = ?
165
- AND browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
166
- AND provider_session_id = ?
167
- AND COALESCE(provider_lookup_status, '') <> 'complete'
168
- `,args:[e.lookupStatus,e.providerStatus??null,e.errorCode??null,e.errorMessage??null,e.reasonSource??null,e.durationMs??null,e.bandwidthBytes??null,e.captcha==null?null:e.captcha?1:0,e.checkedAt,e.detail==null?null:ho(e.detail),e.attemptId,e.jobId,e.userId,e.providerSessionId]})).rowsAffected===1}async function ki(e=25){let t=Math.max(1,Math.min(100,Math.trunc(e)));return(await m().execute({sql:`
169
- SELECT * FROM harvest_attempts
170
- WHERE browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
171
- AND provider_session_id IS NOT NULL
172
- AND provider_lookup_status IN ('pending', 'temporary_error')
173
- ORDER BY COALESCE(provider_checked_at, created_at) ASC
174
- LIMIT ?
175
- `,args:[t]})).rows.map(o=>_o(o))}async function vo(e,t){return(t==null?await m().execute({sql:"SELECT * FROM harvest_attempts WHERE job_id = ? ORDER BY attempt_number ASC",args:[e]}):await m().execute({sql:`
176
- SELECT ha.*
177
- FROM harvest_attempts ha
178
- INNER JOIN jobs j ON j.id = ha.job_id
179
- WHERE ha.job_id = ? AND j.user_id = ?
180
- ORDER BY ha.attempt_number ASC
181
- `,args:[e,t]})).rows.map(o=>_o(o))}import{createHash as ji}from"crypto";var gn=1e9;function It(e){return e==="timeout"?"timed_out":e==="request_aborted"?"cancelled":e==="browser_session_interrupted"?"interrupted":e==="captcha"||e==="proxy_tunnel_failed"||e==="proxy_unavailable"||e==="location_mismatch"||e==="error"?"failed":"succeeded"}function _n(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 Eo(e,t,r=0){let o=new Map,n=null;return async i=>{if(e)try{if(i.type==="started"){let a=r+i.attemptNumber;if(a>1&&!n){let c=(await _r(e))?.attempts.at(-1);n=c?.id==null?null:String(c.id)}let l=await ne({runId:e,attemptNumber:a,method:i.method,provider:i.provider,parentAttemptId:a===1?null:n,edgeKind:a===1?null:r>0&&i.attemptNumber===1?"durable_resume":i.retryKind==="provider_fallback"?"provider_fallback":"same_method_retry",retryKind:a===1?null:r>0&&i.attemptNumber===1?"durable_resume":i.retryKind,retryReason:a===1?null:r>0&&i.attemptNumber===1?"durable_worker_resume":i.retryReason,retryOwner:a===1?null:r>0&&i.attemptNumber===1?"durable_reconciler":"harvest",normalizedFlags:{maxAttempts:i.maxAttempts,maxQuestions:i.maxQuestions,hasLocation:!!i.location,plannedProvider:i.provider,planReason:i.planReason??null,planTimeoutMs:i.planTimeoutMs??null},startedAt:i.startedAt}),u=await K({attemptId:l,provider:i.provider,providerProduct:i.provider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser_api":"\u006b\u0065\u0072\u006e\u0065\u006c_browser",billingTier:i.provider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?Ie("https://www.google.com/search"):null,accountScope:t,method:i.method,providerStatus:"started"});o.set(i.attemptNumber,{attemptId:l,receiptId:u.id,plannedProvider:i.provider,observedProvider:null,providerMismatch:!1,method:i.method,startedAtMs:Date.parse(i.startedAt),billingMode:null}),n=l;return}let s=o.get(i.attemptNumber);if(!s)throw new Error(`Missing operation attempt state for attempt ${i.attemptNumber}`);if(i.type==="provider_session_started"){let a=_n(i.provider);if(s.observedProvider=a,s.billingMode=i.billingMode??null,a!==s.plannedProvider){s.providerMismatch=!0,await X({receiptId:s.receiptId,costState:"unavailable",providerStatus:"provider_mismatch",errorCode:"provider_mismatch",errorMessage:`Planned ${s.plannedProvider}; observed ${a}`,finalizedAt:i.observedAt});let l=a==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser":"\u006b\u0065\u0072\u006e\u0065\u006c_browser",u=await K({attemptId:s.attemptId,provider:a,providerProduct:a==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser_api":"\u006b\u0065\u0072\u006e\u0065\u006c_browser",billingTier:a==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?Ie("https://www.google.com/search"):null,accountScope:t,method:l,providerStatus:"observed_provider_mismatch"});s.receiptId=u.id,s.method=l}await V(s.receiptId,i.providerSessionId);return}if(await se({attemptId:s.attemptId,status:s.providerMismatch?"failed":It(i.outcome),errorCode:s.providerMismatch?"provider_mismatch":It(i.outcome)==="succeeded"?null:i.outcome,errorMessage:i.error,durationMs:i.durationMs,endedAt:i.completedAt}),(s.observedProvider??s.plannedProvider)==="\u006b\u0065\u0072\u006e\u0065\u006c"){let a=s.billingMode==="headful",l=s.billingMode==="headless"||s.billingMode==="headful"?or(i.durationMs,a):null;await X({receiptId:s.receiptId,costState:"estimated",units:i.durationMs/1e3,unitType:"wall_open_second",amountUsdNanos:l==null?null:Math.round(l*gn),providerProduct:"\u006b\u0065\u0072\u006e\u0065\u006c_browser",billingTier:s.billingMode,billableEvent:"provider_active_gb_second",measurementSource:"wall_open_time_proxy",rateSource:l!=null?`${rr};\u006b\u0065\u0072\u006e\u0065\u006c_usd_per_second:${tr}`:null,providerStatus:s.providerMismatch?"provider_mismatch":i.outcome,providerDurationMs:i.durationMs,errorCode:s.providerMismatch?"provider_mismatch":It(i.outcome)==="succeeded"?null:i.outcome,errorMessage:i.error,finalizedAt:i.completedAt})}}catch(s){console.warn(JSON.stringify({event:"operation_attempt_telemetry_failed",operation_run_id:e,attempt_number:i.attemptNumber,message:s instanceof Error?s.message:String(s)}))}}}function wo(e,t,r=null,o="production-default",n=0){let i=Eo(r,o,n);return async s=>{if(await i(s),s.type==="started"){await fo({jobId:e,userId:t,attemptNumber:s.attemptNumber,maxAttempts:s.maxAttempts,query:s.query,location:s.location,maxQuestions:s.maxQuestions,startedAt:s.startedAt});return}if(s.type==="provider_session_started"){await yo({jobId:e,attemptNumber:s.attemptNumber,browserProvider:s.provider,providerSessionId:s.providerSessionId,observedAt:s.observedAt});return}await bo({jobId:e,attemptNumber:s.attemptNumber,outcome:s.outcome,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:s.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:s.questionCount,durationMs:s.durationMs,error:s.error,willRetry:s.willRetry,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:s.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:s.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:s.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError,browserCloseSucceeded:s.cleanup.browserCloseSucceeded,browserCloseError:s.cleanup.browserCloseError,browserProvider:s.cleanup.provider??null,providerSessionId:s.cleanup.providerSessionId??null,providerLookupStatus:s.cleanup.providerSessionId?"pending":"not_applicable",providerErrorCode:s.cleanup.providerDisconnectObserved?"browser_session_interrupted":null,providerErrorMessage:s.cleanup.providerDisconnectMessage??null,providerReasonSource:s.cleanup.providerDisconnectObserved?"client_runtime":null,providerDisconnectObserved:s.cleanup.providerDisconnectObserved??!1,providerDisconnectMessage:s.cleanup.providerDisconnectMessage??null,debug:s.debug,completedAt:s.completedAt})}}function fn(e){return e instanceof Error?e.message:String(e)}function yn(e,t){return e instanceof DOMException&&(e.name==="TimeoutError"||e.name==="AbortError")?!0:/timeout|timed out|Timeout \d+ms exceeded|deadline/i.test(t)}function bn(e){return/captcha|recaptcha|unusual traffic|google\.com\/sorry|blocked/i.test(e)}function hn(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 vn(e){return/proxy unavailable|proxy_unavailable|connection_test_failed|did not return a proxy id|configured fallback/i.test(e)}function En(e){return/(?:spending|billing|organization|account).{0,80}(?:cap|limit|blocked|disabled)|(?:quota|capacity).{0,40}(?:reached|exceeded)|https?:\/\/\S*dashboard/i.test(e)}function wn(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(e)}function Rt(e){let t=fn(e);return e instanceof Kt?{error_code:"request_aborted",error_type:"request_aborted",message:F("request_aborted"),retryable:!0,httpStatus:408,terminalStatus:"cancelled"}:e instanceof zt||bn(t)?{error_code:"captcha_exhausted",error_type:"captcha",message:F("captcha_exhausted"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:fr(e,t)?{error_code:"vendor_unavailable",error_type:"service_unavailable",message:F("vendor_unavailable"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:e instanceof Vt?{error_code:"location_mismatch",error_type:"location_mismatch",message:F("location_mismatch"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:hn(t)?{error_code:"proxy_tunnel_failed",error_type:"connection",message:F("proxy_tunnel_failed"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:vn(t)?{error_code:"proxy_unavailable",error_type:"connection",message:F("proxy_unavailable"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:wn(t)?{error_code:"browser_session_interrupted",error_type:"extraction",message:F("browser_session_interrupted"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:yn(e,t)?{error_code:"harvest_timeout",error_type:"timeout",message:F("harvest_timeout"),retryable:!0,httpStatus:504,terminalStatus:"failed"}:En(t)?{error_code:"service_unavailable",error_type:"service_unavailable",message:ut,retryable:!0,httpStatus:503,terminalStatus:"failed"}:{error_code:"extraction_failed",error_type:"extraction",message:ut,retryable:!1,httpStatus:500,terminalStatus:"failed"}}function Bi(e){return JSON.stringify({error_code:e.error_code,error_type:e.error_type,message:e.message,retryable:e.retryable})}function So(e,t={}){let r=z({errorCode:e.error_code,errorType:e.error_type,retryable:e.retryable,retryAfterSeconds:t.retryAfterSeconds,chargeStatus:t.chargeStatus,details:t.details});return{error:r.message,...r}}function Ao(e,t={}){let{error:r,...o}=So(e,t);return o}function Wi(e,t={}){let r=Rt(e);return{body:So(r,t),status:r.httpStatus}}import{randomUUID as Io}from"crypto";var Sn=3e4;async function Ro(e,t,r){if(!e.receiptJson)return;let o=De(e.id);if((await T(o,e.userId,"paa_callback",e.jobId))?.phase==="published")return;if(r){if(await Ue(r,{status:"succeeded",json:e.receiptJson}))return;await re(r)}let i=await $e(o,e.userId);i&&await Je(i,{status:"unknown",json:e.receiptJson},Pe(e,t,"accepted"))}function An(e){return!!(e.payloadJson&&e.payloadSha256===O(e.payloadJson)&&e.sendNonce&&e.sendToken&&e.httpStatus&&e.httpStatus>=200&&e.httpStatus<300&&e.receiptJson===b({deliveryId:e.id,idempotencyKey:e.id,payloadSha256:e.payloadSha256,httpStatus:e.httpStatus}))}async function No(e){let t=e.record,r,o=!1;try{if(t=await j(t.id,t.userId)??t,t.state==="accepted")return An(t)?(await Ro(t,e.domain).catch(()=>{}),M(t)):{state:"unavailable",deliveryId:t.id};if(["sending","unknown","expired","unavailable"].includes(t.state))return M(t);if(t.expiresAtMs<=t.nowMs)return await ot(t,"expired"),M(await j(t.id,t.userId));if(t.payloadJson||(t=await Vr(t,await e.compose(),e.domain)),!t.payloadJson||t.payloadSha256!==O(t.payloadJson))throw Error("Delivery payload conflicts");let n=Pe(t,e.domain,"frozen"),i=De(t.id),s={version:1,purpose:"outbound-callback",request:U(t),payloadSha256:t.payloadSha256},a=await Se({id:i,userId:t.userId,ownerScope:`user:${t.userId}`,tool:"paa_callback",jobId:t.jobId,idempotencyKey:t.id,requestFingerprint:O(b(s)),normalizedFlags:s},Io(),Sn,n);if(a.kind!=="claimed"){let u=await T(i,t.userId,"paa_callback",t.jobId);if(u&&["effects_started","unknown","published"].includes(u.phase)){await ht(t),u.phase==="published"&&await ot(t,"unavailable",n);let d=await j(t.id,t.userId);return d?M(d):{state:"unknown",deliveryId:t.id}}return{state:"pending",deliveryId:t.id,expiresAtMs:t.expiresAtMs}}if(r=a.claim,!await e.validate(t.url))return M(t);if(!await Be(r,n))throw Error("Delivery effects start is unconfirmed");if(o=!0,t=await Xr(t,r,Io(),e.domain),!await Qr(t,r,e.domain))throw Error("Delivery authority was lost before send");let l=await fetch(t.url,{method:"POST",headers:{"content-type":"application/json","idempotency-key":t.id},body:t.payloadJson,redirect:"error",signal:AbortSignal.timeout(1e4)});if(!l.ok||l.status<200||l.status>=300)throw Error("Recipient acceptance is unconfirmed");return t=await Yr(t,l.status),await Ro(t,e.domain,r).catch(()=>{}),M(t)}catch(n){if(n instanceof Q&&await ot(t,"unavailable",e.domain).catch(()=>{}),r){let s=await T(r.runId,r.userId,"paa_callback",t.jobId).catch(()=>null);(o||s?.phase==="effects_started"||s?.phase==="unknown")&&await re(r).catch(()=>{})}t.sendNonce?await Zr(t).catch(()=>{}):await ht(t).catch(()=>{});let i=await j(t.id,t.userId).catch(()=>null);return i?M(i):{state:"unknown",deliveryId:t.id}}finally{r&&!o&&await we(r).catch(()=>{})}}async function Nt(e,t){let r=await oo(e,t);return r.kind==="none"?{state:"none"}:r.kind==="unavailable"?{state:"unavailable"}:r.kind==="pending"?(await M(r.record),{state:"pending",deliveryId:r.record.id,expiresAtMs:r.record.expiresAtMs}):No({record:r.record,domain:r.domain,validate:async o=>{let n=await mr(o,{field:"callback_url",requireHttps:!0});return!n.error&&n.parsed?.href===o&&!n.parsed.username&&!n.parsed.password},compose:async()=>{let o=(await nt(r.job,!1)).body;return{...o,...o.result?{result:sr(o.result)}:{},...r.record.profile==="paa-queue"?{attempts:nr(await vo(r.job.id,r.job.user_id))}:{}}}})}async function aa(e=25){let t=0,r=0,o=await eo(e);for(let n of o)try{(await Nt(n.jobId,n.userId)).state==="accepted"?t++:r++}catch{r++}return{checked:o.length,accepted:t,pending:r}}var xo=2,xt=0;async function ko(){let e=await po(),t=e?void 0:await br(),r=e??(t?await S(t.id,Number(t.user_id)):void 0);if(!r)return{claimed:!1};let o=Date.now();xt++;try{let n=await mo(r,{\u006b\u0065\u0072\u006e\u0065\u006cApiKey:Gt(),apifyToken:process.env.APIFY_API_TOKEN?.trim(),onAttemptEvent:wo(r.id,r.user_id,`harvest:${r.id}`),withCostContext:Yt,classifyFailure:i=>{let s=Rt(i);return{publicError:Ao(s),httpStatus:s.httpStatus,terminalStatus:s.terminalStatus}}});return n.completed&&r.callback_url&&await Nt(r.id,r.user_id).catch(()=>{}),{claimed:!0,jobId:r.id,completed:n.completed,durationMs:Date.now()-o}}finally{xt--}}async function ya(e){let t=[];for(let r=0;r<e.maxJobs&&!(Date.now()>=e.deadlineMs);r++){let o=await ko();if(t.push(o),!o.claimed)break}return t}function ba(){setInterval(async()=>{xt>=xo||ko()},2e3),console.log(`[worker] started \u2014 polling every 2s, max ${xo} concurrent`)}export{In as a,pt as b,kn as c,Dn as d,Pn as e,On as f,Tn as g,$n as h,Un as i,Jn as j,Gn as k,Bn as l,Wn as m,zn as n,Kn as o,Wr as p,tt as q,Ie as r,Ve as s,Fo as t,is as u,xi as v,ki as w,vo as x,Rt as y,Bi as z,Ao as A,Wi as B,to as C,ro as D,B as E,cn as F,no as G,nt as H,Et as I,St as J,uo as K,Nt as L,aa as M,Yn as N,hr as O,Jr as P,bt as Q,Ai as R,pn as S,wo as T,ko as U,ya as V,ba as W};
@@ -1 +0,0 @@
1
- var o="0.96.0";export{o as a};
@@ -1 +0,0 @@
1
- import{g as v,i as S}from"./chunk-C7MGJUTU.js";var C={\u006b\u0065\u0072\u006e\u0065\u006c:"browserRuntime"},b=/error|message/i,P=(new RegExp("(?:spending|billing|organization|account).{0,80}(?:cap|limit|blocked|disabled)|(?:quota|capacity).{0,40}(?:reached|exceeded)|https?:\\/\\/\\S*(?:dashboard|on\u006b\u0065\u0072\u006e\u0065\u006c)", "i")),A=/\b(?:ENOENT|ENOTDIR|EACCES|EPERM|EISDIR|EMFILE|ENFILE)\b|\b(?:mkdir|open|stat|lstat|readFile|writeFile)\s+['"]?(?:\/|[A-Za-z]:\\)|(?:^|[\s'"])(?:\/Users|\/home|\/tmp|\/var|\/private|\/opt|\/srv|\/root)\//i,I=new Set(["\u006b\u0065\u0072\u006e\u0065\u006c_session_id","browser_session_id","\u006b\u0065\u0072\u006e\u0065\u006cSessionId","browserSessionId","sessionId","\u006b\u0065\u0072\u006e\u0065\u006c_delete_started","session_cleanup_started","\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted","sessionCleanupStarted","\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded","session_cleanup_succeeded","\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded","sessionCleanupSucceeded","\u006b\u0065\u0072\u006e\u0065\u006c_delete_error","session_cleanup_error","\u006b\u0065\u0072\u006e\u0065\u006cDeleteError","sessionCleanupError","\u006b\u0065\u0072\u006e\u0065\u006cProxyId","proxyId","requestedProxyIdSuffix","retrievedProxyIdSuffix","provider","providerName","service","serviceName","vendor","vendorName","organization","organizationId","accountId","browser_provider","provider_session_id","provider_session_observed_at","provider_lookup_status","provider_status","provider_error_code","provider_error_message","provider_reason_source","provider_duration_ms","provider_bandwidth_bytes","provider_captcha","provider_checked_at","provider_detail","provider_detail_json","provider_disconnect_observed","provider_disconnect_message","browserProvider","providerSessionId","providerLookupStatus","providerStatus","providerErrorCode","providerErrorMessage","providerReasonSource","providerDurationMs","providerBandwidthBytes","providerCaptcha","providerCheckedAt","providerDetail","providerDisconnectObserved","providerDisconnectMessage"]),T=new Set(["hosted_url","hostedUrl","live_view_url","liveViewUrl","cdp_ws_url","cdpWsUrl","browser_live_view_url"]),O=(new RegExp("\\b(?:wss?|https?):\\/\\/[^\\s\"'<>]*\\bon\u006b\u0065\u0072\u006e\u0065\u006c\\.com[^\\s\"'<>]*", "gi"));function E(e){return e.replace(O,"[browser-service]")}var x=new Set(["\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api","\u006b\u0065\u0072\u006e\u0065\u006c","local"]),q=new Set(["pending","complete","not_found","unavailable_credentials","temporary_error","invalid_payload","not_applicable"]),F=new Set(["active","running","complete","completed","failed","closed","stopped","terminated","timed_out"]),L=new Set(["provider_session_api","client_runtime","extractor","unknown"]),N=new Set(["browser_disconnected","worker_disconnect","job_killed","cdp_cmd_timeout","network_inactivity_timeout","session_timeout","client_timeout","navigate_domains_limit","cdp_error","browser_session_interrupted","provider_detail_pending","provider_lookup_unavailable","provider_reported_no_error","provider_session_not_found","provider_invalid_json","provider_invalid_payload","provider_lookup_timeout","provider_lookup_network_error","unknown"]),D=new Set(["browser_provider","provider_session_id","provider_lookup_status","provider_status","provider_error_code","provider_error_message","provider_reason_source","provider_duration_ms","provider_bandwidth_bytes","provider_captcha","provider_checked_at","provider_detail","provider_detail_json","provider_disconnect_observed","provider_disconnect_message"]),U=512,M=320;function p(e,r){return typeof e=="string"&&r.has(e)?e:null}function z(e){return typeof e!="string"?null:N.has(e)||/^provider_http_(?:429|5\d\d)$/.test(e)?e:null}function V(e){return typeof e!="string"||e.length<1||e.length>U||/^(?:authorization|bearer|password|secret|token|api[_-]?key|account)/i.test(e)?null:/^[A-Za-z0-9._:-]+$/.test(e)&&!e.includes("://")?e:null}function f(e){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=0?e:null}function y(e){if(typeof e!="string"||e.length>40)return null;let r=Date.parse(e);return Number.isFinite(r)&&new Date(r).toISOString()===e?e:null}function h(e){if(typeof e!="string")return null;let r=e.replace(/[\u0000-\u001f\u007f]+/g," ").replace(/\s+/g," ").trim();if(!r||r.startsWith("{")||r.startsWith("["))return null;let n=r.replace(/\b(?:wss?|https?):\/\/\S+/gi,"[redacted endpoint]").replace(/\b(?:authorization|proxy-authorization)\s*:\s*(?:Bearer\s+)?\S+/gi,"[redacted credential]").replace(/\bBearer\s+\S+/gi,"[redacted credential]").replace(/\b(?:api[_-]?key|password|secret|token|account[_-]?id)\s*[=:]\s*[^\s,;]+/gi,"[redacted credential]").replace(/\b(?:account|organization)\s+(?:id\s+)?[A-Za-z0-9_-]{4,}/gi,"[redacted account]");return E(n).slice(0,M)}function w(e){return typeof e=="boolean"?e:null}function H(e){return{browser_provider:p(e.browser_provider,x),provider_session_id:V(e.provider_session_id),provider_session_observed_at:y(e.provider_session_observed_at),provider_lookup_status:p(e.provider_lookup_status,q),provider_status:p(e.provider_status,F),provider_error_code:z(e.provider_error_code),provider_error_message:h(e.provider_error_message),provider_reason_source:p(e.provider_reason_source,L),provider_duration_ms:f(e.provider_duration_ms),provider_bandwidth_bytes:f(e.provider_bandwidth_bytes),provider_captcha:w(e.provider_captcha),provider_checked_at:y(e.provider_checked_at),provider_disconnect_observed:w(e.provider_disconnect_observed),provider_disconnect_message:h(e.provider_disconnect_message)}}function l(e,r=""){if(typeof e=="string"){let n=E(e);return b.test(r)&&(P.test(e)||A.test(e))?n=v("service_unavailable"):b.test(r)&&(n=S(n)),n}if(Array.isArray(e))return e.map(n=>l(n,r));if(e!==null&&typeof e=="object"){let n={};for(let[t,s]of Object.entries(e)){if(I.has(t))continue;let a=C[t]??t;if(T.has(t)){n[a]=null;continue}n[a]=l(s,t)}return n}return e}function K(e){return e.map(r=>{if(r===null||typeof r!="object"||Array.isArray(r))return l(r);let n=r,t=l(n);return Object.keys(n).some(a=>D.has(a))?{...t,...H(n)}:t})}function W(e){let r=e?.diagnostics;if(!r)return e;let n=r.serpCompleteness,t=n?.queryIntegrity;return!r.debug&&!t?e:{...e,diagnostics:{...r,...r.debug?{debug:l(r.debug)}:{},...t?{serpCompleteness:{...n,queryIntegrity:{...t,outboundProviderMethod:"search"}}}:{}}}}import{createHash as Q}from"crypto";var j=["observed_present","observed_absent","incomplete","not_requested","unknown","unsupported"],B=["provider_transport","invalid_payload","serp_readiness","query_integrity","pagination","optional_feature_parsing","unknown"],R=class extends Error{stage;failureCode;constructor(r,n,t){super(t),this.name="SerpExtractionError",this.stage=r,this.failureCode=n}};function _(e){return Q("sha256").update(e).digest("hex")}function G(e){return e.normalize("NFKC").toLocaleLowerCase("en-US").split(/[^\p{L}\p{N}]+/u).filter(Boolean).slice(0,64)}function X(e){try{let r=new URL(e);return r.hash="",r.pathname.length>1&&(r.pathname=r.pathname.replace(/\/+$/,"")),r.toString()}catch{return e.trim()}}function J(e,r){let n=e===2?[1,2]:[1],t=r.filter(o=>o.attempted).map(o=>o.page),s=r.filter(o=>o.captured&&o.resultCount>0).map(o=>o.page),a=r.find(o=>o.failureCode);return{status:n.every(o=>s.includes(o))?"complete":"incomplete",requestedPages:n,attemptedPages:t,capturedPages:s,pageResultCounts:n.map(o=>({page:o,resultCount:r.find(g=>g.page===o)?.resultCount??0})),providerRequestCount:t.length,evidence:r,failureCode:a?.failureCode??null}}function ee(e){return e.requested?e.moduleObserved?!e.rawShapeValid||e.rawCount>0&&e.mappedCount===0?"incomplete":e.mappedCount>0?"observed_present":"observed_absent":"unknown":"not_requested"}function re(e){let r=_(e.query),n=e.finalQuery==null?null:_(e.finalQuery),t=e.locationResolutionSource==="unresolved";return{status:n!==null&&n!==r?"query_mismatch":t?"unresolved_location":"matched",queryHash:r,normalizedQueryTokens:G(e.query),canonicalLocation:e.canonicalLocation??null,locationResolutionSource:e.locationResolutionSource,locationAmbiguousCandidates:Math.max(0,Math.trunc(e.locationAmbiguousCandidates??0)),uulePresent:!!e.uule,uuleHash:e.uule?_(e.uule):null,outboundProviderMethod:e.outboundProviderMethod,finalQueryHash:n}}function ne(e){return _(JSON.stringify(Object.fromEntries(Object.entries(e).filter(([r,n])=>r!=="requestFingerprint"&&n!==void 0).sort(([r],[n])=>r.localeCompare(n)))))}function c(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function m(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.trunc(e):0}function u(e,r){return typeof e=="string"&&e.length<=r?e:null}function te(e){let r=c(e),n=c(r.pagination),t=c(r.features),s=c(r.queryIntegrity),a=i=>Array.isArray(i)?i.filter(d=>d===1||d===2).slice(0,2):[],o=a(n.requestedPages);if(o.length===0)return null;let g=new Set(j),k=new Set(B);return{pagination:{status:n.status==="complete"?"complete":"incomplete",requestedPages:o,attemptedPages:a(n.attemptedPages),capturedPages:a(n.capturedPages),pageResultCounts:Array.isArray(n.pageResultCounts)?n.pageResultCounts.slice(0,2).map(i=>{let d=c(i);return{page:d.page===2?2:1,resultCount:m(d.resultCount)}}):[],providerRequestCount:m(n.providerRequestCount),failureCode:u(n.failureCode,100)},features:Object.fromEntries(["localPack","forums","videos","aiOverview","whatPeopleSaying","aiMode","paaPreview","entityIds"].map(i=>[i,g.has(String(t[i]))?t[i]:"unknown"])),queryIntegrity:{status:["matched","unresolved_location","query_mismatch"].includes(String(s.status))?s.status:"query_mismatch",queryHash:u(s.queryHash,64)??"",normalizedQueryTokens:Array.isArray(s.normalizedQueryTokens)?s.normalizedQueryTokens.slice(0,64).flatMap(i=>typeof i=="string"?[i.slice(0,100)]:[]):[],canonicalLocation:u(s.canonicalLocation,500),locationResolutionSource:u(s.locationResolutionSource,100)??"unknown",locationAmbiguousCandidates:m(s.locationAmbiguousCandidates),uulePresent:s.uulePresent===!0,uuleHash:u(s.uuleHash,64),outboundProviderMethod:"search",finalQueryHash:u(s.finalQueryHash,64)},failureStage:k.has(String(r.failureStage))?r.failureStage:null}}export{l as a,K as b,W as c,R as d,X as e,J as f,ee as g,re as h,ne as i,te as j};