mcp-scraper 0.96.3 → 0.97.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -1
- package/README.md +12 -18
- package/dist/actions-5X5CQAKO.js +1 -0
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.js +26 -27
- package/dist/bin/mcp-scraper-core.js +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.js +1 -1
- package/dist/bin/paa-harvest.js +1 -1
- package/dist/bundle-GS657HXG.js +1 -0
- package/dist/chunk-2L7CHN5N.js +4 -0
- package/dist/chunk-4AEW53RU.js +954 -0
- package/dist/chunk-4YZ74SJ6.js +1 -0
- package/dist/chunk-5RQWFYXY.js +930 -0
- package/dist/{chunk-U7BZ5KTE.js → chunk-5TQINRZN.js} +1 -1
- package/dist/{chunk-CFZXZKFT.js → chunk-5UQAL7HV.js} +1 -1
- package/dist/{chunk-GLCR4KJI.js → chunk-6D25Q5BR.js} +20 -14
- package/dist/chunk-B5Y26E3A.js +1 -0
- package/dist/chunk-C3JWX6KM.js +10 -0
- package/dist/{chunk-WP3QS4CJ.js → chunk-EYGA6LOU.js} +1 -1
- package/dist/{chunk-PANT6VEM.js → chunk-F3M7INSN.js} +7 -7
- package/dist/chunk-FLAWC5PF.js +5 -0
- package/dist/{chunk-WBJ6Y7WP.js → chunk-FM7BX2LU.js} +2 -2
- package/dist/chunk-IPQOBOFY.js +1 -0
- package/dist/chunk-J7XDXIB6.js +163 -0
- package/dist/chunk-JHDD6R3O.js +8 -0
- package/dist/chunk-KBZY2OGP.js +11 -0
- package/dist/{chunk-P55O4IDC.js → chunk-NQFTETVC.js} +1 -1
- package/dist/{chunk-3HXMW2UJ.js → chunk-P6CDR3RM.js} +1 -1
- package/dist/chunk-QCBCOEH5.js +1 -0
- package/dist/chunk-SJNSTO3C.js +42 -0
- package/dist/{chunk-MVMWPKRC.js → chunk-TZYITYL4.js} +1 -1
- package/dist/{chunk-JREMJRSS.js → chunk-UUJYICAJ.js} +1 -1
- package/dist/{chunk-DJT2547J.js → chunk-XNTAHMPA.js} +1 -1
- package/dist/chunk-ZDECILF6.js +16 -0
- package/dist/{chunk-42SLBGDI.js → chunk-ZNPGM3XE.js} +2 -2
- package/dist/compatibility-UPPKZ4KY.js +1 -0
- package/dist/{core-schema-423BSTE6.js → core-schema-Y47YFKH2.js} +7 -44
- package/dist/direct-completion-ZVPPEBDU.js +1 -0
- package/dist/dispatch-GRMMPKQD.js +1 -0
- package/dist/index.cjs +34 -34
- package/dist/index.js +1 -1
- package/dist/jobs-NRZHGQ7I.js +1 -0
- package/dist/queue-2VKW7SGH.js +1 -0
- package/dist/reconciliation-QC6SILLR.js +1 -0
- package/dist/{report-artifact-offload-6OOY2PTM.js → report-artifact-offload-PQNFDNPL.js} +1 -1
- package/dist/{server-74VGVXA4.js → server-EYMJROPX.js} +699 -1018
- package/dist/settlement-47EUTSGX.js +1 -0
- package/dist/vendor-errors-647LSH6H.js +1 -0
- package/dist/worker-AWJF7UYR.js +1 -0
- package/package.json +2 -2
- package/dist/actions-FKAX2PYT.js +0 -1
- package/dist/bundle-7JMACIIR.js +0 -1
- package/dist/chunk-2IATUJO6.js +0 -1
- package/dist/chunk-4KHDV5E7.js +0 -11
- package/dist/chunk-63VWBMYR.js +0 -3
- package/dist/chunk-7ZR5IO3B.js +0 -16
- package/dist/chunk-E7I3OQHQ.js +0 -203
- package/dist/chunk-JGGQ3UX5.js +0 -1
- package/dist/chunk-M5QHXNFZ.js +0 -10
- package/dist/chunk-MJOXIDKF.js +0 -935
- package/dist/chunk-OY24ERPV.js +0 -8
- package/dist/chunk-QYPSFZK3.js +0 -955
- package/dist/chunk-U4WIJZCX.js +0 -1
- package/dist/dispatch-E6VTNHHS.js +0 -1
- package/dist/queue-4XHYUV7J.js +0 -1
- package/dist/reconciliation-43CSC3XD.js +0 -1
- package/dist/settlement-I5IBIK6U.js +0 -1
- package/dist/worker-L5NISZQV.js +0 -1
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import{D as Oe,F as Re,G as Ce,H as j,c as R,h as Ee,i as C,j as y,k as ye,l as Se,m as P,n as he,o as Ae,p as we,q as T,r as xe,s as w,t as p,u as Ne,x as Ie,y as De,z as ke}from"./chunk-SJNSTO3C.js";import{L as ee}from"./chunk-6D25Q5BR.js";import{b as F}from"./chunk-C3JWX6KM.js";import{b as re,c as te}from"./chunk-QCBCOEH5.js";import{d as O}from"./chunk-KBZY2OGP.js";import{a as ue,b as ce,c as pe,f as me}from"./chunk-4YZ74SJ6.js";import{d as de}from"./chunk-JHDD6R3O.js";import{b as be,d as ge,e as D,f as ve,j as k,p as fe}from"./chunk-7SR7MEU5.js";import{d as oe,e as ne,f as ie,g as se,i as I,l as ae,s as le,t as b}from"./chunk-ANQ4JJVI.js";import{a as g,b as E,c}from"./chunk-FLAWC5PF.js";import{c as W,d as B}from"./chunk-B4ZKPLSP.js";import{a as V,b as X,c as Z}from"./chunk-VVSHZV5S.js";import{b as Y}from"./chunk-4ZVO6GX4.js";import{b as N,d as z,g as m,h as A,j as K,m as G,o as Q}from"./chunk-C7MGJUTU.js";import{a}from"./chunk-WNUXMPVX.js";import{b as _e}from"./chunk-B3JRL45T.js";import{c as h,d as f}from"./chunk-HNNYXMSI.js";import{randomUUID as tr}from"crypto";async function Ar(e,r,t){let n=tr();return await a().execute({sql:"INSERT INTO jobs (id, user_id, query, options, status, started_at) VALUES (?, ?, ?, ?, 'running', datetime('now'))",args:[n,e,r,JSON.stringify(t)]}),n}async function wr(e,r,t,n){let s=await a().execute({sql:`INSERT INTO jobs (id, user_id, query, options, status, started_at)
|
|
2
|
+
VALUES (?, ?, ?, ?, 'running', datetime('now'))
|
|
3
|
+
ON CONFLICT(id) DO NOTHING`,args:[e,r,t,JSON.stringify(n)]}),i=await c(e,r);if(!i)throw new Error(`getOrCreateRunningJob: row missing immediately after insert/lookup for ${e}`);return{job:i,created:s.rowsAffected===1}}async function xr(e,r,t){await a().execute({sql:`UPDATE jobs
|
|
4
|
+
SET status = 'running', started_at = COALESCE(started_at, datetime('now')),
|
|
5
|
+
options = CASE WHEN ? = 'runtime' THEN json_set(options, '$.executionOwner', 'runtime') ELSE options END
|
|
6
|
+
WHERE id = ?
|
|
7
|
+
AND (status = 'pending' OR (
|
|
8
|
+
status = 'running' AND ? = 'runtime'
|
|
9
|
+
AND json_extract(options, '$.executionOwner') = 'inngest'
|
|
10
|
+
AND EXISTS (SELECT 1 FROM operation_executions e JOIN operation_runs r ON r.id = e.run_id
|
|
11
|
+
WHERE e.run_id = 'extract-url-execution:' || jobs.id AND r.user_id = jobs.user_id
|
|
12
|
+
AND r.status = 'running' AND e.phase = 'claimed'
|
|
13
|
+
AND e.expires_at_ms <= CAST(strftime('%s', 'now') AS INTEGER) * 1000)
|
|
14
|
+
))
|
|
15
|
+
AND (json_extract(options, '$.executionOwner') = ?
|
|
16
|
+
OR (? = 'runtime' AND json_extract(options, '$.executionOwner') = 'inngest'))
|
|
17
|
+
AND json_extract(options, '$.jobKind') = ?`,args:[r,e,r,r,r,t]});let n=await c(e);if(!(!n||n.options.executionOwner!==r||n.options.jobKind!==t))return n}async function Nr(e=25){let r=Math.max(1,Math.min(100,Math.floor(e)));return(await a().execute({sql:`SELECT * FROM jobs
|
|
18
|
+
WHERE status IN ('pending', 'running')
|
|
19
|
+
AND json_extract(options, '$.executionOwner') IN ('runtime', 'inngest')
|
|
20
|
+
AND json_extract(options, '$.jobKind') = 'extract_url'
|
|
21
|
+
AND json_extract(options, '$.billingDebitKey') IS NOT NULL
|
|
22
|
+
AND EXISTS (SELECT 1 FROM billing_debits d
|
|
23
|
+
WHERE d.idempotency_key = json_extract(jobs.options, '$.billingDebitKey')
|
|
24
|
+
AND d.user_id = jobs.user_id AND d.status = 'applied'
|
|
25
|
+
AND d.operation = ? AND d.amount_mc = ?)
|
|
26
|
+
AND (
|
|
27
|
+
NOT EXISTS (SELECT 1 FROM operation_executions e
|
|
28
|
+
WHERE e.run_id = 'extract-url-execution:' || jobs.id)
|
|
29
|
+
AND (status = 'pending' OR json_extract(options, '$.executionOwner') = 'runtime')
|
|
30
|
+
OR EXISTS (SELECT 1 FROM operation_executions e JOIN operation_runs r ON r.id = e.run_id
|
|
31
|
+
WHERE e.run_id = 'extract-url-execution:' || jobs.id AND r.user_id = jobs.user_id
|
|
32
|
+
AND r.status = 'running' AND e.phase = 'claimed'
|
|
33
|
+
AND e.expires_at_ms <= CAST(strftime('%s', 'now') AS INTEGER) * 1000)
|
|
34
|
+
)
|
|
35
|
+
AND created_at <= datetime('now', '-30 seconds')
|
|
36
|
+
AND (status = 'pending' OR datetime(COALESCE(started_at, created_at)) <= datetime('now', '-30 seconds'))
|
|
37
|
+
AND datetime(COALESCE(json_extract(options, '$.extractUrlLastDispatchAt'), '1970-01-01')) <= datetime('now', '-30 seconds')
|
|
38
|
+
ORDER BY created_at
|
|
39
|
+
LIMIT ?`,args:[ce.EXTRACT_URL,ue.page_scrape,r]})).rows.map(n=>E(g(n)))}async function Ir(e,r){return(await a().execute({sql:`UPDATE jobs
|
|
40
|
+
SET options = json_set(options,
|
|
41
|
+
'$.extractUrlDispatchAttempts', COALESCE(json_extract(options, '$.extractUrlDispatchAttempts'), 0) + 1,
|
|
42
|
+
'$.extractUrlLastDispatchAt', ?,
|
|
43
|
+
'$.extractUrlLastDispatchError', ?)
|
|
44
|
+
WHERE id = ? AND (status = 'pending' OR (status = 'running' AND (
|
|
45
|
+
json_extract(options, '$.executionOwner') = 'runtime'
|
|
46
|
+
OR EXISTS (SELECT 1 FROM operation_executions e JOIN operation_runs r ON r.id = e.run_id
|
|
47
|
+
WHERE e.run_id = 'extract-url-execution:' || jobs.id AND r.user_id = jobs.user_id
|
|
48
|
+
AND r.status = 'running' AND e.phase = 'claimed'
|
|
49
|
+
AND e.expires_at_ms <= CAST(strftime('%s', 'now') AS INTEGER) * 1000)
|
|
50
|
+
)))
|
|
51
|
+
AND json_extract(options, '$.executionOwner') IN ('runtime', 'inngest')
|
|
52
|
+
AND json_extract(options, '$.jobKind') = 'extract_url'`,args:[new Date().toISOString(),r??null,e]})).rowsAffected===1}async function Dr(e){return(await a().execute({sql:"SELECT * FROM jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[e]})).rows.map(t=>E(g(t)))}async function Pe(){let e=a(),r=await e.execute(`
|
|
53
|
+
SELECT * FROM jobs
|
|
54
|
+
WHERE status = 'pending'
|
|
55
|
+
AND COALESCE(json_extract(options, '$.executionOwner'), 'cron') NOT IN ('direct', 'runtime', 'inngest')
|
|
56
|
+
AND json_extract(options,'$.queueExecutionProtocol') IS NOT 0
|
|
57
|
+
ORDER BY created_at
|
|
58
|
+
LIMIT 1
|
|
59
|
+
`),t=r.rows[0]?g(r.rows[0]):void 0;return t?(await e.execute({sql:"UPDATE jobs SET status = 'running', started_at = datetime('now') WHERE id = ? AND status = 'pending'",args:[t.id]})).rowsAffected===0?void 0:{...t,status:"running"}:void 0}async function kr(e,r){await a().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now') WHERE id = ? AND ${O}`,args:[JSON.stringify(r),e]})}async function Or(e,r,t){await a().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now') WHERE id = ? AND ${O}`,args:[r,z(t),e]})}async function Tr(e=25){let r=Math.max(1,Math.min(100,Math.floor(e)));return(await a().execute({sql:`SELECT * FROM jobs
|
|
60
|
+
WHERE status IN ('done', 'failed', 'cancelled')
|
|
61
|
+
AND json_extract(options, '$.executionOwner') IN ('direct', 'inngest')
|
|
62
|
+
AND json_extract(options, '$.billingDebitKey') IS NOT NULL
|
|
63
|
+
AND CAST(json_extract(options, '$.billingHoldMc') AS INTEGER) > 0
|
|
64
|
+
AND json_extract(options, '$.billingSettledAt') IS NULL
|
|
65
|
+
ORDER BY completed_at DESC
|
|
66
|
+
LIMIT ?`,args:[r]})).rows.map(n=>E(g(n)))}async function Te(e,r=25,t="1"){if(!/^[a-z_]+$/.test(e)||!t.trim()||t.length>8192)throw Error("Invalid intent selection");return(await a().execute({sql:`SELECT r.id,r.user_id,r.job_id FROM operation_runs r
|
|
67
|
+
JOIN operation_executions e ON e.run_id=r.id
|
|
68
|
+
WHERE r.tool=? AND r.status='running' AND e.phase='claimed'
|
|
69
|
+
AND e.expires_at_ms <= CAST(strftime('%s','now') AS INTEGER)*1000
|
|
70
|
+
AND json_extract(r.normalized_flags_json,'$._storeGateRequired') IS 1 AND (${t})
|
|
71
|
+
ORDER BY r.started_at LIMIT ?`,args:[e,Math.max(1,Math.min(100,Math.floor(r)))]})).rows.map(s=>({runId:String(s.id),userId:Number(s.user_id),jobId:String(s.job_id)}))}function je(e){let r=JSON.parse(f(e.options)),t=r.serpOnly===!0&&!r.serpIdentity;return{profile:"queue",jobId:e.jobId,userId:e.userId,tool:"search_serp",requestFingerprint:e.requestFingerprint,options:r,callbackUrl:e.callbackUrl??null,deadlineAt:0,budgetMs:W(Number(r.maxQuestions??30),!0,r.mode,r.pages,!!r.recency,t).serverMs,hold:{userId:e.userId,key:`serp-search:${e.jobId}:hold`,amountMc:e.amountMc,operation:"serp",description:`SERP search: ${r.query}`.slice(0,500)},refundOperation:"serp_refund",sourceSurface:"serp_search"}}var Gr=e=>j(je(e));async function or(e,r){let t;try{t=await b(`harvest:${r}`,e,"search_serp",r)}catch{return{kind:"unknown",reply:{status:503,body:{job_id:r,status:"pending",executionState:"unknown",hold_state:"unconfirmed",status_tool:"harvest_paa_status",...A({errorCode:"response_lost",retryable:!0})}}}}return t?.flags.syncExecutionProtocol!==1||t.flags.intent?.profile!=="queue"?null:j(t.flags.intent,!1)}async function Me(){for(let r of await Te("search_serp",1,`json_extract(r.normalized_flags_json,'$.intent.profile')='queue' AND (EXISTS(SELECT 1 FROM (SELECT r.user_id AS user_id,json_extract(r.normalized_flags_json,'$.intent') AS normalized_flags_json) saved WHERE ${de("saved.user_id","json_extract(saved.normalized_flags_json,'$.hold.key')")}))`))await c(r.jobId,r.userId)||await or(r.userId,r.jobId);let e=(await a().execute(`SELECT j.id,j.user_id FROM jobs j JOIN operation_runs r ON r.id='harvest:'||j.id AND r.user_id=j.user_id JOIN operation_executions x ON x.run_id=r.id
|
|
72
|
+
WHERE json_extract(j.options,'$.queueExecutionProtocol')=1 AND x.phase IN ('effects_started','unknown') AND x.expires_at_ms<=CAST(strftime('%s','now') AS INTEGER)*1000
|
|
73
|
+
ORDER BY j.created_at LIMIT 1`)).rows[0];return e?c(String(e.id),Number(e.user_id)):void 0}async function Le(e,r){if(e.options.queueExecutionProtocol!==1)return await a().execute({sql:"UPDATE jobs SET options=json_set(options,'$.queueExecutionProtocol',0,'$.executionState','unknown','$.holdState','unconfirmed') WHERE id=? AND user_id=? AND json_extract(options,'$.queueExecutionProtocol') IS NULL",args:[e.id,e.user_id]}),{completed:!1,replayed:!1,reply:null};let t=await Re(e);if(t)return{completed:(await c(e.id,e.user_id))?.options.executionState==="finalized"&&t.status===200,replayed:!0,reply:t};let n=e.options,s=Object.fromEntries(Object.entries(n).filter(([d])=>!["executionOwner","queueExecutionProtocol","billingHoldMc","billingDebitKey","requestFingerprint","compatDeadlineAt","executionState","holdState"].includes(d))),i=je({jobId:e.id,userId:e.user_id,options:s,requestFingerprint:String(n.requestFingerprint),amountMc:Number(n.billingHoldMc),callbackUrl:e.callback_url}),o=await Ce(i,async d=>{let u={value:null},_=n.serpOnly===!0&&!n.serpIdentity,v=`harvest:${e.id}`,x=null,J=AbortSignal.timeout(Math.max(0,d.deadlineAt-Date.now()));if(_&&!De({pages:n.pages===2?2:1,recency:n.recency==="week"||n.recency==="month"?n.recency:void 0,mode:n.mode,token:r.apifyToken}))throw Error("Search providers are not configured");let er=await r.withCostContext({op:"serp",userId:e.user_id,headlessSentOut:u,operationRunId:v,operationAccountScope:"production-default"},async()=>_?ke({query:String(n.query??e.query),pages:n.pages===2?2:1,mode:n.mode,recency:n.recency==="week"||n.recency==="month"?n.recency:void 0,token:r.apifyToken,operationRunId:v,accountScope:"production-default",signal:J,onAttemptEvent:r.onAttemptEvent,physicalFactory:d.physicalFactory}).then($=>(x=$,$.result)):ee({...n,physicalExecution:await d.physicalFactory(),\u006b\u0065\u0072\u006e\u0065\u006cApiKey:r.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,headless:!0,format:"json",outputDir:"/tmp/paa-output-api",signal:J,onAttemptEvent:r.onAttemptEvent}));if(_&&!x)throw Error("Search provider billing receipt is missing");let U=x,rr=_?me(U.deliveredPages,U.deliveryProvider):pe(u.value);return{result:er,amountMc:Math.min(Number(n.billingHoldMc),rr)}},r.classifyFailure);return{completed:(await c(e.id,e.user_id))?.options.executionState==="finalized"&&!!(o.body.status&&["done","failed","cancelled"].includes(String(o.body.status))),replayed:!1,reply:o}}import{randomUUID as nr}from"crypto";function S(e){return e==null?null:Number(e)===1}function He(e){if(e==null)return null;try{return JSON.parse(String(e))}catch{return null}}function qe(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:S(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:S(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:S(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:S(e.provider_captcha),provider_checked_at:e.provider_checked_at!=null?String(e.provider_checked_at):null,provider_detail:He(e.provider_detail_json),provider_disconnect_observed:S(e.provider_disconnect_observed),provider_disconnect_message:e.provider_disconnect_message!=null?String(e.provider_disconnect_message):null,debug:He(e.debug_json),created_at:String(e.created_at),completed_at:e.completed_at!=null?String(e.completed_at):null}}async function Je(e){await a().execute({sql:`
|
|
74
|
+
INSERT INTO harvest_attempts (
|
|
75
|
+
id, job_id, user_id, attempt_number, max_attempts, query, location, max_questions, status, created_at
|
|
76
|
+
)
|
|
77
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'running', ?)
|
|
78
|
+
ON CONFLICT(job_id, attempt_number) DO NOTHING
|
|
79
|
+
`,args:[nr(),e.jobId,e.userId,e.attemptNumber,e.maxAttempts,e.query,e.location,e.maxQuestions,e.startedAt]})}async function Ue(e){return(await a().execute({sql:`
|
|
80
|
+
UPDATE harvest_attempts SET
|
|
81
|
+
browser_provider = ?,
|
|
82
|
+
provider_session_id = ?,
|
|
83
|
+
provider_session_observed_at = COALESCE(provider_session_observed_at, ?),
|
|
84
|
+
provider_lookup_status = CASE
|
|
85
|
+
WHEN provider_lookup_status = 'complete' THEN provider_lookup_status
|
|
86
|
+
ELSE 'pending'
|
|
87
|
+
END
|
|
88
|
+
WHERE job_id = ? AND attempt_number = ? AND status = 'running'
|
|
89
|
+
`,args:[e.browserProvider,e.providerSessionId,e.observedAt,e.jobId,e.attemptNumber]})).rowsAffected===1}async function $e(e){await a().execute({sql:`
|
|
90
|
+
UPDATE harvest_attempts SET
|
|
91
|
+
status = 'finished',
|
|
92
|
+
outcome = ?,
|
|
93
|
+
\u006b\u0065\u0072\u006e\u0065\u006c_session_id = ?,
|
|
94
|
+
question_count = ?,
|
|
95
|
+
duration_ms = ?,
|
|
96
|
+
error = ?,
|
|
97
|
+
will_retry = ?,
|
|
98
|
+
\u006b\u0065\u0072\u006e\u0065\u006c_delete_started = ?,
|
|
99
|
+
\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded = ?,
|
|
100
|
+
\u006b\u0065\u0072\u006e\u0065\u006c_delete_error = ?,
|
|
101
|
+
browser_close_succeeded = ?,
|
|
102
|
+
browser_close_error = ?,
|
|
103
|
+
browser_provider = COALESCE(browser_provider, ?),
|
|
104
|
+
provider_session_id = COALESCE(provider_session_id, ?),
|
|
105
|
+
provider_lookup_status = CASE
|
|
106
|
+
WHEN provider_lookup_status = 'complete' THEN provider_lookup_status
|
|
107
|
+
ELSE COALESCE(?, provider_lookup_status)
|
|
108
|
+
END,
|
|
109
|
+
provider_status = COALESCE(provider_status, ?),
|
|
110
|
+
provider_error_code = CASE
|
|
111
|
+
WHEN provider_reason_source = 'provider_session_api' THEN provider_error_code
|
|
112
|
+
ELSE COALESCE(?, provider_error_code)
|
|
113
|
+
END,
|
|
114
|
+
provider_error_message = CASE
|
|
115
|
+
WHEN provider_reason_source = 'provider_session_api' THEN provider_error_message
|
|
116
|
+
ELSE COALESCE(?, provider_error_message)
|
|
117
|
+
END,
|
|
118
|
+
provider_reason_source = CASE
|
|
119
|
+
WHEN provider_reason_source = 'provider_session_api' THEN provider_reason_source
|
|
120
|
+
ELSE COALESCE(?, provider_reason_source)
|
|
121
|
+
END,
|
|
122
|
+
provider_duration_ms = COALESCE(provider_duration_ms, ?),
|
|
123
|
+
provider_bandwidth_bytes = COALESCE(provider_bandwidth_bytes, ?),
|
|
124
|
+
provider_captcha = COALESCE(provider_captcha, ?),
|
|
125
|
+
provider_checked_at = COALESCE(provider_checked_at, ?),
|
|
126
|
+
provider_detail_json = COALESCE(provider_detail_json, ?),
|
|
127
|
+
provider_disconnect_observed = COALESCE(provider_disconnect_observed, ?),
|
|
128
|
+
provider_disconnect_message = COALESCE(provider_disconnect_message, ?),
|
|
129
|
+
debug_json = ?,
|
|
130
|
+
completed_at = ?
|
|
131
|
+
WHERE job_id = ? AND attempt_number = ?
|
|
132
|
+
`,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:Fe(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 Fe(e,r=4096){let t=JSON.stringify(e);return t.length<=r?t:JSON.stringify({truncated:!0})}async function Xr(e){return(await a().execute({sql:`
|
|
133
|
+
UPDATE harvest_attempts SET
|
|
134
|
+
provider_lookup_status = ?,
|
|
135
|
+
provider_status = ?,
|
|
136
|
+
provider_error_code = ?,
|
|
137
|
+
provider_error_message = ?,
|
|
138
|
+
provider_reason_source = ?,
|
|
139
|
+
provider_duration_ms = ?,
|
|
140
|
+
provider_bandwidth_bytes = ?,
|
|
141
|
+
provider_captcha = ?,
|
|
142
|
+
provider_checked_at = ?,
|
|
143
|
+
provider_detail_json = ?
|
|
144
|
+
WHERE id = ?
|
|
145
|
+
AND job_id = ?
|
|
146
|
+
AND user_id = ?
|
|
147
|
+
AND browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
|
|
148
|
+
AND provider_session_id = ?
|
|
149
|
+
AND COALESCE(provider_lookup_status, '') <> 'complete'
|
|
150
|
+
`,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:Fe(e.detail),e.attemptId,e.jobId,e.userId,e.providerSessionId]})).rowsAffected===1}async function Zr(e=25){let r=Math.max(1,Math.min(100,Math.trunc(e)));return(await a().execute({sql:`
|
|
151
|
+
SELECT * FROM harvest_attempts
|
|
152
|
+
WHERE browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
|
|
153
|
+
AND provider_session_id IS NOT NULL
|
|
154
|
+
AND provider_lookup_status IN ('pending', 'temporary_error')
|
|
155
|
+
ORDER BY COALESCE(provider_checked_at, created_at) ASC
|
|
156
|
+
LIMIT ?
|
|
157
|
+
`,args:[r]})).rows.map(n=>qe(n))}async function We(e,r){return(r==null?await a().execute({sql:"SELECT * FROM harvest_attempts WHERE job_id = ? ORDER BY attempt_number ASC",args:[e]}):await a().execute({sql:`
|
|
158
|
+
SELECT ha.*
|
|
159
|
+
FROM harvest_attempts ha
|
|
160
|
+
INNER JOIN jobs j ON j.id = ha.job_id
|
|
161
|
+
WHERE ha.job_id = ? AND j.user_id = ?
|
|
162
|
+
ORDER BY ha.attempt_number ASC
|
|
163
|
+
`,args:[e,r]})).rows.map(n=>qe(n))}import{createHash as it}from"crypto";var ir=1e9;function M(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 sr(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 Be(e,r,t=0){let n=new Map,s=null;return async i=>{if(e)try{if(i.type==="started"){let l=t+i.attemptNumber;if(l>1&&!s){let v=(await fe(e))?.attempts.at(-1);s=v?.id==null?null:String(v.id)}let d=await be({runId:e,attemptNumber:l,method:i.method,provider:i.provider,parentAttemptId:l===1?null:s,edgeKind:l===1?null:t>0&&i.attemptNumber===1?"durable_resume":i.retryKind==="provider_fallback"?"provider_fallback":"same_method_retry",retryKind:l===1?null:t>0&&i.attemptNumber===1?"durable_resume":i.retryKind,retryReason:l===1?null:t>0&&i.attemptNumber===1?"durable_worker_resume":i.retryReason,retryOwner:l===1?null:t>0&&i.attemptNumber===1?"durable_reconciler":"harvest",normalizedFlags:{maxAttempts:i.maxAttempts,maxQuestions:i.maxQuestions,hasLocation:!!i.location,plannedProvider:i.provider,planReason:i.planReason??null,planTimeoutMs:i.planTimeoutMs??null},startedAt:i.startedAt}),u=await D({attemptId:d,provider:i.provider,providerProduct:i.provider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser_api":"\u006b\u0065\u0072\u006e\u0065\u006c_browser",billingTier:i.provider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?R("https://www.google.com/search"):null,accountScope:r,method:i.method,providerStatus:"started"});n.set(i.attemptNumber,{attemptId:d,receiptId:u.id,plannedProvider:i.provider,observedProvider:null,providerMismatch:!1,method:i.method,startedAtMs:Date.parse(i.startedAt),billingMode:null}),s=d;return}let o=n.get(i.attemptNumber);if(!o)throw new Error(`Missing operation attempt state for attempt ${i.attemptNumber}`);if(i.type==="provider_session_started"){let l=sr(i.provider);if(o.observedProvider=l,o.billingMode=i.billingMode??null,l!==o.plannedProvider){o.providerMismatch=!0,await k({receiptId:o.receiptId,costState:"unavailable",providerStatus:"provider_mismatch",errorCode:"provider_mismatch",errorMessage:`Planned ${o.plannedProvider}; observed ${l}`,finalizedAt:i.observedAt});let d=l==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser":"\u006b\u0065\u0072\u006e\u0065\u006c_browser",u=await D({attemptId:o.attemptId,provider:l,providerProduct:l==="\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:l==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?R("https://www.google.com/search"):null,accountScope:r,method:d,providerStatus:"observed_provider_mismatch"});o.receiptId=u.id,o.method=d}await ve(o.receiptId,i.providerSessionId);return}if(await ge({attemptId:o.attemptId,status:o.providerMismatch?"failed":M(i.outcome),errorCode:o.providerMismatch?"provider_mismatch":M(i.outcome)==="succeeded"?null:i.outcome,errorMessage:i.error,durationMs:i.durationMs,endedAt:i.completedAt}),(o.observedProvider??o.plannedProvider)==="\u006b\u0065\u0072\u006e\u0065\u006c"){let l=o.billingMode==="headful",d=o.billingMode==="headless"||o.billingMode==="headful"?Z(i.durationMs,l):null;await k({receiptId:o.receiptId,costState:"estimated",units:i.durationMs/1e3,unitType:"wall_open_second",amountUsdNanos:d==null?null:Math.round(d*ir),providerProduct:"\u006b\u0065\u0072\u006e\u0065\u006c_browser",billingTier:o.billingMode,billableEvent:"provider_active_gb_second",measurementSource:"wall_open_time_proxy",rateSource:d!=null?`${X};\u006b\u0065\u0072\u006e\u0065\u006c_usd_per_second:${V}`:null,providerStatus:o.providerMismatch?"provider_mismatch":i.outcome,providerDurationMs:i.durationMs,errorCode:o.providerMismatch?"provider_mismatch":M(i.outcome)==="succeeded"?null:i.outcome,errorMessage:i.error,finalizedAt:i.completedAt})}}catch(o){console.warn(JSON.stringify({event:"operation_attempt_telemetry_failed",operation_run_id:e,attempt_number:i.attemptNumber,message:o instanceof Error?o.message:String(o)}))}}}function ze(e,r,t=null,n="production-default",s=0){let i=Be(t,n,s);return async o=>{if(await i(o),o.type==="started"){await Je({jobId:e,userId:r,attemptNumber:o.attemptNumber,maxAttempts:o.maxAttempts,query:o.query,location:o.location,maxQuestions:o.maxQuestions,startedAt:o.startedAt});return}if(o.type==="provider_session_started"){await Ue({jobId:e,attemptNumber:o.attemptNumber,browserProvider:o.provider,providerSessionId:o.providerSessionId,observedAt:o.observedAt});return}await $e({jobId:e,attemptNumber:o.attemptNumber,outcome:o.outcome,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:o.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:o.questionCount,durationMs:o.durationMs,error:o.error,willRetry:o.willRetry,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:o.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:o.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:o.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError,browserCloseSucceeded:o.cleanup.browserCloseSucceeded,browserCloseError:o.cleanup.browserCloseError,browserProvider:o.cleanup.provider??null,providerSessionId:o.cleanup.providerSessionId??null,providerLookupStatus:o.cleanup.providerSessionId?"pending":"not_applicable",providerErrorCode:o.cleanup.providerDisconnectObserved?"browser_session_interrupted":null,providerErrorMessage:o.cleanup.providerDisconnectMessage??null,providerReasonSource:o.cleanup.providerDisconnectObserved?"client_runtime":null,providerDisconnectObserved:o.cleanup.providerDisconnectObserved??!1,providerDisconnectMessage:o.cleanup.providerDisconnectMessage??null,debug:o.debug,completedAt:o.completedAt})}}function ar(e){return e instanceof Error?e.message:String(e)}function lr(e,r){return e instanceof DOMException&&(e.name==="TimeoutError"||e.name==="AbortError")?!0:/timeout|timed out|Timeout \d+ms exceeded|deadline/i.test(r)}function dr(e){return/captcha|recaptcha|unusual traffic|google\.com\/sorry|blocked/i.test(e)}function ur(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 cr(e){return/proxy unavailable|proxy_unavailable|connection_test_failed|did not return a proxy id|configured fallback/i.test(e)}function pr(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 mr(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 L(e){let r=ar(e);return e instanceof G?{error_code:"request_aborted",error_type:"request_aborted",message:m("request_aborted"),retryable:!0,httpStatus:408,terminalStatus:"cancelled"}:e instanceof K||dr(r)?{error_code:"captcha_exhausted",error_type:"captcha",message:m("captcha_exhausted"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:F(e,r)?{error_code:"vendor_unavailable",error_type:"service_unavailable",message:m("vendor_unavailable"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:e instanceof Q?{error_code:"location_mismatch",error_type:"location_mismatch",message:m("location_mismatch"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:ur(r)?{error_code:"proxy_tunnel_failed",error_type:"connection",message:m("proxy_tunnel_failed"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:cr(r)?{error_code:"proxy_unavailable",error_type:"connection",message:m("proxy_unavailable"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:mr(r)?{error_code:"browser_session_interrupted",error_type:"extraction",message:m("browser_session_interrupted"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:lr(e,r)?{error_code:"harvest_timeout",error_type:"timeout",message:m("harvest_timeout"),retryable:!0,httpStatus:504,terminalStatus:"failed"}:pr(r)?{error_code:"service_unavailable",error_type:"service_unavailable",message:N,retryable:!0,httpStatus:503,terminalStatus:"failed"}:{error_code:"extraction_failed",error_type:"extraction",message:N,retryable:!1,httpStatus:500,terminalStatus:"failed"}}function bt(e){return JSON.stringify({error_code:e.error_code,error_type:e.error_type,message:e.message,retryable:e.retryable})}function Ke(e,r={}){let t=A({errorCode:e.error_code,errorType:e.error_type,retryable:e.retryable,retryAfterSeconds:r.retryAfterSeconds,chargeStatus:r.chargeStatus,details:r.details});return{error:t.message,...t}}function Ge(e,r={}){let{error:t,...n}=Ke(e,r);return n}function gt(e,r={}){let t=L(e);return{body:Ke(t,r),status:t.httpStatus}}import{randomUUID as Qe}from"crypto";var _r=3e4;async function Ye(e,r,t){if(!e.receiptJson)return;let n=C(e.id);if((await b(n,e.userId,"paa_callback",e.jobId))?.phase==="published")return;if(t){if(await ne(t,{status:"succeeded",json:e.receiptJson}))return;await I(t)}let i=await oe(n,e.userId);i&&await ie(i,{status:"unknown",json:e.receiptJson},P(e,r,"accepted"))}function br(e){return!!(e.payloadJson&&e.payloadSha256===h(e.payloadJson)&&e.sendNonce&&e.sendToken&&e.httpStatus&&e.httpStatus>=200&&e.httpStatus<300&&e.receiptJson===f({deliveryId:e.id,idempotencyKey:e.id,payloadSha256:e.payloadSha256,httpStatus:e.httpStatus}))}async function Ve(e){let r=e.record,t,n=!1;try{if(r=await y(r.id,r.userId)??r,r.state==="accepted")return br(r)?(await Ye(r,e.domain).catch(()=>{}),p(r)):{state:"unavailable",deliveryId:r.id};if(["sending","unknown","expired","unavailable"].includes(r.state))return p(r);if(r.expiresAtMs<=r.nowMs)return await w(r,"expired"),p(await y(r.id,r.userId));if(r.payloadJson||(r=await Se(r,await e.compose(),e.domain)),!r.payloadJson||r.payloadSha256!==h(r.payloadJson))throw Error("Delivery payload conflicts");let s=P(r,e.domain,"frozen"),i=C(r.id),o={version:1,purpose:"outbound-callback",request:ye(r),payloadSha256:r.payloadSha256},l=await ae({id:i,userId:r.userId,ownerScope:`user:${r.userId}`,tool:"paa_callback",jobId:r.jobId,idempotencyKey:r.id,requestFingerprint:h(f(o)),normalizedFlags:o},Qe(),_r,s);if(l.kind!=="claimed"){let u=await b(i,r.userId,"paa_callback",r.jobId);if(u&&["effects_started","unknown","published"].includes(u.phase)){await T(r),u.phase==="published"&&await w(r,"unavailable",s);let _=await y(r.id,r.userId);return _?p(_):{state:"unknown",deliveryId:r.id}}return{state:"pending",deliveryId:r.id,expiresAtMs:r.expiresAtMs}}if(t=l.claim,!await e.validate(r.url))return p(r);if(!await le(t,s))throw Error("Delivery effects start is unconfirmed");if(n=!0,r=await he(r,t,Qe(),e.domain),!await Ae(r,t,e.domain))throw Error("Delivery authority was lost before send");let d=await fetch(r.url,{method:"POST",headers:{"content-type":"application/json","idempotency-key":r.id},body:r.payloadJson,redirect:"error",signal:AbortSignal.timeout(1e4)});if(!d.ok||d.status<200||d.status>=300)throw Error("Recipient acceptance is unconfirmed");return r=await we(r,d.status),await Ye(r,e.domain,t).catch(()=>{}),p(r)}catch(s){if(s instanceof Ee&&await w(r,"unavailable",e.domain).catch(()=>{}),t){let o=await b(t.runId,t.userId,"paa_callback",r.jobId).catch(()=>null);(n||o?.phase==="effects_started"||o?.phase==="unknown")&&await I(t).catch(()=>{})}r.sendNonce?await xe(r).catch(()=>{}):await T(r).catch(()=>{});let i=await y(r.id,r.userId).catch(()=>null);return i?p(i):{state:"unknown",deliveryId:r.id}}finally{t&&!n&&await se(t).catch(()=>{})}}async function H(e,r){let t=await Ie(e,r);return t.kind==="none"?{state:"none"}:t.kind==="unavailable"?{state:"unavailable"}:t.kind==="pending"?(await p(t.record),{state:"pending",deliveryId:t.record.id,expiresAtMs:t.record.expiresAtMs}):Ve({record:t.record,domain:t.domain,validate:async n=>{let s=await _e(n,{field:"callback_url",requireHttps:!0});return!s.error&&s.parsed?.href===n&&!s.parsed.username&&!s.parsed.password},compose:async()=>{let n=(await Oe(t.job,!1)).body;return{...n,...n.result?{result:te(n.result)}:{},...t.record.profile==="paa-queue"?{attempts:re(await We(t.job.id,t.job.user_id))}:{}}}})}async function Rt(e=25){let r=0,t=0,n=await Ne(e);for(let s of n)try{(await H(s.jobId,s.userId)).state==="accepted"?r++:t++}catch{t++}return{checked:n.length,accepted:r,pending:t}}var Xe=2,q=0;async function Ze(){let e=await Me(),r=e?void 0:await Pe(),t=e??(r?await c(r.id,Number(r.user_id)):void 0);if(!t)return{claimed:!1};let n=Date.now();q++;try{let s=await Le(t,{\u006b\u0065\u0072\u006e\u0065\u006cApiKey:B(),apifyToken:process.env.APIFY_API_TOKEN?.trim(),onAttemptEvent:ze(t.id,t.user_id,`harvest:${t.id}`),withCostContext:Y,classifyFailure:i=>{let o=L(i);return{publicError:Ge(o),httpStatus:o.httpStatus,terminalStatus:o.terminalStatus}}});return s.completed&&t.callback_url&&await H(t.id,t.user_id).catch(()=>{}),{claimed:!0,jobId:t.id,completed:s.completed,durationMs:Date.now()-n}}finally{q--}}async function Ut(e){let r=[];for(let t=0;t<e.maxJobs&&!(Date.now()>=e.deadlineMs);t++){let n=await Ze();if(r.push(n),!n.claimed)break}return r}function $t(){setInterval(async()=>{q>=Xe||Ze()},2e3),console.log(`[worker] started \u2014 polling every 2s, max ${Xe} concurrent`)}export{Ar as a,wr as b,xr as c,Nr as d,Ir as e,Dr as f,kr as g,Or as h,Xr as i,Zr as j,We as k,L as l,bt as m,Ge as n,gt as o,H as p,Rt as q,Tr as r,Te as s,Gr as t,or as u,ze as v,Ze as w,Ut as x,$t as y};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
var n=class extends Error{constructor(){super("Current operation wallet claim and matching durable plan are required"),this.name="WalletClaimLostError"}},t=class extends Error{constructor(){super("Named operation debit plan conflicts with durable billing history"),this.name="DebitPlanConflictError"}};function i(e){if(!Number.isSafeInteger(e.userId)||e.userId<=0||!Number.isSafeInteger(e.amountMc)||e.amountMc<=0||!e.key||e.key.length>500||!e.operation||!e.description||e.description.length>500)throw new t;return{sql:`EXISTS (SELECT 1 FROM billing_debits d WHERE d.idempotency_key=? AND d.user_id=?
|
|
2
|
+
AND d.amount_mc=? AND d.operation=? AND d.description=? AND d.status='applied'
|
|
3
|
+
AND NOT EXISTS (SELECT 1 FROM billing_events b WHERE b.user_id=d.user_id
|
|
4
|
+
AND b.billing_class='wallet_hold_settlement'
|
|
5
|
+
AND json_extract(b.metadata,'$.debitIdempotencyKey')=d.idempotency_key))`,args:[e.key,e.userId,e.amountMc,e.operation,e.description]}}function o(e,r){if(!/^[a-z_]+\.[a-z_]+$/.test(e)||!/^json_extract\([a-z_]+\.[a-z_]+,'\$\.hold\.key'\)$/.test(r))throw new Error("Invalid stored hold selector");return`EXISTS (SELECT 1 FROM billing_debits d WHERE d.user_id=${e}
|
|
6
|
+
AND d.idempotency_key=${r} AND d.status='applied'
|
|
7
|
+
AND NOT EXISTS (SELECT 1 FROM billing_events b WHERE b.user_id=d.user_id
|
|
8
|
+
AND b.billing_class='wallet_hold_settlement' AND json_extract(b.metadata,'$.debitIdempotencyKey')=d.idempotency_key))`}export{n as a,t as b,i as c,o as d};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import{c as y}from"./chunk-JHDD6R3O.js";var b="strftime('%Y-%m-%dT%H:%M:%fZ','now')",c="julianday('now')";var L=20,S="(json_extract(options,'$.executionOwner')='direct' AND json_extract(options,'$.serpOnly') IS NOT 1)",I=`NOT COALESCE(${S},0) AND json_extract(options,'$.syncExecutionProtocol') IS NOT 1 AND json_extract(options,'$.queueExecutionProtocol') IS NULL`,v=`${S} AND julianday(json_extract(options,'$.paaLeaseExpiresAt')) > ${c}`,O=`${S} AND (
|
|
2
|
+
(json_extract(options,'$.paaLeaseExpiresAt') IS NOT NULL AND COALESCE(julianday(json_extract(options,'$.paaLeaseExpiresAt')),0) <= ${c})
|
|
3
|
+
OR (json_extract(options,'$.paaLeaseExpiresAt') IS NULL AND julianday(started_at) <= julianday('now','-15 minutes'))
|
|
4
|
+
)`;function h(e){return{jobId:e.id,userId:e.user_id,leaseToken:typeof e.options.paaLeaseToken=="string"?e.options.paaLeaseToken:null,recoveryCount:Number(e.options.paaRecoveryCount??0),resultJson:e.result==null?null:JSON.stringify(e.result)}}function T(e,t){return!t||t.jobId!==e||!Number.isSafeInteger(t.userId)||t.userId<=0||!Number.isSafeInteger(t.recoveryCount)||t.recoveryCount<0||t.leaseToken!==null&&(typeof t.leaseToken!="string"||t.leaseToken.length===0)?{sql:"0",args:[]}:{sql:`user_id=? AND json_extract(options,'$.paaLeaseToken') IS ?
|
|
5
|
+
AND COALESCE(json_extract(options,'$.paaRecoveryCount'),0)=? AND json(result) IS json(?)`,args:[t.userId,t.leaseToken,t.recoveryCount,t.resultJson]}}function q(e,t,n){let a={userId:e.user_id,tool:"harvest_paa",jobId:e.id,sql:"0",args:[]},r=e.options.requestFingerprint;if(e.options.executionProtocol!==1||e.options.executionOwner!=="direct"||e.options.serpOnly===!0||typeof r!="string"||!/^[a-f0-9]{64}$/.test(r)||!t||n.userId!==e.user_id||n.key!==e.options.billingDebitKey||n.amountMc!==e.options.billingHoldMc)return a;let i=y(n);return{...a,sql:`EXISTS (SELECT 1 FROM jobs j WHERE j.id=? AND j.user_id=? AND j.query=? AND j.status='running'
|
|
6
|
+
AND json_extract(j.options,'$.executionOwner')='direct' AND json_extract(j.options,'$.serpOnly') IS NOT 1
|
|
7
|
+
AND json_extract(j.options,'$.executionProtocol')=1 AND json_extract(j.options,'$.requestFingerprint')=?
|
|
8
|
+
AND json_extract(j.options,'$.paaLeaseToken')=?
|
|
9
|
+
AND julianday(json_extract(j.options,'$.paaLeaseExpiresAt')) > ${c}
|
|
10
|
+
AND json_extract(j.options,'$.billingDebitKey')=? AND json_extract(j.options,'$.billingHoldMc')=?
|
|
11
|
+
AND json_extract(j.options,'$.billingSettledAt') IS NULL AND (${i.sql}))`,args:[e.id,e.user_id,e.query,r,t,n.key,n.amountMc,...i.args]}}import{createHash as C}from"crypto";var A=["observed_present","observed_absent","incomplete","not_requested","unknown","unsupported"],x=["provider_transport","invalid_payload","serp_readiness","query_integrity","pagination","optional_feature_parsing","unknown"],f=class extends Error{stage;failureCode;constructor(t,n,a){super(a),this.name="SerpExtractionError",this.stage=t,this.failureCode=n}};function d(e){return C("sha256").update(e).digest("hex")}function E(e){return e.normalize("NFKC").toLocaleLowerCase("en-US").split(/[^\p{L}\p{N}]+/u).filter(Boolean).slice(0,64)}function k(e){try{let t=new URL(e);return t.hash="",t.pathname.length>1&&(t.pathname=t.pathname.replace(/\/+$/,"")),t.toString()}catch{return e.trim()}}function D(e,t){let n=e===2?[1,2]:[1],a=t.filter(o=>o.attempted).map(o=>o.page),r=t.filter(o=>o.captured&&o.resultCount>0).map(o=>o.page),i=t.find(o=>o.failureCode);return{status:n.every(o=>r.includes(o))?"complete":"incomplete",requestedPages:n,attemptedPages:a,capturedPages:r,pageResultCounts:n.map(o=>({page:o,resultCount:t.find(g=>g.page===o)?.resultCount??0})),providerRequestCount:a.length,evidence:t,failureCode:i?.failureCode??null}}function F(e){return e.requested?e.moduleObserved?!e.rawShapeValid||e.rawCount>0&&e.mappedCount===0?"incomplete":e.mappedCount>0?"observed_present":"observed_absent":"unknown":"not_requested"}function $(e){let t=d(e.query),n=e.finalQuery==null?null:d(e.finalQuery),a=e.locationResolutionSource==="unresolved";return{status:n!==null&&n!==t?"query_mismatch":a?"unresolved_location":"matched",queryHash:t,normalizedQueryTokens:E(e.query),canonicalLocation:e.canonicalLocation??null,locationResolutionSource:e.locationResolutionSource,locationAmbiguousCandidates:Math.max(0,Math.trunc(e.locationAmbiguousCandidates??0)),uulePresent:!!e.uule,uuleHash:e.uule?d(e.uule):null,outboundProviderMethod:e.outboundProviderMethod,finalQueryHash:n}}function Q(e){return d(JSON.stringify(Object.fromEntries(Object.entries(e).filter(([t,n])=>t!=="requestFingerprint"&&n!==void 0).sort(([t],[n])=>t.localeCompare(n)))))}function p(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function m(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.trunc(e):0}function u(e,t){return typeof e=="string"&&e.length<=t?e:null}function H(e){let t=p(e),n=p(t.pagination),a=p(t.features),r=p(t.queryIntegrity),i=s=>Array.isArray(s)?s.filter(l=>l===1||l===2).slice(0,2):[],o=i(n.requestedPages);if(o.length===0)return null;let g=new Set(A),_=new Set(x);return{pagination:{status:n.status==="complete"?"complete":"incomplete",requestedPages:o,attemptedPages:i(n.attemptedPages),capturedPages:i(n.capturedPages),pageResultCounts:Array.isArray(n.pageResultCounts)?n.pageResultCounts.slice(0,2).map(s=>{let l=p(s);return{page:l.page===2?2:1,resultCount:m(l.resultCount)}}):[],providerRequestCount:m(n.providerRequestCount),failureCode:u(n.failureCode,100)},features:Object.fromEntries(["localPack","forums","videos","aiOverview","whatPeopleSaying","aiMode","paaPreview","entityIds"].map(s=>[s,g.has(String(a[s]))?a[s]:"unknown"])),queryIntegrity:{status:["matched","unresolved_location","query_mismatch"].includes(String(r.status))?r.status:"query_mismatch",queryHash:u(r.queryHash,64)??"",normalizedQueryTokens:Array.isArray(r.normalizedQueryTokens)?r.normalizedQueryTokens.slice(0,64).flatMap(s=>typeof s=="string"?[s.slice(0,100)]:[]):[],canonicalLocation:u(r.canonicalLocation,500),locationResolutionSource:u(r.locationResolutionSource,100)??"unknown",locationAmbiguousCandidates:m(r.locationAmbiguousCandidates),uulePresent:r.uulePresent===!0,uuleHash:u(r.uuleHash,64),outboundProviderMethod:"search",finalQueryHash:u(r.finalQueryHash,64)},failureStage:_.has(String(t.failureStage))?t.failureStage:null}}export{b as a,L as b,S as c,I as d,v as e,O as f,h as g,T as h,q as i,f as j,k,D as l,F as m,$ as n,Q as o,H as p};
|
|
@@ -182,7 +182,7 @@ import{i as T,m as j}from"./chunk-KXJCGV3H.js";import{n as f,r as w}from"./chunk
|
|
|
182
182
|
public_error_json = CASE WHEN json_valid(public_error_json) THEN json_set(public_error_json, '$.charge_status', ?) ELSE public_error_json END,
|
|
183
183
|
updated_at = datetime('now')
|
|
184
184
|
WHERE id = ? AND user_id = ? AND execution_generation = ? AND status = ?
|
|
185
|
-
AND billed_mc IS NULL AND settlement_plan_json = ?`,args:[e.netChargeMc,JSON.stringify(e),n,t.jobId,t.userId,t.generation,t.status,JSON.stringify(t)]})}async function jt(t,e,n,r,a,s=0){let{settleExtractJobCharge:i}=await import("./settlement-
|
|
185
|
+
AND billed_mc IS NULL AND settlement_plan_json = ?`,args:[e.netChargeMc,JSON.stringify(e),n,t.jobId,t.userId,t.generation,t.status,JSON.stringify(t)]})}async function jt(t,e,n,r,a,s=0){let{settleExtractJobCharge:i}=await import("./settlement-47EUTSGX.js");return i(t,e,n,r,a,s)}var B=25;async function*It(t){let e=o(),n=0;for(;;){let r=await e.execute({sql:`SELECT rowid AS cursor_id, page
|
|
186
186
|
FROM site_extract_pages
|
|
187
187
|
WHERE job_id = ? AND rowid > ?
|
|
188
188
|
ORDER BY rowid
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as j}from"./chunk-U7BZ5KTE.js";import{k as X}from"./chunk-PANT6VEM.js";import{A as F,c as A,d as $,g as b,h as C,o as K,p as U,q as G,r as M,s as D,t as W,z as q}from"./chunk-P55O4IDC.js";import{a as B,b as L,c as H}from"./chunk-QER2ELZP.js";import{b as k,c as S,d as y,e as x,f as O,g as I,i as h,j as m,l as E,p as N}from"./chunk-ANQ4JJVI.js";import{h as v,i as z}from"./chunk-C7MGJUTU.js";import{a as d,b as J,c as T,d as R}from"./chunk-HNNYXMSI.js";import{randomUUID as oe}from"crypto";import{createHash as Q,randomUUID as V}from"crypto";function _(e,i=new Set){if(e===null||typeof e=="string"||typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e))return e;if(typeof e!="object"||!e)throw new d("Operation inputs must be finite JSON data");if(i.has(e))throw new d("Operation inputs cannot be cyclic");if(!Array.isArray(e)&&![Object.prototype,null].includes(Object.getPrototypeOf(e)))throw new d("Operation inputs must be plain JSON data");i.add(e);try{return Array.isArray(e)?e.map(t=>_(t,i)):Object.fromEntries(Object.keys(e).sort().map(t=>[t,_(e[t],i)]))}finally{i.delete(e)}}async function P(e){if(!Number.isSafeInteger(e.userId)||e.userId<=0)throw new d("Authenticated operation principal is required");if(e.jobId!=null&&(!e.jobId.trim()||e.jobId.length>512))throw new d("Operation job ID is invalid");let i=e.tool.trim();if(!i||i.length>100)throw new d("Operation tool is required and bounded");if(e.idempotencyKey!=null&&(!e.idempotencyKey.trim()||e.idempotencyKey.length>512))throw new d("Operation idempotency key is invalid");let t=e.leaseMs??3e5;if(!Number.isSafeInteger(t)||t<1e3||t>36e5)throw new d("Execution lease must be between one second and one hour");let n=JSON.stringify(_(e.normalizedInput));if(Buffer.byteLength(n)>64*1024)throw new d("Operation inputs exceed 64 KiB");let r=e.idempotencyKey?.trim()??V();return E({userId:e.userId,ownerScope:`user:${e.userId}`,tool:i,jobId:e.jobId??null,normalizedFlags:e.normalizedInput,idempotencyKey:r,requestFingerprint:Q("sha256").update(n).digest("hex")},V(),t,e.storeGate)}async function Y(e){let i=JSON.stringify(_(e.normalizedInput));if(!Number.isSafeInteger(e.userId)||e.userId<=0||Buffer.byteLength(i)>64*1024)throw new d("Invalid operation receipt principal/input");let{readOperationIntentResult:t}=await import("./repository-UKDA4IWP.js"),{operationIdentityHash:n}=await import("./contracts-GUXGFCVV.js");return t(e.userId,n(`user:${e.userId}\0${e.tool}\0${e.idempotencyKey}`),Q("sha256").update(i).digest("hex"))}async function we(e){let i=Date.now()+27e4,t=e.idempotencyKey?.trim()??oe();if(!t||t.length>512)return{status:400,body:{error_code:"invalid_request",message:"Idempotency-Key must contain 1 to 512 characters"}};let n=(a,c,p)=>({...a,body:{...a.body,operation:{runId:c,idempotencyKey:t,state:p}}}),r=(a,c,p)=>n({status:c==="pending"?202:503,headers:{"Retry-After":"2"},body:{...v({errorCode:"response_lost",retryable:!0,chargeStatus:p,details:{retry_guidance:"Retry the identical request with the returned idempotencyKey. Pending work is not started again; a saved response replays. Unknown work permits compensation only."}}),message:c==="pending"?"This operation is still running. Retry with the same idempotencyKey.":"The execution outcome is unknown. Retry with the same idempotencyKey for result or compensation recovery."}},a,c),s;try{s=await P({...e,idempotencyKey:t,leaseMs:3e5})}catch(a){return a instanceof d?n({status:400,body:{error_code:"invalid_request",message:a.message,retryable:!1}},null,"not_started"):a instanceof J?n({status:409,body:{error_code:"idempotency_conflict",message:a.message,retryable:!1}},null,"conflict"):r(null,"unknown")}let o=s.kind==="claimed"?s.claim.runId:s.runId;if(s.kind==="replay"){let a=JSON.parse(s.result.json);return!a||typeof a.status!="number"||!a.body||typeof a.body!="object"?r(o,"unknown"):n(a,o,"replayed")}if(s.kind==="pending")return r(o,"pending");if(s.kind==="unknown")try{let a=await y(o,e.userId);if(!a)return r(o,"unknown");let c=await e.recover(a);if(c.recover)return await h(a),n(c.reply,o,"unknown");let p=n(c.reply,o,"recovered_unknown"),l={json:JSON.stringify(p),status:"unknown"};return await O(a,l)?p:r(o,"unknown")}catch{return r(o,"unknown","refund_pending")}if(s.kind!=="claimed")return r(o,"unknown");let u=s.claim,f;try{if(f=await e.prepare(),f.rejection)return await I(u),n(f.rejection,o,"not_started");if(!await k(u))return r(o,"unknown");let a={claim:u,deadlineAt:i,assertActive:async()=>{if(B(i),!await m(u))throw Error("Execution ownership is no longer current")}},c;try{c=await e.execute(a,f.value)}catch{return await h(u),r(o,"unknown","refund_pending")}if(c.recover)return await h(u),n(c.reply,o,"unknown");let p=n(c.reply,o,c.reply.status<400?"succeeded":"failed");try{return await x(u,{json:JSON.stringify(p),status:p.status<400?"succeeded":"failed"})?p:r(o,"unknown")}catch{return await h(u).catch(()=>{}),r(o,"unknown")}}catch{return await I(u).catch(()=>{}),r(o,"unknown")}finally{await f?.release().catch(()=>{})}}var g=3e5;function ee(e){if(!e?.trim()||e.length>512)throw new d("A bounded framework workflow ID is required");return T(`workflow:${e}`)}async function ye(e){if(!Number.isSafeInteger(e.userId)||e.userId<=0)throw new d("Workflow principal is required");let i=ee(e.workflowId),t=await E(e,i,g);if(t.kind==="claimed"){let n;try{n=await k(t.claim)}catch(r){if(!await m(t.claim))throw r;n=!0}if(!n)throw Error("workflow_execution_start_unknown");return t}if(t.kind==="pending"){let n={runId:t.runId,userId:e.userId,token:i};if(await m(n)&&await S(n,g))return{kind:"claimed",claim:n}}return t}var te=e=>`${e.workflow.runId}:${e.phase}`;async function he(e){if(!await S(e.workflow,g))throw Error("workflow_execution_not_current");let i=te(e),t=await P({userId:e.workflow.userId,tool:e.tool,jobId:e.jobId,normalizedInput:e.normalizedInput,idempotencyKey:i,leaseMs:g});if(t.kind==="replay"){if(t.result.status!=="succeeded")throw Error(`operation_phase_unknown:${t.runId}`);return JSON.parse(t.result.json)}if(t.kind!=="claimed")throw Error(`operation_phase_${t.kind}:${t.runId}`);let n=t.claim;try{await e.prepare()}catch(r){throw await I(n).catch(()=>{}),r}try{let r;try{r=await k(n)}catch(a){if(!await m(n))throw a;r=!0}if(!r)throw Error("operation_phase_start_unknown");let s=Date.now()+g,o=async()=>{if(Date.now()>=s)throw new L(e.phase);if(!await m(e.workflow)||!await m(n))throw Error("operation_phase_claim_not_current")};await o();let u=await H(s,()=>e.execute({claim:n,deadlineAt:s,assertActive:o}),e.phase);await o();let f=JSON.stringify(u);if(f==null||!await x(n,{status:"succeeded",json:f}))throw Error("operation_phase_publication_unknown");return u}catch(r){await h(n).catch(()=>{});let s=await y(n.runId,n.userId).catch(()=>null);throw s&&await O(s,{status:"unknown",json:JSON.stringify({phase:e.phase,outcome:"unknown"})}).catch(()=>{}),r}}async function be(e,i){let t=await Y({userId:e.workflow.userId,tool:e.tool,idempotencyKey:te(e),normalizedInput:e.normalizedInput});if(!t||t.result.status!=="succeeded"||R({value:JSON.parse(t.result.json)})!==R({value:i}))throw Error("operation_phase_cache_receipt_unknown")}async function ge(e,i,t){let n={runId:e,userId:i,token:ee(t)};if(await m(n))return{claim:n,recovery:!1};let r=await y(e,i);return r?{claim:r,recovery:!0}:null}async function re(e,i,t){let n={json:JSON.stringify(i),status:e.recovery?"unknown":t};if(!(e.recovery?await O(e.claim,n,e.settlementGate):await x(e.claim,n)))throw Error("workflow_result_publication_unknown")}async function je(e){if(!await b(e))return{kind:"missing",body:{error:"job not found"}};let t=await M(e);if(!t)return{kind:"conflict",body:{error:"Only failed or expired recovery jobs can be re-finalized.",status:(await b(e))?.status??"missing"}};let n=t.executionGeneration;if(!await D(e,n))return{kind:"conflict",body:{error:"job state changed during re-finalization claim"}};let r;try{r=await X(t,{})}catch(l){throw await F(e,l instanceof Error?l.message:String(l),void 0,n).catch(()=>!1),l}let s=A(t),o=$(t,s.creditTruncated),u=o==="failed"?`No pages were extracted successfully (${t.failedUrls} failed, ${t.remainingUrls} remaining).`:o==="partial"?`${t.successfulUrls} pages succeeded; ${t.failedUrls} failed and ${t.remainingUrls} remain.${s.creditTruncated?` Credit availability limited this request from ${s.requestedMaxPages} to ${s.effectiveMaxPages} pages.`:""}`:null,f;try{f=await q(e,r,o,u,!1,null,n)}catch(l){let w=await b(e).catch(()=>null);if(!w||w.id!==e||w.executionGeneration!==n||w.status!==o||JSON.stringify(w.artifacts)!==JSON.stringify(r)||w.error!==(u?z(u).slice(0,2e3):null)||w.publicError!==null)throw l;f=!0}if(!f)return{kind:"conflict",body:{error:"job state changed during re-finalization"}};let a=await b(e);if(!a||a.executionGeneration!==n||a.status!==o)return{kind:"conflict",body:{error:"job state changed before re-finalization settlement"}};let c="already_settled_or_refunded";if(a.billedMc==null&&a.userId!=null){let l=await j(a);if(!l)throw Error("extract_settlement_acknowledgment_unknown");c=`settled: billed ${l.netChargeMc} mc, refunded ${l.refundMc} mc${l.expiredRefundMc?`, expired refund ${l.expiredRefundMc} mc`:""}`}let p=r.find(l=>l.contentType==="application/zip"||l.filename?.endsWith(".zip"));return{kind:"complete",body:{ok:!0,jobId:e,artifacts:r.length,settlement:c,bundleUrl:p?.url??null,bundleBytes:p?.bytes??null}}}async function Pe(e=25){let i=await U(e);for(let r of i)await G(r.id).catch(()=>!1);let t=await C(e),n={checked:new Set([...i,...t].map(r=>r.id)).size,settled:0,failed:0};for(let r of t){if(r.userId==null){await W(r.id,"Settlement abandoned because the legacy job has no user owner.",r.executionGeneration??0),n.failed+=1;continue}try{if(!await j(r))throw Error("extract_settlement_acknowledgment_unknown");if(r.executionGeneration===0&&await N(`extract-site:${r.id}`,r.userId)){let o=await y(`extract-site:${r.id}`,r.userId);o&&await re({claim:o,recovery:!0},{jobId:r.id,status:r.status,artifacts:r.artifacts??[]},"unknown")}n.settled+=1}catch(s){n.failed+=1;let o=s instanceof Error?s.message:String(s);await K(r.id,o,r.executionGeneration??0).catch(()=>{}),console.warn("[site-extract/reconcile]",r.id,o)}}return n}export{P as a,we as b,g as c,ee as d,ye as e,he as f,be as g,ge as h,re as i,je as j,Pe as k};
|
|
1
|
+
import{c as j}from"./chunk-5TQINRZN.js";import{k as X}from"./chunk-F3M7INSN.js";import{A as F,c as A,d as $,g as b,h as C,o as K,p as U,q as G,r as M,s as D,t as W,z as q}from"./chunk-NQFTETVC.js";import{a as B,b as L,c as H}from"./chunk-QER2ELZP.js";import{b as k,c as S,d as y,e as x,f as O,g as I,i as h,j as m,l as E,p as N}from"./chunk-ANQ4JJVI.js";import{h as v,i as z}from"./chunk-C7MGJUTU.js";import{a as d,b as J,c as T,d as R}from"./chunk-HNNYXMSI.js";import{randomUUID as oe}from"crypto";import{createHash as Q,randomUUID as V}from"crypto";function _(e,i=new Set){if(e===null||typeof e=="string"||typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e))return e;if(typeof e!="object"||!e)throw new d("Operation inputs must be finite JSON data");if(i.has(e))throw new d("Operation inputs cannot be cyclic");if(!Array.isArray(e)&&![Object.prototype,null].includes(Object.getPrototypeOf(e)))throw new d("Operation inputs must be plain JSON data");i.add(e);try{return Array.isArray(e)?e.map(t=>_(t,i)):Object.fromEntries(Object.keys(e).sort().map(t=>[t,_(e[t],i)]))}finally{i.delete(e)}}async function P(e){if(!Number.isSafeInteger(e.userId)||e.userId<=0)throw new d("Authenticated operation principal is required");if(e.jobId!=null&&(!e.jobId.trim()||e.jobId.length>512))throw new d("Operation job ID is invalid");let i=e.tool.trim();if(!i||i.length>100)throw new d("Operation tool is required and bounded");if(e.idempotencyKey!=null&&(!e.idempotencyKey.trim()||e.idempotencyKey.length>512))throw new d("Operation idempotency key is invalid");let t=e.leaseMs??3e5;if(!Number.isSafeInteger(t)||t<1e3||t>36e5)throw new d("Execution lease must be between one second and one hour");let n=JSON.stringify(_(e.normalizedInput));if(Buffer.byteLength(n)>64*1024)throw new d("Operation inputs exceed 64 KiB");let r=e.idempotencyKey?.trim()??V();return E({userId:e.userId,ownerScope:`user:${e.userId}`,tool:i,jobId:e.jobId??null,normalizedFlags:e.normalizedInput,idempotencyKey:r,requestFingerprint:Q("sha256").update(n).digest("hex")},V(),t,e.storeGate)}async function Y(e){let i=JSON.stringify(_(e.normalizedInput));if(!Number.isSafeInteger(e.userId)||e.userId<=0||Buffer.byteLength(i)>64*1024)throw new d("Invalid operation receipt principal/input");let{readOperationIntentResult:t}=await import("./repository-UKDA4IWP.js"),{operationIdentityHash:n}=await import("./contracts-GUXGFCVV.js");return t(e.userId,n(`user:${e.userId}\0${e.tool}\0${e.idempotencyKey}`),Q("sha256").update(i).digest("hex"))}async function we(e){let i=Date.now()+27e4,t=e.idempotencyKey?.trim()??oe();if(!t||t.length>512)return{status:400,body:{error_code:"invalid_request",message:"Idempotency-Key must contain 1 to 512 characters"}};let n=(a,c,p)=>({...a,body:{...a.body,operation:{runId:c,idempotencyKey:t,state:p}}}),r=(a,c,p)=>n({status:c==="pending"?202:503,headers:{"Retry-After":"2"},body:{...v({errorCode:"response_lost",retryable:!0,chargeStatus:p,details:{retry_guidance:"Retry the identical request with the returned idempotencyKey. Pending work is not started again; a saved response replays. Unknown work permits compensation only."}}),message:c==="pending"?"This operation is still running. Retry with the same idempotencyKey.":"The execution outcome is unknown. Retry with the same idempotencyKey for result or compensation recovery."}},a,c),s;try{s=await P({...e,idempotencyKey:t,leaseMs:3e5})}catch(a){return a instanceof d?n({status:400,body:{error_code:"invalid_request",message:a.message,retryable:!1}},null,"not_started"):a instanceof J?n({status:409,body:{error_code:"idempotency_conflict",message:a.message,retryable:!1}},null,"conflict"):r(null,"unknown")}let o=s.kind==="claimed"?s.claim.runId:s.runId;if(s.kind==="replay"){let a=JSON.parse(s.result.json);return!a||typeof a.status!="number"||!a.body||typeof a.body!="object"?r(o,"unknown"):n(a,o,"replayed")}if(s.kind==="pending")return r(o,"pending");if(s.kind==="unknown")try{let a=await y(o,e.userId);if(!a)return r(o,"unknown");let c=await e.recover(a);if(c.recover)return await h(a),n(c.reply,o,"unknown");let p=n(c.reply,o,"recovered_unknown"),l={json:JSON.stringify(p),status:"unknown"};return await O(a,l)?p:r(o,"unknown")}catch{return r(o,"unknown","refund_pending")}if(s.kind!=="claimed")return r(o,"unknown");let u=s.claim,f;try{if(f=await e.prepare(),f.rejection)return await I(u),n(f.rejection,o,"not_started");if(!await k(u))return r(o,"unknown");let a={claim:u,deadlineAt:i,assertActive:async()=>{if(B(i),!await m(u))throw Error("Execution ownership is no longer current")}},c;try{c=await e.execute(a,f.value)}catch{return await h(u),r(o,"unknown","refund_pending")}if(c.recover)return await h(u),n(c.reply,o,"unknown");let p=n(c.reply,o,c.reply.status<400?"succeeded":"failed");try{return await x(u,{json:JSON.stringify(p),status:p.status<400?"succeeded":"failed"})?p:r(o,"unknown")}catch{return await h(u).catch(()=>{}),r(o,"unknown")}}catch{return await I(u).catch(()=>{}),r(o,"unknown")}finally{await f?.release().catch(()=>{})}}var g=3e5;function ee(e){if(!e?.trim()||e.length>512)throw new d("A bounded framework workflow ID is required");return T(`workflow:${e}`)}async function ye(e){if(!Number.isSafeInteger(e.userId)||e.userId<=0)throw new d("Workflow principal is required");let i=ee(e.workflowId),t=await E(e,i,g);if(t.kind==="claimed"){let n;try{n=await k(t.claim)}catch(r){if(!await m(t.claim))throw r;n=!0}if(!n)throw Error("workflow_execution_start_unknown");return t}if(t.kind==="pending"){let n={runId:t.runId,userId:e.userId,token:i};if(await m(n)&&await S(n,g))return{kind:"claimed",claim:n}}return t}var te=e=>`${e.workflow.runId}:${e.phase}`;async function he(e){if(!await S(e.workflow,g))throw Error("workflow_execution_not_current");let i=te(e),t=await P({userId:e.workflow.userId,tool:e.tool,jobId:e.jobId,normalizedInput:e.normalizedInput,idempotencyKey:i,leaseMs:g});if(t.kind==="replay"){if(t.result.status!=="succeeded")throw Error(`operation_phase_unknown:${t.runId}`);return JSON.parse(t.result.json)}if(t.kind!=="claimed")throw Error(`operation_phase_${t.kind}:${t.runId}`);let n=t.claim;try{await e.prepare()}catch(r){throw await I(n).catch(()=>{}),r}try{let r;try{r=await k(n)}catch(a){if(!await m(n))throw a;r=!0}if(!r)throw Error("operation_phase_start_unknown");let s=Date.now()+g,o=async()=>{if(Date.now()>=s)throw new L(e.phase);if(!await m(e.workflow)||!await m(n))throw Error("operation_phase_claim_not_current")};await o();let u=await H(s,()=>e.execute({claim:n,deadlineAt:s,assertActive:o}),e.phase);await o();let f=JSON.stringify(u);if(f==null||!await x(n,{status:"succeeded",json:f}))throw Error("operation_phase_publication_unknown");return u}catch(r){await h(n).catch(()=>{});let s=await y(n.runId,n.userId).catch(()=>null);throw s&&await O(s,{status:"unknown",json:JSON.stringify({phase:e.phase,outcome:"unknown"})}).catch(()=>{}),r}}async function be(e,i){let t=await Y({userId:e.workflow.userId,tool:e.tool,idempotencyKey:te(e),normalizedInput:e.normalizedInput});if(!t||t.result.status!=="succeeded"||R({value:JSON.parse(t.result.json)})!==R({value:i}))throw Error("operation_phase_cache_receipt_unknown")}async function ge(e,i,t){let n={runId:e,userId:i,token:ee(t)};if(await m(n))return{claim:n,recovery:!1};let r=await y(e,i);return r?{claim:r,recovery:!0}:null}async function re(e,i,t){let n={json:JSON.stringify(i),status:e.recovery?"unknown":t};if(!(e.recovery?await O(e.claim,n,e.settlementGate):await x(e.claim,n)))throw Error("workflow_result_publication_unknown")}async function je(e){if(!await b(e))return{kind:"missing",body:{error:"job not found"}};let t=await M(e);if(!t)return{kind:"conflict",body:{error:"Only failed or expired recovery jobs can be re-finalized.",status:(await b(e))?.status??"missing"}};let n=t.executionGeneration;if(!await D(e,n))return{kind:"conflict",body:{error:"job state changed during re-finalization claim"}};let r;try{r=await X(t,{})}catch(l){throw await F(e,l instanceof Error?l.message:String(l),void 0,n).catch(()=>!1),l}let s=A(t),o=$(t,s.creditTruncated),u=o==="failed"?`No pages were extracted successfully (${t.failedUrls} failed, ${t.remainingUrls} remaining).`:o==="partial"?`${t.successfulUrls} pages succeeded; ${t.failedUrls} failed and ${t.remainingUrls} remain.${s.creditTruncated?` Credit availability limited this request from ${s.requestedMaxPages} to ${s.effectiveMaxPages} pages.`:""}`:null,f;try{f=await q(e,r,o,u,!1,null,n)}catch(l){let w=await b(e).catch(()=>null);if(!w||w.id!==e||w.executionGeneration!==n||w.status!==o||JSON.stringify(w.artifacts)!==JSON.stringify(r)||w.error!==(u?z(u).slice(0,2e3):null)||w.publicError!==null)throw l;f=!0}if(!f)return{kind:"conflict",body:{error:"job state changed during re-finalization"}};let a=await b(e);if(!a||a.executionGeneration!==n||a.status!==o)return{kind:"conflict",body:{error:"job state changed before re-finalization settlement"}};let c="already_settled_or_refunded";if(a.billedMc==null&&a.userId!=null){let l=await j(a);if(!l)throw Error("extract_settlement_acknowledgment_unknown");c=`settled: billed ${l.netChargeMc} mc, refunded ${l.refundMc} mc${l.expiredRefundMc?`, expired refund ${l.expiredRefundMc} mc`:""}`}let p=r.find(l=>l.contentType==="application/zip"||l.filename?.endsWith(".zip"));return{kind:"complete",body:{ok:!0,jobId:e,artifacts:r.length,settlement:c,bundleUrl:p?.url??null,bundleBytes:p?.bytes??null}}}async function Pe(e=25){let i=await U(e);for(let r of i)await G(r.id).catch(()=>!1);let t=await C(e),n={checked:new Set([...i,...t].map(r=>r.id)).size,settled:0,failed:0};for(let r of t){if(r.userId==null){await W(r.id,"Settlement abandoned because the legacy job has no user owner.",r.executionGeneration??0),n.failed+=1;continue}try{if(!await j(r))throw Error("extract_settlement_acknowledgment_unknown");if(r.executionGeneration===0&&await N(`extract-site:${r.id}`,r.userId)){let o=await y(`extract-site:${r.id}`,r.userId);o&&await re({claim:o,recovery:!0},{jobId:r.id,status:r.status,artifacts:r.artifacts??[]},"unknown")}n.settled+=1}catch(s){n.failed+=1;let o=s instanceof Error?s.message:String(s);await K(r.id,o,r.executionGeneration??0).catch(()=>{}),console.warn("[site-extract/reconcile]",r.id,o)}}return n}export{P as a,we as b,g as c,ee as d,ye as e,he as f,be as g,ge as h,re as i,je as j,Pe as k};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{g as t,i as d}from"./chunk-C7MGJUTU.js";var p={\u006b\u0065\u0072\u006e\u0065\u006c:"browserRuntime"},c=/error|message/i,_=(new RegExp("(?:spending|billing|organization|account).{0,80}(?:cap|limit|blocked|disabled|suspended)|(?:quota|capacity).{0,40}(?:reached|exceeded)|https?:\\/\\/\\S*(?:dashboard|on\u006b\u0065\u0072\u006e\u0065\u006c)", "i")),u=/\b(?:ENOENT|ENOTDIR|EACCES|EPERM|EISDIR|EMFILE|ENFILE)\b|\b(?:mkdir|open|stat|lstat|readFile|writeFile)\s+['"]?(?:\/|[A-Za-z]:\\)|(?:^|[\s'"])(?:\/Users|\/home|\/tmp|\/var|\/private|\/opt|\/srv|\/root)\//i,l=new Set(["\u006b\u0065\u0072\u006e\u0065\u006c_session_id","browser_session_id","\u006b\u0065\u0072\u006e\u0065\u006cSessionId","browserSessionId","sessionId","\u006b\u0065\u0072\u006e\u0065\u006c_delete_started","session_cleanup_started","\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted","sessionCleanupStarted","\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded","session_cleanup_succeeded","\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded","sessionCleanupSucceeded","\u006b\u0065\u0072\u006e\u0065\u006c_delete_error","session_cleanup_error","\u006b\u0065\u0072\u006e\u0065\u006cDeleteError","sessionCleanupError","\u006b\u0065\u0072\u006e\u0065\u006cProxyId","proxyId","requestedProxyIdSuffix","retrievedProxyIdSuffix","provider","capture","providerName","fallbackFrom","acquisitionProvider","providerSessionObservedAt","reasonSource","outboundProviderMethod","service","serviceName","vendor","vendorName","organization","organizationId","accountId","browser_provider","provider_session_id","provider_session_observed_at","provider_lookup_status","provider_status","provider_error_code","provider_error_message","provider_reason_source","provider_duration_ms","provider_bandwidth_bytes","provider_captcha","provider_checked_at","provider_detail","provider_detail_json","provider_disconnect_observed","provider_disconnect_message","browserProvider","providerSessionId","providerLookupStatus","providerStatus","providerErrorCode","providerErrorMessage","providerReasonSource","providerDurationMs","providerBandwidthBytes","providerCaptcha","providerCheckedAt","providerDetail","providerDisconnectObserved","providerDisconnectMessage"]),v=new Set(["hosted_url","hostedUrl","live_view_url","liveViewUrl","cdp_ws_url","cdpWsUrl","browser_live_view_url"]),E=(new RegExp("\\b(?:wss?|https?):\\/\\/[^\\s\"'<>]*\\bon\u006b\u0065\u0072\u006e\u0065\u006c\\.com[^\\s\"'<>]*", "gi"));function b(e){return e.replace(E,"[browser-service]")}function n(e,o=""){if(typeof e=="string"){let r=b(e);return c.test(o)&&(_.test(e)||u.test(e))?r=t("service_unavailable"):c.test(o)&&(r=d(r)),r}if(Array.isArray(e))return e.map(r=>n(r,o));if(e!==null&&typeof e=="object"){let r={};for(let[s,a]of Object.entries(e)){if(l.has(s))continue;let i=p[s]??s;if(v.has(s)){r[i]=null;continue}r[i]=n(a,s)}return r}return e}function R(e){return e.map(o=>n(o))}function f(e){let o=e?.diagnostics;if(!o)return n(e);let r=o.serpCompleteness,s=r?.queryIntegrity;return!o.debug&&!s?n(e):n({...e,diagnostics:{...o,...o.debug?{debug:n(o.debug)}:{},...s?{serpCompleteness:{...r,queryIntegrity:{...s,outboundProviderMethod:"search"}}}:{}}})}export{n as a,R as b,f as c};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import{e as ze,f as Pt,g as Tt,h as xt,i as Ot}from"./chunk-XNTAHMPA.js";import{L as At,d as gt,e as X,f as G,g as yt,h as _t,m as bt,n as St,u as vt}from"./chunk-6D25Q5BR.js";import{c as ft}from"./chunk-C3JWX6KM.js";import{b as Ke,j as Y,k as Ye,l as Q,m as Z,n as Pe}from"./chunk-KBZY2OGP.js";import{c as Dt}from"./chunk-JHDD6R3O.js";import{b as Re,d as Ne,e as ke,f as me,g as Ct,j as De,p as qt}from"./chunk-7SR7MEU5.js";import{d as It,e as Rt,f as Nt,g as We,i as Ve,l as Xe,n as z,p as Ie,s as kt,t as K}from"./chunk-ANQ4JJVI.js";import{c as N,e as jt}from"./chunk-FLAWC5PF.js";import{b as ht}from"./chunk-B4ZKPLSP.js";import{c as Et}from"./chunk-4ZVO6GX4.js";import{e as wt,h as pe}from"./chunk-C7MGJUTU.js";import{a as v}from"./chunk-WNUXMPVX.js";import{c as L,d as h,f as de}from"./chunk-HNNYXMSI.js";async function Mt(e,n){if(e.user_id!==n.userId||e.result!=null)return!1;let t=(await v().execute({sql:`SELECT id,attempt_number,error FROM harvest_attempts
|
|
2
|
+
WHERE job_id=? AND user_id=? AND status='finished' AND outcome='error' AND will_retry=0 AND completed_at IS NOT NULL`,args:[e.id,e.user_id]})).rows,r=!1;for(let o of t)ft(String(o.error??""))&&(r=await _t({claim:n,attemptNumber:Number(o.attempt_number),evidenceId:String(o.id),jobId:e.id})||r);return r}import{randomUUID as hr}from"crypto";var Ft="2026-10-10-operation-final-settlements.1";async function Lt(e){let n=async()=>{let[t,r,o]=await Promise.all([e.execute("SELECT sql FROM sqlite_master WHERE name='operation_final_settlements'"),e.execute("PRAGMA index_info(operation_final_settlement_key)"),e.execute({sql:"SELECT 1 FROM schema_migrations WHERE version=?",args:[Ft]})]),i=String(t.rows[0]?.sql??"").replace(/\s+/g," ");return o.rows.length===1&&r.rows.map(s=>s.name).join(",")==="debit_key"&&i.includes("run_id TEXT NOT NULL REFERENCES operation_runs(id)")&&i.includes("user_id INTEGER NOT NULL CHECK (user_id > 0)")&&i.includes("final_amount_mc INTEGER NOT NULL CHECK (final_amount_mc >= 0)")&&i.includes("receipt_json TEXT NOT NULL CHECK (json_valid(receipt_json))")};if(!await n()){try{await e.batch([`CREATE TABLE IF NOT EXISTS operation_final_settlements (
|
|
3
|
+
id TEXT NOT NULL PRIMARY KEY,
|
|
4
|
+
run_id TEXT NOT NULL REFERENCES operation_runs(id),
|
|
5
|
+
user_id INTEGER NOT NULL CHECK (user_id > 0),
|
|
6
|
+
debit_key TEXT NOT NULL REFERENCES operation_debit_plans(debit_key),
|
|
7
|
+
final_amount_mc INTEGER NOT NULL CHECK (final_amount_mc >= 0),
|
|
8
|
+
refund_operation TEXT NOT NULL,source_surface TEXT NOT NULL,
|
|
9
|
+
receipt_json TEXT NOT NULL CHECK (json_valid(receipt_json)),
|
|
10
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
11
|
+
)`,"CREATE UNIQUE INDEX IF NOT EXISTS operation_final_settlement_key ON operation_final_settlements(debit_key)",{sql:"INSERT OR IGNORE INTO schema_migrations(version) VALUES (?)",args:[Ft]}],"write")}catch(t){if(!await n().catch(()=>!1))throw t}if(!await n())throw Error("Final settlement schema is incomplete")}}var Pr="(CAST(strftime('%s','now') AS INTEGER)*1000)";async function Ht(e){let{claim:n,gate:t}=e;if(de({userId:n.userId,tool:t.tool,jobId:t.jobId},t),!Number.isSafeInteger(e.amountMc)||e.amountMc<0||!e.key||!e.refundOperation||!e.sourceSurface)throw Error("Invalid final settlement input");let r=h({key:e.key,amountMc:e.amountMc,refundOperation:e.refundOperation,sourceSurface:e.sourceSurface,material:e.material});if(Buffer.byteLength(r)>16*1024*1024)throw Error("Final settlement material exceeds budget");let o=v();await Lt(o),await G({userId:n.userId,runId:n.runId});let i=yt(n.userId,t.jobId),s="settlement:"+L(`${n.runId}\0${e.key}`),a=`EXISTS(SELECT 1 FROM operation_runs r JOIN operation_executions x ON x.run_id=r.id
|
|
12
|
+
WHERE r.id=? AND r.user_id=? AND r.tool=? AND r.job_id=? AND r.status=? AND x.claim_token=? AND x.phase=? AND x.expires_at_ms>${Pr}) AND (${t.sql}) AND (${i.sql})`,l=[n.runId,n.userId,t.tool,t.jobId,e.recovery?"unknown":"running",n.token,e.recovery?"unknown":"effects_started",...t.args,...i.args];try{await o.execute({sql:`INSERT OR IGNORE INTO operation_final_settlements(id,run_id,user_id,debit_key,final_amount_mc,refund_operation,source_surface,receipt_json)
|
|
13
|
+
SELECT ?,?,?,?,?,?,?,? WHERE (${a}) AND EXISTS(SELECT 1 FROM operation_debit_plans p JOIN billing_debits d ON d.idempotency_key=p.debit_key
|
|
14
|
+
WHERE p.run_id=? AND p.debit_key=? AND p.refund_operation=? AND p.source_surface=? AND d.user_id=? AND d.status='applied' AND ?>=0 AND ?<=p.amount_mc)`,args:[s,n.runId,n.userId,e.key,e.amountMc,e.refundOperation,e.sourceSurface,r,...l,n.runId,e.key,e.refundOperation,e.sourceSurface,n.userId,e.amountMc,e.amountMc]})}catch{}let u=(await o.execute({sql:`SELECT s.* FROM operation_final_settlements s WHERE s.id=? AND s.run_id=? AND s.user_id=? AND (${a})`,args:[s,n.runId,n.userId,...l]})).rows[0];if(!u||u.receipt_json!==r)throw Error("final_settlement_plan_unknown_or_conflicting");return{...n,mode:e.recovery?"compensate":"execute",settlementPlanId:s}}function Te(e){return{...e,sql:`EXISTS(SELECT 1 FROM operation_final_settlements s JOIN billing_events b ON b.user_id=s.user_id
|
|
15
|
+
WHERE s.run_id=? AND s.user_id=? AND s.debit_key=? AND b.billing_class='wallet_hold_settlement' AND b.status='settled'
|
|
16
|
+
AND b.source_surface=s.source_surface AND b.amount_mc=s.final_amount_mc AND json_extract(b.metadata,'$.debitIdempotencyKey')=s.debit_key
|
|
17
|
+
AND json_extract(b.metadata,'$.refundOperation')=s.refund_operation)`,args:[e.runId,e.userId,e.key]}}var Ut="2026-10-10-outbound-delivery.1";async function xe(e){let n=async()=>{let t=(await e.execute("SELECT sql FROM sqlite_master WHERE name='outbound_deliveries'")).rows[0],r=(await e.execute({sql:"SELECT 1 FROM schema_migrations WHERE version=?",args:[Ut]})).rows,o=String(t?.sql??"").replace(/\s+/g," "),i=(await e.execute("PRAGMA index_info(outbound_delivery_job)")).rows.map(s=>s.name).join(",");return r.length===1&&i==="job_id,user_id"&&o.includes("request_json TEXT NOT NULL CHECK (json_valid(request_json))")&&o.includes("expires_at_ms INTEGER NOT NULL")&&o.includes("'accepted','unknown','expired','unavailable'")};if(!await n()){try{await e.batch([`CREATE TABLE IF NOT EXISTS outbound_deliveries (
|
|
18
|
+
id TEXT NOT NULL PRIMARY KEY,user_id INTEGER NOT NULL CHECK (user_id > 0),job_id TEXT NOT NULL,
|
|
19
|
+
parent_run_id TEXT NOT NULL REFERENCES operation_runs(id),request_json TEXT NOT NULL CHECK (json_valid(request_json)),
|
|
20
|
+
state TEXT NOT NULL CHECK (state IN ('requested','frozen','sending','accepted','unknown','expired','unavailable')),
|
|
21
|
+
expires_at_ms INTEGER NOT NULL,payload_json TEXT CHECK (payload_json IS NULL OR json_valid(payload_json)),payload_sha256 TEXT,
|
|
22
|
+
send_nonce TEXT,send_token TEXT,http_status INTEGER,receipt_json TEXT CHECK (receipt_json IS NULL OR json_valid(receipt_json)),
|
|
23
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
24
|
+
)`,"CREATE UNIQUE INDEX IF NOT EXISTS outbound_delivery_job ON outbound_deliveries(job_id,user_id)",{sql:"INSERT OR IGNORE INTO schema_migrations(version) VALUES (?)",args:[Ut]}],"write")}catch(t){if(!await n().catch(()=>!1))throw t}if(!await n())throw Error("Delivery schema is incomplete")}}var fe=class extends Error{};var ee="(CAST(strftime('%s','now') AS INTEGER)*1000)",$t=e=>`delivery:${e}`,B=e=>h(e);async function te(e,n){let t=v();await xe(t);let r=(await t.execute({sql:`SELECT *,${ee} AS now_ms FROM outbound_deliveries WHERE id=? AND user_id=?`,args:[e,n]})).rows[0];if(!r)return null;let o=JSON.parse(String(r.request_json));if(o.id!==e||o.userId!==n||o.jobId!==r.job_id||o.parentRunId!==r.parent_run_id)throw Error("Delivery request conflicts");return{...o,state:String(r.state),expiresAtMs:Number(r.expires_at_ms),nowMs:Number(r.now_ms),payloadJson:r.payload_json==null?null:String(r.payload_json),payloadSha256:r.payload_sha256==null?null:String(r.payload_sha256),sendNonce:r.send_nonce==null?null:String(r.send_nonce),sendToken:r.send_token==null?null:String(r.send_token),httpStatus:r.http_status==null?null:Number(r.http_status),receiptJson:r.receipt_json==null?null:String(r.receipt_json)}}async function Gt(e,n,t){if(de({userId:e.userId,tool:t.tool,jobId:e.jobId},t),!e.id||!e.url||!["paa-direct","paa-queue"].includes(e.profile)||!Number.isSafeInteger(e.userId)||e.userId<=0||n.runId!==e.parentRunId||n.userId!==e.userId||!/^[a-f0-9]{64}$/.test(e.fingerprint))throw Error("Invalid delivery request");let r=v();await xe(r);let o;try{await r.execute({sql:`INSERT OR IGNORE INTO outbound_deliveries(id,user_id,job_id,parent_run_id,request_json,state,expires_at_ms)
|
|
25
|
+
SELECT ?,?,?,?,?,'requested',${ee}+? WHERE (${t.sql}) AND EXISTS(SELECT 1 FROM operation_runs r JOIN operation_executions x ON x.run_id=r.id
|
|
26
|
+
WHERE r.id=? AND r.user_id=? AND r.tool=? AND r.job_id=? AND r.status='running' AND x.phase='claimed' AND x.claim_token=? AND x.expires_at_ms>${ee})`,args:[e.id,e.userId,e.jobId,e.parentRunId,B(e),864e5,...t.args,n.runId,n.userId,t.tool,t.jobId,n.token]})}catch(s){o=s}let i=await te(e.id,e.userId);if(!i||B(J(i))!==B(e))throw o??Error("Delivery request receipt is unavailable or conflicting");return i}function J(e){return{id:e.id,userId:e.userId,jobId:e.jobId,parentRunId:e.parentRunId,url:e.url,profile:e.profile,fingerprint:e.fingerprint}}async function In(e,n,t){let r;try{r=h(n)}catch{throw new fe("Delivery payload cannot be serialized")}let o=L(r);if(Buffer.byteLength(r)>16777216)throw new fe("Delivery payload exceeds budget");de({userId:e.userId,tool:t.tool,jobId:e.jobId},t);let i;try{await v().execute({sql:`UPDATE outbound_deliveries SET state='frozen',payload_json=?,payload_sha256=?,updated_at=datetime('now') WHERE id=? AND user_id=? AND request_json=? AND state='requested' AND expires_at_ms>${ee} AND (${t.sql})`,args:[r,o,e.id,e.userId,B(J(e)),...t.args]})}catch(a){i=a}let s=await te(e.id,e.userId);if(!s||s.payloadJson!==r||s.payloadSha256!==o)throw i??Error("Delivery payload receipt is unavailable or conflicting");return s}function Bt(e,n,t,r){return{userId:e.userId,tool:"paa_callback",jobId:e.jobId,sql:`(${n.sql}) AND EXISTS(SELECT 1 FROM outbound_deliveries d WHERE d.id=? AND d.user_id=? AND d.request_json=? AND d.state=? AND d.payload_json=? AND d.payload_sha256=? ${t==="accepted"?"":`AND d.expires_at_ms>${ee}`} ${r?"AND d.send_nonce=?":""})`,args:[...n.args,e.id,e.userId,B(J(e)),t,e.payloadJson,e.payloadSha256,...r?[r]:[]]}}async function Rn(e,n,t,r){let o=Bt(e,r,"frozen"),i=z(n,{tool:o.tool,jobId:e.jobId}),s;try{await v().execute({sql:`UPDATE outbound_deliveries SET state='sending',send_nonce=?,send_token=?,updated_at=datetime('now') WHERE id=? AND user_id=? AND state='frozen' AND (${o.sql}) AND (${i.sql})`,args:[t,n.token,e.id,e.userId,...o.args,...i.args]})}catch(l){s=l}let a=await te(e.id,e.userId);if(!a||a.state!=="sending"||a.sendNonce!==t||a.sendToken!==n.token||a.payloadSha256!==e.payloadSha256)throw s??Error("Delivery send permission is unavailable");return a}async function Nn(e,n,t){let r=Bt(e,t,"sending",e.sendNonce),o=z(n,{tool:r.tool,jobId:e.jobId});return(await v().execute({sql:`SELECT 1 WHERE (${r.sql}) AND (${o.sql})`,args:[...r.args,...o.args]})).rows.length===1}async function kn(e,n){if(!e.sendNonce||!e.sendToken||!e.payloadSha256||n<200||n>=300)throw Error("Invalid endpoint acceptance");let t=h({deliveryId:e.id,idempotencyKey:e.id,payloadSha256:e.payloadSha256,httpStatus:n}),r=v(),o;try{await r.execute({sql:`UPDATE outbound_deliveries SET state='accepted',http_status=?,receipt_json=?,updated_at=datetime('now') WHERE id=? AND user_id=? AND state IN ('sending','unknown') AND send_nonce=? AND send_token=? AND payload_sha256=? AND request_json=?
|
|
27
|
+
AND EXISTS(SELECT 1 FROM operation_runs WHERE id=? AND user_id=? AND tool='paa_callback' AND job_id=?)`,args:[n,t,e.id,e.userId,e.sendNonce,e.sendToken,e.payloadSha256,B(J(e)),$t(e.id),e.userId,e.jobId]})}catch(s){o=s}let i=await te(e.id,e.userId);if(!i||i.state!=="accepted"||i.receiptJson!==t)throw o??Error("Endpoint acceptance receipt is unavailable");return i}async function Dn(e){await v().execute({sql:"UPDATE outbound_deliveries SET state='unknown',updated_at=datetime('now') WHERE id=? AND user_id=? AND request_json=? AND state='frozen' AND send_nonce IS NULL AND EXISTS(SELECT 1 FROM operation_executions x JOIN operation_runs o ON o.id=x.run_id WHERE o.id=? AND o.user_id=? AND o.tool='paa_callback' AND o.job_id=? AND x.phase IN ('effects_started','unknown'))",args:[e.id,e.userId,B(J(e)),$t(e.id),e.userId,e.jobId]})}async function Pn(e){await v().execute({sql:"UPDATE outbound_deliveries SET state='unknown',updated_at=datetime('now') WHERE id=? AND user_id=? AND state='sending' AND send_nonce=?",args:[e.id,e.userId,e.sendNonce]})}async function Tn(e,n,t){await v().execute({sql:`UPDATE outbound_deliveries SET state=?,updated_at=datetime('now') WHERE id=? AND user_id=? AND state IN ('requested','frozen') AND send_nonce IS NULL ${n==="expired"?`AND expires_at_ms<=${ee}`:""} ${t?`AND (${t.sql})`:""}`,args:[n,e.id,e.userId,...t?t.args:[]]})}async function xn(e){let n=e.state==="sending"?"unknown":e.state;return await v().execute({sql:"UPDATE jobs SET options=json_set(options,'$.callbackDeliveryState',?,'$.callbackDeliveryId',?,'$.callbackDeliveryExpiresAtMs',?) WHERE id=? AND user_id=? AND callback_url=? AND json_extract(options,'$.callbackDeliveryProtocol')=1",args:[n,e.id,e.expiresAtMs,e.jobId,e.userId,e.url]}).catch(()=>{}),{state:n,deliveryId:e.id,expiresAtMs:e.expiresAtMs,...e.httpStatus?{httpStatus:e.httpStatus}:{}}}async function On(e=25){let n=v();return await xe(n),(await n.execute({sql:"SELECT d.id,d.user_id,d.job_id FROM outbound_deliveries d JOIN jobs j ON j.id=d.job_id AND j.user_id=d.user_id WHERE (d.state IN ('requested','frozen') OR (d.state='accepted' AND EXISTS(SELECT 1 FROM operation_executions x WHERE x.run_id='delivery:'||d.id AND x.phase<>'published'))) AND j.status IN ('done','failed','cancelled') AND json_extract(j.options,'$.executionState')='finalized' ORDER BY d.created_at LIMIT ?",args:[Math.max(1,Math.min(100,Math.floor(e)))]})).rows.map(t=>({id:String(t.id),userId:Number(t.user_id),jobId:String(t.job_id)}))}function Qe(e){if(!e.callback_url||e.options.callbackDeliveryProtocol!==1)return null;let n=e.options.executionProtocol===1&&e.options.directCompletionProtocol===1&&e.options.executionOwner==="direct",t=e.options.queueExecutionProtocol===1&&e.options.executionOwner==="cron";if(!n&&!t)throw Error("Callback parent profile is unavailable");return{id:`paa-callback:${e.id}`,userId:e.user_id,jobId:e.id,parentRunId:n?`paa-execution:${e.id}`:`harvest:${e.id}`,url:e.callback_url,profile:n?"paa-direct":"paa-queue",fingerprint:String(e.options.requestFingerprint)}}async function Jt(e,n,t){let r=Qe(e);r&&await Gt(r,n,{...t,sql:`(${t.sql}) AND EXISTS(SELECT 1 FROM jobs WHERE id=? AND user_id=? AND callback_url=? AND json_extract(options,'$.callbackDeliveryProtocol')=1 AND json_extract(options,'$.requestFingerprint')=?)`,args:[...t.args,e.id,e.user_id,e.callback_url,r.fingerprint]})}function Wt(e,n){let t=Qe(e);return t?{...n,sql:`(${n.sql}) AND EXISTS(SELECT 1 FROM outbound_deliveries WHERE id=? AND user_id=? AND request_json=? AND state='requested')`,args:[...n.args,t.id,t.userId,h(t)]}:n}async function Un(e,n){let t=await N(e,n);if(!t?.callback_url)return{kind:"none"};let r=Qe(t);if(!r)return{kind:"unavailable"};let o=await te(r.id,t.user_id);if(!o||h(J(o))!==h(r))return{kind:"unavailable"};if(!["done","failed","cancelled"].includes(t.status)||t.options.executionState!=="finalized"||t.options.holdState!=="settled"||!t.options.syncCapturedAt)return{kind:"pending",record:o};let i=await K(r.parentRunId,t.user_id,r.profile==="paa-direct"?"harvest_paa":"search_serp",t.id);if(!i||i.phase!=="published")return{kind:"pending",record:o};let s=r.profile==="paa-direct"?i.flags:i.flags.intent;if(!s||s.callbackUrl!==r.url||s.requestFingerprint!==r.fingerprint||s.userId!==t.user_id||s.jobId!==t.id||t.query!==s.options?.query||h(Object.fromEntries(Object.keys(s.options).map(p=>[p,t.options[p]])))!==h(s.options)||s.hold?.userId!==t.user_id||s.hold.key!==t.options.billingDebitKey||s.hold.amountMc!==t.options.billingHoldMc||t.status!==t.options.syncTerminalStatus||t.options.syncFinalAmountMc!==t.options.billingFinalAmountMc)return{kind:"unavailable"};if(t.options.syncRequiresPhysicalReceipt===1&&(await X(r.parentRunId,t.user_id)).length===0)return{kind:"pending",record:o};if(await G({runId:r.parentRunId,userId:t.user_id}))return{kind:"pending",record:o};let a=L(h({result:t.result,error:t.publicError,httpStatus:t.options.syncHttpStatus,requiresPhysical:t.options.syncRequiresPhysicalReceipt})),l={jobId:t.id,requestFingerprint:s.requestFingerprint,captureSha256:a,status:t.status},u=h({...l,amountMc:Number(t.options.syncFinalAmountMc),physicalOutcome:"terminated"}),d=Te({userId:t.user_id,jobId:t.id,tool:r.profile==="paa-direct"?"harvest_paa":"search_serp",runId:r.parentRunId,key:s.hold.key}),c={...d,sql:`(${d.sql}) AND EXISTS(SELECT 1 FROM jobs j JOIN operation_runs r ON r.job_id=j.id AND r.user_id=j.user_id JOIN operation_executions x ON x.run_id=r.id JOIN operation_final_settlements s ON s.run_id=r.id AND s.user_id=r.user_id
|
|
28
|
+
WHERE j.id=? AND j.user_id=? AND r.id=? AND x.phase='published' AND r.status=x.result_status AND x.result_json=? AND j.status=?
|
|
29
|
+
AND j.callback_url=? AND json_extract(j.options,'$.requestFingerprint')=? AND r.request_fingerprint=? AND j.query=json_extract(r.normalized_flags_json,?)
|
|
30
|
+
AND NOT EXISTS(SELECT 1 FROM json_each(r.normalized_flags_json,?) v WHERE NOT EXISTS(SELECT 1 FROM json_each(j.options) actual WHERE actual.key=v.key AND actual.type=v.type AND actual.value IS v.value))
|
|
31
|
+
AND json_extract(j.options,'$.callbackDeliveryProtocol')=1 AND json_extract(j.options,'$.executionState')='finalized' AND json_extract(j.options,'$.holdState')='settled'
|
|
32
|
+
AND json_extract(j.options,'$.syncFinalAmountMc')=? AND json_extract(j.options,'$.billingFinalAmountMc')=? AND json_extract(j.options,'$.syncTerminalStatus')=? AND json(j.result) IS json(?) AND j.public_error_json IS ?
|
|
33
|
+
AND s.debit_key=? AND s.final_amount_mc=? AND json_extract(s.receipt_json,'$.material.captureSha256')=?)`,args:[...d.args,t.id,t.user_id,r.parentRunId,u,t.status,r.url,r.fingerprint,i.fingerprint,r.profile==="paa-direct"?"$.options.query":"$.intent.options.query",r.profile==="paa-direct"?"$.options":"$.intent.options",Number(t.options.syncFinalAmountMc),Number(t.options.syncFinalAmountMc),t.status,t.result==null?null:h(t.result),t.publicError==null?null:JSON.stringify(t.publicError),s.hold.key,Number(t.options.syncFinalAmountMc),a]};return{kind:"ready",job:t,record:o,domain:c}}import{request as Mr}from"https";import{HttpsProxyAgent as Fr}from"https-proxy-agent";var Oe={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 Jn=Oe.source,Wn=Oe.retrievedAt,Cr=new Set(Oe.domains);function Vt(e){let n=new URL(e).hostname.toLowerCase().replace(/\.$/,"");for(let t of Cr)if(n===t||n.endsWith(`.${t}`))return"premium";return"standard"}function ge(e){for(let n of["providerProduct","billingTier","billableEvent","unitType","source","policyVersion","effectiveAt"])if(!e[n]?.trim())throw new Error(`Provider rate ${n} 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 Ce(e,n){if(ge(e),!Number.isSafeInteger(n)||n<0)throw new Error("Billable units must be a non-negative safe integer");let t=BigInt(e.numeratorUsdNanos)*BigInt(n),r=BigInt(e.denominatorUnits),o=(t*2n+r)/(r*2n);if(o>BigInt(Number.MAX_SAFE_INTEGER))throw new Error("Provider amount exceeds safe integer range");return Number(o)}function qr(){return ge({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 Xt(e=process.env){let n=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_CONTRACT_USD_PER_1000?.trim(),t=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(),o=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_RATE_EFFECTIVE_AT?.trim();if(!n&&!t&&!r&&!o)return qr();if(!n||!t||!r||!o)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP contract rate requires amount, source, policy version, and effective date");let i=Number(n);if(!Number.isFinite(i)||i<0)throw new Error("Invalid \u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP contract amount");return ge({providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_api",billingTier:"payg",billableEvent:"successful_delivery",unitType:"request",numeratorUsdNanos:Math.round(i*1e9),denominatorUnits:1e3,source:t,policyVersion:r,effectiveAt:o})}function jr(e){return ge({providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser_api",billingTier:e,billableEvent:"transferred_byte",unitType:"byte",numeratorUsdNanos:8e9,denominatorUnits:1e9,source:"owner_confirmed_2026-10-12",policyVersion:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061-browser-account-2026-10-12",effectiveAt:"2026-10-12T00:00:00Z"})}function zn(e){return jr(Vt(e))}function zt(){return ge({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 Lr="https://api.\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061.com/request",Hr=8e3,Ur="brd.superproxy.io",$r="44445",Gr=10*1024*1024;async function Br(e,n){let t=new URL(`http://${n.host}:${n.port}`);t.username=n.username,t.password=n.password;let r=new Fr(t);try{return await new Promise((o,i)=>{let s=Mr(e,{agent:r,headers:{"x-unblock-data-format":"parsed"},rejectUnauthorized:!1,signal:n.signal},a=>{let l=[],u=0;a.on("data",d=>{let c=Buffer.isBuffer(d)?d:Buffer.from(d);if(u+=c.length,u>Gr){s.destroy(new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP response exceeded the maximum size"));return}l.push(c)}),a.on("end",()=>o({ok:(a.statusCode??500)>=200&&(a.statusCode??500)<300,status:a.statusCode??500,rawText:Buffer.concat(l).toString("utf8"),providerRequestId:typeof a.headers["x-response-id"]=="string"?a.headers["x-response-id"]:typeof a.headers["x-request-id"]=="string"?a.headers["x-request-id"]:null}))});s.on("error",()=>i(new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 native SERP request failed"))),s.end()})}finally{r.destroy()}}function ir(e){let n=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_USERNAME?.trim(),t=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PASSWORD?.trim();if(n||t){if(!n||!t)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP requires both \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_USERNAME and \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PASSWORD");if(/[\u0000-\u001f\u007f]/.test(n+t))throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP native credentials contain invalid control characters");return{method:"native",username:n,password:t}}let r=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_API_KEY?.trim(),o=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_ZONE?.trim();if(!r||!o)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP requires \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_API_KEY and \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_ZONE, or complete native SERP proxy credentials; \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_API_KEY is not used for SERP");if(/\s|[\u0000-\u001f\u007f]/.test(r)||!/^[a-zA-Z0-9_-]+$/.test(o))throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API key or zone has an invalid format");return{method:"rest",apiKey:r,zone:o}}function Fe(e=process.env){try{return ir(e),!0}catch{return!1}}function f(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)?e:null}function O(e){return Array.isArray(e)?e:[]}function W(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,n){for(let t of n){let r=W(e[t]);if(r)return r}return null}function ne(e){try{return new URL(e).hostname.replace(/^www\./,"")}catch{return""}}function ar(e){return{rawUrl:e,resolvedUrl:e,linkType:"plain",resolutionStatus:"not_needed"}}function Jr(e){let n=e;if(typeof n=="string")try{n=JSON.parse(n)}catch{throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API returned invalid JSON")}let t=f(n);if(!t)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API returned an invalid payload");if(typeof t.body=="string")try{let o=JSON.parse(t.body);if(f(o))return f(o)}catch{}let r=f(t.body);return r?f(r.result)??f(r.data)??r:f(t.result)??f(t.data)??t}function oe(e,n){for(let r of n){let o=O(e[r]);if(o.length)return o}let t=f(e.results);if(t)for(let r of n){let o=O(t[r]);if(o.length)return o}return[]}function re(e,n){let t=[e,f(e.results)].filter(r=>!!r);for(let r of t)for(let o of n)if(Object.prototype.hasOwnProperty.call(r,o))return{observed:!0,rawShapeValid:Array.isArray(r[o]),rawCount:O(r[o]).length};return{observed:!1,rawShapeValid:!1,rawCount:0}}function Ze(e,n){let t=[e,f(e.results)].filter(r=>!!r);for(let r of t)for(let o of n){if(!Object.prototype.hasOwnProperty.call(r,o))continue;let i=f(r[o]);return{observed:!0,rawShapeValid:i!==null,rawCount:i&&Object.keys(i).length>0?1:0}}return{observed:!1,rawShapeValid:!1,rawCount:0}}function Kt(e){return oe(e,["organic","organic_results","organicResults"]).flatMap((n,t)=>{let r=f(n);if(!r)return[];let o=g(r,["link","url","href"]),i=g(r,["title","name"]);if(!o||!i)return[];let s=f(r.rating)??f(r.inline_rating);return[{position:Math.max(1,Math.trunc(R(r.global_rank)??R(r.rank)??R(r.position)??t+1)),title:i,url:o,...ar(o),domain:ne(o),cite:g(r,["display_link","displayLink","cite"]),snippet:g(r,["description","snippet","text"]),isRedditStyle:ne(o)==="reddit.com",inlineRating:s?{value:String(s.value??s.rating??""),count:String(s.count??s.reviews??"")}:null}]}).sort((n,t)=>n.position-t.position)}function Yt(e){return oe(e,["snack_pack","local","local_results","local_pack","localPack"]).flatMap((n,t)=>{let r=f(n);if(!r)return[];let o=g(r,["title","name"]);if(!o)return[];let i=O(r.extensions??r.metadata).map(W).filter(s=>!!s);return[{position:Math.max(1,Math.trunc(R(r.global_rank)??R(r.rank)??R(r.position)??t+1)),name:o,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:i,websiteUrl:g(r,["website","website_url","link"]),directionsUrl:g(r,["directions","directions_url"])}]})}function ur(e){let n=f(e);return O(n?.citations??n?.sources??n?.references).flatMap(t=>{let r=f(t);if(!r)return[];let o=g(r,["link","url","href"]);return o?[{text:g(r,["title","text","name"])??ne(o),href:o,...ar(o)}]:[]})}function Me(e,n=0){if(n>4)return[];if(Array.isArray(e))return e.flatMap(i=>Me(i,n+1));let t=f(e);if(!t)return[];let r=g(t,["snippet","text","answer"]),o=Me(t.texts??t.list??t.items,n+1);return[...r?[r]:[],...o]}function Qt(e,n){if(!n)return{detected:!1,text:null,citations:[]};let t=f(e.ai_overview)??f(e.aiOverview)??f(e.overview);if(!t)return{detected:!1,text:null,citations:[]};let r=g(t,["text","answer","description"])??(Me(t.texts).join(`
|
|
34
|
+
|
|
35
|
+
`).slice(0,5e4)||null),o=ur(t);return{detected:!!(r||o.length),text:r,citations:o}}function Zt(e,n){if(!n)return{detected:!1,text:null,citations:[]};let t=f(e.ai_mode)??f(e.aiMode);if(!t)return{detected:!1,text:null,citations:[]};let r=g(t,["text","answer","description"])??(Me(t.texts).join(`
|
|
36
|
+
|
|
37
|
+
`).slice(0,5e4)||null),o=ur(t);return{detected:!!(r||o.length),text:r,citations:o}}function er(e,n){return n?[...oe(e,["videos","video_results"]),...oe(e,["short_videos","shorts"])].flatMap(t=>{let r=f(t);if(!r)return[];let o=g(r,["link","url"]),i=g(r,["title","name"]);return!o||!i?[]:[{type:"video",title:i,channel:g(r,["channel","source"])??"",platform:ne(o),duration:g(r,["duration"])??"",url:o}]}):[]}function tr(e,n){if(!n)return[];let t=f(e.forums);return[...oe(e,["discussions","forums","forum_results"]),...O(t?.items)].flatMap(r=>{let o=f(r);if(!o)return[];let i=g(o,["link","url"]),s=g(o,["title","name"]);return!i||!s?[]:[{title:s,source:g(o,["source"])??ne(i),url:i}]})}function rr(e,n){return n?oe(e,["what_people_are_saying","whatPeopleSaying"]).flatMap(t=>{let r=f(t);if(!r)return[];let o=g(r,["link","url"]),i=g(r,["title","name"]);if(!o||!i)return[];let s=g(r,["platform","source"])??ne(o),a=s.toLowerCase();return[{type:a.includes("reddit")?"reddit":a.includes("facebook")?"facebook":a.includes("instagram")?"instagram":a.includes("tiktok")?"tiktok":a.includes("youtube")?"youtube":a.includes("news")?"news":"unknown",title:i,url:o,source:s,platform:s,popularComment:g(r,["comment","popular_comment"]),engagement:g(r,["engagement"])??"",date:g(r,["date"])??"",duration:g(r,["duration"]),authorNote:g(r,["author_note"])}]}):[]}var Wr={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 qe(e,n){for(let t of[e,f(e.results)])if(t){for(let r of n)if(Object.prototype.hasOwnProperty.call(t,r))return{observed:!0,value:t[r]}}return{observed:!1,value:null}}function je(e,n,t){return e?n==null||Array.isArray(n)&&n.length===0?"observed_absent":Array.isArray(n)?t>0?"observed_present":"incomplete":f(n)?t>0?"observed_present":Object.keys(f(n)).length===0?"observed_absent":"incomplete":"incomplete":"unknown"}function Vr(e){let n=g(e,["answer","snippet","text"]);return n||O(e.answers).flatMap((r,o)=>{let i=f(r),s=f(i?.value),a=i?.type==="answer"?W(s?.text):null;return a?[{prose:a,rank:R(i?.rank)??o+1,index:o}]:[]}).sort((r,o)=>r.rank-o.rank||r.index-o.index).map(r=>r.prose).join(`
|
|
38
|
+
|
|
39
|
+
`)||null}function Xr(e,n){let t={},r=[["localPack",["snack_pack","local","local_results","local_pack","localPack"],n.localPack],["forums",["discussions","forums","forum_results"],n.forums],["videos",["videos","video_results","short_videos","shorts"],n.videos],["aiOverview",["ai_overview","aiOverview","overview"],n.aiOverview],["whatPeopleSaying",["what_people_are_saying","whatPeopleSaying"],n.whatPeopleSaying],["entityIds",["knowledge","knowledge_graph","knowledgeGraph"],n.entityIds]];for(let[l,u,d]of r){let c=qe(e,u);t[l]=je(c.observed,c.value,d)}let o=qe(e,["ai_mode","aiMode"]);t.aiMode=je(o.observed,o.value,n.aiMode);let i=qe(e,["people_also_ask","peopleAlsoAsk","related_questions","paa"]),s=O(i.value).slice(0,30).flatMap(l=>{let u=f(l);if(!u)return[];let d=g(u,["question","title"]);if(!d)return[];let c=W(u.question)?W(u.title)?.slice(0,1e3):null,p=W(u.answer_source)?.slice(0,1e3),_=g(u,["answer_display_link","display_link"])?.slice(0,2e3);return[{question:d.slice(0,1e3),answer:Vr(u)?.slice(0,1e4)??null,url:g(u,["answer_link","link","url"])??null,...c?{sourceTitle:c}:{},...p?{sourceName:p}:{},..._?{displayLink:_}:{}}]});t.paaPreview=je(i.observed,i.value,s.length);let a=[];for(let[l,u]of Object.entries(Wr)){let d=qe(e,u);if(!d.observed)continue;let c=f(d.value),_=(Array.isArray(d.value)?d.value:c&&(Array.isArray(c.items)||Array.isArray(c.posts))?[...O(c.items),...O(c.posts)]:[d.value]).slice(0,20).flatMap(y=>{let b=f(y);if(!b)return[];let x=g(b,["title","name","heading"]),q=g(b,["link","url","website"]),M=g(b,["description","snippet","text","summary","story"]);return!x&&!q&&!M?[]:[{title:x?.slice(0,1e3)??null,url:q,description:M?.slice(0,1e4)??null,position:R(b.global_rank)??R(b.rank)??R(b.position)??null}]});t[l]=je(d.observed,d.value,_.length);let w=Object.fromEntries(Object.entries(c??{}).slice(0,30).flatMap(([y,b])=>/^[a-zA-Z0-9_]{1,80}$/.test(y)&&(b===null||["string","number","boolean"].includes(typeof b))?[[y,typeof b=="string"?b.slice(0,2e3):b]]:[]));a.push({name:l,attributes:w,items:_})}return{status:t,paaPreview:s,additional:a}}function nr(e,n){let t=new Set,r=new Set(n.map(s=>s.cid).filter(s=>!!s)),o=new Set,i=(s,a=0)=>{if(a>6||s==null)return;if(Array.isArray(s)){for(let u of s)i(u,a+1);return}let l=f(s);if(l)for(let[u,d]of Object.entries(l)){let c=u.toLowerCase().replace(/[^a-z]/g,""),p=W(d);p&&(c==="kgid"||c==="kgmid"||c==="mid")?t.add(p):p&&c==="cid"?r.add(p):p&&c==="gcid"?o.add(p):typeof d=="object"&&i(d,a+1)}};return i(e),{entities:[],kgIds:[...t],cids:[...r],gcids:[...o]}}function or(e,n){let t=e instanceof Error?e.message:String(e);return n.aborted||/timeout|timed out/i.test(t)?"timeout":/captcha|recaptcha|unusual traffic|google\.com\/sorry|blocked/i.test(t)?"captcha":/invalid (?:json|payload)/i.test(t)?"invalid_payload":"provider_error"}function sr(e){return e==="invalid_payload"?"invalid_payload":e==="captcha"?"serp_readiness":e==="timeout"||e==="provider_error"?"provider_transport":"pagination"}async function et(e,n=process.env,t=fetch,r=Br,o){if(e.pages!==1)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP supports one page only; use Apify for two pages");let i=ir(n),s=i.method==="native",a=Date.now(),l=Et(),u=null,d=e.location?St(e.location):null;if(e.location&&!d?.canonical)throw new Y("query_integrity","location_unresolved",`SERP location could not be resolved without changing the query (candidates: ${d?.ambiguousCandidates??0})`);let c=d?.canonical?bt(d.canonical):null,p=AbortSignal.timeout(e.includeAllSerpFeatures?33e3:Hr),_=e.signal?AbortSignal.any([e.signal,p]):p,w=1,y=[],b=[],x=0,q=async m=>{let P=Date.now(),I=s?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_native_proxy":"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_rest",T=null,F=null,ae=!1,ue=!1,V=null,le=null;if(l?.operationRunId&&(m===1||u))try{T=await Re({runId:l.operationRunId,attemptNumber:o?o.attemptNumber+m-1:m,method:I,provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",...m===2?{parentAttemptId:u,edgeKind:"next_phase"}:o?{parentAttemptId:o.parentAttemptId,edgeKind:"provider_fallback",retryKind:"provider_fallback"}:{},normalizedFlags:{page:m,device:e.device,hasLocation:!!e.location}}),m===1&&(u=T),F=(await ke({attemptId:T,provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_api",accountScope:l.operationAccountScope??"production-default",method:I,providerStatus:"started"})).id}catch(E){throw console.warn(JSON.stringify({event:"direct_serp_telemetry_start_failed",page:m,message:E instanceof Error?E.message:String(E)})),E}let k=new URLSearchParams({q:e.query,gl:e.gl,hl:e.hl,pws:"0",num:"10",...m===2?{start:"10"}:{}}),Ae=ht(e.recency);Ae&&k.set("tbs",Ae),e.device==="mobile"&&k.set("brd_mobile","1"),e.includeAiOverview&&k.set("brd_ai_overview","2"),c&&k.set("uule",c),s&&k.set("brd_json","1"),x+=1;let j;try{if(i.method==="native"){let D=n.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_HOST?.trim()||Ur,ce=n.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PORT?.trim()||$r;j=await r(`https://www.google.com/search?${k}`,{username:i.username,password:i.password,host:D,port:ce,signal:_})}else{let D=await t(Lr,{method:"POST",headers:{Authorization:`Bearer ${i.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({zone:i.zone,url:`https://www.google.com/search?${k}`,format:"json",data_format:"parsed"}),signal:_});j={ok:D.ok,status:D.status,rawText:await D.text(),providerRequestId:D.headers.get("x-response-id")??D.headers.get("x-request-id")}}if(le=`http_${j.status}`,F&&j.providerRequestId&&await me(F,j.providerRequestId),!j.ok)throw new Error(`\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API failed with HTTP ${j.status}`);ae=!0;let E;try{E=Jr(JSON.parse(j.rawText))}catch(D){let ce=D instanceof Error&&D.message!=="Unexpected end of JSON input"?D.message:"\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API returned invalid JSON";throw new Y("invalid_payload","invalid_provider_payload",ce)}let S=Kt(E);return y.push({page:m,attempted:!0,captured:S.length>0,resultCount:S.length,requestOffset:m===2?10:0,providerRequestIdObserved:!!j.providerRequestId,...S.length===0?{failureCode:"empty_page"}:{}}),ue=!0,E}catch(E){V=E;let S=or(E,_);if(y.some(ce=>ce.page===m)||y.push({page:m,attempted:!0,captured:!1,resultCount:0,requestOffset:m===2?10:0,providerRequestIdObserved:!1,failureCode:S}),m===2)throw E;let D=E instanceof Y?E.stage:sr(S);throw E instanceof Y?E:new Y(D,S,E instanceof Error?E.message:String(E))}finally{let E=null;if(F&&ae)try{let S=Xt(n);await De({receiptId:F,costState:"measured",units:1,unitType:"request",amountUsdNanos:Ce(S,1),rateSource:S.source,providerProduct:S.providerProduct,billingTier:S.billingTier,billableEvent:S.billableEvent,measurementSource:"provider_http_delivery",rateNumerator:S.numeratorUsdNanos,rateDenominator:S.denominatorUnits,ratePolicyVersion:S.policyVersion,rateEffectiveAt:S.effectiveAt,providerStatus:le??"delivered",providerDurationMs:Date.now()-P})}catch(S){console.warn(JSON.stringify({event:"direct_serp_receipt_finalize_failed",page:m,message:S instanceof Error?S.message:String(S)})),E=S}if(T&&await Ne({attemptId:T,status:ue?"succeeded":_.aborted?"timed_out":"failed",errorCode:V?or(V,_):null,durationMs:Date.now()-P}).catch(S=>console.warn(JSON.stringify({event:"direct_serp_attempt_finish_failed",page:m,message:S instanceof Error?S.message:String(S)}))),E)throw E}};try{b.push({page:1,payload:await q(1)})}catch(m){throw m}let M=null;if(w===2)try{b.push({page:2,payload:await q(2)})}catch(m){M=m}let $e=Date.now()-a,we=Date.now(),A=b[0].payload,be=b.flatMap(({page:m,payload:P})=>Kt(P).map(I=>({...I,position:m===2&&I.position<=10?I.position+10:I.position,sourcePage:m}))).filter((m,P,I)=>I.findIndex(T=>Ye(T.url)===Ye(m.url))===P),Se=e.includeLocalPack||e.includeAllSerpFeatures,$=Se?Yt(A):[],ie=re(A,["snack_pack","local","local_results","local_pack","localPack"]),Ar=Z({requested:Se,moduleObserved:ie.observed,rawCount:ie.rawCount,mappedCount:$.length,rawShapeValid:ie.rawShapeValid}),nt=e.includeAiOverview||e.includeAllSerpFeatures,ot=Qt(A,nt),st=e.includeForums||e.includeAllSerpFeatures,it=tr(A,st),at=e.includeVideos||e.includeAllSerpFeatures,ut=er(A,at),lt=e.includeWhatPeopleSaying||e.includeAllSerpFeatures,ct=rr(A,lt),Ge=f(A.forums),Be=Ge&&Array.isArray(Ge.items)?{observed:!0,rawCount:Ge.items.length,rawShapeValid:!0}:re(A,["discussions","forums","forum_results"]),Je=re(A,["videos","video_results","short_videos","shorts"]),dt={localPack:Ar,forums:Z({requested:st,moduleObserved:Be.observed,rawCount:Be.rawCount,mappedCount:it.length,rawShapeValid:Be.rawShapeValid}),videos:Z({requested:at,moduleObserved:Je.observed,rawCount:Je.rawCount,mappedCount:ut.length,rawShapeValid:Je.rawShapeValid}),aiOverview:Z({requested:nt,moduleObserved:Ze(A,["ai_overview","aiOverview","overview"]).observed,rawCount:Ze(A,["ai_overview","aiOverview","overview"]).rawCount,mappedCount:ot.detected?1:0,rawShapeValid:Ze(A,["ai_overview","aiOverview","overview"]).rawShapeValid}),whatPeopleSaying:Z({requested:lt,moduleObserved:re(A,["what_people_are_saying","whatPeopleSaying"]).observed,rawCount:re(A,["what_people_are_saying","whatPeopleSaying"]).rawCount,mappedCount:ct.length,rawShapeValid:re(A,["what_people_are_saying","whatPeopleSaying"]).rawShapeValid})},Ir=Q(1,y),Rr=y.find(m=>m.page===1)?.resultCount??0,Ee=y.find(m=>m.page===2)?.resultCount??0,Nr=Pe({query:e.query,finalQuery:e.query,canonicalLocation:d?.canonical??null,locationResolutionSource:d?.source??"not_requested",locationAmbiguousCandidates:d?.ambiguousCandidates??0,uule:c,outboundProviderMethod:s?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_native_proxy":"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_rest"}),ve=M?sr(y.find(m=>m.page===2)?.failureCode??"provider_error"):Object.values(dt).some(m=>m==="incomplete"||m==="unknown")?"optional_feature_parsing":null,kr={pagination:{...Ir,providerRequestCount:x},features:dt,queryIntegrity:Nr,failureStage:ve},pt=e.includeAllSerpFeatures?(()=>{let m=b.map(({page:P,payload:I})=>{let T=Yt(I),F=tr(I,!0),ae=er(I,!0),ue=rr(I,!0),V=Qt(I,!0),le=Zt(I,!0),k=nr(I,T),Ae=Xr(I,{localPack:T.length,forums:F.length,videos:ae.length,aiOverview:V.detected?1:0,aiMode:le.detected?1:0,whatPeopleSaying:ue.length,entityIds:k.entities.length+k.kgIds.length+k.cids.length+k.gcids.length});return{page:P,...Ae,localPack:T,forums:F,videos:ae,whatPeopleSaying:ue,aiOverview:V,aiMode:le,entityIds:k}});return{status:m[0].status,paaPreview:m.flatMap(P=>P.paaPreview),additional:m.flatMap(P=>P.additional),pages:m}})():void 0,Dr=new Date().toISOString(),mt=Date.now()-a;return{seed:e.query,location:e.location??null,extractedAt:Dr,diagnostics:{phaseTimings:{providerConnectMs:$e,serpParseMs:Date.now()-we,totalServerMs:mt},pagination:{requestedPages:w,capturedPages:w===2&&Ee>0?2:1,page2Status:w===2?Ee>0?"captured":"failed":"not_requested",page1OrganicCount:Rr,page2OrganicCount:Ee,...w===2&&Ee===0?{failureCode:y.find(m=>m.page===2)?.failureCode==="captcha"?"captcha":y.find(m=>m.page===2)?.failureCode==="timeout"?"timeout":"empty_page"}:{}},completionStatus:"serp_only",problem:null,resultQuality:ve?"partial":"complete",degradedResult:!!ve,degradationReasons:[],retryRecommended:!!ve,serpCompleteness:kr},totalQuestions:0,surface:"web",aiOverview:ot,aiMode:Zt(A,e.includeAllSerpFeatures),...pt?{fullSerpFeatures:pt}:{},whatPeopleSaying:ct,tree:[],flat:[],videos:ut,forums:it,organicResults:be,localPack:$,entityIds:nr(A,$),stats:{seed:e.query,totalQuestions:0,maxDepthReached:0,durationMs:mt,errorCount:0}}}var zr="scraperlink~google-search-results-serp-scraper",ye="https://api.apify.com/v2";var C=class extends Error{constructor(t,r=null,o=!1,i=null){super(t);this.runId=r;this.retrySafe=o;this.terminalStatus=i;this.name="ApifyGoogleRunError"}runId;retrySafe;terminalStatus};function _e(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:null}function he(e){return typeof e=="string"&&e.trim()?e.trim():null}function Kr(e){try{return["http:","https:"].includes(new URL(e).protocol)}catch{return!1}}function Yr(e){if(typeof e!="string")return e;try{return JSON.parse(e)}catch{throw new Error("Apify searchResults is not valid JSON")}}function lr(e,n){if(!Array.isArray(e)||e.length===0)throw new Error("Apify dataset contains no search results");let t=[];for(let[i,s]of e.entries()){let a=_e(s);if(!a)throw new Error("Apify dataset contains an invalid row");let l=Yr(a.searchResults??a),u=_e(l),d=Array.isArray(l)?l:Array.isArray(u?.results)?u.results:Array.isArray(u?.organicResults)?u.organicResults:Array.isArray(u?.organic)?u.organic:u&&(u.position!==void 0||u.title!==void 0)?[u]:null;if(!d)throw new Error("Apify dataset search result shape is unsupported");let c=Number(a.page_number??u?.page_number??i+1);if(!Number.isInteger(c)||c<1||c>n)throw new Error("Apify dataset has an unexpected page number");t.push(...d.map(p=>({row:p,page:c})))}let r=t.map(({row:i,page:s},a)=>{let l=_e(i),u=l?.position,d=he(l?.title),c=he(l?.url??l?.link);if(!l||!d||!c||!Kr(c)||u!==void 0&&(!Number.isInteger(u)||u<1))throw new Error(`Apify search result ${a+1} is missing a valid position, URL, or title`);let p=he(l.description??l.snippet),_=typeof u=="number"?u:a%10+1;return{position:s>1&&_<=10?_+(s-1)*10:_,url:c,title:d,description:p}});if(r.length>n*10)throw new Error("Apify returned more results than requested");let o={page1:r.filter(i=>i.position<=10).length,page2:r.filter(i=>i.position>10).length};if(o.page1===0)throw new Error("Apify did not return the first result page");return{results:r,pageResultCounts:o}}async function Le(e,n,t,r){let o=await t(e,{headers:{Authorization:`Bearer ${n}`},signal:r});if(!o.ok)throw new Error(`Apify API returned HTTP ${o.status}`);return o.json()}function tt(e){let n=_e(_e(e)?.data),t=he(n?.id),r=he(n?.status);if(!t||!r)throw new Error("Apify returned an invalid run receipt");return{id:t,status:r}}async function Qr(e,n=fetch){let t=performance.now(),r=AbortSignal.timeout(9e4),o=e.signal?AbortSignal.any([e.signal,r]):r,i=e.runId,s=!1,a=null;try{if(!/^[A-Za-z0-9]+$/.test(i))throw new Error("Invalid Apify run ID");let l=tt(await Le(`${ye}/actor-runs/${i}?waitForFinish=30`,e.token,n,o));for(;["READY","RUNNING","TIMING-OUT","ABORTING"].includes(l.status);)l=tt(await Le(`${ye}/actor-runs/${i}?waitForFinish=30`,e.token,n,o));if(s=!0,a=l.status,l.status!=="SUCCEEDED")throw new Error(`Apify run ended with status ${l.status}`);let u=e.pages??1,d=await Le(`${ye}/actor-runs/${i}/dataset/items?format=json`,e.token,n,o);return{query:e.query,...lr(d,u),requestedPages:u,runId:i,elapsedMs:Math.round(performance.now()-t)}}catch(l){throw new C(l instanceof Error?l.message:String(l),i,s,a)}}async function cr(e,n,t=fetch){let r=performance.now(),o=e.query.trim(),i=e.pages??1;if(!o||o.includes(`
|
|
40
|
+
`))throw new Error("Apify search requires one nonempty query");if(i!==1&&i!==2)throw new Error("Apify search supports one or two pages");let s=n.token.trim();if(!s)throw new Error("Apify API token is required");let a=n.maxChargeUsd??.01;if(!Number.isFinite(a)||a<=0)throw new Error("Invalid Apify charge cap");let l=AbortSignal.timeout(9e4),u=e.signal?AbortSignal.any([e.signal,l]):l,d=`${ye}/actors/${zr}/runs?maxTotalChargeUsd=${a}&restartOnError=false&waitForFinish=30`,c=null,p=!1,_=null;try{let w=await t(d,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({keyword:o,limit:i===2?"20":"10",page:1,proxy_location:"us",include_merged:!1}),signal:u});if(!w.ok)throw new Error(`Apify run start returned HTTP ${w.status}`);let y=tt(await w.json());if(c=y.id,p=!["READY","RUNNING","TIMING-OUT","ABORTING"].includes(y.status),p&&(_=y.status),y.status!=="SUCCEEDED"&&y.status!=="READY"&&y.status!=="RUNNING")throw new Error(`Apify run ended with status ${y.status}`);if(y.status==="SUCCEEDED"){let x=await Le(`${ye}/actor-runs/${c}/dataset/items?format=json`,s,t,u);return{query:o,...lr(x,i),requestedPages:i,runId:c,elapsedMs:Math.round(performance.now()-r)}}return{...await Qr({runId:c,query:o,token:s,pages:i,signal:u},t),elapsedMs:Math.round(performance.now()-r)}}catch(w){throw w instanceof C?w:new C(w instanceof Error?w.message:String(w),c,p,_)}}var dr="apify_google_serp",pr="apify",Zr="apify_google_serp_scraperlink";async function mr(e,n,t,r){let o=zt();await De({receiptId:e,costState:"estimated",units:n,unitType:o.unitType,amountUsdNanos:Ce(o,n),rateSource:o.source,providerProduct:o.providerProduct,billingTier:o.billingTier,billableEvent:o.billableEvent,measurementSource:"actor_run_succeeded",rateNumerator:o.numeratorUsdNanos,rateDenominator:o.denominatorUnits,ratePolicyVersion:o.policyVersion,rateEffectiveAt:o.effectiveAt,providerStatus:r,providerDurationMs:t})}async function fr(e){let n=performance.now(),t=await Re({runId:e.operationRunId,attemptNumber:e.attemptNumber,method:dr,provider:pr,parentAttemptId:e.parentAttemptId,edgeKind:e.edgeKind,retryKind:e.retryKind,normalizedFlags:{page:1,pages:e.options.pages??1,proxyLocation:"us"}}),r=await ke({attemptId:t,provider:pr,providerProduct:Zr,billingTier:"store_pay_per_event",accountScope:e.accountScope,method:dr,providerStatus:"before_actor_start"}),o=null,i=null;try{return o=await cr(e.options,{token:e.token},e.fetchImpl),await me(r.id,o.runId),await mr(r.id,o.requestedPages,o.elapsedMs,"succeeded_estimated"),{...o,attemptId:t}}catch(s){throw i=s,o?Object.assign(new C("Apify cost tracking failed after run completion",o.runId),{attemptId:t}):(s instanceof C&&s.runId&&(await me(r.id,s.runId),s.terminalStatus==="SUCCEEDED"?await mr(r.id,e.options.pages??1,Math.round(performance.now()-n),"succeeded_dataset_unavailable"):await Ct({receiptId:r.id,units:e.options.pages??1,unitType:"page",providerStatus:"run_outcome_or_cost_pending"})),Object.assign(s instanceof Error?s:new Error(String(s)),{attemptId:t}))}finally{await Ne({attemptId:t,status:i?e.options.signal?.aborted?"timed_out":"failed":"succeeded",errorCode:i?"apify_search_failed":null,durationMs:Math.round(performance.now()-n)})}}function gr(e,n=e.requestedPages){let t=e.results.map(s=>{let a=new URL(s.url).hostname.replace(/^www\./,"");return{position:s.position,title:s.title,url:s.url,rawUrl:s.url,resolvedUrl:s.url,linkType:"plain",resolutionStatus:"not_needed",domain:a,cite:null,snippet:s.description,isRedditStyle:a==="reddit.com",inlineRating:null}}),r=n===2&&e.pageResultCounts.page2>0?2:1,o=n===2&&r===1,i=Q(n,[{page:1,attempted:!0,captured:!0,resultCount:e.pageResultCounts.page1,requestOffset:0,providerRequestIdObserved:!0},...n===2?[{page:2,attempted:!0,captured:!o,resultCount:e.pageResultCounts.page2,requestOffset:10,providerRequestIdObserved:!0,...o?{failureCode:"empty_page"}:{}}]:[]]);return{seed:e.query,location:null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:{providerConnectMs:e.elapsedMs,totalServerMs:e.elapsedMs},pagination:{requestedPages:n,capturedPages:r,page2Status:n===2?o?"failed":"captured":"not_requested",page1OrganicCount:e.pageResultCounts.page1,page2OrganicCount:e.pageResultCounts.page2},completionStatus:"serp_only",problem:null,resultQuality:o?"partial":"complete",degradedResult:o,degradationReasons:o?["page_two_missing"]:[],retryRecommended:!1,serpCompleteness:{pagination:i,features:{localPack:"not_requested",forums:"not_requested",videos:"not_requested",aiOverview:"not_requested",whatPeopleSaying:"not_requested"},queryIntegrity:Pe({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:t,localPack:[],entityIds:{entities:[],kgIds:[],cids:[],gcids:[]},stats:{seed:e.query,totalQuestions:0,maxDepthReached:0,durationMs:e.elapsedMs,errorCount:0}}}var en=12e3;async function _r(e){let n=await qt(e.runId);if(!n||String(n.run.id)!==e.runId||Number(n.run.user_id)!==e.userId||n.run.tool!=="search_serp"||n.run.job_id!==e.jobId||n.attempts.length===0||!n.attempts.every(r=>r.run_id===e.runId&&(r.provider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"&&["\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"].includes(String(r.method))||r.provider==="apify"&&r.method==="apify_google_serp")&&["failed","timed_out","cancelled"].includes(String(r.status))&&typeof r.ended_at=="string"&&Number.isFinite(Date.parse(r.ended_at))&&r.duration_ms!=null&&Number.isSafeInteger(Number(r.duration_ms))&&Number(r.duration_ms)>=0))return null;let t=n.attempts[n.attempts.length-1].status;return t==="cancelled"?{errorCode:"request_aborted",httpStatus:408,terminalStatus:"cancelled"}:t==="timed_out"?{errorCode:"harvest_timeout",httpStatus:504,terminalStatus:"failed"}:{errorCode:"service_unavailable",httpStatus:503,terminalStatus:"failed"}}function vo(e){return e.recency?vt():e.mode==="full"&&e.pages===1?Fe():!!e.token||Fe()}async function tn(e){if(e.signal.throwIfAborted(),e.recency)return rn(e);if(e.mode==="full")return nn(e);if(!e.token)return yr(e);let n=performance.now(),t;for(let r=1;r<=2;r++){let o=AbortSignal.any([e.signal,AbortSignal.timeout(en)]),i=e.pages;try{let s=await fr({options:{query:e.query,pages:i,signal:o},token:e.token,operationRunId:e.operationRunId,accountScope:e.accountScope,attemptNumber:r,...t?{parentAttemptId:t,edgeKind:"same_method_retry",retryKind:"same_method"}:{}});console.info(JSON.stringify({event:"serp_provider_succeeded",provider:"apify",operationRunId:e.operationRunId,attemptNumber:r,durationMs:s.elapsedMs,resultCount:s.results.length,requestedPages:e.pages,providerRequestedPages:s.requestedPages,deliveredPages:s.pageResultCounts.page2>0?2:1,runId:s.runId}));let a=gr(s,e.pages);return a.stats.durationMs=Math.round(performance.now()-n),a.diagnostics.phaseTimings&&(a.diagnostics.phaseTimings.totalServerMs=a.stats.durationMs),{result:a,mode:"light",deliveryProvider:"apify",deliveredPages:s.pageResultCounts.page2>0?2:1}}catch(s){t=s&&typeof s=="object"&&"attemptId"in s?String(s.attemptId):void 0;let a=s instanceof C?s:null;if(console.warn(JSON.stringify({event:"serp_provider_failed",provider:"apify",operationRunId:e.operationRunId,attemptNumber:r,runId:a?.runId??null,requestedPages:e.pages,attemptPages:i,retrySafe:a?.retrySafe===!0,error:s instanceof Error?s.message:String(s)})),e.signal.aborted||!t||a?.retrySafe!==!0)throw s}}return yr(e,t)}async function yr(e,n){if(e.signal.throwIfAborted(),!Fe())throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API fallback is not configured; set \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_API_KEY and \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_ZONE, or the SERP proxy username and password");let t=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 o=await et(r,process.env,fetch,void 0,n?{attemptNumber:3,parentAttemptId:n}:void 0);if(o.organicResults.length===0)throw new Error("Search returned no organic results");if(e.pages===2){o.diagnostics.pagination={requestedPages:2,capturedPages:1,page2Status:"unavailable",page1OrganicCount:o.organicResults.length,page2OrganicCount:0},o.diagnostics.resultQuality="partial",o.diagnostics.degradedResult=!0,o.diagnostics.degradationReasons=[...new Set([...o.diagnostics.degradationReasons??[],"page_two_missing"])],o.diagnostics.retryRecommended=!1;let i=o.diagnostics;i.serpCompleteness&&(i.serpCompleteness.pagination=Q(2,i.serpCompleteness.pagination.evidence.filter(s=>s.page===1)),i.serpCompleteness.failureStage="pagination")}return o.stats.durationMs=Math.round(performance.now()-t),o.diagnostics.phaseTimings&&(o.diagnostics.phaseTimings.totalServerMs=o.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:o.stats.durationMs,resultCount:o.organicResults.length,requestedPages:e.pages,providerRequestedPages:1,deliveredPages:1,resultQuality:o.diagnostics.resultQuality})),{result:o,mode:"light",deliveryProvider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",deliveredPages:1}}catch(o){throw console.warn(JSON.stringify({event:"serp_provider_failed",provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",operationRunId:e.operationRunId,attemptNumber:3,error:o instanceof Error?o.message:String(o)})),o}}async function rn(e){let n=await At({...e.physicalFactory?{physicalExecution:await e.physicalFactory()}:{},query:e.query,gl:"us",hl:"en",device:"desktop",pages:e.pages,recency:e.recency,serpOnly:!0,forceManagedSerp:!0,maxAttempts:2,proxyMode:"none",maxQuestions:1,depth:1,headless:!0,format:"json",outputDir:"/tmp/paa-output-api",softDeadlineMs:Date.now()+23e4,signal:e.signal,onAttemptEvent:e.onAttemptEvent});if(n.organicResults.length===0)throw new Error("Search returned no organic results");let t=n.diagnostics.pagination?.capturedPages===2?2:1;if(e.pages===2&&t===1&&(n.diagnostics.resultQuality="partial",n.diagnostics.degradedResult=!0,n.diagnostics.degradationReasons=["page_two_missing"],n.diagnostics.retryRecommended=!0),e.mode==="full"){let r=Object.fromEntries(["localPack","forums","videos","aiOverview","aiMode","whatPeopleSaying","entityIds","paaPreview","topStories"].map(o=>[o,"unsupported"]));n.fullSerpFeatures={status:r,paaPreview:[],additional:[],pages:[]}}return{result:n,mode:e.mode==="full"?"full":"light",deliveryProvider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",deliveredPages:t}}async function nn(e){if(e.pages===2){let n=await tn({...e,mode:"light",pages:2}),t=Object.fromEntries(["localPack","forums","videos","aiOverview","aiMode","whatPeopleSaying","entityIds","paaPreview","topStories"].map(o=>[o,"unsupported"]));n.result.fullSerpFeatures={status:t,paaPreview:[],additional:[],pages:[]};let r=n.result.diagnostics;return r.serpCompleteness&&(r.serpCompleteness.features={localPack:"unsupported",forums:"unsupported",videos:"unsupported",aiOverview:"unsupported",whatPeopleSaying:"unsupported"}),{...n,mode:"full"}}return on({...e,mode:"full"})}async function on(e){let n=performance.now(),t=e.mode==="full",r={query:e.query,gl:"us",hl:"en",device:"desktop",pages:1,...e.recency?{recency:e.recency}:{},includeAllSerpFeatures:t,includeLocalPack:t,includeForums:t,includeVideos:t,includeAiOverview:t,includeWhatPeopleSaying:t,signal:e.signal},o=await et(r);if(o.organicResults.length===0)throw new Error("Search returned no organic results");return o.stats.durationMs=Math.round(performance.now()-n),o.diagnostics.phaseTimings&&(o.diagnostics.phaseTimings.totalServerMs=o.stats.durationMs),{result:o,mode:t?"full":"light",deliveryProvider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",deliveredPages:o.diagnostics.pagination?.capturedPages===2?2:1}}var U=e=>`harvest:${e}`,wr=e=>e.profile==="direct"?"executionProtocol":e.profile==="queue"?"queueExecutionProtocol":"syncExecutionProtocol";function se(e,n="'running'"){let t=h(e.options),r=Object.keys(JSON.parse(t)).sort();if(r.some(o=>!/^[a-zA-Z][a-zA-Z0-9]*$/.test(o)))throw Error("Invalid synchronous option key");return{userId:e.userId,tool:e.tool,jobId:e.jobId,sql:`EXISTS(SELECT 1 FROM jobs j WHERE j.id=? AND j.user_id=? AND j.status IN (${n}) AND json_extract(j.options,'$.${wr(e)}')=1 AND j.query=? AND j.callback_url IS ? ${e.profile==="direct"?"AND json_extract(j.options,'$.executionOwner')='direct' AND json_extract(j.options,'$.directCompletionProtocol')=1 AND json_extract(j.options,'$.paaLeaseToken')=? AND json_extract(j.options,'$.executionRunId')=?":e.profile==="queue"?"AND json_extract(j.options,'$.executionOwner')='cron'":""} AND json_extract(j.options,'$.requestFingerprint')=? AND json_extract(j.options,'$.billingHoldMc')=? ${r.map(()=>"AND json_extract(j.options,?) IS json_extract(?,?)").join(" ")})`,args:[e.jobId,e.userId,String(e.options.query),e.callbackUrl??null,...e.profile==="direct"?[e.recordToken,`paa-execution:${e.jobId}`]:[],e.requestFingerprint,e.hold.amountMc,...r.flatMap(o=>[`$.${o}`,t,`$.${o}`])]}}function rt(e){let n=JSON.parse(h(e));if(!n.jobId||!Number.isSafeInteger(n.userId)||n.userId<=0||!["harvest_paa","search_serp"].includes(n.tool)||!Number.isSafeInteger(n.deadlineAt)||!Number.isSafeInteger(n.hold.amountMc)||n.hold.amountMc<=0||n.hold.userId!==n.userId||n.hold.key!==(n.profile==="queue"?`serp-search:${n.jobId}:hold`:`harvest-sync:${n.jobId}:charge`)||!/^[a-f0-9]{64}$/.test(n.requestFingerprint)||!n.refundOperation||!n.sourceSurface)throw Error("Invalid synchronous funded intent");if(n.profile==="queue"&&(n.tool!=="search_serp"||n.options.serpOnly!==!0||n.deadlineAt!==0||!Number.isSafeInteger(n.budgetMs)||n.budgetMs<1e3||n.budgetMs>36e5||n.hold.operation!=="serp"||n.refundOperation!=="serp_refund"||n.sourceSurface!=="serp_search"||n.hold.description!==`SERP search: ${n.options.query}`.slice(0,500)))throw Error("Invalid queued compatibility intent");return n}async function br(e){let n=await K(U(e.id),e.user_id,e.options.serpOnly===!0?"search_serp":"harvest_paa",e.id);if(!n||n.flags.syncExecutionProtocol!==1||!n.flags.intent)return null;let t=rt(n.flags.intent);if((t.profile==="queue"?e.options.queueExecutionProtocol:e.options.syncExecutionProtocol)!==1||t.jobId!==e.id||t.userId!==e.user_id||n.fingerprint!==t.requestFingerprint)throw Error("Synchronous intent receipt conflicts");return t}async function H(e,n="held"){let t=e.options.serpOnly===!0?2:Ke;return{status:503,headers:{"Retry-After":String(t)},body:{job_id:e.id,status:"running",saved_status:e.status,...pe({errorCode:"response_lost",retryable:!0,chargeStatus:n==="held"?"refund_pending":void 0,details:{retry_guidance:`Wait at least ${t} seconds before retrying this exact request with the same idempotencyKey or reading the returned job. Saved content and settlement resume without another acquisition.`}}),executionState:"unknown",hold_state:n,status_tool:e.options.queueExecutionProtocol===1?"harvest_paa_status":e.options.serpOnly===!0?"search_serp":"harvest_paa_status",...e.result?{result:e.result}:{}}}}async function sn(e,n){await v().execute({sql:`UPDATE jobs SET options=json_set(options,'$.executionState','unknown','$.holdState',CASE WHEN json_extract(options,'$.billingSettledAt') IS NOT NULL THEN 'settled' ELSE 'held' END) WHERE id=? AND user_id=? AND json_extract(options,'$.${wr(e)}')=1 AND EXISTS(SELECT 1 FROM operation_executions x WHERE x.run_id=? AND x.claim_token=?)`,args:[e.jobId,e.userId,n.runId,n.token]})}async function He(e,n,t,r,o,i=null,s=200,a=!0){if(!Number.isSafeInteger(r)||r<0||r>e.hold.amountMc)throw Error("Invalid captured synchronous charge");let l=t==null?null:h(t),u=i==null?null:JSON.stringify(i),d=se(e),c;try{await v().execute({sql:`UPDATE jobs SET result=?,public_error_json=?,options=json_set(options,'$.syncCapturedAt',datetime('now'),'$.syncFinalAmountMc',?,'$.syncTerminalStatus',?,'$.syncHttpStatus',?,'$.syncRequiresPhysicalReceipt',?)
|
|
41
|
+
WHERE id=? AND user_id=? AND json_extract(options,'$.syncCapturedAt') IS NULL AND (${d.sql})
|
|
42
|
+
AND EXISTS(SELECT 1 FROM operation_runs r JOIN operation_executions x ON x.run_id=r.id WHERE r.id=? AND r.user_id=? AND x.claim_token=? AND x.phase IN ('effects_started','unknown') AND r.status IN ('running','unknown'))`,args:[l,u,r,o,s,a?1:0,e.jobId,e.userId,...d.args,n.runId,n.userId,n.token]})}catch(_){c=_}let p=await N(e.jobId,e.userId);if(!p?.options.syncCapturedAt||h({result:p.result})!==h({result:t==null?null:JSON.parse(l)})||p.options.syncFinalAmountMc!==r||p.options.syncTerminalStatus!==o||h({error:p.publicError})!==h({error:wt(i)})||p.options.syncHttpStatus!==s||p.options.syncRequiresPhysicalReceipt!==(a?1:0))throw c??Error("synchronous_capture_receipt_unknown_or_conflicting");return p}async function Sr(e,n){return{status:n?200:Number(e.options.syncHttpStatus??200),body:{job_id:e.id,status:e.status,...e.result?{result:e.result}:{},...e.publicError?{...e.publicError,error:e.publicError.message,...e.options.holdState==="settled"&&e.options.billingFinalAmountMc===0?{charge_status:"refunded"}:{}}:{},...n?{replayed:!0}:{}}}}async function Er(e,n){if(e.profile!==void 0||e.tool!=="search_serp"||e.options.serpOnly!==!0||!["light","full"].includes(String(e.options.mode))||![1,2].includes(Number(e.options.pages))||e.options.recency||e.options.serpIdentity||n.runId!==U(e.jobId)||n.userId!==e.userId||await G({userId:n.userId,runId:n.runId})||(await X(n.runId,n.userId)).length!==0)return null;let t=await _r({runId:n.runId,userId:n.userId,jobId:e.jobId});return t?{publicError:pe({errorCode:t.errorCode,retryable:t.terminalStatus!=="cancelled"}),httpStatus:t.httpStatus,terminalStatus:t.terminalStatus}:null}async function Ue(e,n,t,r=!1){let o=await N(e.jobId,e.userId);if(!o?.options.syncCapturedAt)throw Error("Synchronous capture is not known");if(o.options.syncRequiresPhysicalReceipt===1&&(await X(n.runId,n.userId)).length===0)throw Error("synchronous_physical_receipt_missing");if(await G({userId:e.userId,runId:n.runId}))throw Error("synchronous_physical_outcome_unknown");let i=Number(o.options.syncFinalAmountMc),s=String(o.options.syncTerminalStatus);if(!["done","failed","cancelled"].includes(s))throw Error("Invalid synchronous terminal receipt");let a={jobId:o.id,requestFingerprint:e.requestFingerprint,captureSha256:L(h({result:o.result,error:o.publicError,httpStatus:o.options.syncHttpStatus,requiresPhysical:o.options.syncRequiresPhysicalReceipt})),status:s},l=se(e,"'running','done','failed','cancelled'"),u={...l,sql:`(${l.sql}) AND EXISTS(SELECT 1 FROM jobs WHERE id=? AND user_id=? AND json_extract(options,'$.syncCapturedAt') IS NOT NULL AND json_extract(options,'$.syncFinalAmountMc')=? AND json_extract(options,'$.syncTerminalStatus')=? AND json(result) IS json(?) AND public_error_json IS ? AND json_extract(options,'$.syncHttpStatus')=? AND json_extract(options,'$.syncRequiresPhysicalReceipt')=?)`,args:[...l.args,o.id,o.user_id,i,s,o.result==null?null:h(o.result),o.publicError==null?null:JSON.stringify(o.publicError),Number(o.options.syncHttpStatus),Number(o.options.syncRequiresPhysicalReceipt)]},d=await Ht({claim:n,recovery:t,gate:u,key:e.hold.key,amountMc:i,refundOperation:e.refundOperation,sourceSurface:e.sourceSurface,material:a});if((await Ot(e.userId,e.hold.key,e.sourceSurface)??await Tt(e.userId,e.hold.key,i,e.refundOperation,"Synchronous harvest settlement",e.sourceSurface,d)).final_amount_mc!==i)throw Error("Synchronous settlement receipt conflicts");let p=Te({userId:o.user_id,tool:e.tool,jobId:o.id,runId:n.runId,key:e.hold.key}),_=z(n,{tool:e.tool,jobId:o.id,recovery:t}),w;try{await v().execute({sql:`UPDATE jobs SET status=?,completed_at=COALESCE(completed_at,datetime('now')),options=json_set(options,'$.executionState','finalized','$.holdState','settled','$.physicalOutcome','terminated','$.billingSettledAt',COALESCE(json_extract(options,'$.billingSettledAt'),datetime('now')),'$.billingFinalAmountMc',?${e.profile==="direct"?",'$.billedMc',?":""}) WHERE id=? AND user_id=? AND (${u.sql}) AND (${_.sql}) AND (${p.sql})`,args:[s,i,...e.profile==="direct"?[i]:[],o.id,o.user_id,...u.args,..._.args,...p.args]})}catch(q){w=q}let y=await N(o.id,o.user_id);if(!y||y.status!==s||y.options.billingFinalAmountMc!==i||y.options.holdState!=="settled"||h({result:y.result})!==h({result:o.result}))throw w??Error("synchronous_publication_receipt_unknown");let b={status:t?"unknown":s==="done"?"succeeded":s,json:h({...a,amountMc:i,physicalOutcome:"terminated"})};if(!(t?await Nt(n,b,p):await Rt(n,b)))throw Error("Synchronous execution receipt publication unknown");return Sr(y,r)}async function an(e){if(e.options.syncExecutionProtocol!==1&&e.options.queueExecutionProtocol!==1)return null;let n=await br(e);if(!n)return e.options.queueExecutionProtocol===1||await Ie(U(e.id),e.user_id)?H(e,"unconfirmed"):null;let t=await K(U(e.id),e.user_id,n.tool,e.id);if(t?.phase==="published"&&e.options.holdState==="settled")return Sr(e,!0);if(t?.phase==="claimed"&&t.expiresAtMs<=t.nowMs&&e.status==="running"&&!e.options.syncCapturedAt)return null;if(t?.phase==="claimed"||t?.phase==="effects_started"&&t.expiresAtMs>t.nowMs)return{status:409,headers:{"Retry-After":String(n.tool==="harvest_paa"?Ke:2)},body:{job_id:e.id,error:"This request is already running under the supplied Idempotency-Key.",errorCode:"idempotency_in_progress",retryable:!0,...e.result?{result:e.result}:{}}};let r=await It(U(e.id),e.user_id);if(!r)return H(e);try{let o=await Mt(e,r);if(!e.options.syncCapturedAt){let i=o?{terminalStatus:"failed",publicError:pe({errorCode:"service_unavailable",retryable:!0}),httpStatus:503}:await Er(n,r);i&&await He(n,r,null,0,i.terminalStatus,i.publicError,i.httpStatus,!1)}return await Ue(n,r,!0,!0)}catch{return H(await N(e.id,e.user_id)??e,e.options.holdState==="settled"?"settled":"held")}}async function vr(e,n,t=!0){let r=await ze(n.userId,n.hold.key);if(!r||r.status!=="applied"){if(!t)throw Error("Original applied hold is unavailable");let o=await Pt(n.userId,n.hold.amountMc,n.hold.operation,n.hold.description,n.hold.key);if(!o.ok)return{status:402,body:{job_id:n.jobId,error:"Insufficient balance",error_code:"insufficient_balance",balance_mc:o.balance_mc,required_mc:n.hold.amountMc}}}return await xt(e,{hold:n.hold,label:n.profile==="queue"?"original-queue-hold":"original-sync-hold",refundOperation:n.refundOperation,sourceSurface:n.sourceSurface,tool:n.tool,jobId:n.jobId}),null}async function Lo(e,n,t){let r=rt(e),o,i=!1,s=!1,a=!1,l=await N(r.jobId,r.userId);try{let u=await br(l);if(u){if(u.requestFingerprint!==r.requestFingerprint)throw Error("Synchronous request conflicts");r=u}else if(r.profile==="queue"||await Ie(U(r.jobId),r.userId)||(await ze(r.userId,r.hold.key))?.status==="applied")return H(l,"unconfirmed");if(r.profile!=="queue"&&Date.now()>=r.deadlineAt)return H(l,"unconfirmed");let d=await Xe({id:U(r.jobId),userId:r.userId,ownerScope:`user:${r.userId}`,tool:r.tool,jobId:r.jobId,idempotencyKey:`job:${r.jobId}`,requestFingerprint:r.requestFingerprint,normalizedFlags:{syncExecutionProtocol:1,intent:r}},hr(),Math.min(36e5,Math.max(1e3,(r.profile==="queue"?r.budgetMs:r.deadlineAt-Date.now())+3e4)),se(r));if(d.kind!=="claimed")return H(l,"unconfirmed");o=d.claim;let c=await vr(o,r);if(c)return c;let p=se(r),_=Dt(r.hold),w=await N(r.jobId,r.userId),y=Wt(w,{...p,sql:`(${p.sql}) AND (${_.sql})`,args:[...p.args,..._.args]});if(!await kt(o,y))throw Error("Synchronous effect start unknown");if(i=!0,r.profile==="queue"){let we=z(o,{tool:r.tool,jobId:r.jobId}),A=se(r),be;try{await v().execute({sql:`UPDATE jobs SET options=json_set(options,'$.compatDeadlineAt',CAST(strftime('%s','now') AS INTEGER)*1000+?) WHERE id=? AND user_id=? AND json_extract(options,'$.compatDeadlineAt') IS NULL AND (${A.sql}) AND (${we.sql})`,args:[r.budgetMs,r.jobId,r.userId,...A.args,...we.args]})}catch(ie){be=ie}let Se=await N(r.jobId,r.userId),$=Number(Se?.options.compatDeadlineAt);if(!Number.isSafeInteger($)||$<=Date.now())throw be??Error("Queued deadline unavailable or expired");r={...r,deadlineAt:$}}let b=0,x=o,q={claim:o,deadlineAt:r.deadlineAt,physicalFactory:async()=>gt({claim:x,gate:y,deadlineAt:r.deadlineAt,scope:`sync-browser-${++b}`,profile:"customer-funded"})},M=await n(q);a=!0,await He(r,o,M.result,M.amountMc,"done",null,200,r.options.serpOnly!==!0||b>0);let $e=await Ue(r,o,!1);return s=!0,$e}catch(u){if(o&&i){if(!(await N(r.jobId,r.userId))?.options.syncCapturedAt&&!a){let c=await X(o.runId,o.userId).catch(()=>[]);if(c.length>0&&c.every(p=>p.state==="terminated"||p.state==="not_started")){let p=t(u);try{await He(r,o,null,0,p.terminalStatus==="cancelled"?"cancelled":"failed",p.publicError,p.httpStatus);let _=await Ue(r,o,!1);return s=!0,_}catch{}}if(c.length===0){let p=await Er(r,o).catch(()=>null);if(p)try{await He(r,o,null,0,p.terminalStatus,p.publicError,p.httpStatus,!1);let _=await Ue(r,o,!1);return s=!0,_}catch{}}}await Ve(o).catch(()=>{}),await sn(r,o).catch(()=>{})}return H(await N(r.jobId,r.userId)??l)}finally{o&&!i&&await We(o).catch(()=>{}),o&&i&&!s&&await Ve(o).catch(()=>{})}}async function Ho(e,n=!0){let t=rt(e);if(t.profile!=="queue")throw Error("Queue profile required");let r=!1,o=U(t.jobId),i=await N(t.jobId,t.userId),s=async()=>({kind:"unknown",reply:i?await H(i):{status:503,body:{job_id:t.jobId,status:"pending",executionState:"unknown",hold_state:r?"held":"unconfirmed",status_tool:"harvest_paa_status",...pe({errorCode:"response_lost",retryable:!0})}}});if(i&&i.options.queueExecutionProtocol!==1)return s();let a=await K(o,t.userId,t.tool,t.jobId);if(a){if(a.flags.syncExecutionProtocol!==1||h({intent:a.flags.intent})!==h({intent:t}))return s();if(["effects_started","unknown","published"].includes(a.phase)){if(!i)return s();let d=await an(i);if(d&&d.status!==200)return{kind:"unknown",reply:d};let c=await N(t.jobId,t.userId);return c?{kind:"ready",job:c,replayed:!0}:s()}}else if(i||await Ie(o,t.userId))return s();let l={userId:t.userId,tool:t.tool,jobId:t.jobId,sql:"EXISTS(SELECT 1 FROM users WHERE id=? AND active=1)",args:[t.userId]},u;try{let d=await Xe({id:o,userId:t.userId,ownerScope:`user:${t.userId}`,tool:t.tool,jobId:t.jobId,idempotencyKey:`job:${t.jobId}`,requestFingerprint:t.requestFingerprint,normalizedFlags:{syncExecutionProtocol:1,intent:t}},hr(),45e3,l);if(d.kind!=="claimed")return s();u=d.claim;let c=await vr(u,t,n);if(c)return{kind:"unfunded",reply:c};if(r=!0,!i&&(await jt(t.jobId,t.userId,String(t.options.query),{...t.options,executionOwner:"cron",queueExecutionProtocol:1,...t.callbackUrl?{callbackDeliveryProtocol:1}:{},billingHoldMc:t.hold.amountMc,billingDebitKey:t.hold.key,requestFingerprint:t.requestFingerprint},t.callbackUrl??void 0)).kind==="unknown")return s();let p=se(t,"'pending','running','done','failed','cancelled'"),_=(await v().execute({sql:`SELECT 1 WHERE (${p.sql})`,args:p.args})).rows.length>0,w=await N(t.jobId,t.userId);return _&&w&&await Jt(w,u,p),_&&w?{kind:"ready",job:w,replayed:!!(i||a)}:s()}catch{return s()}finally{u&&await We(u).catch(()=>{})}}export{Ht as a,Te as b,Vt as c,Ce as d,jr as e,zn as f,Mt as g,fe as h,$t as i,te as j,J as k,In as l,Bt as m,Rn as n,Nn as o,kn as p,Dn as q,Pn as r,Tn as s,xn as t,On as u,Jt as v,Wt as w,Un as x,vo as y,tn as z,H as A,sn as B,He as C,Sr as D,Ue as E,an as F,Lo as G,Ho as H};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{a as p,f as w,i as x}from"./chunk-3F7AFM53.js";import{a as d,e as E,k as g}from"./chunk-RDHGQ2WZ.js";import{a as T,b as R,e as c,i as u}from"./chunk-SEZETSB3.js";import{i as l,k as m}from"./chunk-SDQW7IJN.js";import{c as _}from"./chunk-FLAWC5PF.js";import{createHash as h,randomBytes as C}from"crypto";var D=1440*60*1e3,y="mcp-reports/",F="extract-url-job-results/",O=2e3;function P(){return 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()||process.env.BLOB_READ_WRITE_TOKEN?.trim()||void 0}var A={prefix:y,artifactTtlMs:D,downloadTtlMs:900*1e3,token:P()},b={...A,hosted:!1,token:void 0},a="mcp-results/";function v(t){return{prefix:a,artifactTtlMs:T,downloadTtlMs:R,hosted:!t,token:t?void 0:P()}}var M=process.env.MCP_SCRAPER_ARTIFACT_OFFLOAD!=="false";async function j(t,e,r){let i=Date.now(),n=C(6).toString("hex"),o=await c({policy:A,ownerId:e,artifactKey:`${n}.md`,createdAt:i,filename:`${t}-${i}.md`,contentType:"text/markdown",content:r,scopeSegments:[t]});return{artifactId:o.artifactId,mimeType:o.contentType,sizeBytes:o.bytes,bytes:o.bytes,sha256:o.sha256,expiresAt:o.expiresAt,downloadUrl:o.downloadUrl,downloadUrlExpiresAt:o.downloadUrlExpiresAt,preview:r.slice(0,O)}}async function k(t,e,r){let i=JSON.stringify(r),n=await c({policy:b,ownerId:t,artifactKey:`${e}.json`,createdAt:Date.now(),filename:`${e}.json`,contentType:"application/json",content:i,scopeSegments:["extract_url"]});return{artifactId:n.artifactId,mimeType:n.contentType,sizeBytes:n.bytes,bytes:n.bytes,sha256:n.sha256,expiresAt:n.expiresAt,downloadUrl:n.downloadUrl,downloadUrlExpiresAt:n.downloadUrlExpiresAt,preview:i.slice(0,O)}}function J(t){if(t.startsWith(a))return l(t,a);let e=f(t)?.ownerId;return e||(t.startsWith(p)?w(t):t.startsWith(d)?E(t):l(t,y))}function f(t){let e=t.match(/^extract-url-job-results\/([a-f0-9]{24})\/([1-9][0-9]*)\/(exurl-[a-f0-9]{24})\.json$/);if(!e)return null;let r=Number(e[2]);return Number.isSafeInteger(r)?{ownerId:e[1],userId:r,jobId:e[3]}:null}async function I(t,e){let r=await _(t,e);if(!r||r.status!=="done"||r.options.jobKind!=="extract_url"||!r.result)return null;let i=Date.parse(`${r.created_at.replace(" ","T")}Z`);if(!Number.isFinite(i))return null;let n=new Date(i+1080*60*60*1e3);return n.getTime()<=Date.now()?null:{content:Buffer.from(JSON.stringify(r.result)),expiresAt:n.toISOString()}}async function K(t,e,r){let i=`${F}${e}/${r}/${t}.json`;if(!f(i))return null;let n=await I(t,r);return n?{artifactId:i,mimeType:"application/json",sizeBytes:n.content.length,bytes:n.content.length,sha256:h("sha256").update(n.content).digest("hex"),expiresAt:n.expiresAt,downloadUrl:null,downloadUrlExpiresAt:null,preview:n.content.toString("utf8",0,Math.min(2e3,n.content.length))}:null}async function z(t,e,r,i,n=!1){let o=f(t);if(o){if(o.userId!==i||!Number.isSafeInteger(e)||e<0||!Number.isSafeInteger(r)||r<=0)return null;let s=await I(o.jobId,o.userId);return s?{...m(s.content.subarray(e,e+r+1),e,r,s.content.length),totalBytes:s.content.length}:null}return t.startsWith(a)?u({policy:v(n),artifactId:t,offset:e,maxBytes:r}):t.startsWith(p)?x(t,e,r):t.startsWith(d)?g(t,e,r):u({policy:n?b:A,artifactId:t,offset:e,maxBytes:r})}function X(t){return t.downloadUrl?{type:"resource_link",name:"Full MCP Scraper report",title:"Download full report",uri:t.downloadUrl,mimeType:t.mimeType,size:t.sizeBytes}:null}function Y(t,e){return[t.trim(),"","--- Full report stored as artifact ---",`artifactId: ${e.artifactId} \xB7 ${e.bytes} bytes \xB7 expires ${e.expiresAt}`,"Read it with report_artifact_read (supports offset/maxBytes windowing)."].join(`
|
|
2
2
|
`)}export{D as a,y as b,F as c,O as d,A as e,a as f,v as g,M as h,j as i,k as j,J as k,K as l,z as m,X as n,Y as o};
|