mcp-scraper 0.95.1 → 0.95.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 (53) hide show
  1. package/CHANGELOG.md +51 -39
  2. package/README.md +8 -6
  3. package/THIRD_PARTY_NOTICES.html +203 -0
  4. package/dist/{analytics-repository-A7VMA24D.js → analytics-repository-DZZKDZL6.js} +1 -1
  5. package/dist/bin/api-server.js +1 -1
  6. package/dist/bin/mcp-scraper-cli.js +1 -1
  7. package/dist/bin/mcp-scraper-core.js +1 -1
  8. package/dist/bin/mcp-scraper-install.js +1 -1
  9. package/dist/bin/mcp-stdio-server.js +1 -1
  10. package/dist/bin/paa-harvest.js +1 -1
  11. package/dist/{chunk-FCJXL4PU.js → chunk-6DRKDSXY.js} +1 -1
  12. package/dist/chunk-7XDBGQDY.js +6 -0
  13. package/dist/{chunk-ZPK5LYEN.js → chunk-7YOXSMHG.js} +23 -23
  14. package/dist/{chunk-OS4XFDIG.js → chunk-BLVBUMH5.js} +2 -2
  15. package/dist/{chunk-FN7U6KRI.js → chunk-ENZUJEIM.js} +1 -1
  16. package/dist/{chunk-MVDMZ3N2.js → chunk-GLTECY3U.js} +77 -77
  17. package/dist/chunk-GPSPSJBJ.js +1 -1
  18. package/dist/{chunk-56C243PX.js → chunk-IXJQHXDC.js} +1 -1
  19. package/dist/{chunk-RPA5ADXW.js → chunk-K3D2S36Q.js} +4 -4
  20. package/dist/{chunk-DOJMTFLB.js → chunk-KFOFU3LA.js} +1 -1
  21. package/dist/{chunk-ZUGTYD2I.js → chunk-LMWU7VPZ.js} +5 -5
  22. package/dist/{chunk-Y6STAKF3.js → chunk-M5QHXNFZ.js} +3 -3
  23. package/dist/{chunk-DYDAQQMC.js → chunk-MC4W6TZT.js} +3 -3
  24. package/dist/{chunk-YK4OAZRQ.js → chunk-O4LUUIYG.js} +1 -1
  25. package/dist/{chunk-ZJTUAWZA.js → chunk-OLSW4AN4.js} +1 -1
  26. package/dist/{chunk-QQ7OD7BJ.js → chunk-RLFCJGHA.js} +1 -1
  27. package/dist/{chunk-L552AQQY.js → chunk-T4VTJNDZ.js} +1 -1
  28. package/dist/{chunk-NA76FFGD.js → chunk-VREXSMC6.js} +15 -15
  29. package/dist/chunk-VXOXB3IB.js +1 -0
  30. package/dist/chunk-WO46LTBW.js +1 -0
  31. package/dist/{chunk-AK6HVF5F.js → chunk-XG6GCEUE.js} +1 -1
  32. package/dist/chunk-XPEJB4BZ.js +1 -1
  33. package/dist/{chunk-I3HNHCIJ.js → chunk-Y3Q4FIKK.js} +2 -2
  34. package/dist/{chunk-DYKSPHHR.js → chunk-ZH75KWBI.js} +1 -1
  35. package/dist/{db-B6RNXKEI.js → db-CDEZHBRN.js} +1 -1
  36. package/dist/{extract-bundle-X7SRN63Y.js → extract-bundle-SXC6EWJR.js} +1 -1
  37. package/dist/{gmail-service-FZVJBSUT.js → gmail-service-EWR76XE7.js} +1 -1
  38. package/dist/index.cjs +21 -21
  39. package/dist/index.d.cts +14 -14
  40. package/dist/index.d.ts +14 -14
  41. package/dist/index.js +1 -1
  42. package/dist/{lead-list-enrichment-repository-SXYSS7ZX.js → lead-list-enrichment-repository-SIWGXWQV.js} +1 -1
  43. package/dist/{location-data-repository-NWWKDYG6.js → location-data-repository-A2QZVP7O.js} +1 -1
  44. package/dist/{operation-metering-OBKSWJVJ.js → operation-metering-UJ53YX7S.js} +1 -1
  45. package/dist/{server-JV6L7F2X.js → server-QVEKDIDQ.js} +369 -369
  46. package/dist/{site-extract-repository-UVE7TWJO.js → site-extract-repository-23ND4N77.js} +1 -1
  47. package/dist/{stripe-event-worker-2LSUVQOM.js → stripe-event-worker-LPXTITVC.js} +1 -1
  48. package/dist/worker-EDN2TJH3.js +1 -0
  49. package/package.json +17 -137
  50. package/dist/chunk-6NE4OIXR.js +0 -6
  51. package/dist/chunk-NZSDHDX3.js +0 -1
  52. package/dist/chunk-YWUNN24S.js +0 -1
  53. package/dist/worker-XPIO5TAV.js +0 -1
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{a as e}from"../chunk-YK4OAZRQ.js";import"../chunk-MVDMZ3N2.js";import"../chunk-NZSDHDX3.js";import"../chunk-W2BVJ7S2.js";import"../chunk-DOJMTFLB.js";import"../chunk-ZUGTYD2I.js";import"../chunk-TMB56NCA.js";import"../chunk-HUV2WTRW.js";import"../chunk-YGBTTW5D.js";import"../chunk-EDQ57S4P.js";import"../chunk-GPSPSJBJ.js";import"../chunk-NA76FFGD.js";import"../chunk-6DTXIZY2.js";import"../chunk-RPA5ADXW.js";import"../chunk-WO3N5FH2.js";import"../chunk-HE45FFBU.js";import"../chunk-YWUNN24S.js";import"../chunk-ZPK5LYEN.js";var _=["harvest_paa","search_serp","extract_url","diff_page","map_site_urls","map_wayback_snapshots","extract_site","analyze_site_similarity","audit_site","check_site_export","site_export_read","site_export_image","archive_read","youtube_harvest","youtube_transcribe","facebook_page_intel","facebook_ad_search","reddit_thread","reddit_trending","video_frame_analysis","video_frame_analysis_status","facebook_ad_transcribe","google_ads_search","google_ads_page_intel","google_ads_transcribe","facebook_video_transcribe","instagram_profile_content","instagram_media_download","maps_place_intel","maps_search","trustpilot_reviews","g2_reviews","capture_serp_snapshot","capture_serp_page_snapshots"];e({toolsets:new Set(["paa","serp"]),allowedToolNames:_});
2
+ import{a as e}from"../chunk-O4LUUIYG.js";import"../chunk-GLTECY3U.js";import"../chunk-WO46LTBW.js";import"../chunk-W2BVJ7S2.js";import"../chunk-KFOFU3LA.js";import"../chunk-LMWU7VPZ.js";import"../chunk-TMB56NCA.js";import"../chunk-HUV2WTRW.js";import"../chunk-YGBTTW5D.js";import"../chunk-EDQ57S4P.js";import"../chunk-GPSPSJBJ.js";import"../chunk-VREXSMC6.js";import"../chunk-6DTXIZY2.js";import"../chunk-K3D2S36Q.js";import"../chunk-WO3N5FH2.js";import"../chunk-HE45FFBU.js";import"../chunk-VXOXB3IB.js";import"../chunk-7YOXSMHG.js";var _=["harvest_paa","search_serp","extract_url","diff_page","map_site_urls","map_wayback_snapshots","extract_site","analyze_site_similarity","audit_site","check_site_export","site_export_read","site_export_image","archive_read","youtube_harvest","youtube_transcribe","facebook_page_intel","facebook_ad_search","reddit_thread","reddit_trending","video_frame_analysis","video_frame_analysis_status","facebook_ad_transcribe","google_ads_search","google_ads_page_intel","google_ads_transcribe","facebook_video_transcribe","instagram_profile_content","instagram_media_download","maps_place_intel","maps_search","trustpilot_reviews","g2_reviews","capture_serp_snapshot","capture_serp_page_snapshots"];e({toolsets:new Set(["paa","serp"]),allowedToolNames:_});
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import{a as s}from"../chunk-RPA5ADXW.js";import{a as e}from"../chunk-YWUNN24S.js";var r=process.argv.includes("--no-color")||process.env.NO_COLOR!==void 0||process.env.FORCE_COLOR==="0"||!process.stdout.isTTY,n=process.argv.includes("--help")||process.argv.includes("-h");n&&(process.stdout.write(["Usage: mcp-scraper-install [--no-color]","","Prints the branded MCP Scraper terminal install card and copyable install commands.","mcp-scraper prints the same card in a human terminal and runs as the MCP stdio server in clients.",""].join(`
2
+ import{a as s}from"../chunk-K3D2S36Q.js";import{a as e}from"../chunk-VXOXB3IB.js";var r=process.argv.includes("--no-color")||process.env.NO_COLOR!==void 0||process.env.FORCE_COLOR==="0"||!process.stdout.isTTY,n=process.argv.includes("--help")||process.argv.includes("-h");n&&(process.stdout.write(["Usage: mcp-scraper-install [--no-color]","","Prints the branded MCP Scraper terminal install card and copyable install commands.","mcp-scraper prints the same card in a human terminal and runs as the MCP stdio server in clients.",""].join(`
3
3
  `)),process.exit(0));process.stdout.write(s({version:e,color:!r,apiKeyConfigured:!!process.env.MCP_SCRAPER_API_KEY?.trim()}));
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{a as r}from"../chunk-YK4OAZRQ.js";import"../chunk-MVDMZ3N2.js";import"../chunk-NZSDHDX3.js";import"../chunk-W2BVJ7S2.js";import"../chunk-DOJMTFLB.js";import"../chunk-ZUGTYD2I.js";import"../chunk-TMB56NCA.js";import"../chunk-HUV2WTRW.js";import"../chunk-YGBTTW5D.js";import"../chunk-EDQ57S4P.js";import"../chunk-GPSPSJBJ.js";import"../chunk-NA76FFGD.js";import"../chunk-6DTXIZY2.js";import"../chunk-RPA5ADXW.js";import"../chunk-WO3N5FH2.js";import"../chunk-HE45FFBU.js";import"../chunk-YWUNN24S.js";import"../chunk-ZPK5LYEN.js";r();
2
+ import{a as r}from"../chunk-O4LUUIYG.js";import"../chunk-GLTECY3U.js";import"../chunk-WO46LTBW.js";import"../chunk-W2BVJ7S2.js";import"../chunk-KFOFU3LA.js";import"../chunk-LMWU7VPZ.js";import"../chunk-TMB56NCA.js";import"../chunk-HUV2WTRW.js";import"../chunk-YGBTTW5D.js";import"../chunk-EDQ57S4P.js";import"../chunk-GPSPSJBJ.js";import"../chunk-VREXSMC6.js";import"../chunk-6DTXIZY2.js";import"../chunk-K3D2S36Q.js";import"../chunk-WO3N5FH2.js";import"../chunk-HE45FFBU.js";import"../chunk-VXOXB3IB.js";import"../chunk-7YOXSMHG.js";r();
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{z as t}from"../chunk-DYDAQQMC.js";import"../chunk-Y6STAKF3.js";import{b as r}from"../chunk-GPSPSJBJ.js";import"../chunk-NA76FFGD.js";import"../chunk-6DTXIZY2.js";import"../chunk-XPEJB4BZ.js";import"../chunk-ZPK5LYEN.js";import{Command as s,Option as a}from"commander";var i=new s;i.name("paa-harvest").description("Recursively extract Google People Also Ask questions").requiredOption("-q, --query <query>","Seed query").option("-l, --location <location>",'Location name (e.g. "austin" or "Austin,Texas,United States")').option("--gl <gl>","Google country code","us").option("--hl <hl>","Google language code","en").option("-d, --depth <depth>","BFS depth (1-30)","3").option("-m, --max-questions <n>","Max questions to harvest","100").option("-o, --output <dir>","Output directory","./paa-output").option("-f, --format <format>","Output format: json, csv, or both","both").option("--headless","Run browser in headless mode",!1).option("--profile <dir>","Persistent browser profile directory").option("--proxy <url>","Proxy server URL").option("--browser-api-key <key>","Browser service API key (or set BROWSER_SERVICE_API_KEY env var)").addOption(new a("--kernel-api-key <key>").hideHelp()).action(async e=>{try{let o=await t({query:e.query,location:e.location,gl:e.gl,hl:e.hl,depth:parseInt(e.depth,10),maxQuestions:parseInt(e.maxQuestions,10),outputDir:e.output,format:e.format,headless:e.headless,profileDir:e.profile,proxy:e.proxy,kernelApiKey:e.browserApiKey??e.kernelApiKey??r()});console.log(JSON.stringify({totalQuestions:o.totalQuestions,outputDir:o.stats.seed}))}catch(o){console.error(o instanceof Error?o.message:String(o)),process.exit(1)}});async function n(){await i.parseAsync()}n();
2
+ import{z as t}from"../chunk-MC4W6TZT.js";import"../chunk-M5QHXNFZ.js";import{b as r}from"../chunk-GPSPSJBJ.js";import"../chunk-VREXSMC6.js";import"../chunk-6DTXIZY2.js";import"../chunk-XPEJB4BZ.js";import"../chunk-7YOXSMHG.js";import{Command as s,Option as a}from"commander";var i=new s;i.name("paa-harvest").description("Recursively extract Google People Also Ask questions").requiredOption("-q, --query <query>","Seed query").option("-l, --location <location>",'Location name (e.g. "austin" or "Austin,Texas,United States")').option("--gl <gl>","Google country code","us").option("--hl <hl>","Google language code","en").option("-d, --depth <depth>","BFS depth (1-30)","3").option("-m, --max-questions <n>","Max questions to harvest","100").option("-o, --output <dir>","Output directory","./paa-output").option("-f, --format <format>","Output format: json, csv, or both","both").option("--headless","Run browser in headless mode",!1).option("--profile <dir>","Persistent browser profile directory").option("--proxy <url>","Proxy server URL").option("--browser-api-key <key>","Browser service API key (or set BROWSER_SERVICE_API_KEY env var)").addOption(new a("--\u006b\u0065\u0072\u006e\u0065\u006c-api-key <key>").hideHelp()).action(async e=>{try{let o=await t({query:e.query,location:e.location,gl:e.gl,hl:e.hl,depth:parseInt(e.depth,10),maxQuestions:parseInt(e.maxQuestions,10),outputDir:e.output,format:e.format,headless:e.headless,profileDir:e.profile,proxy:e.proxy,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:e.browserApiKey??e.\u006b\u0065\u0072\u006e\u0065\u006cApiKey??r()});console.log(JSON.stringify({totalQuestions:o.totalQuestions,outputDir:o.stats.seed}))}catch(o){console.error(o instanceof Error?o.message:String(o)),process.exit(1)}});async function n(){await i.parseAsync()}n();
@@ -1,4 +1,4 @@
1
- import{a as j,b as T,c as P,d as C,f as S}from"./chunk-TMB56NCA.js";import{ba as w}from"./chunk-EDQ57S4P.js";import{Kb as N,Tb as D,d as m,e as I,i as u,t as s}from"./chunk-ZPK5LYEN.js";import{createHash as W}from"crypto";import{gunzipSync as $,gzipSync as q}from"zlib";var y="site-extracts/",L=10080*60*1e3,H=900*1e3;function U(){return process.env.SITE_EXTRACT_ARTIFACT_READ_WRITE_TOKEN?.trim()||process.env.PRIVATE_ARTIFACT_READ_WRITE_TOKEN?.trim()||process.env.CONNECTED_DATA_READ_WRITE_TOKEN?.trim()||process.env.CONNECTED_DATA_BLOB_READ_WRITE_TOKEN?.trim()||null}function v(){return process.env.VERCEL==="1"||process.env.NODE_ENV==="production"}function p(){return{prefix:y,artifactTtlMs:L,downloadTtlMs:H,token:U()}}function h(t){return j(t,y)}async function V(t){let e=await P({policy:p(),ownerId:t.ownerId,artifactKey:`${t.jobId}.zip`,createdAt:t.createdAt,filename:`${t.jobId}-site-export.zip`,contentType:"application/zip",content:t.content});return{key:e.artifactId,url:e.downloadUrl??"",bytes:e.bytes,contentType:e.contentType,filename:e.filename,sha256:e.sha256,expiresAt:e.expiresAt,downloadUrlExpiresAt:e.downloadUrlExpiresAt,kind:"bundle"}}async function G(t){let e=await T({policy:p(),ownerId:t.ownerId,scopeSegments:[t.jobId,"images"],artifactKey:`${t.imageId}.bin`,createdAt:new Date,filename:t.filename,contentType:t.contentType,content:t.content});return{key:e.artifactId,url:e.downloadUrl??"",bytes:e.bytes,contentType:e.contentType,filename:e.filename,sha256:e.sha256,expiresAt:e.expiresAt,downloadUrlExpiresAt:e.downloadUrlExpiresAt,kind:"image",imageId:t.imageId,sourceUrl:t.sourceUrl,sourcePage:t.sourcePage}}async function O(t){return T({policy:p(),ownerId:t.ownerId,scopeSegments:[t.jobId,"content"],artifactKey:`${t.chunkKey}.json.gz`,createdAt:t.createdAt,filename:`${t.chunkKey}.json.gz`,contentType:"application/gzip",content:t.content})}async function Q(t){return C({policy:p(),artifactId:t.artifactId,ownerId:t.ownerId})}async function J(t){return S({policy:p(),artifactId:t,maxBytes:50*1024*1024})}async function Z(t){return h(t.artifactId)!==t.ownerId?null:J(t.artifactId)}async function k(t){return h(t.artifactId)!==t.ownerId?null:S({policy:p(),artifactId:t.artifactId,maxBytes:25*1024*1024})}async function tt(t){return h(t.artifactId)!==t.ownerId?null:S({policy:p(),artifactId:t.artifactId,maxBytes:10*1024*1024})}async function et(t={}){let e=t.now??new Date,n=U();if(!n)return{deleted:0,store:v()?"none":"local"};if(!t.force&&!(e.getUTCHours()===3&&e.getUTCMinutes()===21))return{deleted:0,store:"private-vercel-blob",skipped:!0};let r=e.getTime()-L,{list:i,del:a}=await import("@vercel/blob"),o,c=0;for(let d=0;d<20;d+=1){let l=await i({prefix:y,token:n,limit:1e3,cursor:o}),f=l.blobs.filter(A=>new Date(A.uploadedAt).getTime()<=r);if(f.length>0&&(await a(f.map(A=>A.pathname),{token:n}),c+=f.length),!l.hasMore||!l.cursor)break;o=l.cursor}return{deleted:c,store:"private-vercel-blob"}}var F=10,b=20*1024*1024;function E(t){return W("sha256").update(t).digest("hex")}function B(t){return!t.acquiredHtml||t.extractionStatus==="failed"?null:{pageId:t.pageId??E(t.archivedUrl??t.url),url:t.archivedUrl??t.url,html:t.acquiredHtml,mainHtml:t.mainHtml??"",markdown:t.bodyMarkdown,htmlSha256:t.htmlSha256??E(t.acquiredHtml),markdownSha256:t.markdownSha256??E(t.bodyMarkdown)}}function R(t){return Buffer.from(JSON.stringify({version:"site-extract-content.v1",pages:t}))}async function M(t){let e=t.pages.flatMap(o=>{let c=B(o);return c?[c]:[]}),n=new Map,r=[],i=0,a=async()=>{if(!r.length)return;let o=R(r);if(o.length>b)throw new Error(`site export content chunk exceeds ${b} bytes`);let c=E(r.map(l=>l.pageId).join("\0")).slice(0,16),d=await O({ownerId:t.ownerId,jobId:t.jobId,createdAt:t.createdAt,chunkKey:`content-${String(i).padStart(4,"0")}-${c}`,content:q(o,{level:6})});for(let l of r)n.set(l.url,{artifactId:d.artifactId,artifactSha256:d.sha256,pageId:l.pageId,uncompressedBytes:o.length});i++,r=[]};for(let o of e){let c=[...r,o];if(r.length>0&&(c.length>F||R(c).length>b)&&await a(),r.push(o),R(r).length>b)throw new Error(`page ${o.pageId} exceeds the durable content chunk limit`)}return await a(),n}function it(t){let e=new Map;return async n=>{let r=e.get(n.artifactId);if(!r){let a=await k({artifactId:n.artifactId,ownerId:t});if(!a)throw new Error("site export content chunk is missing or unauthorized");if(E(a)!==n.artifactSha256)throw new Error("site export content chunk checksum mismatch");let o=$(a);if(o.length>b)throw new Error("site export content chunk exceeds its read limit");if(r=JSON.parse(o.toString("utf8")),r.version!=="site-extract-content.v1"||!Array.isArray(r.pages))throw new Error("site export content chunk has an unsupported contract");for(e.set(n.artifactId,r);e.size>2;)e.delete(e.keys().next().value)}let i=r.pages.find(a=>a.pageId===n.pageId);if(!i)throw new Error("site export page is missing from its content chunk");if(E(i.html)!==i.htmlSha256||E(i.markdown)!==i.markdownSha256)throw new Error("site export page checksum mismatch");return i}}var g="xray_entitlement";function pt(t){let e=Math.max(1,Number(t.options.effectiveMaxPages??t.options.maxPages??1)),n=Math.max(e,Number(t.options.requestedMaxPages??e)),r=n>e;return{requestedMaxPages:n,effectiveMaxPages:e,creditLimited:r,creditTruncated:r&&t.totalUrls>=e}}function Et(t,e=!1){return t.successfulUrls===0?"failed":t.failedUrls>0||t.remainingUrls>0||e?"partial":"complete"}function _(t){let e=Number(t.total_urls??0),n=t.attempted_urls==null,r=Number(n?t.done_urls??0:t.attempted_urls),i=Number(n?t.done_urls??0:t.successful_urls??0),a=Number(t.failed_urls??Math.max(0,r-i));return{id:String(t.id),userId:t.user_id!=null?Number(t.user_id):null,idempotencyKey:t.idempotency_key!=null?String(t.idempotency_key):null,requestFingerprint:t.request_fingerprint!=null?String(t.request_fingerprint):null,status:t.status!=null?String(t.status):"pending",startUrl:String(t.start_url??""),options:t.options?JSON.parse(String(t.options)):{},totalUrls:e,doneUrls:r,attemptedUrls:r,successfulUrls:i,failedUrls:a,remainingUrls:Math.max(0,e-r),artifacts:t.artifacts?JSON.parse(String(t.artifacts)):null,error:t.error!=null?String(t.error):null,publicError:I(t.public_error_json),billedMc:t.billed_mc!=null?Number(t.billed_mc):null,createdAt:String(t.created_at??""),updatedAt:String(t.updated_at??"")}}async function mt(t,e,n,r){await s().execute({sql:`INSERT INTO site_extract_jobs (id, user_id, status, start_url, options, created_at, updated_at)
1
+ import{a as j,b as T,c as P,d as C,f as S}from"./chunk-TMB56NCA.js";import{ba as w}from"./chunk-EDQ57S4P.js";import{Kb as N,Tb as D,d as m,e as I,i as u,t as s}from"./chunk-7YOXSMHG.js";import{createHash as W}from"crypto";import{gunzipSync as $,gzipSync as q}from"zlib";var y="site-extracts/",L=10080*60*1e3,H=900*1e3;function U(){return process.env.SITE_EXTRACT_ARTIFACT_READ_WRITE_TOKEN?.trim()||process.env.PRIVATE_ARTIFACT_READ_WRITE_TOKEN?.trim()||process.env.CONNECTED_DATA_READ_WRITE_TOKEN?.trim()||process.env.CONNECTED_DATA_BLOB_READ_WRITE_TOKEN?.trim()||null}function v(){return process.env.VERCEL==="1"||process.env.NODE_ENV==="production"}function p(){return{prefix:y,artifactTtlMs:L,downloadTtlMs:H,token:U()}}function h(t){return j(t,y)}async function V(t){let e=await P({policy:p(),ownerId:t.ownerId,artifactKey:`${t.jobId}.zip`,createdAt:t.createdAt,filename:`${t.jobId}-site-export.zip`,contentType:"application/zip",content:t.content});return{key:e.artifactId,url:e.downloadUrl??"",bytes:e.bytes,contentType:e.contentType,filename:e.filename,sha256:e.sha256,expiresAt:e.expiresAt,downloadUrlExpiresAt:e.downloadUrlExpiresAt,kind:"bundle"}}async function G(t){let e=await T({policy:p(),ownerId:t.ownerId,scopeSegments:[t.jobId,"images"],artifactKey:`${t.imageId}.bin`,createdAt:new Date,filename:t.filename,contentType:t.contentType,content:t.content});return{key:e.artifactId,url:e.downloadUrl??"",bytes:e.bytes,contentType:e.contentType,filename:e.filename,sha256:e.sha256,expiresAt:e.expiresAt,downloadUrlExpiresAt:e.downloadUrlExpiresAt,kind:"image",imageId:t.imageId,sourceUrl:t.sourceUrl,sourcePage:t.sourcePage}}async function O(t){return T({policy:p(),ownerId:t.ownerId,scopeSegments:[t.jobId,"content"],artifactKey:`${t.chunkKey}.json.gz`,createdAt:t.createdAt,filename:`${t.chunkKey}.json.gz`,contentType:"application/gzip",content:t.content})}async function Q(t){return C({policy:p(),artifactId:t.artifactId,ownerId:t.ownerId})}async function J(t){return S({policy:p(),artifactId:t,maxBytes:50*1024*1024})}async function Z(t){return h(t.artifactId)!==t.ownerId?null:J(t.artifactId)}async function k(t){return h(t.artifactId)!==t.ownerId?null:S({policy:p(),artifactId:t.artifactId,maxBytes:25*1024*1024})}async function tt(t){return h(t.artifactId)!==t.ownerId?null:S({policy:p(),artifactId:t.artifactId,maxBytes:10*1024*1024})}async function et(t={}){let e=t.now??new Date,n=U();if(!n)return{deleted:0,store:v()?"none":"local"};if(!t.force&&!(e.getUTCHours()===3&&e.getUTCMinutes()===21))return{deleted:0,store:"private-vercel-blob",skipped:!0};let r=e.getTime()-L,{list:i,del:a}=await import("@vercel/blob"),o,c=0;for(let d=0;d<20;d+=1){let l=await i({prefix:y,token:n,limit:1e3,cursor:o}),f=l.blobs.filter(A=>new Date(A.uploadedAt).getTime()<=r);if(f.length>0&&(await a(f.map(A=>A.pathname),{token:n}),c+=f.length),!l.hasMore||!l.cursor)break;o=l.cursor}return{deleted:c,store:"private-vercel-blob"}}var F=10,b=20*1024*1024;function E(t){return W("sha256").update(t).digest("hex")}function B(t){return!t.acquiredHtml||t.extractionStatus==="failed"?null:{pageId:t.pageId??E(t.archivedUrl??t.url),url:t.archivedUrl??t.url,html:t.acquiredHtml,mainHtml:t.mainHtml??"",markdown:t.bodyMarkdown,htmlSha256:t.htmlSha256??E(t.acquiredHtml),markdownSha256:t.markdownSha256??E(t.bodyMarkdown)}}function R(t){return Buffer.from(JSON.stringify({version:"site-extract-content.v1",pages:t}))}async function M(t){let e=t.pages.flatMap(o=>{let c=B(o);return c?[c]:[]}),n=new Map,r=[],i=0,a=async()=>{if(!r.length)return;let o=R(r);if(o.length>b)throw new Error(`site export content chunk exceeds ${b} bytes`);let c=E(r.map(l=>l.pageId).join("\0")).slice(0,16),d=await O({ownerId:t.ownerId,jobId:t.jobId,createdAt:t.createdAt,chunkKey:`content-${String(i).padStart(4,"0")}-${c}`,content:q(o,{level:6})});for(let l of r)n.set(l.url,{artifactId:d.artifactId,artifactSha256:d.sha256,pageId:l.pageId,uncompressedBytes:o.length});i++,r=[]};for(let o of e){let c=[...r,o];if(r.length>0&&(c.length>F||R(c).length>b)&&await a(),r.push(o),R(r).length>b)throw new Error(`page ${o.pageId} exceeds the durable content chunk limit`)}return await a(),n}function it(t){let e=new Map;return async n=>{let r=e.get(n.artifactId);if(!r){let a=await k({artifactId:n.artifactId,ownerId:t});if(!a)throw new Error("site export content chunk is missing or unauthorized");if(E(a)!==n.artifactSha256)throw new Error("site export content chunk checksum mismatch");let o=$(a);if(o.length>b)throw new Error("site export content chunk exceeds its read limit");if(r=JSON.parse(o.toString("utf8")),r.version!=="site-extract-content.v1"||!Array.isArray(r.pages))throw new Error("site export content chunk has an unsupported contract");for(e.set(n.artifactId,r);e.size>2;)e.delete(e.keys().next().value)}let i=r.pages.find(a=>a.pageId===n.pageId);if(!i)throw new Error("site export page is missing from its content chunk");if(E(i.html)!==i.htmlSha256||E(i.markdown)!==i.markdownSha256)throw new Error("site export page checksum mismatch");return i}}var g="xray_entitlement";function pt(t){let e=Math.max(1,Number(t.options.effectiveMaxPages??t.options.maxPages??1)),n=Math.max(e,Number(t.options.requestedMaxPages??e)),r=n>e;return{requestedMaxPages:n,effectiveMaxPages:e,creditLimited:r,creditTruncated:r&&t.totalUrls>=e}}function Et(t,e=!1){return t.successfulUrls===0?"failed":t.failedUrls>0||t.remainingUrls>0||e?"partial":"complete"}function _(t){let e=Number(t.total_urls??0),n=t.attempted_urls==null,r=Number(n?t.done_urls??0:t.attempted_urls),i=Number(n?t.done_urls??0:t.successful_urls??0),a=Number(t.failed_urls??Math.max(0,r-i));return{id:String(t.id),userId:t.user_id!=null?Number(t.user_id):null,idempotencyKey:t.idempotency_key!=null?String(t.idempotency_key):null,requestFingerprint:t.request_fingerprint!=null?String(t.request_fingerprint):null,status:t.status!=null?String(t.status):"pending",startUrl:String(t.start_url??""),options:t.options?JSON.parse(String(t.options)):{},totalUrls:e,doneUrls:r,attemptedUrls:r,successfulUrls:i,failedUrls:a,remainingUrls:Math.max(0,e-r),artifacts:t.artifacts?JSON.parse(String(t.artifacts)):null,error:t.error!=null?String(t.error):null,publicError:I(t.public_error_json),billedMc:t.billed_mc!=null?Number(t.billed_mc):null,createdAt:String(t.created_at??""),updatedAt:String(t.updated_at??"")}}async function mt(t,e,n,r){await s().execute({sql:`INSERT INTO site_extract_jobs (id, user_id, status, start_url, options, created_at, updated_at)
2
2
  VALUES (?, ?, 'pending', ?, ?, datetime('now'), datetime('now'))`,args:[t,e,n,JSON.stringify(r)]})}async function K(t,e){let r=await s().execute({sql:"SELECT * FROM site_extract_jobs WHERE user_id = ? AND idempotency_key = ? LIMIT 1",args:[t,e]});return r.rows[0]?_(r.rows[0]):null}async function gt(t){let n=await s().execute({sql:`INSERT OR IGNORE INTO site_extract_jobs
3
3
  (id, user_id, status, start_url, options, idempotency_key, request_fingerprint, created_at, updated_at)
4
4
  VALUES (?, ?, 'pending', ?, ?, ?, ?, datetime('now'), datetime('now'))`,args:[t.jobId,t.userId,t.startUrl,JSON.stringify(t.options),t.idempotencyKey,t.requestFingerprint]}),r=await K(t.userId,t.idempotencyKey);if(!r)throw new Error("idempotent extract job was not persisted");return{job:r,created:n.rowsAffected===1,conflict:r.requestFingerprint!==t.requestFingerprint}}async function x(t){let n=await s().execute({sql:"SELECT * FROM site_extract_jobs WHERE id = ?",args:[t]});return n.rows[0]?_(n.rows[0]):null}async function _t(t){return(await s().execute({sql:"SELECT * FROM site_extract_jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[t]})).rows.map(r=>_(r))}async function xt(t=25){return(await s().execute({sql:`SELECT * FROM site_extract_jobs
@@ -0,0 +1,6 @@
1
+ import{a as Dt}from"./chunk-XG6GCEUE.js";import{k as H,m as kt,n as Ot,z as ue}from"./chunk-MC4W6TZT.js";import{a as L,c as xe,d as ce,e as V,f as de,j as Me,k as Nt}from"./chunk-WO46LTBW.js";import{b as It,c as Tt,d as $,f as z,g as B,h as U,i as Ct,k as F,n as xt,q as Mt}from"./chunk-LMWU7VPZ.js";import{a as Ne,b as De,g as qe}from"./chunk-EDQ57S4P.js";import{a as pt,b as mt}from"./chunk-GPSPSJBJ.js";import{a as Rt,b as Pt,d as Et}from"./chunk-VREXSMC6.js";import{b as St,c as At}from"./chunk-6DTXIZY2.js";import{e as dt}from"./chunk-XPEJB4BZ.js";import{Nb as le,Rb as Te,Tb as Ce,Va as Oe,b as Ee,g as M,h as gt,hb as vt,ia as bt,j as ft,ja as _t,jb as Ie,la as wt,m as ht,o as yt,oa as ke}from"./chunk-7YOXSMHG.js";import{request as Rr}from"https";import{HttpsProxyAgent as Pr}from"https-proxy-agent";var pe={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 oo=pe.source,qt=pe.retrievedAt,vr=new Set(pe.domains);function Z(e){let t=new URL(e).hostname.toLowerCase().replace(/\.$/,"");for(let o of vr)if(t===o||t.endsWith(`.${o}`))return"premium";return"standard"}function ee(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 me(e,t){if(ee(e),!Number.isSafeInteger(t)||t<0)throw new Error("Billable units must be a non-negative safe integer");let o=BigInt(e.numeratorUsdNanos)*BigInt(t),r=BigInt(e.denominatorUnits),n=(o*2n+r)/(r*2n);if(n>BigInt(Number.MAX_SAFE_INTEGER))throw new Error("Provider amount exceeds safe integer range");return Number(n)}function Sr(){return ee({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 Ht(e=process.env){let t=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_CONTRACT_USD_PER_1000?.trim(),o=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_RATE_SOURCE?.trim(),r=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&&!o&&!r&&!n)return Sr();if(!t||!o||!r||!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 s=Number(t);if(!Number.isFinite(s)||s<0)throw new Error("Invalid \u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP contract amount");return ee({providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_api",billingTier:"payg",billableEvent:"successful_delivery",unitType:"request",numeratorUsdNanos:Math.round(s*1e9),denominatorUnits:1e3,source:o,policyVersion:r,effectiveAt:n})}function Ar(e){return ee({providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser_api",billingTier:e,billableEvent:"transferred_byte",unitType:"byte",numeratorUsdNanos:(e==="premium"?11:8)*1e9,denominatorUnits:1e9,source:`owner_confirmed_payg_2026-09-23;\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_domain_snapshot_${qt}`,policyVersion:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061-browser-domain-tier-2026-09-23",effectiveAt:"2026-09-23T00:00:00Z"})}function so(e){return Ar(Z(e))}function Bt(){return ee({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 Er="https://api.\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061.com/request",kr=8e3,Or="brd.superproxy.io",Ir="44445",Tr=10*1024*1024;async function Cr(e,t){let o=new URL(`http://${t.host}:${t.port}`);o.username=t.username,o.password=t.password;let r=new Pr(o);try{return await new Promise((n,s)=>{let a=Rr(e,{agent:r,headers:{"x-unblock-data-format":"parsed"},rejectUnauthorized:!1,signal:t.signal},i=>{let u=[],l=0;i.on("data",c=>{let p=Buffer.isBuffer(c)?c:Buffer.from(c);if(l+=p.length,l>Tr){a.destroy(new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP response exceeded the maximum size"));return}u.push(p)}),i.on("end",()=>n({ok:(i.statusCode??500)>=200&&(i.statusCode??500)<300,status:i.statusCode??500,rawText:Buffer.concat(u).toString("utf8"),providerRequestId:typeof i.headers["x-response-id"]=="string"?i.headers["x-response-id"]:typeof i.headers["x-request-id"]=="string"?i.headers["x-request-id"]:null}))});a.on("error",()=>s(new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 native SERP request failed"))),a.end()})}finally{r.destroy()}}function ye(e=process.env){let t=!!(e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_USERNAME?.trim()&&e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PASSWORD?.trim()),o=!!((e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_API_KEY||e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_API_KEY)?.trim()&&e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_ZONE?.trim());return t||o}function m(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)?e:null}function N(e){return Array.isArray(e)?e:[]}function Be(e){return typeof e=="string"&&e.trim()?e.trim():null}function R(e){return typeof e=="number"&&Number.isFinite(e)?e:typeof e=="string"&&e.trim()&&Number.isFinite(Number(e))?Number(e):null}function g(e,t){for(let o of t){let r=Be(e[o]);if(r)return r}return null}function J(e){try{return new URL(e).hostname.replace(/^www\./,"")}catch{return""}}function Qt(e){return{rawUrl:e,resolvedUrl:e,linkType:"plain",resolutionStatus:"not_needed"}}function xr(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 o=m(t);if(!o)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API returned an invalid payload");if(typeof o.body=="string")try{let n=JSON.parse(o.body);if(m(n))return m(n)}catch{}let r=m(o.body);return r?m(r.result)??m(r.data)??r:m(o.result)??m(o.data)??o}function j(e,t){for(let r of t){let n=N(e[r]);if(n.length)return n}let o=m(e.results);if(o)for(let r of t){let n=N(o[r]);if(n.length)return n}return[]}function K(e,t){let o=[e,m(e.results)].filter(r=>!!r);for(let r of o)for(let n of t)if(Object.prototype.hasOwnProperty.call(r,n))return{observed:!0,rawShapeValid:Array.isArray(r[n]),rawCount:N(r[n]).length};return{observed:!1,rawShapeValid:!1,rawCount:0}}function He(e,t){let o=[e,m(e.results)].filter(r=>!!r);for(let r of o)for(let n of t){if(!Object.prototype.hasOwnProperty.call(r,n))continue;let s=m(r[n]);return{observed:!0,rawShapeValid:s!==null,rawCount:s&&Object.keys(s).length>0?1:0}}return{observed:!1,rawShapeValid:!1,rawCount:0}}function Ut(e){return j(e,["organic","organic_results","organicResults"]).flatMap((t,o)=>{let r=m(t);if(!r)return[];let n=g(r,["link","url","href"]),s=g(r,["title","name"]);if(!n||!s)return[];let a=m(r.rating)??m(r.inline_rating);return[{position:Math.max(1,Math.trunc(R(r.global_rank)??R(r.rank)??R(r.position)??o+1)),title:s,url:n,...Qt(n),domain:J(n),cite:g(r,["display_link","displayLink","cite"]),snippet:g(r,["description","snippet","text"]),isRedditStyle:J(n)==="reddit.com",inlineRating:a?{value:String(a.value??a.rating??""),count:String(a.count??a.reviews??"")}:null}]}).sort((t,o)=>t.position-o.position)}function Ft(e){return j(e,["snack_pack","local","local_results","local_pack","localPack"]).flatMap((t,o)=>{let r=m(t);if(!r)return[];let n=g(r,["title","name"]);if(!n)return[];let s=N(r.extensions??r.metadata).map(Be).filter(a=>!!a);return[{position:Math.max(1,Math.trunc(R(r.global_rank)??R(r.rank)??R(r.position)??o+1)),name:n,cid:g(r,["cid"]),rating:g(r,["rating"])??(R(r.rating)!=null?String(R(r.rating)):null),reviewCount:g(r,["reviews_cnt","reviews","review_count","reviewCount"])??(R(r.reviews_cnt)!=null?String(R(r.reviews_cnt)):R(r.reviews)!=null?String(R(r.reviews)):null),metadata:s,websiteUrl:g(r,["website","website_url","link"]),directionsUrl:g(r,["directions","directions_url"])}]})}function Wt(e){let t=m(e);return N(t?.citations??t?.sources??t?.references).flatMap(o=>{let r=m(o);if(!r)return[];let n=g(r,["link","url","href"]);return n?[{text:g(r,["title","text","name"])??J(n),href:n,...Qt(n)}]:[]})}function he(e,t=0){if(t>4)return[];if(Array.isArray(e))return e.flatMap(s=>he(s,t+1));let o=m(e);if(!o)return[];let r=g(o,["snippet","text","answer"]),n=he(o.texts??o.list??o.items,t+1);return[...r?[r]:[],...n]}function Gt(e,t){if(!t)return{detected:!1,text:null,citations:[]};let o=m(e.ai_overview)??m(e.aiOverview)??m(e.overview);if(!o)return{detected:!1,text:null,citations:[]};let r=g(o,["text","answer","description"])??(he(o.texts).join(`
2
+
3
+ `).slice(0,5e4)||null),n=Wt(o);return{detected:!!(r||n.length),text:r,citations:n}}function Lt(e,t){if(!t)return{detected:!1,text:null,citations:[]};let o=m(e.ai_mode)??m(e.aiMode);if(!o)return{detected:!1,text:null,citations:[]};let r=g(o,["text","answer","description"])??(he(o.texts).join(`
4
+
5
+ `).slice(0,5e4)||null),n=Wt(o);return{detected:!!(r||n.length),text:r,citations:n}}function Vt(e,t){return t?[...j(e,["videos","video_results"]),...j(e,["short_videos","shorts"])].flatMap(o=>{let r=m(o);if(!r)return[];let n=g(r,["link","url"]),s=g(r,["title","name"]);return!n||!s?[]:[{type:"video",title:s,channel:g(r,["channel","source"])??"",platform:J(n),duration:g(r,["duration"])??"",url:n}]}):[]}function $t(e,t){if(!t)return[];let o=m(e.forums);return[...j(e,["discussions","forums","forum_results"]),...N(o?.items)].flatMap(r=>{let n=m(r);if(!n)return[];let s=g(n,["link","url"]),a=g(n,["title","name"]);return!s||!a?[]:[{title:a,source:g(n,["source"])??J(s),url:s}]})}function zt(e,t){return t?j(e,["what_people_are_saying","whatPeopleSaying"]).flatMap(o=>{let r=m(o);if(!r)return[];let n=g(r,["link","url"]),s=g(r,["title","name"]);if(!n||!s)return[];let a=g(r,["platform","source"])??J(n),i=a.toLowerCase();return[{type:i.includes("reddit")?"reddit":i.includes("facebook")?"facebook":i.includes("instagram")?"instagram":i.includes("tiktok")?"tiktok":i.includes("youtube")?"youtube":i.includes("news")?"news":"unknown",title:s,url:n,source:a,platform:a,popularComment:g(r,["comment","popular_comment"]),engagement:g(r,["engagement"])??"",date:g(r,["date"])??"",duration:g(r,["duration"]),authorNote:g(r,["author_note"])}]}):[]}var Mr={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 ge(e,t){for(let o of[e,m(e.results)])if(o){for(let r of t)if(Object.prototype.hasOwnProperty.call(o,r))return{observed:!0,value:o[r]}}return{observed:!1,value:null}}function fe(e,t,o){return e?t==null||Array.isArray(t)&&t.length===0?"observed_absent":Array.isArray(t)?o>0?"observed_present":"incomplete":m(t)?o>0?"observed_present":Object.keys(m(t)).length===0?"observed_absent":"incomplete":"incomplete":"unknown"}function Nr(e,t){let o={},r=[["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[u,l,c]of r){let p=ge(e,l);o[u]=fe(p.observed,p.value,c)}let n=ge(e,["ai_mode","aiMode"]);o.aiMode=fe(n.observed,n.value,t.aiMode);let s=ge(e,["people_also_ask","peopleAlsoAsk","related_questions","paa"]),a=N(s.value).slice(0,30).flatMap(u=>{let l=m(u);if(!l)return[];let c=g(l,["question","title"]);return c?[{question:c.slice(0,1e3),answer:g(l,["answer","snippet","text"])?.slice(0,1e4)??null,url:g(l,["link","url"])??null}]:[]});o.paaPreview=fe(s.observed,s.value,a.length);let i=[];for(let[u,l]of Object.entries(Mr)){let c=ge(e,l);if(!c.observed)continue;let p=m(c.value),w=(Array.isArray(c.value)?c.value:p&&(Array.isArray(p.items)||Array.isArray(p.posts))?[...N(p.items),...N(p.posts)]:[c.value]).slice(0,20).flatMap(S=>{let y=m(S);if(!y)return[];let T=g(y,["title","name","heading"]),k=g(y,["link","url","website"]),D=g(y,["description","snippet","text","summary","story"]);return!T&&!k&&!D?[]:[{title:T?.slice(0,1e3)??null,url:k,description:D?.slice(0,1e4)??null,position:R(y.global_rank)??R(y.rank)??R(y.position)??null}]});o[u]=fe(c.observed,c.value,w.length);let A=Object.fromEntries(Object.entries(p??{}).slice(0,30).flatMap(([S,y])=>/^[a-zA-Z0-9_]{1,80}$/.test(S)&&(y===null||["string","number","boolean"].includes(typeof y))?[[S,typeof y=="string"?y.slice(0,2e3):y]]:[]));i.push({name:u,attributes:A,items:w})}return{status:o,paaPreview:a,additional:i}}function Kt(e,t){let o=new Set,r=new Set(t.map(a=>a.cid).filter(a=>!!a)),n=new Set,s=(a,i=0)=>{if(i>6||a==null)return;if(Array.isArray(a)){for(let l of a)s(l,i+1);return}let u=m(a);if(u)for(let[l,c]of Object.entries(u)){let p=l.toLowerCase().replace(/[^a-z]/g,""),b=Be(c);b&&(p==="kgid"||p==="kgmid"||p==="mid")?o.add(b):b&&p==="cid"?r.add(b):b&&p==="gcid"?n.add(b):typeof c=="object"&&s(c,i+1)}};return s(e),{entities:[],kgIds:[...o],cids:[...r],gcids:[...n]}}function Jt(e,t){let o=e instanceof Error?e.message:String(e);return t.aborted||/timeout|timed out/i.test(o)?"timeout":/captcha|recaptcha|unusual traffic|google\.com\/sorry|blocked/i.test(o)?"captcha":/invalid (?:json|payload)/i.test(o)?"invalid_payload":"provider_error"}function jt(e){return e==="invalid_payload"?"invalid_payload":e==="captcha"?"serp_readiness":e==="timeout"||e==="provider_error"?"provider_transport":"pagination"}async function Ue(e,t=process.env,o=fetch,r=Cr,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 s=(t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_API_KEY||t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_API_KEY)?.trim(),a=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_ZONE?.trim(),i=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_USERNAME?.trim(),u=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PASSWORD?.trim(),l=!!(i&&u);if(!l&&(!s||!a))throw new Error("Direct SERP API is not configured");let c=Date.now(),p=At(),b=null,w=e.location?Ot(e.location):null;if(e.location&&!w?.canonical)throw new L("query_integrity","location_unresolved",`SERP location could not be resolved without changing the query (candidates: ${w?.ambiguousCandidates??0})`);let A=w?.canonical?kt(w.canonical):null,S=AbortSignal.timeout(e.includeAllSerpFeatures?33e3:kr),y=e.signal?AbortSignal.any([e.signal,S]):S,T=1,k=[],D=[],We=0,Ye=async d=>{let O=Date.now(),_=l?"\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",I=null,q=null,Q=!1,W=!1,G=null,Y=null;if(p?.operationRunId&&(d===1||b))try{I=await $({runId:p.operationRunId,attemptNumber:n?n.attemptNumber+d-1:d,method:_,provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",...d===2?{parentAttemptId:b,edgeKind:"next_phase"}:n?{parentAttemptId:n.parentAttemptId,edgeKind:"provider_fallback",retryKind:"provider_fallback"}:{},normalizedFlags:{page:d,device:e.device,hasLocation:!!e.location}}),d===1&&(b=I),q=(await B({attemptId:I,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:p.operationAccountScope??"production-default",method:_,providerStatus:"started"})).id}catch(h){throw console.warn(JSON.stringify({event:"direct_serp_telemetry_start_failed",page:d,message:h instanceof Error?h.message:String(h)})),h}let P=new URLSearchParams({q:e.query,gl:e.gl,hl:e.hl,pws:"0",num:"10",...d===2?{start:"10"}:{}}),ie=dt(e.recency);ie&&P.set("tbs",ie),e.device==="mobile"&&P.set("brd_mobile","1"),(e.includeAiOverview||e.includeAllSerpFeatures)&&P.set("brd_ai_overview","2"),A&&P.set("uule",A),l&&P.set("brd_json","1"),We+=1;let x;try{if(l){let E=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_HOST?.trim()||Or,X=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PORT?.trim()||Ir;x=await r(`https://www.google.com/search?${P}`,{username:i,password:u,host:E,port:X,signal:y})}else{let E=await o(Er,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({zone:a,url:`https://www.google.com/search?${P}`,format:"json",data_format:"parsed"}),signal:y});x={ok:E.ok,status:E.status,rawText:await E.text(),providerRequestId:E.headers.get("x-response-id")??E.headers.get("x-request-id")}}if(Y=`http_${x.status}`,q&&x.providerRequestId&&await U(q,x.providerRequestId),!x.ok)throw new Error(`\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API failed with HTTP ${x.status}`);Q=!0;let h;try{h=xr(JSON.parse(x.rawText))}catch(E){let X=E instanceof Error&&E.message!=="Unexpected end of JSON input"?E.message:"\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API returned invalid JSON";throw new L("invalid_payload","invalid_provider_payload",X)}let f=Ut(h);return k.push({page:d,attempted:!0,captured:f.length>0,resultCount:f.length,requestOffset:d===2?10:0,providerRequestIdObserved:!!x.providerRequestId,...f.length===0?{failureCode:"empty_page"}:{}}),W=!0,h}catch(h){G=h;let f=Jt(h,y);if(k.some(X=>X.page===d)||k.push({page:d,attempted:!0,captured:!1,resultCount:0,requestOffset:d===2?10:0,providerRequestIdObserved:!1,failureCode:f}),d===2)throw h;let E=h instanceof L?h.stage:jt(f);throw h instanceof L?h:new L(E,f,h instanceof Error?h.message:String(h))}finally{let h=null;if(q&&Q)try{let f=Ht(t);await F({receiptId:q,costState:"measured",units:1,unitType:"request",amountUsdNanos:me(f,1),rateSource:f.source,providerProduct:f.providerProduct,billingTier:f.billingTier,billableEvent:f.billableEvent,measurementSource:"provider_http_delivery",rateNumerator:f.numeratorUsdNanos,rateDenominator:f.denominatorUnits,ratePolicyVersion:f.policyVersion,rateEffectiveAt:f.effectiveAt,providerStatus:Y??"delivered",providerDurationMs:Date.now()-O})}catch(f){console.warn(JSON.stringify({event:"direct_serp_receipt_finalize_failed",page:d,message:f instanceof Error?f.message:String(f)})),h=f}if(I&&await z({attemptId:I,status:W?"succeeded":y.aborted?"timed_out":"failed",errorCode:G?Jt(G,y):null,durationMs:Date.now()-O}).catch(f=>console.warn(JSON.stringify({event:"direct_serp_attempt_finish_failed",page:d,message:f instanceof Error?f.message:String(f)}))),h)throw h}};try{D.push({page:1,payload:await Ye(1)})}catch(d){throw d}let Xe=null;if(T===2)try{D.push({page:2,payload:await Ye(2)})}catch(d){Xe=d}let dr=Date.now()-c,pr=Date.now(),v=D[0].payload,mr=D.flatMap(({page:d,payload:O})=>Ut(O).map(_=>({..._,position:d===2&&_.position<=10?_.position+10:_.position,sourcePage:d}))).filter((d,O,_)=>_.findIndex(I=>xe(I.url)===xe(d.url))===O),Ze=e.includeLocalPack||e.includeAllSerpFeatures,ve=Ze?Ft(v):[],Se=K(v,["snack_pack","local","local_results","local_pack","localPack"]),gr=V({requested:Ze,moduleObserved:Se.observed,rawCount:Se.rawCount,mappedCount:ve.length,rawShapeValid:Se.rawShapeValid}),et=e.includeAiOverview||e.includeAllSerpFeatures,tt=Gt(v,et),rt=e.includeForums||e.includeAllSerpFeatures,ot=$t(v,rt),nt=e.includeVideos||e.includeAllSerpFeatures,at=Vt(v,nt),st=e.includeWhatPeopleSaying||e.includeAllSerpFeatures,it=zt(v,st),Ae=m(v.forums),Re=Ae&&Array.isArray(Ae.items)?{observed:!0,rawCount:Ae.items.length,rawShapeValid:!0}:K(v,["discussions","forums","forum_results"]),Pe=K(v,["videos","video_results","short_videos","shorts"]),lt={localPack:gr,forums:V({requested:rt,moduleObserved:Re.observed,rawCount:Re.rawCount,mappedCount:ot.length,rawShapeValid:Re.rawShapeValid}),videos:V({requested:nt,moduleObserved:Pe.observed,rawCount:Pe.rawCount,mappedCount:at.length,rawShapeValid:Pe.rawShapeValid}),aiOverview:V({requested:et,moduleObserved:He(v,["ai_overview","aiOverview","overview"]).observed,rawCount:He(v,["ai_overview","aiOverview","overview"]).rawCount,mappedCount:tt.detected?1:0,rawShapeValid:He(v,["ai_overview","aiOverview","overview"]).rawShapeValid}),whatPeopleSaying:V({requested:st,moduleObserved:K(v,["what_people_are_saying","whatPeopleSaying"]).observed,rawCount:K(v,["what_people_are_saying","whatPeopleSaying"]).rawCount,mappedCount:it.length,rawShapeValid:K(v,["what_people_are_saying","whatPeopleSaying"]).rawShapeValid})},fr=ce(1,k),hr=k.find(d=>d.page===1)?.resultCount??0,ae=k.find(d=>d.page===2)?.resultCount??0,yr=de({query:e.query,finalQuery:e.query,canonicalLocation:w?.canonical??null,locationResolutionSource:w?.source??"not_requested",locationAmbiguousCandidates:w?.ambiguousCandidates??0,uule:A,outboundProviderMethod:l?"\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"}),se=Xe?jt(k.find(d=>d.page===2)?.failureCode??"provider_error"):Object.values(lt).some(d=>d==="incomplete"||d==="unknown")?"optional_feature_parsing":null,br={pagination:{...fr,providerRequestCount:We},features:lt,queryIntegrity:yr,failureStage:se},ut=e.includeAllSerpFeatures?(()=>{let d=D.map(({page:O,payload:_})=>{let I=Ft(_),q=$t(_,!0),Q=Vt(_,!0),W=zt(_,!0),G=Gt(_,!0),Y=Lt(_,!0),P=Kt(_,I),ie=Nr(_,{localPack:I.length,forums:q.length,videos:Q.length,aiOverview:G.detected?1:0,aiMode:Y.detected?1:0,whatPeopleSaying:W.length,entityIds:P.entities.length+P.kgIds.length+P.cids.length+P.gcids.length});return{page:O,...ie,localPack:I,forums:q,videos:Q,whatPeopleSaying:W,aiOverview:G,aiMode:Y,entityIds:P}});return{status:d[0].status,paaPreview:d.flatMap(O=>O.paaPreview),additional:d.flatMap(O=>O.additional),pages:d}})():void 0,_r=new Date().toISOString(),ct=Date.now()-c;return{seed:e.query,location:e.location??null,extractedAt:_r,diagnostics:{phaseTimings:{providerConnectMs:dr,serpParseMs:Date.now()-pr,totalServerMs:ct},pagination:{requestedPages:T,capturedPages:T===2&&ae>0?2:1,page2Status:T===2?ae>0?"captured":"failed":"not_requested",page1OrganicCount:hr,page2OrganicCount:ae,...T===2&&ae===0?{failureCode:k.find(d=>d.page===2)?.failureCode==="captcha"?"captcha":k.find(d=>d.page===2)?.failureCode==="timeout"?"timeout":"empty_page"}:{}},completionStatus:"serp_only",problem:null,resultQuality:se?"partial":"complete",degradedResult:!!se,degradationReasons:[],retryRecommended:!!se,serpCompleteness:br},totalQuestions:0,surface:"web",aiOverview:tt,aiMode:Lt(v,e.includeAllSerpFeatures),...ut?{fullSerpFeatures:ut}:{},whatPeopleSaying:it,tree:[],flat:[],videos:at,forums:ot,organicResults:mr,localPack:ve,entityIds:Kt(v,ve),stats:{seed:e.query,totalQuestions:0,maxDepthReached:0,durationMs:ct,errorCount:0}}}var Dr="scraperlink~google-search-results-serp-scraper",te="https://api.apify.com/v2";var C=class extends Error{constructor(o,r=null,n=!1,s=null){super(o);this.runId=r;this.retrySafe=n;this.terminalStatus=s;this.name="ApifyGoogleRunError"}runId;retrySafe;terminalStatus};function re(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:null}function oe(e){return typeof e=="string"&&e.trim()?e.trim():null}function qr(e){try{return["http:","https:"].includes(new URL(e).protocol)}catch{return!1}}function Hr(e){if(typeof e!="string")return e;try{return JSON.parse(e)}catch{throw new Error("Apify searchResults is not valid JSON")}}function Yt(e,t){if(!Array.isArray(e)||e.length===0)throw new Error("Apify dataset contains no search results");let o=[];for(let[s,a]of e.entries()){let i=re(a);if(!i)throw new Error("Apify dataset contains an invalid row");let u=Hr(i.searchResults??i),l=re(u),c=Array.isArray(u)?u:Array.isArray(l?.results)?l.results:Array.isArray(l?.organicResults)?l.organicResults:Array.isArray(l?.organic)?l.organic:l&&(l.position!==void 0||l.title!==void 0)?[l]:null;if(!c)throw new Error("Apify dataset search result shape is unsupported");let p=Number(i.page_number??l?.page_number??s+1);if(!Number.isInteger(p)||p<1||p>t)throw new Error("Apify dataset has an unexpected page number");o.push(...c.map(b=>({row:b,page:p})))}let r=o.map(({row:s,page:a},i)=>{let u=re(s),l=u?.position,c=oe(u?.title),p=oe(u?.url??u?.link);if(!u||!c||!p||!qr(p)||l!==void 0&&(!Number.isInteger(l)||l<1))throw new Error(`Apify search result ${i+1} is missing a valid position, URL, or title`);let b=oe(u.description??u.snippet),w=typeof l=="number"?l:i%10+1;return{position:a>1&&w<=10?w+(a-1)*10:w,url:p,title:c,description:b}});if(r.length>t*10)throw new Error("Apify returned more results than requested");let n={page1:r.filter(s=>s.position<=10).length,page2:r.filter(s=>s.position>10).length};if(n.page1===0)throw new Error("Apify did not return the first result page");return{results:r,pageResultCounts:n}}async function be(e,t,o,r){let n=await o(e,{headers:{Authorization:`Bearer ${t}`},signal:r});if(!n.ok)throw new Error(`Apify API returned HTTP ${n.status}`);return n.json()}function Fe(e){let t=re(re(e)?.data),o=oe(t?.id),r=oe(t?.status);if(!o||!r)throw new Error("Apify returned an invalid run receipt");return{id:o,status:r}}async function Br(e,t=fetch){let o=performance.now(),r=AbortSignal.timeout(9e4),n=e.signal?AbortSignal.any([e.signal,r]):r,s=e.runId,a=!1,i=null;try{if(!/^[A-Za-z0-9]+$/.test(s))throw new Error("Invalid Apify run ID");let u=Fe(await be(`${te}/actor-runs/${s}?waitForFinish=30`,e.token,t,n));for(;["READY","RUNNING","TIMING-OUT","ABORTING"].includes(u.status);)u=Fe(await be(`${te}/actor-runs/${s}?waitForFinish=30`,e.token,t,n));if(a=!0,i=u.status,u.status!=="SUCCEEDED")throw new Error(`Apify run ended with status ${u.status}`);let l=e.pages??1,c=await be(`${te}/actor-runs/${s}/dataset/items?format=json`,e.token,t,n);return{query:e.query,...Yt(c,l),requestedPages:l,runId:s,elapsedMs:Math.round(performance.now()-o)}}catch(u){throw new C(u instanceof Error?u.message:String(u),s,a,i)}}async function Xt(e,t,o=fetch){let r=performance.now(),n=e.query.trim(),s=e.pages??1;if(!n||n.includes(`
6
+ `))throw new Error("Apify search requires one nonempty query");if(s!==1&&s!==2)throw new Error("Apify search supports one or two pages");let a=t.token.trim();if(!a)throw new Error("Apify API token is required");let i=t.maxChargeUsd??.01;if(!Number.isFinite(i)||i<=0)throw new Error("Invalid Apify charge cap");let u=AbortSignal.timeout(9e4),l=e.signal?AbortSignal.any([e.signal,u]):u,c=`${te}/actors/${Dr}/runs?maxTotalChargeUsd=${i}&restartOnError=false&waitForFinish=30`,p=null,b=!1,w=null;try{let A=await o(c,{method:"POST",headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"},body:JSON.stringify({keyword:n,limit:s===2?"20":"10",page:1,proxy_location:"us",include_merged:!1}),signal:l});if(!A.ok)throw new Error(`Apify run start returned HTTP ${A.status}`);let S=Fe(await A.json());if(p=S.id,b=!["READY","RUNNING","TIMING-OUT","ABORTING"].includes(S.status),b&&(w=S.status),S.status!=="SUCCEEDED"&&S.status!=="READY"&&S.status!=="RUNNING")throw new Error(`Apify run ended with status ${S.status}`);if(S.status==="SUCCEEDED"){let T=await be(`${te}/actor-runs/${p}/dataset/items?format=json`,a,o,l);return{query:n,...Yt(T,s),requestedPages:s,runId:p,elapsedMs:Math.round(performance.now()-r)}}return{...await Br({runId:p,query:n,token:a,pages:s,signal:l},o),elapsedMs:Math.round(performance.now()-r)}}catch(A){throw A instanceof C?A:new C(A instanceof Error?A.message:String(A),p,b,w)}}var Zt="apify_google_serp",er="apify",Ur="apify_google_serp_scraperlink";async function tr(e,t,o,r){let n=Bt();await F({receiptId:e,costState:"estimated",units:t,unitType:n.unitType,amountUsdNanos:me(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:r,providerDurationMs:o})}async function rr(e){let t=performance.now(),o=await $({runId:e.operationRunId,attemptNumber:e.attemptNumber,method:Zt,provider:er,parentAttemptId:e.parentAttemptId,edgeKind:e.edgeKind,retryKind:e.retryKind,normalizedFlags:{page:1,pages:e.options.pages??1,proxyLocation:"us"}}),r=await B({attemptId:o,provider:er,providerProduct:Ur,billingTier:"store_pay_per_event",accountScope:e.accountScope,method:Zt,providerStatus:"before_actor_start"}),n=null,s=null;try{return n=await Xt(e.options,{token:e.token},e.fetchImpl),await U(r.id,n.runId),await tr(r.id,n.requestedPages,n.elapsedMs,"succeeded_estimated"),{...n,attemptId:o}}catch(a){throw s=a,n?Object.assign(new C("Apify cost tracking failed after run completion",n.runId),{attemptId:o}):(a instanceof C&&a.runId&&(await U(r.id,a.runId),a.terminalStatus==="SUCCEEDED"?await tr(r.id,e.options.pages??1,Math.round(performance.now()-t),"succeeded_dataset_unavailable"):await Ct({receiptId:r.id,units:e.options.pages??1,unitType:"page",providerStatus:"run_outcome_or_cost_pending"})),Object.assign(a instanceof Error?a:new Error(String(a)),{attemptId:o}))}finally{await z({attemptId:o,status:s?e.options.signal?.aborted?"timed_out":"failed":"succeeded",errorCode:s?"apify_search_failed":null,durationMs:Math.round(performance.now()-t)})}}function or(e,t=e.requestedPages){let o=e.results.map(a=>{let i=new URL(a.url).hostname.replace(/^www\./,"");return{position:a.position,title:a.title,url:a.url,rawUrl:a.url,resolvedUrl:a.url,linkType:"plain",resolutionStatus:"not_needed",domain:i,cite:null,snippet:a.description,isRedditStyle:i==="reddit.com",inlineRating:null}}),r=t===2&&e.pageResultCounts.page2>0?2:1,n=t===2&&r===1,s=ce(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:r,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:s,features:{localPack:"not_requested",forums:"not_requested",videos:"not_requested",aiOverview:"not_requested",whatPeopleSaying:"not_requested"},queryIntegrity:de({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:o,localPack:[],entityIds:{entities:[],kgIds:[],cids:[],gcids:[]},stats:{seed:e.query,totalQuestions:0,maxDepthReached:0,durationMs:e.elapsedMs,errorCount:0}}}var Fr=12e3;function ar(e){return e.recency?H():e.pages===2?!!e.token||H():e.mode==="full"?ye()||H():!!e.token||ye()||H()}async function Ge(e){if(e.recency)return ne(e);if(e.mode==="full")return Gr(e);if(!e.token)return nr(e);let t=performance.now(),o;for(let r=1;r<=2;r++){let n=AbortSignal.any([e.signal,AbortSignal.timeout(Fr)]),s=e.pages===2&&r===2?1:e.pages;try{let a=await rr({options:{query:e.query,pages:s,signal:n},token:e.token,operationRunId:e.operationRunId,accountScope:e.accountScope,attemptNumber:r,...o?{parentAttemptId:o,edgeKind:"same_method_retry",retryKind:"same_method"}:{}});console.info(JSON.stringify({event:"serp_provider_succeeded",provider:"apify",operationRunId:e.operationRunId,attemptNumber:r,durationMs:a.elapsedMs,resultCount:a.results.length,requestedPages:e.pages,providerRequestedPages:a.requestedPages,deliveredPages:a.pageResultCounts.page2>0?2:1,runId:a.runId}));let i=or(a,e.pages);return i.stats.durationMs=Math.round(performance.now()-t),i.diagnostics.phaseTimings&&(i.diagnostics.phaseTimings.totalServerMs=i.stats.durationMs),{result:i,mode:"light",deliveryProvider:"apify",deliveredPages:a.pageResultCounts.page2>0?2:1}}catch(a){o=a&&typeof a=="object"&&"attemptId"in a?String(a.attemptId):void 0;let i=a instanceof C?a:null;if(console.warn(JSON.stringify({event:"serp_provider_failed",provider:"apify",operationRunId:e.operationRunId,attemptNumber:r,runId:i?.runId??null,requestedPages:e.pages,attemptPages:s,retrySafe:i?.retrySafe===!0,error:a instanceof Error?a.message:String(a)})),e.signal.aborted||!o||i?.retrySafe!==!0)throw a}}return nr(e,o)}async function nr(e,t){if(e.pages===2||!ye())return ne(e);let o=performance.now(),r={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 Ue(r,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");return n.stats.durationMs=Math.round(performance.now()-o),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){if(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)})),e.signal.aborted||!H())throw n;return ne(e)}}async function ne(e){let t=await ue({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 o=t.diagnostics.pagination?.capturedPages===2?2:1;if(e.pages===2&&o===1&&(t.diagnostics.resultQuality="partial",t.diagnostics.degradedResult=!0,t.diagnostics.degradationReasons=["page_two_missing"],t.diagnostics.retryRecommended=!0),e.mode==="full"){let r=Object.fromEntries(["localPack","forums","videos","aiOverview","aiMode","whatPeopleSaying","entityIds","paaPreview","topStories"].map(n=>[n,"unsupported"]));t.fullSerpFeatures={status:r,paaPreview:[],additional:[],pages:[]}}return{result:t,mode:e.mode==="full"?"full":"light",deliveryProvider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",deliveredPages:o}}async function Gr(e){if(e.pages===2){let t=await Ge({...e,mode:"light",pages:2}),o=Object.fromEntries(["localPack","forums","videos","aiOverview","aiMode","whatPeopleSaying","entityIds","paaPreview","topStories"].map(n=>[n,"unsupported"]));t.result.fullSerpFeatures={status:o,paaPreview:[],additional:[],pages:[]};let r=t.result.diagnostics;return r.serpCompleteness&&(r.serpCompleteness.features={localPack:"unsupported",forums:"unsupported",videos:"unsupported",aiOverview:"unsupported",whatPeopleSaying:"unsupported"}),{...t,mode:"full"}}try{return await Lr({...e,mode:"full"})}catch(t){if(e.signal.aborted||!H())throw t;return ne({...e,mode:"full"})}}async function Lr(e){let t=performance.now(),o=e.mode==="full",r={query:e.query,gl:"us",hl:"en",device:"desktop",pages:1,...e.recency?{recency:e.recency}:{},includeAllSerpFeatures:o,includeLocalPack:o,includeForums:o,includeVideos:o,includeAiOverview:o,includeWhatPeopleSaying:o,signal:e.signal},n=await Ue(r);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:o?"full":"light",deliveryProvider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",deliveredPages:n.diagnostics.pagination?.capturedPages===2?2:1}}async function Le(e,t,o=3){for(let r=1;r<=o;r++){try{let n=await fetch(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t),signal:AbortSignal.timeout(1e4)});if(n.ok)return;console.warn(`[webhook] attempt ${r} \u2192 ${n.status} from ${e}`)}catch(n){console.warn(`[webhook] attempt ${r} failed:`,n instanceof Error?n.message:n)}r<o&&await new Promise(n=>setTimeout(n,1e3*r*2))}console.error(`[webhook] gave up after ${o} attempts for ${e}`)}function Vr(e){return e instanceof Error?e.message:String(e)}function $r(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 zr(e){return/captcha|recaptcha|unusual traffic|google\.com\/sorry|blocked/i.test(e)}function Kr(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 Jr(e){return/proxy unavailable|proxy_unavailable|connection_test_failed|did not return a proxy id|configured fallback/i.test(e)}function jr(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 Qr(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 Ve(e){let t=Vr(e);return e instanceof ht?{error_code:"request_aborted",error_type:"request_aborted",message:M("request_aborted"),retryable:!0,httpStatus:408,terminalStatus:"cancelled"}:e instanceof ft||zr(t)?{error_code:"captcha_exhausted",error_type:"captcha",message:M("captcha_exhausted"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:Dt(e,t)?{error_code:"vendor_unavailable",error_type:"service_unavailable",message:M("vendor_unavailable"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:e instanceof yt?{error_code:"location_mismatch",error_type:"location_mismatch",message:M("location_mismatch"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:Kr(t)?{error_code:"proxy_tunnel_failed",error_type:"connection",message:M("proxy_tunnel_failed"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:Jr(t)?{error_code:"proxy_unavailable",error_type:"connection",message:M("proxy_unavailable"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:Qr(t)?{error_code:"browser_session_interrupted",error_type:"extraction",message:M("browser_session_interrupted"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:$r(e,t)?{error_code:"harvest_timeout",error_type:"timeout",message:M("harvest_timeout"),retryable:!0,httpStatus:504,terminalStatus:"failed"}:jr(t)?{error_code:"service_unavailable",error_type:"service_unavailable",message:Ee,retryable:!0,httpStatus:503,terminalStatus:"failed"}:{error_code:"extraction_failed",error_type:"extraction",message:Ee,retryable:!1,httpStatus:500,terminalStatus:"failed"}}function $e(e){return JSON.stringify({error_code:e.error_code,error_type:e.error_type,message:e.message,retryable:e.retryable})}function _e(e,t={}){let o=gt({errorCode:e.error_code,errorType:e.error_type,retryable:e.retryable,retryAfterSeconds:t.retryAfterSeconds,chargeStatus:t.chargeStatus,details:t.details});return{error:o.message,...o}}function ze(e,t={}){let{error:o,...r}=_e(e,t);return r}function qo(e,t={}){let o=Ve(e);return{body:_e(o,t),status:o.httpStatus}}import{createHash as Wr}from"crypto";var Yr=1e9;function Xr(e){return Wr("sha256").update(JSON.stringify(e)).digest("hex")}function we(e){return`harvest:${e}`}async function Lo(e){let t=we(e.jobId);try{return(await It({id:t,userId:e.userId,ownerScope:`user:${e.userId}`,tool:e.tool,normalizedFlags:e.normalizedFlags,idempotencyKey:`job:${e.jobId}`,requestFingerprint:Xr(e.normalizedFlags),jobId:e.jobId,requestId:e.requestId??null,deploymentCommit:process.env.VERCEL_GIT_COMMIT_SHA?.trim()||process.env.GIT_COMMIT_SHA?.trim()||null})).id}catch(o){return console.warn(JSON.stringify({event:"operation_run_start_failed",job_id:e.jobId,tool:e.tool,message:o instanceof Error?o.message:String(o)})),null}}async function Je(e,t,o){if(e)try{await Tt({runId:e,status:t,failureClass:o})}catch(r){console.warn(JSON.stringify({event:"operation_run_finish_failed",operation_run_id:e,message:r instanceof Error?r.message:String(r)}))}}async function Vo(e,t,o,r){if(!(!e||!t))try{await xt({runId:e,billingTable:"billing_debits",billingKey:t,relation:o,amountMc:r})}catch(n){console.warn(JSON.stringify({event:"operation_billing_link_failed",operation_run_id:e,relation:o,message:n instanceof Error?n.message:String(n)}))}}function Ke(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 Zr(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 sr(e,t,o=0){let r=new Map,n=null;return async s=>{if(e)try{if(s.type==="started"){let i=o+s.attemptNumber;if(i>1&&!n){let p=(await Mt(e))?.attempts.at(-1);n=p?.id==null?null:String(p.id)}let u=await $({runId:e,attemptNumber:i,method:s.method,provider:s.provider,parentAttemptId:i===1?null:n,edgeKind:i===1?null:o>0&&s.attemptNumber===1?"durable_resume":s.retryKind==="provider_fallback"?"provider_fallback":"same_method_retry",retryKind:i===1?null:o>0&&s.attemptNumber===1?"durable_resume":s.retryKind,retryReason:i===1?null:o>0&&s.attemptNumber===1?"durable_worker_resume":s.retryReason,retryOwner:i===1?null:o>0&&s.attemptNumber===1?"durable_reconciler":"harvest",normalizedFlags:{maxAttempts:s.maxAttempts,maxQuestions:s.maxQuestions,hasLocation:!!s.location,plannedProvider:s.provider,planReason:s.planReason??null,planTimeoutMs:s.planTimeoutMs??null},startedAt:s.startedAt}),l=await B({attemptId:u,provider:s.provider,providerProduct:s.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:s.provider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?Z("https://www.google.com/search"):null,accountScope:t,method:s.method,providerStatus:"started"});r.set(s.attemptNumber,{attemptId:u,receiptId:l.id,plannedProvider:s.provider,observedProvider:null,providerMismatch:!1,method:s.method,startedAtMs:Date.parse(s.startedAt),billingMode:null}),n=u;return}let a=r.get(s.attemptNumber);if(!a)throw new Error(`Missing operation attempt state for attempt ${s.attemptNumber}`);if(s.type==="provider_session_started"){let i=Zr(s.provider);if(a.observedProvider=i,a.billingMode=s.billingMode??null,i!==a.plannedProvider){a.providerMismatch=!0,await F({receiptId:a.receiptId,costState:"unavailable",providerStatus:"provider_mismatch",errorCode:"provider_mismatch",errorMessage:`Planned ${a.plannedProvider}; observed ${i}`,finalizedAt:s.observedAt});let u=i==="\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",l=await B({attemptId:a.attemptId,provider:i,providerProduct:i==="\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==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?Z("https://www.google.com/search"):null,accountScope:t,method:u,providerStatus:"observed_provider_mismatch"});a.receiptId=l.id,a.method=u}await U(a.receiptId,s.providerSessionId);return}if(await z({attemptId:a.attemptId,status:a.providerMismatch?"failed":Ke(s.outcome),errorCode:a.providerMismatch?"provider_mismatch":Ke(s.outcome)==="succeeded"?null:s.outcome,errorMessage:s.error,durationMs:s.durationMs,endedAt:s.completedAt}),(a.observedProvider??a.plannedProvider)==="\u006b\u0065\u0072\u006e\u0065\u006c"){let i=a.billingMode==="headful",u=a.billingMode==="headless"||a.billingMode==="headful"?Et(s.durationMs,i):null;await F({receiptId:a.receiptId,costState:"estimated",units:s.durationMs/1e3,unitType:"wall_open_second",amountUsdNanos:u==null?null:Math.round(u*Yr),providerProduct:"\u006b\u0065\u0072\u006e\u0065\u006c_browser",billingTier:a.billingMode,billableEvent:"provider_active_gb_second",measurementSource:"wall_open_time_proxy",rateSource:u!=null?`\u006b\u0065\u0072\u006e\u0065\u006c_${a.billingMode}_usd_per_second:${i?Pt:Rt}`:null,providerStatus:a.providerMismatch?"provider_mismatch":s.outcome,providerDurationMs:s.durationMs,errorCode:a.providerMismatch?"provider_mismatch":Ke(s.outcome)==="succeeded"?null:s.outcome,errorMessage:s.error,finalizedAt:s.completedAt})}}catch(a){console.warn(JSON.stringify({event:"operation_attempt_telemetry_failed",operation_run_id:e,attempt_number:s.attemptNumber,message:a instanceof Error?a.message:String(a)}))}}}function je(e,t,o=null,r="production-default",n=0){let s=sr(o,r,n);return async a=>{if(await s(a),a.type==="started"){await bt({jobId:e,userId:t,attemptNumber:a.attemptNumber,maxAttempts:a.maxAttempts,query:a.query,location:a.location,maxQuestions:a.maxQuestions,startedAt:a.startedAt});return}if(a.type==="provider_session_started"){await _t({jobId:e,attemptNumber:a.attemptNumber,browserProvider:a.provider,providerSessionId:a.providerSessionId,observedAt:a.observedAt});return}await wt({jobId:e,attemptNumber:a.attemptNumber,outcome:a.outcome,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:a.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:a.questionCount,durationMs:a.durationMs,error:a.error,willRetry:a.willRetry,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:a.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:a.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:a.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError,browserCloseSucceeded:a.cleanup.browserCloseSucceeded,browserCloseError:a.cleanup.browserCloseError,browserProvider:a.cleanup.provider??null,providerSessionId:a.cleanup.providerSessionId??null,providerLookupStatus:a.cleanup.providerSessionId?"pending":"not_applicable",providerErrorCode:a.cleanup.providerDisconnectObserved?"browser_session_interrupted":null,providerErrorMessage:a.cleanup.providerDisconnectMessage??null,providerReasonSource:a.cleanup.providerDisconnectObserved?"client_runtime":null,providerDisconnectObserved:a.cleanup.providerDisconnectObserved??!1,providerDisconnectMessage:a.cleanup.providerDisconnectMessage??null,debug:a.debug,completedAt:a.completedAt})}}var ir=2,Qe=0;function lr(e){if(!e||typeof e!="object")return 0;let t=e;return typeof t.totalQuestions=="number"?t.totalQuestions:Array.isArray(t.flat)?t.flat.length:0}function ur(e){return Ne.paa_base+Math.max(1,e)*Ne.paa}async function cr(e){Qe++;try{let t=typeof e.options=="string"?JSON.parse(e.options):e.options,o={value:null},r=null,n=t.serpOnly&&!t.serpIdentity,s=we(e.id),a=process.env.APIFY_API_TOKEN?.trim();if(n&&!ar({pages:t.pages===2?2:1,recency:t.recency==="week"||t.recency==="month"?t.recency:void 0,mode:t.mode,token:a}))throw new Error("Search providers are not configured");let i=await St({op:t.serpOnly?"serp":"paa",userId:Number(e.user_id),headlessSentOut:o,operationRunId:s,operationAccountScope:"production-default"},()=>n?Ge({query:t.query??e.query,pages:t.pages===2?2:1,token:a,mode:t.mode,recency:t.recency==="week"||t.recency==="month"?t.recency:void 0,operationRunId:s,accountScope:"production-default",signal:AbortSignal.timeout(pt(t.maxQuestions??30,!0,t.mode,t.pages,!!t.recency,n).serverMs),onAttemptEvent:je(e.id,e.user_id,s)}).then(l=>(r=l,l.result)):ue({...t,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:mt(),headless:!0,format:"json",outputDir:"/tmp/paa-output-api",onAttemptEvent:je(e.id,e.user_id,s)}));if(n&&!r)throw new Error("Search provider billing receipt is missing");await vt(e.id,i),await Je(s,"succeeded");let u=await ke(e.id,e.user_id);if(typeof t.billingHoldMc=="number"&&t.billingDebitKey){let l=t.serpOnly?n?qe(r.deliveredPages,r.deliveryProvider):De(o.value):ur(lr(i));await Ce(Number(e.user_id),t.billingDebitKey,l,t.serpOnly?"serp_refund":"paa_refund",t.serpOnly?"SERP search settlement":"PAA harvest settlement",t.serpOnly?"serp_search":"paa_harvest")}else if(!t.serpOnly&&typeof t.billingHoldMc=="number"){let l=ur(lr(i)),c=t.billingHoldMc-l;c>0?await le(e.user_id,c,"paa_refund","overestimate refund"):c<0&&await Te(e.user_id,-c,"paa",t.query??e.query)}else if(t.serpOnly&&typeof t.billingHoldMc=="number"){let l=n?qe(r.deliveredPages,r.deliveryProvider):De(o.value),c=t.billingHoldMc-l;c>0?await le(e.user_id,c,"serp_refund","headless-mode pricing settle"):c<0&&await Te(e.user_id,-c,"serp",t.query??e.query)}e.callback_url&&await Le(e.callback_url,{job_id:e.id,status:"done",result:Nt(i),attempts:Me(u)})}catch(t){console.error("[harvest/worker] failed",{jobId:e.id,error:t instanceof Error?t.message:String(t)});let o=Ve(t);await Je(we(e.id),o.error_code==="harvest_timeout"?"timed_out":o.terminalStatus,o.error_code);let r=typeof e.options=="string"?JSON.parse(e.options):e.options,n=typeof r.billingHoldMc=="number"&&r.billingHoldMc>0;await Ie(e.id,$e(o),ze(o,{chargeStatus:n?"refund_pending":"not_charged"}));let s=await ke(e.id,e.user_id);try{n&&(r.billingDebitKey?await Ce(Number(e.user_id),r.billingDebitKey,0,r.serpOnly?"serp_refund":"paa_refund","failed call",r.serpOnly?"serp_search":"paa_harvest"):await le(e.user_id,r.billingHoldMc,"refund","failed call"),await Ie(e.id,$e(o),ze(o,{chargeStatus:"refunded"})))}catch{}e.callback_url&&await Le(e.callback_url,{job_id:e.id,status:"failed",..._e(o),attempts:Me(s)})}finally{Qe--}}async function eo(){let e=await Oe();if(!e)return{claimed:!1};let t=Date.now();return await cr(e),{claimed:!0,jobId:e.id,completed:!0,durationMs:Date.now()-t}}async function sn(e){let t=[];for(let o=0;o<e.maxJobs&&!(Date.now()>=e.deadlineMs);o++){let r=await eo();if(t.push(r),!r.claimed)break}return t}function ln(){setInterval(async()=>{if(Qe>=ir)return;let e=await Oe();e&&cr(e)},2e3),console.log(`[worker] started \u2014 polling every 2s, max ${ir} concurrent`)}export{Z as a,me as b,Ar as c,so as d,ar as e,Ge as f,Ve as g,$e as h,_e as i,ze as j,qo as k,we as l,Lo as m,Je as n,Vo as o,je as p,Le as q,eo as r,sn as s,ln as t};
@@ -1,4 +1,4 @@
1
- import{createClient as Ve}from"@libsql/client/http";import{createHash as v,randomBytes as q,randomUUID as N,scryptSync as Ne,timingSafeEqual as ze}from"crypto";import{z as p}from"zod";var k="2026-06-26 21:58:03";var Lt="Google returned a CAPTCHA. Run with --headless=false to re-warm the browser profile, then retry.",ve="This operation is temporarily unavailable. Please retry later.",ke=["request_aborted","captcha_exhausted","captcha_or_blocked","location_mismatch","proxy_tunnel_failed","proxy_unavailable","harvest_timeout","mcp_request_timeout","mcp_http_error","extraction_failed","concurrency_limit_exceeded","unauthorized","forbidden","invalid_request","rate_limited","upstream_rate_limited","insufficient_balance","service_unavailable","response_lost","vendor_unavailable","page_not_found","page_forbidden","page_rate_limited","page_server_error","page_http_error","bot_check_unresolved","page_too_large","page_unreachable","browser_session_interrupted","site_export_not_found","site_export_format_unavailable","site_export_read_failed","site_export_image_not_found","image_url_invalid","image_url_not_https","image_host_unresolvable","image_host_blocked","image_redirect_invalid","image_source_unavailable","image_too_large","image_redirect_limit","image_base64_invalid","image_source_missing","image_source_ambiguous","image_source_type_invalid","image_artifact_not_found","image_page_too_large","page_image_not_found","page_image_candidates_unusable","image_format_unsupported","image_storage_unconfigured","featured_image_unhostable"],Xe=["request_aborted","captcha","location_mismatch","connection","timeout","extraction","concurrency_limit","unauthorized","forbidden","invalid_request","rate_limit","billing","service_unavailable"];function O(e){return e?JSON.stringify(e):null}function ae(e){if(e==null)return null;try{let t=typeof e=="string"?JSON.parse(e):e;if(!t||typeof t!="object"||Array.isArray(t))return null;let r=t;if(typeof r.error_code!="string"||!oe.has(r.error_code))return null;let n=Ge({errorCode:r.error_code,errorType:r.error_type,retryable:r.retryable,retryAfterSeconds:r.retry_after_seconds,chargeStatus:r.charge_status,details:r.details});if(typeof r.message=="string"){let s=_e(r.message).trim().slice(0,1e3);s&&!/https?:\/\//i.test(s)&&(n.message=s)}return n}catch{return null}}var oe=new Set(ke),Fe=new Set(Xe),Me=new Set(["active","limit","operation","upgrade_url","topup_url","upgrade_command","slots_per_pack","pack_price_usd","balance_credits","required_credits","retry_guidance","http_status"]),Pe=12,He=500;function W(e){return typeof e=="string"&&oe.has(e)?e:"service_unavailable"}function qe(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t={};for(let[r,n]of Object.entries(e)){if(Object.keys(t).length>=Pe)break;if(Me.has(r))if(typeof n=="string"){if((r==="upgrade_url"||r==="topup_url")&&!je(n))continue;let s=_e(n).slice(0,He);s&&(t[r]=s)}else(typeof n=="number"&&Number.isFinite(n)||typeof n=="boolean"||n===null)&&(t[r]=n)}return Object.keys(t).length>0?t:void 0}function je(e){if(e.startsWith("/")&&!e.startsWith("//"))return!0;try{let t=new URL(e);return t.protocol==="https:"&&(t.hostname==="mcpscraper.dev"||t.hostname.endsWith(".mcpscraper.dev"))}catch{return!1}}function We(e){let t=W(e);switch(t){case"captcha_exhausted":case"captcha_or_blocked":return"captcha";case"proxy_tunnel_failed":case"proxy_unavailable":case"response_lost":return"connection";case"harvest_timeout":case"mcp_request_timeout":return"timeout";case"concurrency_limit_exceeded":return"concurrency_limit";case"rate_limited":case"upstream_rate_limited":return"rate_limit";case"extraction_failed":case"page_not_found":case"page_forbidden":case"page_rate_limited":case"page_server_error":case"page_http_error":case"bot_check_unresolved":case"page_too_large":case"page_unreachable":case"browser_session_interrupted":case"site_export_not_found":case"site_export_format_unavailable":case"site_export_read_failed":case"site_export_image_not_found":return"extraction";case"image_url_invalid":case"image_url_not_https":case"image_host_unresolvable":case"image_host_blocked":case"image_redirect_invalid":case"image_source_unavailable":case"image_too_large":case"image_redirect_limit":case"image_base64_invalid":case"image_source_missing":case"image_source_ambiguous":case"image_source_type_invalid":case"image_artifact_not_found":case"image_page_too_large":case"page_image_not_found":case"page_image_candidates_unusable":case"image_format_unsupported":case"image_storage_unconfigured":case"featured_image_unhostable":return"invalid_request";case"insufficient_balance":return"billing";case"vendor_unavailable":case"mcp_http_error":return"service_unavailable";default:return t}}function Be(e){switch(W(e)){case"request_aborted":return"The request was cancelled before it completed.";case"captcha_exhausted":case"captcha_or_blocked":return"The target site returned a verification challenge. Heavy traffic can temporarily increase these challenges; retry in a few minutes.";case"location_mismatch":return"The target site returned results for a different location. Please retry.";case"proxy_tunnel_failed":case"proxy_unavailable":return"The web request could not establish a working connection. Please retry later.";case"harvest_timeout":return"The request timed out before it completed. Please retry with a smaller request.";case"mcp_request_timeout":return"The MCP caller stopped waiting before a final response arrived. Durable work may still be running; continue with the returned Task or job handle instead of restarting it.";case"concurrency_limit_exceeded":return"The service is available, but this account has reached its parallel-operation limit. Wait for an active operation to finish or add capacity.";case"unauthorized":return"Authentication is required to perform this operation.";case"forbidden":return"This account does not have permission to perform this operation.";case"invalid_request":return"The request is invalid. Check the supplied inputs and try again.";case"rate_limited":return"This account is sending requests too quickly. Wait briefly and retry.";case"upstream_rate_limited":return"The connected provider is temporarily rate-limiting requests. Wait briefly and retry.";case"mcp_http_error":return"The API returned an unexpected HTTP response.";case"insufficient_balance":return"This account does not have enough Credits for the operation.";case"extraction_failed":return"The target could not be extracted. Please retry later.";case"response_lost":return"The connection was lost before the response arrived. The operation may have already completed and been billed on our side \u2014 check credits_info before retrying blind.";case"vendor_unavailable":return"MCP Scraper's internal browser services require MCP Scraper team attention. Servers or IPs are down until this is fixed \u2014 this is not caused by your request. Please retry in a few minutes.";case"page_not_found":return"The page could not be found. It may have been moved or deleted.";case"page_forbidden":return"The site refused the request.";case"page_rate_limited":return"The site is rate-limiting requests right now. Retrying after a short wait usually works.";case"page_server_error":return"The page's own server returned an error. This is on the target site's side, not something a retry here can fix.";case"page_http_error":return"The page returned an unexpected HTTP response.";case"bot_check_unresolved":return"This site has automated-traffic protection (a bot/CAPTCHA check) that could not be resolved in time. Some sites are simply not extractable this way.";case"page_too_large":return"The page is larger than we can safely process.";case"page_unreachable":return"The page did not respond in time, or the connection could not be completed.";case"browser_session_interrupted":return"The browser session closed before extraction completed. MCP Scraper will retry once with a fresh session; retry the request if this persists.";case"site_export_not_found":return"The site export or requested page was not found, expired, or does not belong to this account.";case"site_export_format_unavailable":return"That representation was not retained for this export page. Read the export manifest and request one of the formats marked available.";case"site_export_read_failed":return"The stored site export could not be read or did not pass its integrity check.";case"site_export_image_not_found":return"The requested site-export image was not found, expired, or does not belong to this account.";case"image_url_invalid":return"The image source is not a valid URL. Use a stable public HTTPS URL or inline image bytes.";case"image_url_not_https":return"Commons image sources must use a public HTTPS URL or inline image bytes.";case"image_host_unresolvable":return"The image host could not be resolved. Use a different stable public URL or inline image bytes.";case"image_host_blocked":return"The image source resolves to a network address Commons cannot fetch safely.";case"image_redirect_invalid":return"The image source redirected to an invalid or unsafe destination.";case"image_source_unavailable":return"The image source could not be fetched. Host a different stable public URL or provide inline image bytes.";case"image_too_large":return"The image exceeds the Commons image size limit.";case"image_redirect_limit":return"The image source exceeded the Commons redirect limit.";case"image_base64_invalid":return"The supplied inline image bytes are invalid.";case"image_source_missing":return"Provide exactly one of a public image or webpage URL, inline image bytes, or an owner-scoped image artifact.";case"image_source_ambiguous":return"Provide only one image source: sourceUrl, imageBase64, or artifactId.";case"image_source_type_invalid":return"Use sourceType only with inline image bytes or an owner-scoped image artifact.";case"image_artifact_not_found":return"The image artifact was not found, expired, or does not belong to this account.";case"image_page_too_large":return"The webpage is too large for bounded Commons image discovery.";case"page_image_not_found":return"The webpage did not expose a usable featured or content image.";case"page_image_candidates_unusable":return"The webpage exposed image candidates, but none returned supported public image bytes.";case"image_format_unsupported":return"Commons accepts JPEG, PNG, GIF, or WebP image bytes.";case"image_storage_unconfigured":return"Commons image storage is temporarily unavailable.";case"featured_image_unhostable":return"The required featured image could not be hosted for Commons publication.";default:return ve}}function Ge(e){let t=W(e.errorCode),r=typeof e.retryAfterSeconds=="number"&&Number.isFinite(e.retryAfterSeconds)?Math.max(1,Math.min(86400,Math.trunc(e.retryAfterSeconds))):void 0,n=e.chargeStatus==="not_charged"||e.chargeStatus==="refund_pending"||e.chargeStatus==="refunded"||e.chargeStatus==="charged"?e.chargeStatus:void 0,s=typeof e.errorType=="string"&&Fe.has(e.errorType)?e.errorType:void 0,a=qe(e.details);return{error_code:t,error_type:s??We(t),message:Be(t),retryable:e.retryable===!0,...r?{retry_after_seconds:r}:{},...n?{charge_status:n}:{},...a?{details:a}:{}}}function _e(e){return e.replace(/https?:\/\/[^\s]*(?:brightdata|onkernel|kernel\.sh)[^\s]*/gi,"the service").replace(/bright\s*data/gi,"the service").replace(/brightdata/gi,"the service").replace(/kernel\.sh\s+sessions?/gi,"sessions").replace(/kernel\.sh\s+session/gi,"this session").replace(/kernel\.sh/gi,"the service").replace(/kernel\s+sessions?/gi,"sessions").replace(/kernel\s+session/gi,"this session").replace(/\b(?:sub|cus|sess|proxy)_[A-Za-z0-9_-]+\b/g,"[redacted]").replace(/\b(?:KERNEL|BRIGHTDATA|BRIGHT_DATA)_[A-Z0-9_]*API_KEY\b/g,"BROWSER_SERVICE_API_KEY").replace(/\bkernel\b/gi,"the service").replace(/ +/g," ").trim()}var ee=class extends Error{constructor(r){super(`CAPTCHA detected. ${r}`);this.instructions=r}instructions;name="CaptchaError"},te=class extends Error{constructor(r,n){super(r);this.cause=n}cause;name="ExtractionError"},re=class extends Error{constructor(r){super(`Google Maps search did not reach a complete result state (${r})`);this.pageState=r}pageState;name="MapsSearchIncompletePageError"},ne=class extends Error{name="RequestAbortedError";constructor(t="Request aborted before harvest completed"){super(t)}},se=class extends Error{name="PaaInteractionInterruptedError"},ie=class extends Error{name="LocationMismatchError";constructor(t="Google returned results for a different location than requested"){super(t)}};var I=["oauth_store_metadata","oauth_clients","oauth_client_redirect_uris","oauth_codes","oauth_code_exchanges","oauth_refresh_families","oauth_refresh_tokens","oauth_refresh_rotations","oauth_security_events","oauth_rate_limit_buckets"],x=["oauth_clients_inactivity_idx","oauth_clients_cleanup_idx","oauth_codes_expiry_idx","oauth_codes_client_idx","oauth_code_exchanges_replay_expiry_idx","oauth_refresh_families_lifecycle_idx","oauth_refresh_families_user_status_idx","oauth_refresh_families_client_idx","oauth_refresh_families_cleanup_idx","oauth_refresh_tokens_expiry_idx","oauth_refresh_rotations_replay_expiry_idx","oauth_security_events_retention_idx","oauth_rate_limit_buckets_expiry_idx"],ue={oauth_clients:"oauth_clients_legacy_raw",oauth_codes:"oauth_codes_legacy_raw",oauth_tokens:"oauth_tokens_legacy_raw"},L="strftime('%Y-%m-%dT%H:%M:%fZ','now')";async function y(e,t,r=!1){try{await e.execute(t)}catch(n){let s=n.code;if(!r||s!=="SQL_PARSE_ERROR")throw n}}var Ye=[`CREATE TABLE IF NOT EXISTS oauth_store_metadata (
1
+ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,randomBytes as j,randomUUID as N,scryptSync as Ne,timingSafeEqual as ze}from"crypto";import{z as p}from"zod";var k="2026-06-26 21:58:03";var Lt="Google returned a CAPTCHA. Run with --headless=false to re-warm the browser profile, then retry.",ve="This operation is temporarily unavailable. Please retry later.",ke=["request_aborted","captcha_exhausted","captcha_or_blocked","location_mismatch","proxy_tunnel_failed","proxy_unavailable","harvest_timeout","mcp_request_timeout","mcp_http_error","extraction_failed","concurrency_limit_exceeded","unauthorized","forbidden","invalid_request","rate_limited","upstream_rate_limited","insufficient_balance","service_unavailable","response_lost","vendor_unavailable","page_not_found","page_forbidden","page_rate_limited","page_server_error","page_http_error","bot_check_unresolved","page_too_large","page_unreachable","browser_session_interrupted","site_export_not_found","directory_job_not_found","site_export_format_unavailable","site_export_read_failed","site_export_image_not_found","image_url_invalid","image_url_not_https","image_host_unresolvable","image_host_blocked","image_redirect_invalid","image_source_unavailable","image_too_large","image_redirect_limit","image_base64_invalid","image_source_missing","image_source_ambiguous","image_source_type_invalid","image_artifact_not_found","image_page_too_large","page_image_not_found","page_image_candidates_unusable","image_format_unsupported","image_storage_unconfigured","featured_image_unhostable"],Xe=["request_aborted","captcha","location_mismatch","connection","timeout","extraction","concurrency_limit","unauthorized","forbidden","invalid_request","not_found","rate_limit","billing","service_unavailable"];function O(e){return e?JSON.stringify(e):null}function ae(e){if(e==null)return null;try{let t=typeof e=="string"?JSON.parse(e):e;if(!t||typeof t!="object"||Array.isArray(t))return null;let r=t;if(typeof r.error_code!="string"||!oe.has(r.error_code))return null;let n=Ge({errorCode:r.error_code,errorType:r.error_type,retryable:r.retryable,retryAfterSeconds:r.retry_after_seconds,chargeStatus:r.charge_status,details:r.details});if(typeof r.message=="string"){let s=_e(r.message).trim().slice(0,1e3);s&&!/https?:\/\//i.test(s)&&(n.message=s)}return n}catch{return null}}var oe=new Set(ke),Fe=new Set(Xe),Me=new Set(["active","limit","operation","upgrade_url","topup_url","upgrade_command","slots_per_pack","pack_price_usd","balance_credits","required_credits","retry_guidance","http_status"]),Pe=12,He=500;function W(e){return typeof e=="string"&&oe.has(e)?e:"service_unavailable"}function je(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t={};for(let[r,n]of Object.entries(e)){if(Object.keys(t).length>=Pe)break;if(Me.has(r))if(typeof n=="string"){if((r==="upgrade_url"||r==="topup_url")&&!qe(n))continue;let s=_e(n).slice(0,He);s&&(t[r]=s)}else(typeof n=="number"&&Number.isFinite(n)||typeof n=="boolean"||n===null)&&(t[r]=n)}return Object.keys(t).length>0?t:void 0}function qe(e){if(e.startsWith("/")&&!e.startsWith("//"))return!0;try{let t=new URL(e);return t.protocol==="https:"&&(t.hostname==="mcpscraper.dev"||t.hostname.endsWith(".mcpscraper.dev"))}catch{return!1}}function We(e){let t=W(e);switch(t){case"captcha_exhausted":case"captcha_or_blocked":return"captcha";case"proxy_tunnel_failed":case"proxy_unavailable":case"response_lost":return"connection";case"harvest_timeout":case"mcp_request_timeout":return"timeout";case"concurrency_limit_exceeded":return"concurrency_limit";case"rate_limited":case"upstream_rate_limited":return"rate_limit";case"extraction_failed":case"page_not_found":case"page_forbidden":case"page_rate_limited":case"page_server_error":case"page_http_error":case"bot_check_unresolved":case"page_too_large":case"page_unreachable":case"browser_session_interrupted":case"site_export_not_found":case"site_export_format_unavailable":case"site_export_read_failed":case"site_export_image_not_found":return"extraction";case"image_url_invalid":case"image_url_not_https":case"image_host_unresolvable":case"image_host_blocked":case"image_redirect_invalid":case"image_source_unavailable":case"image_too_large":case"image_redirect_limit":case"image_base64_invalid":case"image_source_missing":case"image_source_ambiguous":case"image_source_type_invalid":case"image_artifact_not_found":case"image_page_too_large":case"page_image_not_found":case"page_image_candidates_unusable":case"image_format_unsupported":case"image_storage_unconfigured":case"featured_image_unhostable":return"invalid_request";case"insufficient_balance":return"billing";case"vendor_unavailable":case"mcp_http_error":return"service_unavailable";case"directory_job_not_found":return"not_found";default:return t}}function Be(e){switch(W(e)){case"request_aborted":return"The request was cancelled before it completed.";case"captcha_exhausted":case"captcha_or_blocked":return"The target site returned a verification challenge. Heavy traffic can temporarily increase these challenges; retry in a few minutes.";case"location_mismatch":return"The target site returned results for a different location. Please retry.";case"proxy_tunnel_failed":case"proxy_unavailable":return"The web request could not establish a working connection. Please retry later.";case"harvest_timeout":return"The request timed out before it completed. Please retry with a smaller request.";case"mcp_request_timeout":return"The MCP caller stopped waiting before a final response arrived. Durable work may still be running; continue with the returned Task or job handle instead of restarting it.";case"concurrency_limit_exceeded":return"The service is available, but this account has reached its parallel-operation limit. Wait for an active operation to finish or add capacity.";case"unauthorized":return"Authentication is required to perform this operation.";case"forbidden":return"This account does not have permission to perform this operation.";case"invalid_request":return"The request is invalid. Check the supplied inputs and try again.";case"rate_limited":return"This account is sending requests too quickly. Wait briefly and retry.";case"upstream_rate_limited":return"The connected provider is temporarily rate-limiting requests. Wait briefly and retry.";case"mcp_http_error":return"The API returned an unexpected HTTP response.";case"insufficient_balance":return"This account does not have enough Credits for the operation.";case"extraction_failed":return"The target could not be extracted. Check retryable before attempting it again.";case"directory_job_not_found":return"This directory job was not found for the current account.";case"response_lost":return"The connection was lost before the response arrived. The operation may have already completed and been billed on our side \u2014 check credits_info before retrying blind.";case"vendor_unavailable":return"MCP Scraper's internal browser services require MCP Scraper team attention. Servers or IPs are down until this is fixed \u2014 this is not caused by your request. Please retry in a few minutes.";case"page_not_found":return"The page could not be found. It may have been moved or deleted.";case"page_forbidden":return"The site refused the request.";case"page_rate_limited":return"The site is rate-limiting requests right now. Retrying after a short wait usually works.";case"page_server_error":return"The page's own server returned an error. This is on the target site's side, not something a retry here can fix.";case"page_http_error":return"The page returned an unexpected HTTP response.";case"bot_check_unresolved":return"This site has automated-traffic protection (a bot/CAPTCHA check) that could not be resolved in time. Some sites are simply not extractable this way.";case"page_too_large":return"The page is larger than we can safely process.";case"page_unreachable":return"The page did not respond in time, or the connection could not be completed.";case"browser_session_interrupted":return"The browser session closed before extraction completed. MCP Scraper will retry once with a fresh session; retry the request if this persists.";case"site_export_not_found":return"The site export or requested page was not found, expired, or does not belong to this account.";case"site_export_format_unavailable":return"That representation was not retained for this export page. Read the export manifest and request one of the formats marked available.";case"site_export_read_failed":return"The stored site export could not be read or did not pass its integrity check.";case"site_export_image_not_found":return"The requested site-export image was not found, expired, or does not belong to this account.";case"image_url_invalid":return"The image source is not a valid URL. Use a stable public HTTPS URL or inline image bytes.";case"image_url_not_https":return"Commons image sources must use a public HTTPS URL or inline image bytes.";case"image_host_unresolvable":return"The image host could not be resolved. Use a different stable public URL or inline image bytes.";case"image_host_blocked":return"The image source resolves to a network address Commons cannot fetch safely.";case"image_redirect_invalid":return"The image source redirected to an invalid or unsafe destination.";case"image_source_unavailable":return"The image source could not be fetched. Host a different stable public URL or provide inline image bytes.";case"image_too_large":return"The image exceeds the Commons image size limit.";case"image_redirect_limit":return"The image source exceeded the Commons redirect limit.";case"image_base64_invalid":return"The supplied inline image bytes are invalid.";case"image_source_missing":return"Provide exactly one of a public image or webpage URL, inline image bytes, or an owner-scoped image artifact.";case"image_source_ambiguous":return"Provide only one image source: sourceUrl, imageBase64, or artifactId.";case"image_source_type_invalid":return"Use sourceType only with inline image bytes or an owner-scoped image artifact.";case"image_artifact_not_found":return"The image artifact was not found, expired, or does not belong to this account.";case"image_page_too_large":return"The webpage is too large for bounded Commons image discovery.";case"page_image_not_found":return"The webpage did not expose a usable featured or content image.";case"page_image_candidates_unusable":return"The webpage exposed image candidates, but none returned supported public image bytes.";case"image_format_unsupported":return"Commons accepts JPEG, PNG, GIF, or WebP image bytes.";case"image_storage_unconfigured":return"Commons image storage is temporarily unavailable.";case"featured_image_unhostable":return"The required featured image could not be hosted for Commons publication.";default:return ve}}function Ge(e){let t=W(e.errorCode),r=typeof e.retryAfterSeconds=="number"&&Number.isFinite(e.retryAfterSeconds)?Math.max(1,Math.min(86400,Math.trunc(e.retryAfterSeconds))):void 0,n=e.chargeStatus==="not_charged"||e.chargeStatus==="refund_pending"||e.chargeStatus==="refunded"||e.chargeStatus==="charged"?e.chargeStatus:void 0,s=typeof e.errorType=="string"&&Fe.has(e.errorType)?e.errorType:void 0,a=je(e.details);return{error_code:t,error_type:s??We(t),message:Be(t),retryable:e.retryable===!0,...r?{retry_after_seconds:r}:{},...n?{charge_status:n}:{},...a?{details:a}:{}}}function _e(e){return e.replace((new RegExp("https?:\\/\\/[^\\s]*(?:\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061|on\u006b\u0065\u0072\u006e\u0065\u006c|\u006b\u0065\u0072\u006e\u0065\u006c\\.sh)[^\\s]*", "gi")),"the service").replace(/bright\s*data/gi,"the service").replace((new RegExp("\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061", "gi")),"the service").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\.sh\\s+sessions?", "gi")),"sessions").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\.sh\\s+session", "gi")),"this session").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\.sh", "gi")),"the service").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\s+sessions?", "gi")),"sessions").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\s+session", "gi")),"this session").replace(/\b(?:sub|cus|sess|proxy)_[A-Za-z0-9_-]+\b/g,"[redacted]").replace((new RegExp("\\b(?:\u004b\u0045\u0052\u004e\u0045\u004c|\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041|\u0042\u0052\u0049\u0047\u0048\u0054_\u0044\u0041\u0054\u0041)_[A-Z0-9_]*API_KEY\\b", "g")),"BROWSER_SERVICE_API_KEY").replace((new RegExp("\\b\u006b\u0065\u0072\u006e\u0065\u006c\\b", "gi")),"the service").replace(/ +/g," ").trim()}var ee=class extends Error{constructor(r){super(`CAPTCHA detected. ${r}`);this.instructions=r}instructions;name="CaptchaError"},te=class extends Error{constructor(r,n){super(r);this.cause=n}cause;name="ExtractionError"},re=class extends Error{constructor(r){super(`Google Maps search did not reach a complete result state (${r})`);this.pageState=r}pageState;name="MapsSearchIncompletePageError"},ne=class extends Error{name="RequestAbortedError";constructor(t="Request aborted before harvest completed"){super(t)}},se=class extends Error{name="PaaInteractionInterruptedError"},ie=class extends Error{name="LocationMismatchError";constructor(t="Google returned results for a different location than requested"){super(t)}};var I=["oauth_store_metadata","oauth_clients","oauth_client_redirect_uris","oauth_codes","oauth_code_exchanges","oauth_refresh_families","oauth_refresh_tokens","oauth_refresh_rotations","oauth_security_events","oauth_rate_limit_buckets"],x=["oauth_clients_inactivity_idx","oauth_clients_cleanup_idx","oauth_codes_expiry_idx","oauth_codes_client_idx","oauth_code_exchanges_replay_expiry_idx","oauth_refresh_families_lifecycle_idx","oauth_refresh_families_user_status_idx","oauth_refresh_families_client_idx","oauth_refresh_families_cleanup_idx","oauth_refresh_tokens_expiry_idx","oauth_refresh_rotations_replay_expiry_idx","oauth_security_events_retention_idx","oauth_rate_limit_buckets_expiry_idx"],ue={oauth_clients:"oauth_clients_legacy_raw",oauth_codes:"oauth_codes_legacy_raw",oauth_tokens:"oauth_tokens_legacy_raw"},L="strftime('%Y-%m-%dT%H:%M:%fZ','now')";async function y(e,t,r=!1){try{await e.execute(t)}catch(n){let s=n.code;if(!r||s!=="SQL_PARSE_ERROR")throw n}}var Ye=[`CREATE TABLE IF NOT EXISTS oauth_store_metadata (
2
2
  id INTEGER PRIMARY KEY CHECK (id = 1),
3
3
  store_id TEXT NOT NULL UNIQUE,
4
4
  schema_version INTEGER NOT NULL CHECK (schema_version > 0),
@@ -230,14 +230,14 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
230
230
  max_questions INTEGER NOT NULL,
231
231
  status TEXT NOT NULL,
232
232
  outcome TEXT,
233
- kernel_session_id TEXT,
233
+ \u006b\u0065\u0072\u006e\u0065\u006c_session_id TEXT,
234
234
  question_count INTEGER,
235
235
  duration_ms INTEGER,
236
236
  error TEXT,
237
237
  will_retry INTEGER,
238
- kernel_delete_started INTEGER NOT NULL DEFAULT 0,
239
- kernel_delete_succeeded INTEGER,
240
- kernel_delete_error TEXT,
238
+ \u006b\u0065\u0072\u006e\u0065\u006c_delete_started INTEGER NOT NULL DEFAULT 0,
239
+ \u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded INTEGER,
240
+ \u006b\u0065\u0072\u006e\u0065\u006c_delete_error TEXT,
241
241
  browser_close_succeeded INTEGER,
242
242
  browser_close_error TEXT,
243
243
  debug_json TEXT,
@@ -989,8 +989,8 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
989
989
  id TEXT PRIMARY KEY,
990
990
  user_id INTEGER NOT NULL REFERENCES users(id),
991
991
  name TEXT NOT NULL,
992
- kernel_profile_name TEXT NOT NULL,
993
- kernel_proxy_id TEXT NOT NULL,
992
+ \u006b\u0065\u0072\u006e\u0065\u006c_profile_name TEXT NOT NULL,
993
+ \u006b\u0065\u0072\u006e\u0065\u006c_proxy_id TEXT NOT NULL,
994
994
  proxy_type TEXT NOT NULL DEFAULT 'isp',
995
995
  country TEXT NOT NULL DEFAULT 'US',
996
996
  status TEXT NOT NULL DEFAULT 'ready',
@@ -1004,7 +1004,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1004
1004
  ON serp_identities(user_id, name)
1005
1005
  `),!await P(t))throw new Error("core schema migration finished without all required tables, indexes, and columns");await G(t),await t.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[U]})}async function Ut(e={}){let t=await tt(i());return await nt(e),{providerUsageReceipts:t}}async function Dt(e,t,r){await i().execute({sql:"INSERT INTO oauth_clients (client_id, redirect_uris, name) VALUES (?, ?, ?)",args:[e,JSON.stringify(t),r]})}async function vt(e){let r=(await i().execute({sql:"SELECT * FROM oauth_clients WHERE client_id = ?",args:[e]})).rows[0];if(!r)return;let n=[];try{let s=JSON.parse(String(r.redirect_uris));Array.isArray(s)&&(n=s.filter(a=>typeof a=="string"))}catch{n=[]}return{client_id:String(r.client_id),redirect_uris:n,name:r.name!=null?String(r.name):null,created_at:String(r.created_at)}}async function kt(e){await i().execute({sql:"INSERT INTO oauth_codes (code, client_id, redirect_uri, code_challenge, identity, scope, resource, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",args:[e.code,e.client_id,e.redirect_uri,e.code_challenge,e.identity,e.scope,e.resource,e.expires_at]})}async function Xt(e){let t=i(),n=(await t.execute({sql:"SELECT * FROM oauth_codes WHERE code = ?",args:[e]})).rows[0];if(await t.execute({sql:"DELETE FROM oauth_codes WHERE code = ?",args:[e]}),!!n)return{code:String(n.code),client_id:String(n.client_id),redirect_uri:String(n.redirect_uri),code_challenge:String(n.code_challenge),identity:String(n.identity),scope:String(n.scope),resource:n.resource!=null?String(n.resource):null,expires_at:String(n.expires_at)}}async function st(e){await i().execute({sql:"INSERT INTO oauth_tokens (refresh_token, client_id, identity, scope, resource, expires_at, revoked) VALUES (?, ?, ?, ?, ?, ?, 0)",args:[e.refresh_token,e.client_id,e.identity,e.scope,e.resource,e.expires_at]})}async function Ft(e){let r=(await i().execute({sql:"SELECT * FROM oauth_tokens WHERE refresh_token = ?",args:[e]})).rows[0];if(r)return{refresh_token:String(r.refresh_token),client_id:String(r.client_id),identity:String(r.identity),scope:String(r.scope),resource:r.resource!=null?String(r.resource):null,expires_at:String(r.expires_at),revoked:Number(r.revoked??0),replaced_by:r.replaced_by!=null?String(r.replaced_by):null,rotated_at:r.rotated_at!=null?String(r.rotated_at):null}}async function Mt(e){await i().execute({sql:"UPDATE oauth_tokens SET revoked = 1 WHERE refresh_token = ?",args:[e]})}async function Pt(e,t){await st(t),await i().execute({sql:"UPDATE oauth_tokens SET revoked = 1, replaced_by = ?, rotated_at = ? WHERE refresh_token = ?",args:[t.refresh_token,new Date().toISOString(),e]})}async function Ht(e,t,r){return(await i().execute({sql:`INSERT OR IGNORE INTO stripe_events
1006
1006
  (event_id, event_type, stripe_created_at, status, attempt_count, received_at, next_attempt_at, processed_at, updated_at)
1007
- VALUES (?, ?, ?, 'pending', 0, datetime('now'), datetime('now'), datetime('now'), datetime('now'))`,args:[e,t,r]})).rowsAffected===1?"queued":"duplicate"}async function qt(e=50,t=300){let r=Math.max(1,Math.min(500,Math.trunc(e))),n=await i().execute({sql:`SELECT event_id
1007
+ VALUES (?, ?, ?, 'pending', 0, datetime('now'), datetime('now'), datetime('now'), datetime('now'))`,args:[e,t,r]})).rowsAffected===1?"queued":"duplicate"}async function jt(e=50,t=300){let r=Math.max(1,Math.min(500,Math.trunc(e))),n=await i().execute({sql:`SELECT event_id
1008
1008
  FROM stripe_events
1009
1009
  WHERE (status IN ('pending', 'retryable') AND COALESCE(next_attempt_at, received_at) <= datetime('now'))
1010
1010
  OR (status = 'processing' AND claimed_at <= datetime('now', '-' || ? || ' seconds'))
@@ -1015,7 +1015,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1015
1015
  last_error_code = NULL, updated_at = datetime('now')
1016
1016
  WHERE event_id = ?
1017
1017
  AND ((status IN ('pending', 'retryable') AND COALESCE(next_attempt_at, received_at) <= datetime('now'))
1018
- OR (status = 'processing' AND claimed_at <= datetime('now', '-' || ? || ' seconds')))`,args:[u,_,t]})).rowsAffected!==1)continue;let c=await i().execute({sql:"SELECT event_type, attempt_count FROM stripe_events WHERE event_id = ? LIMIT 1",args:[_]});s.push({eventId:_,eventType:c.rows[0]?.event_type!=null?String(c.rows[0].event_type):null,attemptCount:Number(c.rows[0]?.attempt_count??1),token:u})}return s}async function jt(e,t){return(await i().execute({sql:`UPDATE stripe_events
1018
+ OR (status = 'processing' AND claimed_at <= datetime('now', '-' || ? || ' seconds')))`,args:[u,_,t]})).rowsAffected!==1)continue;let c=await i().execute({sql:"SELECT event_type, attempt_count FROM stripe_events WHERE event_id = ? LIMIT 1",args:[_]});s.push({eventId:_,eventType:c.rows[0]?.event_type!=null?String(c.rows[0].event_type):null,attemptCount:Number(c.rows[0]?.attempt_count??1),token:u})}return s}async function qt(e,t){return(await i().execute({sql:`UPDATE stripe_events
1019
1019
  SET status = 'processed',
1020
1020
  claim_token = NULL,
1021
1021
  claimed_at = NULL,
@@ -1043,13 +1043,13 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1043
1043
  SUM(CASE WHEN status = 'dead_letter' THEN 1 ELSE 0 END) AS dead_letter,
1044
1044
  MIN(CASE WHEN status IN ('pending', 'retryable') THEN COALESCE(next_attempt_at, received_at) END) AS oldest_due_at
1045
1045
  FROM stripe_events
1046
- `)).rows[0];return{pending:Number(t?.pending??0),processing:Number(t?.processing??0),retryable:Number(t?.retryable??0),dead_letter:Number(t?.dead_letter??0),oldest_due_at:t?.oldest_due_at!=null?String(t.oldest_due_at):null}}async function Yt(e){return(await i().execute({sql:"SELECT 1 FROM stripe_events WHERE event_id = ? AND status = 'processed' LIMIT 1",args:[e]})).rows.length>0}function Re(){return"sk_"+q(24).toString("hex")}function Ae(e){let t=q(16).toString("hex"),r=Ne(e,t,64);return`${t}:${r.toString("hex")}`}function Kt(e,t){let[r,n]=t.split(":"),s=Buffer.from(n,"hex"),a=Ne(e,r,64);return ze(s,a)}function S(e){return{id:Number(e.id),email:String(e.email),name:e.name!=null?String(e.name):null,api_key:String(e.api_key),key_active:Number(e.key_active??1),password_hash:e.password_hash!=null?String(e.password_hash):null,created_at:String(e.created_at),active:Number(e.active),stripe_customer_id:e.stripe_customer_id!=null?String(e.stripe_customer_id):null,balance_mc:Number(e.balance_mc??0),extra_concurrency_slots:Number(e.extra_concurrency_slots??0),concurrency_stripe_sub_id:e.concurrency_stripe_sub_id!=null?String(e.concurrency_stripe_sub_id):null,concurrency_pack_quantity:Number(e.concurrency_pack_quantity??0),subscription_concurrency:Number(e.subscription_concurrency??0),subscription_tier:e.subscription_tier!=null?String(e.subscription_tier):null,subscription_id:e.subscription_id!=null?String(e.subscription_id):null,memory_plan:e.memory_plan!=null?String(e.memory_plan):"free",memory_subscription_id:e.memory_subscription_id!=null?String(e.memory_subscription_id):null,memory_provisioned:Number(e.memory_provisioned??0)}}async function $t(e){let t=await i().execute({sql:"SELECT * FROM users WHERE email = ? AND active = 1",args:[e]});return t.rows[0]?S(t.rows[0]):void 0}async function Jt(e){let t=await i().execute({sql:"SELECT * FROM users WHERE api_key = ? AND active = 1 AND key_active = 1",args:[e]});return t.rows[0]?S(t.rows[0]):void 0}async function Vt(e){let t=await i().execute({sql:"SELECT * FROM users WHERE id = ? AND active = 1",args:[e]});return t.rows[0]?S(t.rows[0]):void 0}async function zt(e){let r=(await i().execute({sql:"SELECT memory_key, memory_identity FROM users WHERE id = ?",args:[e]})).rows[0];return{memory_key:r?.memory_key!=null?String(r.memory_key):null,memory_identity:r?.memory_identity!=null?String(r.memory_identity):null}}async function Qt(e,t,r){await i().execute({sql:"UPDATE users SET memory_key = ?, memory_identity = ? WHERE id = ?",args:[t,r,e]})}async function Zt(e,t){await i().execute({sql:"UPDATE users SET password_hash = ? WHERE id = ?",args:[Ae(t),e]})}async function er(e){let t=i(),[r,n,s,a,_]=await Promise.all([t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ?",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'failed'",args:[e]}),t.execute({sql:"SELECT COALESCE(SUM(json_extract(result, '$.totalQuestions')), 0) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT MAX(created_at) as t FROM jobs WHERE user_id = ?",args:[e]})]);return{total:Number(r.rows[0]?.n??0),done:Number(n.rows[0]?.n??0),failed:Number(s.rows[0]?.n??0),totalQuestions:Number(a.rows[0]?.n??0),lastUsed:_.rows[0]?.t!=null?String(_.rows[0].t):null}}async function tr(e,t,r,n){let s=i(),a=Re(),_=r??q(6).toString("hex"),u=Ae(_);return{id:(await s.execute({sql:"INSERT INTO users (email, name, api_key, password_hash, stripe_customer_id) VALUES (?, ?, ?, ?, ?)",args:[e,t??null,a,u,n??null]})).lastInsertRowid,email:e,name:t,api_key:a,password:_}}async function rr(e,t,r,n){let s=Math.floor(Date.now()/1e3),a=Math.floor(s/n)*n,_=v("sha256").update(t).digest("hex"),o=await i().execute({sql:`
1046
+ `)).rows[0];return{pending:Number(t?.pending??0),processing:Number(t?.processing??0),retryable:Number(t?.retryable??0),dead_letter:Number(t?.dead_letter??0),oldest_due_at:t?.oldest_due_at!=null?String(t.oldest_due_at):null}}async function Yt(e){return(await i().execute({sql:"SELECT 1 FROM stripe_events WHERE event_id = ? AND status = 'processed' LIMIT 1",args:[e]})).rows.length>0}function Re(){return"sk_"+j(24).toString("hex")}function Ae(e){let t=j(16).toString("hex"),r=Ne(e,t,64);return`${t}:${r.toString("hex")}`}function Kt(e,t){let[r,n]=t.split(":"),s=Buffer.from(n,"hex"),a=Ne(e,r,64);return ze(s,a)}function S(e){return{id:Number(e.id),email:String(e.email),name:e.name!=null?String(e.name):null,api_key:String(e.api_key),key_active:Number(e.key_active??1),password_hash:e.password_hash!=null?String(e.password_hash):null,created_at:String(e.created_at),active:Number(e.active),stripe_customer_id:e.stripe_customer_id!=null?String(e.stripe_customer_id):null,balance_mc:Number(e.balance_mc??0),extra_concurrency_slots:Number(e.extra_concurrency_slots??0),concurrency_stripe_sub_id:e.concurrency_stripe_sub_id!=null?String(e.concurrency_stripe_sub_id):null,concurrency_pack_quantity:Number(e.concurrency_pack_quantity??0),subscription_concurrency:Number(e.subscription_concurrency??0),subscription_tier:e.subscription_tier!=null?String(e.subscription_tier):null,subscription_id:e.subscription_id!=null?String(e.subscription_id):null,memory_plan:e.memory_plan!=null?String(e.memory_plan):"free",memory_subscription_id:e.memory_subscription_id!=null?String(e.memory_subscription_id):null,memory_provisioned:Number(e.memory_provisioned??0)}}async function $t(e){let t=await i().execute({sql:"SELECT * FROM users WHERE email = ? AND active = 1",args:[e]});return t.rows[0]?S(t.rows[0]):void 0}async function Jt(e){let t=await i().execute({sql:"SELECT * FROM users WHERE api_key = ? AND active = 1 AND key_active = 1",args:[e]});return t.rows[0]?S(t.rows[0]):void 0}async function Vt(e){let t=await i().execute({sql:"SELECT * FROM users WHERE id = ? AND active = 1",args:[e]});return t.rows[0]?S(t.rows[0]):void 0}async function zt(e){let r=(await i().execute({sql:"SELECT memory_key, memory_identity FROM users WHERE id = ?",args:[e]})).rows[0];return{memory_key:r?.memory_key!=null?String(r.memory_key):null,memory_identity:r?.memory_identity!=null?String(r.memory_identity):null}}async function Qt(e,t,r){await i().execute({sql:"UPDATE users SET memory_key = ?, memory_identity = ? WHERE id = ?",args:[t,r,e]})}async function Zt(e,t){await i().execute({sql:"UPDATE users SET password_hash = ? WHERE id = ?",args:[Ae(t),e]})}async function er(e){let t=i(),[r,n,s,a,_]=await Promise.all([t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ?",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'failed'",args:[e]}),t.execute({sql:"SELECT COALESCE(SUM(json_extract(result, '$.totalQuestions')), 0) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT MAX(created_at) as t FROM jobs WHERE user_id = ?",args:[e]})]);return{total:Number(r.rows[0]?.n??0),done:Number(n.rows[0]?.n??0),failed:Number(s.rows[0]?.n??0),totalQuestions:Number(a.rows[0]?.n??0),lastUsed:_.rows[0]?.t!=null?String(_.rows[0].t):null}}async function tr(e,t,r,n){let s=i(),a=Re(),_=r??j(6).toString("hex"),u=Ae(_);return{id:(await s.execute({sql:"INSERT INTO users (email, name, api_key, password_hash, stripe_customer_id) VALUES (?, ?, ?, ?, ?)",args:[e,t??null,a,u,n??null]})).lastInsertRowid,email:e,name:t,api_key:a,password:_}}async function rr(e,t,r,n){let s=Math.floor(Date.now()/1e3),a=Math.floor(s/n)*n,_=v("sha256").update(t).digest("hex"),o=await i().execute({sql:`
1047
1047
  INSERT INTO rate_limits (scope, key_hash, window_start, count)
1048
1048
  VALUES (?, ?, ?, 1)
1049
1049
  ON CONFLICT(scope, key_hash, window_start)
1050
1050
  DO UPDATE SET count = count + 1, updated_at = datetime('now')
1051
1051
  RETURNING count
1052
- `,args:[e,_,a]}),c=Number(o.rows[0]?.count);if(!Number.isSafeInteger(c)||c<1)throw new Error("Rate-limit bucket mutation did not return a valid count");return{allowed:c<=r,count:c,remaining:Math.max(0,r-c),resetSeconds:Math.max(1,a+n-s)}}async function nr(e){let t=q(32).toString("hex"),r=v("sha256").update(t).digest("hex"),n=new Date(Date.now()+3600*1e3).toISOString();return await i().execute({sql:"INSERT INTO password_reset_tokens (token, user_id, expires_at) VALUES (?, ?, ?)",args:[r,e,n]}),t}async function sr(e){let t=i(),r=v("sha256").update(e).digest("hex"),s=(await t.execute({sql:"SELECT user_id, expires_at, used FROM password_reset_tokens WHERE token = ?",args:[r]})).rows[0];return!s||Number(s.used)||new Date(String(s.expires_at))<new Date?null:(await t.execute({sql:"UPDATE password_reset_tokens SET used = 1 WHERE token = ?",args:[r]}),Number(s.user_id))}async function ir(e){let t=Re();return await i().execute({sql:"UPDATE users SET api_key = ?, key_active = 1 WHERE id = ?",args:[t,e]}),t}async function ar(e){await i().execute({sql:"UPDATE users SET key_active = 0 WHERE id = ?",args:[e]})}async function or(){return(await i().execute("SELECT id, email, name, created_at, active FROM users ORDER BY created_at DESC")).rows.map(t=>S({...t,api_key:"",key_active:1}))}async function _r(e){await i().execute({sql:"UPDATE users SET active = 0 WHERE id = ?",args:[e]})}function R(e){return{id:String(e.id),user_id:Number(e.user_id),status:String(e.status),query:String(e.query),options:String(e.options),callback_url:e.callback_url!=null?String(e.callback_url):null,result:e.result!=null?String(e.result):null,error:e.error!=null?String(e.error):null,public_error_json:e.public_error_json!=null?String(e.public_error_json):null,created_at:String(e.created_at),started_at:e.started_at!=null?String(e.started_at):null,completed_at:e.completed_at!=null?String(e.completed_at):null}}function C(e){return e==null?null:Number(e)===1}function H(e){if(e==null)return null;try{return JSON.parse(String(e))}catch{return null}}function we(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,kernel_session_id:e.kernel_session_id!=null?String(e.kernel_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:C(e.will_retry),kernel_delete_started:Number(e.kernel_delete_started??0)===1,kernel_delete_succeeded:C(e.kernel_delete_succeeded),kernel_delete_error:e.kernel_delete_error!=null?String(e.kernel_delete_error):null,browser_close_succeeded:C(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:C(e.provider_captcha),provider_checked_at:e.provider_checked_at!=null?String(e.provider_checked_at):null,provider_detail:H(e.provider_detail_json),provider_disconnect_observed:C(e.provider_disconnect_observed),provider_disconnect_message:e.provider_disconnect_message!=null?String(e.provider_disconnect_message):null,debug:H(e.debug_json),created_at:String(e.created_at),completed_at:e.completed_at!=null?String(e.completed_at):null}}function h(e){let{public_error_json:t,...r}=e;return{...r,options:JSON.parse(e.options),result:e.result?JSON.parse(e.result):null,publicError:ae(t)}}async function ur(e,t,r,n){let s=N();return await it(s,e,t,r,n),s}async function it(e,t,r,n,s){if(!/^[a-zA-Z0-9-]{1,100}$/.test(e))throw new Error("job id is invalid");await i().execute({sql:"INSERT INTO jobs (id, user_id, query, options, callback_url) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,JSON.stringify(n),s??null]})}async function cr(e,t,r){let n=N();return await i().execute({sql:"INSERT INTO jobs (id, user_id, query, options, status, started_at) VALUES (?, ?, ?, ?, 'running', datetime('now'))",args:[n,e,t,JSON.stringify(r)]}),n}async function dr(e,t,r,n){let s=await i().execute({sql:`INSERT INTO jobs (id, user_id, query, options, status, started_at)
1052
+ `,args:[e,_,a]}),c=Number(o.rows[0]?.count);if(!Number.isSafeInteger(c)||c<1)throw new Error("Rate-limit bucket mutation did not return a valid count");return{allowed:c<=r,count:c,remaining:Math.max(0,r-c),resetSeconds:Math.max(1,a+n-s)}}async function nr(e){let t=j(32).toString("hex"),r=v("sha256").update(t).digest("hex"),n=new Date(Date.now()+3600*1e3).toISOString();return await i().execute({sql:"INSERT INTO password_reset_tokens (token, user_id, expires_at) VALUES (?, ?, ?)",args:[r,e,n]}),t}async function sr(e){let t=i(),r=v("sha256").update(e).digest("hex"),s=(await t.execute({sql:"SELECT user_id, expires_at, used FROM password_reset_tokens WHERE token = ?",args:[r]})).rows[0];return!s||Number(s.used)||new Date(String(s.expires_at))<new Date?null:(await t.execute({sql:"UPDATE password_reset_tokens SET used = 1 WHERE token = ?",args:[r]}),Number(s.user_id))}async function ir(e){let t=Re();return await i().execute({sql:"UPDATE users SET api_key = ?, key_active = 1 WHERE id = ?",args:[t,e]}),t}async function ar(e){await i().execute({sql:"UPDATE users SET key_active = 0 WHERE id = ?",args:[e]})}async function or(){return(await i().execute("SELECT id, email, name, created_at, active FROM users ORDER BY created_at DESC")).rows.map(t=>S({...t,api_key:"",key_active:1}))}async function _r(e){await i().execute({sql:"UPDATE users SET active = 0 WHERE id = ?",args:[e]})}function R(e){return{id:String(e.id),user_id:Number(e.user_id),status:String(e.status),query:String(e.query),options:String(e.options),callback_url:e.callback_url!=null?String(e.callback_url):null,result:e.result!=null?String(e.result):null,error:e.error!=null?String(e.error):null,public_error_json:e.public_error_json!=null?String(e.public_error_json):null,created_at:String(e.created_at),started_at:e.started_at!=null?String(e.started_at):null,completed_at:e.completed_at!=null?String(e.completed_at):null}}function C(e){return e==null?null:Number(e)===1}function H(e){if(e==null)return null;try{return JSON.parse(String(e))}catch{return null}}function we(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:C(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:C(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:C(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:C(e.provider_captcha),provider_checked_at:e.provider_checked_at!=null?String(e.provider_checked_at):null,provider_detail:H(e.provider_detail_json),provider_disconnect_observed:C(e.provider_disconnect_observed),provider_disconnect_message:e.provider_disconnect_message!=null?String(e.provider_disconnect_message):null,debug:H(e.debug_json),created_at:String(e.created_at),completed_at:e.completed_at!=null?String(e.completed_at):null}}function h(e){let{public_error_json:t,...r}=e;return{...r,options:JSON.parse(e.options),result:e.result?JSON.parse(e.result):null,publicError:ae(t)}}async function ur(e,t,r,n){let s=N();return await it(s,e,t,r,n),s}async function it(e,t,r,n,s){if(!/^[a-zA-Z0-9-]{1,100}$/.test(e))throw new Error("job id is invalid");await i().execute({sql:"INSERT INTO jobs (id, user_id, query, options, callback_url) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,JSON.stringify(n),s??null]})}async function cr(e,t,r){let n=N();return await i().execute({sql:"INSERT INTO jobs (id, user_id, query, options, status, started_at) VALUES (?, ?, ?, ?, 'running', datetime('now'))",args:[n,e,t,JSON.stringify(r)]}),n}async function dr(e,t,r,n){let s=await i().execute({sql:`INSERT INTO jobs (id, user_id, query, options, status, started_at)
1053
1053
  VALUES (?, ?, ?, ?, 'running', datetime('now'))
1054
1054
  ON CONFLICT(id) DO NOTHING`,args:[e,t,r,JSON.stringify(n)]}),a=await K(e,t);if(!a)throw new Error(`getOrCreateRunningJob: row missing immediately after insert/lookup for ${e}`);return{job:a,created:s.rowsAffected===1}}async function Er(e){await i().execute({sql:`
1055
1055
  INSERT INTO harvest_attempts (
@@ -1084,14 +1084,14 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1084
1084
  UPDATE harvest_attempts SET
1085
1085
  status = 'finished',
1086
1086
  outcome = ?,
1087
- kernel_session_id = ?,
1087
+ \u006b\u0065\u0072\u006e\u0065\u006c_session_id = ?,
1088
1088
  question_count = ?,
1089
1089
  duration_ms = ?,
1090
1090
  error = ?,
1091
1091
  will_retry = ?,
1092
- kernel_delete_started = ?,
1093
- kernel_delete_succeeded = ?,
1094
- kernel_delete_error = ?,
1092
+ \u006b\u0065\u0072\u006e\u0065\u006c_delete_started = ?,
1093
+ \u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded = ?,
1094
+ \u006b\u0065\u0072\u006e\u0065\u006c_delete_error = ?,
1095
1095
  browser_close_succeeded = ?,
1096
1096
  browser_close_error = ?,
1097
1097
  browser_provider = COALESCE(browser_provider, ?),
@@ -1123,7 +1123,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1123
1123
  debug_json = ?,
1124
1124
  completed_at = ?
1125
1125
  WHERE job_id = ? AND attempt_number = ?
1126
- `,args:[e.outcome,e.kernelSessionId,e.questionCount,e.durationMs,e.error,e.willRetry?1:0,e.kernelDeleteStarted?1:0,e.kernelDeleteSucceeded==null?null:e.kernelDeleteSucceeded?1:0,e.kernelDeleteError,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:Oe(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 Oe(e,t=4096){let r=JSON.stringify(e);return r.length<=t?r:JSON.stringify({truncated:!0})}async function mr(e){return(await i().execute({sql:`
1126
+ `,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:Oe(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 Oe(e,t=4096){let r=JSON.stringify(e);return r.length<=t?r:JSON.stringify({truncated:!0})}async function mr(e){return(await i().execute({sql:`
1127
1127
  UPDATE harvest_attempts SET
1128
1128
  provider_lookup_status = ?,
1129
1129
  provider_status = ?,
@@ -1138,12 +1138,12 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1138
1138
  WHERE id = ?
1139
1139
  AND job_id = ?
1140
1140
  AND user_id = ?
1141
- AND browser_provider = 'bright_data_browser_api'
1141
+ AND browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
1142
1142
  AND provider_session_id = ?
1143
1143
  AND COALESCE(provider_lookup_status, '') <> 'complete'
1144
1144
  `,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:Oe(e.detail),e.attemptId,e.jobId,e.userId,e.providerSessionId]})).rowsAffected===1}async function Nr(e=25){let t=Math.max(1,Math.min(100,Math.trunc(e)));return(await i().execute({sql:`
1145
1145
  SELECT * FROM harvest_attempts
1146
- WHERE browser_provider = 'bright_data_browser_api'
1146
+ WHERE browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
1147
1147
  AND provider_session_id IS NOT NULL
1148
1148
  AND provider_lookup_status IN ('pending', 'temporary_error')
1149
1149
  ORDER BY COALESCE(provider_checked_at, created_at) ASC
@@ -1208,7 +1208,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1208
1208
  `,args:r})}catch(s){if(e.idempotencyKey){let a=await ct(e.idempotencyKey);if(a)return a}throw s}let n=await ut(t,e.userId);if(!n)throw new Error("Failed to create workflow run");return n}async function ut(e,t){let r=t==null?await i().execute({sql:"SELECT * FROM workflow_runs WHERE id = ? LIMIT 1",args:[e]}):await i().execute({sql:"SELECT * FROM workflow_runs WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]});return r.rows[0]?J(r.rows[0]):null}async function ct(e){let t=await i().execute({sql:"SELECT * FROM workflow_runs WHERE idempotency_key = ? LIMIT 1",args:[e]});return t.rows[0]?J(t.rows[0]):null}async function vr(e,t=50){return(await i().execute({sql:"SELECT * FROM workflow_runs WHERE user_id = ? ORDER BY queued_at DESC LIMIT ?",args:[e,t]})).rows.map(n=>J(n))}async function kr(e){await i().execute({sql:"UPDATE workflow_runs SET status = 'running', started_at = COALESCE(started_at, datetime('now')) WHERE id = ?",args:[e]})}async function Xr(e,t,r){await i().execute({sql:"UPDATE workflow_runs SET status = ?, manifest_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,JSON.stringify(r),e]})}async function Fr(e,t,r){await i().execute({sql:"UPDATE workflow_runs SET status = 'failed', error_message = ?, manifest_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,r==null?null:JSON.stringify(r),e]})}function dt(e){return e==="html_report"?"text/html; charset=utf-8":e==="csv"?"text/csv; charset=utf-8":e==="json"?"application/json; charset=utf-8":"text/plain; charset=utf-8"}async function xe(e,t,r){await i().execute({sql:`
1209
1209
  INSERT INTO workflow_artifacts (id, run_id, user_id, kind, label, path, content_type, bytes, rows_count, content)
1210
1210
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1211
- `,args:[N(),e,t,r.kind,r.label,r.path,dt(r.kind),r.bytes??null,r.rows??null,r.content??null]})}async function Mr(e,t,r){await i().execute({sql:"DELETE FROM workflow_artifacts WHERE run_id = ? AND user_id = ?",args:[e,t]});for(let n of r)await xe(e,t,n);return ye(e,t)}async function Pr(e,t,r){for(let n of r)await xe(e,t,n);return ye(e,t)}async function Hr(e,t){let n=(t==null?await i().execute({sql:"SELECT step_index, total_steps, step_state_json, step_log_json FROM workflow_runs WHERE id = ? LIMIT 1",args:[e]}):await i().execute({sql:"SELECT step_index, total_steps, step_state_json, step_log_json FROM workflow_runs WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]})).rows[0];return n?{stepIndex:n.step_index!=null?Number(n.step_index):0,totalSteps:n.total_steps!=null?Number(n.total_steps):null,state:n.step_state_json!=null?H(n.step_state_json):null,stepLog:he(n.step_log_json)}:null}async function qr(e,t){let r=[...t.appendLog,t.logEntry];await i().execute({sql:"UPDATE workflow_runs SET status = ?, step_index = ?, total_steps = ?, step_state_json = ?, step_log_json = ?, started_at = COALESCE(started_at, datetime('now')) WHERE id = ?",args:[t.status,t.stepIndex,t.totalSteps,JSON.stringify(t.state??null),JSON.stringify(r),e]})}async function ye(e,t){return(await i().execute({sql:"SELECT * FROM workflow_artifacts WHERE run_id = ? AND user_id = ? ORDER BY created_at ASC",args:[e,t]})).rows.map(n=>Ie(n))}async function jr(e,t){let r=await i().execute({sql:"SELECT * FROM workflow_artifacts WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]});return r.rows[0]?Ie(r.rows[0]):null}async function Wr(e){await i().execute({sql:`
1211
+ `,args:[N(),e,t,r.kind,r.label,r.path,dt(r.kind),r.bytes??null,r.rows??null,r.content??null]})}async function Mr(e,t,r){await i().execute({sql:"DELETE FROM workflow_artifacts WHERE run_id = ? AND user_id = ?",args:[e,t]});for(let n of r)await xe(e,t,n);return ye(e,t)}async function Pr(e,t,r){for(let n of r)await xe(e,t,n);return ye(e,t)}async function Hr(e,t){let n=(t==null?await i().execute({sql:"SELECT step_index, total_steps, step_state_json, step_log_json FROM workflow_runs WHERE id = ? LIMIT 1",args:[e]}):await i().execute({sql:"SELECT step_index, total_steps, step_state_json, step_log_json FROM workflow_runs WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]})).rows[0];return n?{stepIndex:n.step_index!=null?Number(n.step_index):0,totalSteps:n.total_steps!=null?Number(n.total_steps):null,state:n.step_state_json!=null?H(n.step_state_json):null,stepLog:he(n.step_log_json)}:null}async function jr(e,t){let r=[...t.appendLog,t.logEntry];await i().execute({sql:"UPDATE workflow_runs SET status = ?, step_index = ?, total_steps = ?, step_state_json = ?, step_log_json = ?, started_at = COALESCE(started_at, datetime('now')) WHERE id = ?",args:[t.status,t.stepIndex,t.totalSteps,JSON.stringify(t.state??null),JSON.stringify(r),e]})}async function ye(e,t){return(await i().execute({sql:"SELECT * FROM workflow_artifacts WHERE run_id = ? AND user_id = ? ORDER BY created_at ASC",args:[e,t]})).rows.map(n=>Ie(n))}async function qr(e,t){let r=await i().execute({sql:"SELECT * FROM workflow_artifacts WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]});return r.rows[0]?Ie(r.rows[0]):null}async function Wr(e){await i().execute({sql:`
1212
1212
  INSERT INTO workflow_webhook_deliveries (
1213
1213
  id, run_id, schedule_id, user_id, webhook_url, status, attempts, last_error, delivered_at
1214
1214
  )
@@ -1406,7 +1406,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1406
1406
  WHERE id IN (
1407
1407
  SELECT lot_id FROM billing_debit_allocations WHERE debit_idempotency_key = ?
1408
1408
  )
1409
- AND EXISTS (SELECT 1 FROM billing_debits WHERE idempotency_key = ? AND status = 'applying')`,args:[s,s,s]},{sql:"INSERT INTO ledger (user_id, amount_mc, operation, description) SELECT user_id, -amount_mc, operation, description FROM billing_debits WHERE idempotency_key = ? AND status = 'applying'",args:[s]},{sql:"UPDATE billing_debits SET status = 'applied', applied_at = datetime('now') WHERE idempotency_key = ? AND status = 'applying'",args:[s]}],"write")}catch(d){try{let E=(await a.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? AND status = 'applied' LIMIT 1",args:[s]})).rows[0];if(E&&Number(E.user_id)===e&&Number(E.amount_mc)===t&&String(E.operation)===r&&String(E.description)===n){let m=await a.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{ok:!0,balance_mc:Number(m.rows[0]?.balance_mc??0),duplicate:!0}}}catch{}throw d}let o=(await a.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? LIMIT 1",args:[s]})).rows[0];if(!o||Number(o.user_id)!==e||Number(o.amount_mc)!==t||String(o.operation)!==r||String(o.description)!==n)throw new Error("idempotent debit key conflicts with another debit");let c=await a.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{ok:String(o.status)==="applied",balance_mc:Number(c.rows[0]?.balance_mc??0),duplicate:_[2]?.rowsAffected===0&&String(o.status)==="applied"}}async function qn(e,t,r,n,s,a){if(!Number.isSafeInteger(r)||r<0)throw new Error("idempotent debit settlement amount must be a non-negative integer");if(!t||t.length>500)throw new Error("idempotent debit settlement key is required and must be bounded");if(!n||!a)throw new Error("idempotent debit settlement operation and source are required");let _=i();await A(e);let u=`debit-settlement:${v("sha256").update(t).digest("hex")}`,o="wallet_hold_settlement",c=N(),d=JSON.stringify({debitIdempotencyKey:t,refundOperation:n,description:s}),l=async()=>{let T=(await _.execute({sql:`SELECT e.user_id,
1409
+ AND EXISTS (SELECT 1 FROM billing_debits WHERE idempotency_key = ? AND status = 'applying')`,args:[s,s,s]},{sql:"INSERT INTO ledger (user_id, amount_mc, operation, description) SELECT user_id, -amount_mc, operation, description FROM billing_debits WHERE idempotency_key = ? AND status = 'applying'",args:[s]},{sql:"UPDATE billing_debits SET status = 'applied', applied_at = datetime('now') WHERE idempotency_key = ? AND status = 'applying'",args:[s]}],"write")}catch(d){try{let E=(await a.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? AND status = 'applied' LIMIT 1",args:[s]})).rows[0];if(E&&Number(E.user_id)===e&&Number(E.amount_mc)===t&&String(E.operation)===r&&String(E.description)===n){let m=await a.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{ok:!0,balance_mc:Number(m.rows[0]?.balance_mc??0),duplicate:!0}}}catch{}throw d}let o=(await a.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? LIMIT 1",args:[s]})).rows[0];if(!o||Number(o.user_id)!==e||Number(o.amount_mc)!==t||String(o.operation)!==r||String(o.description)!==n)throw new Error("idempotent debit key conflicts with another debit");let c=await a.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{ok:String(o.status)==="applied",balance_mc:Number(c.rows[0]?.balance_mc??0),duplicate:_[2]?.rowsAffected===0&&String(o.status)==="applied"}}async function jn(e,t,r,n,s,a){if(!Number.isSafeInteger(r)||r<0)throw new Error("idempotent debit settlement amount must be a non-negative integer");if(!t||t.length>500)throw new Error("idempotent debit settlement key is required and must be bounded");if(!n||!a)throw new Error("idempotent debit settlement operation and source are required");let _=i();await A(e);let u=`debit-settlement:${v("sha256").update(t).digest("hex")}`,o="wallet_hold_settlement",c=N(),d=JSON.stringify({debitIdempotencyKey:t,refundOperation:n,description:s}),l=async()=>{let T=(await _.execute({sql:`SELECT e.user_id,
1410
1410
  e.status,
1411
1411
  e.amount_mc AS final_amount_mc,
1412
1412
  e.billing_class,
@@ -1418,7 +1418,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1418
1418
  WHERE e.idempotency_key = ?
1419
1419
  AND d.user_id = e.user_id
1420
1420
  AND d.status = 'applied'
1421
- LIMIT 1`,args:[t,u]})).rows[0];if(!T)return null;if(Number(T.user_id)!==e||String(T.billing_class)!==o||String(T.source_surface)!==a)throw new Error("idempotent debit settlement key conflicts with another settlement");if(String(T.status)!=="settled")return null;let j=Number(T.held_amount_mc),w=Number(T.final_amount_mc);if(!Number.isSafeInteger(j)||!Number.isSafeInteger(w)||w<0||w>j)throw new Error("idempotent debit settlement receipt is invalid");let Ue=j-w,Q=await _.execute({sql:`WITH ordered AS (
1421
+ LIMIT 1`,args:[t,u]})).rows[0];if(!T)return null;if(Number(T.user_id)!==e||String(T.billing_class)!==o||String(T.source_surface)!==a)throw new Error("idempotent debit settlement key conflicts with another settlement");if(String(T.status)!=="settled")return null;let q=Number(T.held_amount_mc),w=Number(T.final_amount_mc);if(!Number.isSafeInteger(q)||!Number.isSafeInteger(w)||w<0||w>q)throw new Error("idempotent debit settlement receipt is invalid");let Ue=q-w,Q=await _.execute({sql:`WITH ordered AS (
1422
1422
  SELECT a.amount_mc,
1423
1423
  a.expires_at,
1424
1424
  COALESCE(SUM(a.amount_mc) OVER (
@@ -1542,7 +1542,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1542
1542
  WHERE refund_mc > 0`,args:[t,r,t,u,n,s]},{sql:`UPDATE billing_events
1543
1543
  SET status = 'settled', settled_at = datetime('now')
1544
1544
  WHERE idempotency_key = ?
1545
- AND status = 'applying'`,args:[u]}],"write")}catch(g){try{let T=await l();if(T)return T}catch{}throw g}let m=await l();if(!m)throw new Error("idempotent debit settlement did not reach a durable settled state");return{...m,duplicate:E[0]?.rowsAffected===0}}async function jn(e,t=50){return(await i().execute({sql:"SELECT * FROM ledger WHERE user_id = ? ORDER BY created_at DESC LIMIT ?",args:[e,t]})).rows.map(n=>({id:Number(n.id),user_id:Number(n.user_id),amount_mc:Number(n.amount_mc),operation:String(n.operation),description:n.description!=null?String(n.description):null,stripe_pi:n.stripe_pi!=null?String(n.stripe_pi):null,created_at:String(n.created_at)}))}async function Wn(e,t,r){let n=i(),s=r.refund.map(()=>"?").join(", "),a=r.grant.map(()=>"?").join(", "),_=r.purchase.map(()=>"?").join(", "),u=await n.execute({sql:`SELECT
1545
+ AND status = 'applying'`,args:[u]}],"write")}catch(g){try{let T=await l();if(T)return T}catch{}throw g}let m=await l();if(!m)throw new Error("idempotent debit settlement did not reach a durable settled state");return{...m,duplicate:E[0]?.rowsAffected===0}}async function qn(e,t=50){return(await i().execute({sql:"SELECT * FROM ledger WHERE user_id = ? ORDER BY created_at DESC LIMIT ?",args:[e,t]})).rows.map(n=>({id:Number(n.id),user_id:Number(n.user_id),amount_mc:Number(n.amount_mc),operation:String(n.operation),description:n.description!=null?String(n.description):null,stripe_pi:n.stripe_pi!=null?String(n.stripe_pi):null,created_at:String(n.created_at)}))}async function Wn(e,t,r){let n=i(),s=r.refund.map(()=>"?").join(", "),a=r.grant.map(()=>"?").join(", "),_=r.purchase.map(()=>"?").join(", "),u=await n.execute({sql:`SELECT
1546
1546
  COALESCE(SUM(CASE WHEN amount_mc < 0 AND operation NOT IN (${s}) THEN -amount_mc ELSE 0 END), 0) AS spent_mc,
1547
1547
  COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${s}) THEN amount_mc ELSE 0 END), 0) AS refunded_mc,
1548
1548
  COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${a}) THEN amount_mc ELSE 0 END), 0) AS granted_mc,
@@ -1562,4 +1562,4 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1562
1562
  FROM users u
1563
1563
  LEFT JOIN credit_lots l ON l.user_id = u.id
1564
1564
  WHERE u.id = ?
1565
- GROUP BY u.id, u.balance_mc`,args:[e]})).rows[0];if(!_)return 0;if(Number(_.lot_count??0)===0&&(await A(Number(e)),(await r.execute({sql:"SELECT 1 FROM credit_lots WHERE user_id = ? LIMIT 1",args:[e]})).rows.length>0))continue;let u=Number(_.cached_balance_mc??0),o=Number(_.projected_balance_mc??0);if(u===o||(await r.execute({sql:"UPDATE users SET balance_mc = ? WHERE id = ? AND balance_mc = ?",args:[o,e,u]})).rowsAffected===1)return o}let n=await r.execute({sql:"SELECT balance_mc FROM users WHERE id = ? LIMIT 1",args:[e]});return Number(n.rows[0]?.balance_mc??0)}var Gn=p.object({id:p.string(),user_id:p.number(),status:p.string().default("pending"),client_domain:p.string(),session_path:p.string(),request:p.string(),result:p.string().nullable(),error:p.string().nullable(),created_at:p.string(),updated_at:p.string()}),Yn=p.object({id:p.number(),job_id:p.string(),phase:p.string(),completed_at:p.string(),output_summary:p.string()});async function Kn(e){return(await i().execute({sql:"SELECT id, subject, sent_at, opened_at FROM inbox_messages WHERE user_id = ? AND deleted_at IS NULL ORDER BY sent_at DESC, id DESC",args:[e]})).rows.map(r=>({id:String(r.id),subject:String(r.subject),sent_at:String(r.sent_at),opened_at:r.opened_at!=null?String(r.opened_at):null}))}async function $n(e,t){let n=(await i().execute({sql:"SELECT id, subject, body_md, source, sent_at, opened_at FROM inbox_messages WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rows[0];if(n)return{id:String(n.id),subject:String(n.subject),body_md:String(n.body_md),source:String(n.source),sent_at:String(n.sent_at),opened_at:n.opened_at!=null?String(n.opened_at):null}}async function Jn(e,t){let r=i();await r.execute({sql:"UPDATE inbox_messages SET opened_at = datetime('now') WHERE id = ? AND user_id = ? AND deleted_at IS NULL AND opened_at IS NULL",args:[t,e]});let s=(await r.execute({sql:"SELECT opened_at FROM inbox_messages WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rows[0];return s&&s.opened_at!=null?String(s.opened_at):null}async function Vn(e,t){return(await i().execute({sql:"UPDATE inbox_messages SET deleted_at = datetime('now') WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rowsAffected>0}async function zn(e,t,r,n="operator"){let s=N();return await i().execute({sql:"INSERT INTO inbox_messages (id, user_id, subject, body_md, source) VALUES (?, ?, ?, ?, ?)",args:[s,e,t,r,n]}),s}async function Qn(){return(await i().execute("SELECT id FROM users WHERE active = 1")).rows.map(t=>Number(t.id))}export{Lt as a,ve as b,ke as c,O as d,ae as e,W as f,Be as g,Ge as h,_e as i,ee as j,te as k,re as l,ne as m,se as n,ie as o,k as p,U as q,le as r,It as s,i as t,xt as u,yt as v,Ct as w,nt as x,Ut as y,Dt as z,vt as A,kt as B,Xt as C,st as D,Ft as E,Mt as F,Pt as G,Ht as H,qt as I,jt as J,Wt as K,Bt as L,Gt as M,Yt as N,Re as O,Ae as P,Kt as Q,$t as R,Jt as S,Vt as T,zt as U,Qt as V,Zt as W,er as X,tr as Y,rr as Z,nr as _,sr as $,ir as aa,ar as ba,or as ca,_r as da,ur as ea,it as fa,cr as ga,dr as ha,Er as ia,lr as ja,Tr as ka,pr as la,mr as ma,Nr as na,gr as oa,K as pa,Lr as qa,br as ra,Sr as sa,Rr as ta,Ar as ua,wr as va,Or as wa,fr as xa,hr as ya,Y as za,Ir as Aa,xr as Ba,yr as Ca,Cr as Da,Ur as Ea,Dr as Fa,ut as Ga,ct as Ha,vr as Ia,kr as Ja,Xr as Ka,Fr as La,Mr as Ma,Pr as Na,Hr as Oa,qr as Pa,ye as Qa,jr as Ra,Wr as Sa,Br as Ta,Gr as Ua,Yr as Va,Kr as Wa,$r as Xa,Jr as Ya,Vr as Za,zr as _a,Qr as $a,Zr as ab,en as bb,tn as cb,rn as db,nn as eb,sn as fb,an as gb,on as hb,_n as ib,un as jb,cn as kb,dn as lb,En as mb,ln as nb,Tn as ob,pn as pb,mn as qb,Nn as rb,gn as sb,Ln as tb,bn as ub,Sn as vb,Rn as wb,An as xb,lt as yb,wn as zb,On as Ab,fn as Bb,pt as Cb,hn as Db,In as Eb,xn as Fb,yn as Gb,Cn as Hb,Un as Ib,Dn as Jb,D as Kb,vn as Lb,kn as Mb,Xn as Nb,Fn as Ob,Mn as Pb,Pn as Qb,Hn as Rb,mt as Sb,qn as Tb,jn as Ub,Wn as Vb,Bn as Wb,Ce as Xb,Gn as Yb,Yn as Zb,Kn as _b,$n as $b,Jn as ac,Vn as bc,zn as cc,Qn as dc};
1565
+ GROUP BY u.id, u.balance_mc`,args:[e]})).rows[0];if(!_)return 0;if(Number(_.lot_count??0)===0&&(await A(Number(e)),(await r.execute({sql:"SELECT 1 FROM credit_lots WHERE user_id = ? LIMIT 1",args:[e]})).rows.length>0))continue;let u=Number(_.cached_balance_mc??0),o=Number(_.projected_balance_mc??0);if(u===o||(await r.execute({sql:"UPDATE users SET balance_mc = ? WHERE id = ? AND balance_mc = ?",args:[o,e,u]})).rowsAffected===1)return o}let n=await r.execute({sql:"SELECT balance_mc FROM users WHERE id = ? LIMIT 1",args:[e]});return Number(n.rows[0]?.balance_mc??0)}var Gn=p.object({id:p.string(),user_id:p.number(),status:p.string().default("pending"),client_domain:p.string(),session_path:p.string(),request:p.string(),result:p.string().nullable(),error:p.string().nullable(),created_at:p.string(),updated_at:p.string()}),Yn=p.object({id:p.number(),job_id:p.string(),phase:p.string(),completed_at:p.string(),output_summary:p.string()});async function Kn(e){return(await i().execute({sql:"SELECT id, subject, sent_at, opened_at FROM inbox_messages WHERE user_id = ? AND deleted_at IS NULL ORDER BY sent_at DESC, id DESC",args:[e]})).rows.map(r=>({id:String(r.id),subject:String(r.subject),sent_at:String(r.sent_at),opened_at:r.opened_at!=null?String(r.opened_at):null}))}async function $n(e,t){let n=(await i().execute({sql:"SELECT id, subject, body_md, source, sent_at, opened_at FROM inbox_messages WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rows[0];if(n)return{id:String(n.id),subject:String(n.subject),body_md:String(n.body_md),source:String(n.source),sent_at:String(n.sent_at),opened_at:n.opened_at!=null?String(n.opened_at):null}}async function Jn(e,t){let r=i();await r.execute({sql:"UPDATE inbox_messages SET opened_at = datetime('now') WHERE id = ? AND user_id = ? AND deleted_at IS NULL AND opened_at IS NULL",args:[t,e]});let s=(await r.execute({sql:"SELECT opened_at FROM inbox_messages WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rows[0];return s&&s.opened_at!=null?String(s.opened_at):null}async function Vn(e,t){return(await i().execute({sql:"UPDATE inbox_messages SET deleted_at = datetime('now') WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rowsAffected>0}async function zn(e,t,r,n="operator"){let s=N();return await i().execute({sql:"INSERT INTO inbox_messages (id, user_id, subject, body_md, source) VALUES (?, ?, ?, ?, ?)",args:[s,e,t,r,n]}),s}async function Qn(){return(await i().execute("SELECT id FROM users WHERE active = 1")).rows.map(t=>Number(t.id))}export{Lt as a,ve as b,ke as c,O as d,ae as e,W as f,Be as g,Ge as h,_e as i,ee as j,te as k,re as l,ne as m,se as n,ie as o,k as p,U as q,le as r,It as s,i as t,xt as u,yt as v,Ct as w,nt as x,Ut as y,Dt as z,vt as A,kt as B,Xt as C,st as D,Ft as E,Mt as F,Pt as G,Ht as H,jt as I,qt as J,Wt as K,Bt as L,Gt as M,Yt as N,Re as O,Ae as P,Kt as Q,$t as R,Jt as S,Vt as T,zt as U,Qt as V,Zt as W,er as X,tr as Y,rr as Z,nr as _,sr as $,ir as aa,ar as ba,or as ca,_r as da,ur as ea,it as fa,cr as ga,dr as ha,Er as ia,lr as ja,Tr as ka,pr as la,mr as ma,Nr as na,gr as oa,K as pa,Lr as qa,br as ra,Sr as sa,Rr as ta,Ar as ua,wr as va,Or as wa,fr as xa,hr as ya,Y as za,Ir as Aa,xr as Ba,yr as Ca,Cr as Da,Ur as Ea,Dr as Fa,ut as Ga,ct as Ha,vr as Ia,kr as Ja,Xr as Ka,Fr as La,Mr as Ma,Pr as Na,Hr as Oa,jr as Pa,ye as Qa,qr as Ra,Wr as Sa,Br as Ta,Gr as Ua,Yr as Va,Kr as Wa,$r as Xa,Jr as Ya,Vr as Za,zr as _a,Qr as $a,Zr as ab,en as bb,tn as cb,rn as db,nn as eb,sn as fb,an as gb,on as hb,_n as ib,un as jb,cn as kb,dn as lb,En as mb,ln as nb,Tn as ob,pn as pb,mn as qb,Nn as rb,gn as sb,Ln as tb,bn as ub,Sn as vb,Rn as wb,An as xb,lt as yb,wn as zb,On as Ab,fn as Bb,pt as Cb,hn as Db,In as Eb,xn as Fb,yn as Gb,Cn as Hb,Un as Ib,Dn as Jb,D as Kb,vn as Lb,kn as Mb,Xn as Nb,Fn as Ob,Mn as Pb,Pn as Qb,Hn as Rb,mt as Sb,jn as Tb,qn as Ub,Wn as Vb,Bn as Wb,Ce as Xb,Gn as Yb,Yn as Zb,Kn as _b,$n as $b,Jn as ac,Vn as bc,zn as cc,Qn as dc};