mcp-scraper 0.95.2 → 0.96.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 +67 -1
- package/README.md +21 -3
- package/dist/actions-R4EJDLRO.js +1 -0
- package/dist/artifacts-4ZDNP2JW.js +1 -0
- package/dist/artifacts-N62OPIT5.js +1 -0
- package/dist/artifacts-PSADD5OC.js +1 -0
- package/dist/artifacts-RUR3OHAK.js +1 -0
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.js +22 -22
- package/dist/bin/mcp-scraper-core.js +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.js +1 -1
- package/dist/bin/paa-harvest.js +1 -1
- package/dist/blob-store-GIH26EDO.js +1 -0
- package/dist/bundle-FCXZMIRB.js +1 -0
- package/dist/chunk-24YDQ3EO.js +5 -0
- package/dist/chunk-3F7AFM53.js +1 -0
- package/dist/chunk-4HZXATHB.js +27 -0
- package/dist/chunk-55ZANTHL.js +3 -0
- package/dist/chunk-5BKSKLHX.js +1 -0
- package/dist/chunk-5LYINW7Z.js +8 -0
- package/dist/chunk-63VWBMYR.js +3 -0
- package/dist/chunk-6BD75VKS.js +218 -0
- package/dist/chunk-6N5EC7ZO.js +1 -0
- package/dist/chunk-7POHNTVW.js +1 -0
- package/dist/chunk-7SR7MEU5.js +62 -0
- package/dist/chunk-7WPCGRD7.js +182 -0
- package/dist/chunk-B3JRL45T.js +1 -0
- package/dist/chunk-B4ZKPLSP.js +1 -0
- package/dist/chunk-BPKTUCV7.js +12 -0
- package/dist/chunk-C7MGJUTU.js +1 -0
- package/dist/{chunk-W2BVJ7S2.js → chunk-CNSVZTTT.js} +4 -4
- package/dist/chunk-CORWWDHL.js +1 -0
- package/dist/chunk-CVQUHVHX.js +1 -0
- package/dist/chunk-FB4KBB5W.js +16 -0
- package/dist/{chunk-Y3Q4FIKK.js → chunk-H6MODA7W.js} +199 -84
- package/dist/chunk-HCK6PLM3.js +3 -0
- package/dist/chunk-HNNYXMSI.js +1 -0
- package/dist/chunk-HUNSEGUN.js +57 -0
- package/dist/{chunk-MC4W6TZT.js → chunk-HVQZRQRJ.js} +41 -8
- package/dist/chunk-IFPION5D.js +121 -0
- package/dist/chunk-IY6ZUUY7.js +173 -0
- package/dist/chunk-JHT6A4U6.js +11 -0
- package/dist/chunk-JMZIDHYQ.js +2 -0
- package/dist/chunk-KXJCGV3H.js +1 -0
- package/dist/chunk-MVMWPKRC.js +2 -0
- package/dist/chunk-NALXKTUU.js +1 -0
- package/dist/chunk-NNOX3FYG.js +198 -0
- package/dist/chunk-OILOHQNL.js +2 -0
- package/dist/chunk-OLYPLX5C.js +1 -0
- package/dist/chunk-QER2ELZP.js +1 -0
- package/dist/chunk-RDHGQ2WZ.js +1 -0
- package/dist/chunk-RIHI3KH7.js +955 -0
- package/dist/chunk-RN4VG3VH.js +4 -0
- package/dist/chunk-RYX4FJVH.js +1 -0
- package/dist/chunk-SDQW7IJN.js +1 -0
- package/dist/{chunk-ENZUJEIM.js → chunk-SE4VKLEC.js} +1 -1
- package/dist/chunk-SEZETSB3.js +1 -0
- package/dist/chunk-SFUOSJ3A.js +159 -0
- package/dist/chunk-UIOSADPB.js +1718 -0
- package/dist/{chunk-ZH75KWBI.js → chunk-UNEJYZ4T.js} +1 -1
- package/dist/chunk-UXNR3K6I.js +1 -0
- package/dist/{chunk-VREXSMC6.js → chunk-VVSHZV5S.js} +5 -5
- package/dist/chunk-WNUXMPVX.js +1 -0
- package/dist/chunk-WP3QS4CJ.js +1 -0
- package/dist/chunk-ZTMQEDIB.js +41 -0
- package/dist/contracts-GUXGFCVV.js +1 -0
- package/dist/core-schema-423BSTE6.js +936 -0
- package/dist/dispatch-P7IY75LH.js +1 -0
- package/dist/index.cjs +103 -213
- package/dist/index.d.cts +184 -169
- package/dist/index.d.ts +184 -169
- package/dist/index.js +1 -1
- package/dist/media-artifacts-67CJWI7O.js +1 -0
- package/dist/metering-ZH2P62IC.js +1 -0
- package/dist/migrations-3AKEC5QE.js +1 -0
- package/dist/queue-AC4XKD6Z.js +1 -0
- package/dist/reconciliation-UZUZ6B74.js +1 -0
- package/dist/report-artifact-offload-6OOY2PTM.js +1 -0
- package/dist/repository-4EC5EXVN.js +1 -0
- package/dist/{location-data-repository-A2QZVP7O.js → repository-CYXVMYAI.js} +1 -1
- package/dist/server-DXZ27KQO.js +5825 -0
- package/dist/settlement-6CS4JZTY.js +1 -0
- package/dist/worker-ATRD6VKM.js +1 -0
- package/package.json +2 -2
- package/dist/analytics-repository-DZZKDZL6.js +0 -1
- package/dist/chunk-6DRKDSXY.js +0 -182
- package/dist/chunk-6ND5AFV5.js +0 -27
- package/dist/chunk-7XDBGQDY.js +0 -6
- package/dist/chunk-7YOXSMHG.js +0 -1565
- package/dist/chunk-BLVBUMH5.js +0 -21
- package/dist/chunk-EDQ57S4P.js +0 -1
- package/dist/chunk-GLTECY3U.js +0 -1282
- package/dist/chunk-GPSPSJBJ.js +0 -1
- package/dist/chunk-HE45FFBU.js +0 -1
- package/dist/chunk-HUV2WTRW.js +0 -1
- package/dist/chunk-IXJQHXDC.js +0 -2595
- package/dist/chunk-K3D2S36Q.js +0 -16
- package/dist/chunk-KFOFU3LA.js +0 -1
- package/dist/chunk-LMWU7VPZ.js +0 -63
- package/dist/chunk-O4LUUIYG.js +0 -4
- package/dist/chunk-OLSW4AN4.js +0 -19
- package/dist/chunk-RLFCJGHA.js +0 -100
- package/dist/chunk-T4VTJNDZ.js +0 -84
- package/dist/chunk-TMB56NCA.js +0 -1
- package/dist/chunk-VXOXB3IB.js +0 -1
- package/dist/chunk-WO3N5FH2.js +0 -5
- package/dist/chunk-WO46LTBW.js +0 -1
- package/dist/chunk-XPEJB4BZ.js +0 -1
- package/dist/db-CDEZHBRN.js +0 -1
- package/dist/extract-bundle-SXC6EWJR.js +0 -26
- package/dist/gmail-service-EWR76XE7.js +0 -1
- package/dist/lead-list-enrichment-repository-SIWGXWQV.js +0 -1
- package/dist/operation-metering-UJ53YX7S.js +0 -1
- package/dist/server-QVEKDIDQ.js +0 -5014
- package/dist/site-extract-repository-23ND4N77.js +0 -1
- package/dist/stripe-event-worker-LPXTITVC.js +0 -1
- package/dist/worker-EDN2TJH3.js +0 -1
- /package/dist/{chunk-YGBTTW5D.js → chunk-2IATUJO6.js} +0 -0
- /package/dist/{chunk-6DTXIZY2.js → chunk-4ZVO6GX4.js} +0 -0
- /package/dist/{chunk-XG6GCEUE.js → chunk-U4WIJZCX.js} +0 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import{a as I}from"./chunk-7POHNTVW.js";import{b as S}from"./chunk-4ZVO6GX4.js";import{a as R}from"./chunk-WNUXMPVX.js";import{randomUUID as X}from"crypto";import{createMiddleware as b}from"hono/factory";async function j(e){await e.execute(`CREATE TABLE IF NOT EXISTS mcp_analytics_requests (
|
|
2
|
+
id TEXT PRIMARY KEY, parent_request_id TEXT, user_id INTEGER NOT NULL REFERENCES users(id),
|
|
3
|
+
service TEXT NOT NULL, method TEXT NOT NULL, http_status INTEGER NOT NULL,
|
|
4
|
+
duration_ms INTEGER NOT NULL, client_surface TEXT NOT NULL,
|
|
5
|
+
install_channel TEXT NOT NULL, ai_client TEXT, ai_model TEXT,
|
|
6
|
+
attribution_basis TEXT NOT NULL, started_at TEXT NOT NULL, deployment_commit TEXT
|
|
7
|
+
)`),(await e.execute("PRAGMA table_info(mcp_analytics_requests)")).rows.some(n=>n.name==="parent_request_id")||await e.execute("ALTER TABLE mcp_analytics_requests ADD COLUMN parent_request_id TEXT"),await e.execute("CREATE INDEX IF NOT EXISTS mcp_analytics_requests_user_started ON mcp_analytics_requests(user_id, started_at)"),await e.execute("CREATE INDEX IF NOT EXISTS mcp_analytics_requests_started ON mcp_analytics_requests(started_at)")}var k=new Set(["npx","npm","sdk","frontend","mcp-stdio","mcp-http","rest"]),D=new Set(["npx","npm","mcpb","source"]),v=new Set(["claude","claude-desktop","claude-code","chatgpt","codex","cursor","gemini","other"]);function y(e,t){return e&&t.has(e.toLowerCase())?e.toLowerCase():null}function A(e,t=!1){let n=y(e.get("x-mcp-client-surface")??void 0,k),s=e.get("x-mcp-ai-model")??"";return{surface:t?"frontend":n??"unknown",installChannel:y(e.get("x-mcp-install-channel")??void 0,D)??"unknown",aiClient:y(e.get("x-mcp-ai-client")??void 0,v),aiModel:/^[a-zA-Z0-9][a-zA-Z0-9._:/-]{0,79}$/.test(s)?s:null,basis:t?"session_authenticated":n?"caller_declared":"unknown"}}async function q(e,t=50){let n;try{await Promise.race([e,new Promise((s,a)=>{n=setTimeout(()=>a(new Error("analytics_write_budget_exceeded")),t)})])}finally{n&&clearTimeout(n)}}function F(e=2){let t=0;return async n=>{if(t>=e)return!1;t++;let s=Promise.resolve().then(n).finally(()=>{t--});return await q(s),!0}}var H=F();function z(e){return b(async(t,n)=>{let s=X(),a=new Date().toISOString(),o=performance.now(),r=new URL(t.req.url).pathname,d=e(r),i=d??(r==="/mcp"?"mcp_http":"other_authenticated_http"),f={op:i,probeRunId:t.req.header("x-cost-probe-id")??null,requestId:s},_=A(t.req.raw.headers),c={};_.surface!=="unknown"&&(c["x-mcp-client-surface"]=_.surface),new URL(t.req.url).pathname==="/mcp"&&!c["x-mcp-client-surface"]&&(c["x-mcp-client-surface"]="mcp-http"),_.installChannel!=="unknown"&&(c["x-mcp-install-channel"]=_.installChannel),_.aiClient&&(c["x-mcp-ai-client"]=_.aiClient),_.aiModel&&(c["x-mcp-ai-model"]=_.aiModel);let l=t.req.header("x-mcp-parent-request-id"),N=l&&/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(l)?l:null;return I({requestId:s,headers:c},()=>S(f,async()=>{t.header("x-mcp-request-id",s);try{await n()}finally{t.header("x-mcp-request-id",s);let T=t.get("user"),x=t.get("sessionUser"),O=Number(T?.id??x?.id),w=/\/(?:jobs|status|progress|events|history|balance|usage)(?:\/|$)/.test(r);if(process.env.MCP_ANALYTICS_CAPTURE==="1"&&!w&&t.req.method!=="HEAD"&&t.req.method!=="OPTIONS"&&(d!==null||r==="/mcp"&&t.req.method==="POST")&&Number.isSafeInteger(O)&&O>0){let E=A(t.req.raw.headers,!!x?.id);new URL(t.req.url).pathname==="/mcp"&&E.surface==="unknown"&&(E.surface="mcp-http",E.basis="hosted_mcp_route");try{await H(()=>R().execute({sql:`INSERT INTO mcp_analytics_requests
|
|
8
|
+
(id,parent_request_id,user_id,service,method,http_status,duration_ms,client_surface,install_channel,
|
|
9
|
+
ai_client,ai_model,attribution_basis,started_at,deployment_commit)
|
|
10
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,args:[s,N,O,i,t.req.method,t.error?500:t.res.status,Math.max(0,Math.round(performance.now()-o)),E.surface,E.installChannel,E.aiClient,E.aiModel,E.basis,a,process.env.VERCEL_GIT_COMMIT_SHA??null]}))}catch{console.warn("[mcp-analytics] request observation unavailable")}}}}))})}var m=["oauth_store_metadata","oauth_clients","oauth_client_redirect_uris","oauth_codes","oauth_code_exchanges","oauth_refresh_families","oauth_refresh_tokens","oauth_refresh_rotations","oauth_security_events","oauth_rate_limit_buckets"],h=["oauth_clients_inactivity_idx","oauth_clients_cleanup_idx","oauth_codes_expiry_idx","oauth_codes_client_idx","oauth_code_exchanges_replay_expiry_idx","oauth_refresh_families_lifecycle_idx","oauth_refresh_families_user_status_idx","oauth_refresh_families_client_idx","oauth_refresh_families_cleanup_idx","oauth_refresh_tokens_expiry_idx","oauth_refresh_rotations_replay_expiry_idx","oauth_security_events_retention_idx","oauth_rate_limit_buckets_expiry_idx"],C={oauth_clients:"oauth_clients_legacy_raw",oauth_codes:"oauth_codes_legacy_raw",oauth_tokens:"oauth_tokens_legacy_raw"},u="strftime('%Y-%m-%dT%H:%M:%fZ','now')";async function p(e,t,n=!1){try{await e.execute(t)}catch(s){let a=s.code;if(!n||a!=="SQL_PARSE_ERROR")throw s}}var M=[`CREATE TABLE IF NOT EXISTS oauth_store_metadata (
|
|
11
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
12
|
+
store_id TEXT NOT NULL UNIQUE,
|
|
13
|
+
schema_version INTEGER NOT NULL CHECK (schema_version > 0),
|
|
14
|
+
authority_epoch INTEGER NOT NULL CHECK (authority_epoch > 0),
|
|
15
|
+
authority_state TEXT NOT NULL CHECK (authority_state IN ('ready','authoritative','retired')),
|
|
16
|
+
updated_at TEXT NOT NULL DEFAULT (${u})
|
|
17
|
+
) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_clients (
|
|
18
|
+
client_id TEXT PRIMARY KEY,
|
|
19
|
+
client_name TEXT NOT NULL,
|
|
20
|
+
client_type TEXT NOT NULL CHECK (client_type = 'public'),
|
|
21
|
+
token_endpoint_auth_method TEXT NOT NULL CHECK (token_endpoint_auth_method = 'none'),
|
|
22
|
+
status TEXT NOT NULL CHECK (status IN ('active','disabled','expired')),
|
|
23
|
+
created_at TEXT NOT NULL DEFAULT (${u}),
|
|
24
|
+
last_used_at TEXT,
|
|
25
|
+
expires_at TEXT
|
|
26
|
+
) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_client_redirect_uris (
|
|
27
|
+
client_id TEXT NOT NULL REFERENCES oauth_clients(client_id) ON DELETE CASCADE,
|
|
28
|
+
redirect_uri TEXT NOT NULL,
|
|
29
|
+
redirect_kind TEXT NOT NULL CHECK (redirect_kind IN ('https','loopback','private_scheme')),
|
|
30
|
+
PRIMARY KEY (client_id, redirect_uri)
|
|
31
|
+
) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_codes (
|
|
32
|
+
code_digest BLOB PRIMARY KEY,
|
|
33
|
+
lookup_key_id TEXT NOT NULL,
|
|
34
|
+
client_id TEXT NOT NULL REFERENCES oauth_clients(client_id) ON DELETE RESTRICT,
|
|
35
|
+
redirect_uri TEXT NOT NULL,
|
|
36
|
+
code_challenge TEXT NOT NULL,
|
|
37
|
+
challenge_method TEXT NOT NULL CHECK (challenge_method = 'S256'),
|
|
38
|
+
user_id TEXT NOT NULL,
|
|
39
|
+
scope TEXT NOT NULL,
|
|
40
|
+
resource TEXT,
|
|
41
|
+
issued_at TEXT NOT NULL DEFAULT (${u}),
|
|
42
|
+
expires_at TEXT NOT NULL
|
|
43
|
+
) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_code_exchanges (
|
|
44
|
+
code_digest BLOB PRIMARY KEY,
|
|
45
|
+
request_fingerprint BLOB NOT NULL UNIQUE,
|
|
46
|
+
client_id TEXT NOT NULL,
|
|
47
|
+
family_id TEXT NOT NULL UNIQUE,
|
|
48
|
+
grant_scope TEXT NOT NULL,
|
|
49
|
+
grant_resource TEXT,
|
|
50
|
+
scope TEXT NOT NULL,
|
|
51
|
+
resource TEXT,
|
|
52
|
+
sealed_refresh BLOB NOT NULL,
|
|
53
|
+
sealed_nonce BLOB NOT NULL,
|
|
54
|
+
sealed_tag BLOB NOT NULL,
|
|
55
|
+
replay_key_id TEXT NOT NULL,
|
|
56
|
+
completed_at TEXT NOT NULL DEFAULT (${u}),
|
|
57
|
+
replay_expires_at TEXT NOT NULL
|
|
58
|
+
) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_refresh_families (
|
|
59
|
+
family_id TEXT PRIMARY KEY,
|
|
60
|
+
user_id TEXT NOT NULL,
|
|
61
|
+
client_id TEXT NOT NULL REFERENCES oauth_clients(client_id) ON DELETE RESTRICT,
|
|
62
|
+
issuer TEXT NOT NULL,
|
|
63
|
+
scope TEXT NOT NULL,
|
|
64
|
+
resource TEXT,
|
|
65
|
+
status TEXT NOT NULL CHECK (status IN ('active','revoked','compromised','expired')),
|
|
66
|
+
current_generation INTEGER NOT NULL CHECK (current_generation > 0),
|
|
67
|
+
created_at TEXT NOT NULL DEFAULT (${u}),
|
|
68
|
+
expires_at TEXT NOT NULL,
|
|
69
|
+
revoked_at TEXT,
|
|
70
|
+
compromised_at TEXT,
|
|
71
|
+
UNIQUE (family_id, client_id),
|
|
72
|
+
FOREIGN KEY (family_id, current_generation)
|
|
73
|
+
REFERENCES oauth_refresh_tokens(family_id, generation)
|
|
74
|
+
DEFERRABLE INITIALLY DEFERRED
|
|
75
|
+
) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_refresh_tokens (
|
|
76
|
+
family_id TEXT NOT NULL REFERENCES oauth_refresh_families(family_id) ON DELETE CASCADE,
|
|
77
|
+
generation INTEGER NOT NULL CHECK (generation > 0),
|
|
78
|
+
token_digest BLOB NOT NULL UNIQUE,
|
|
79
|
+
lookup_key_id TEXT NOT NULL,
|
|
80
|
+
token_prefix TEXT NOT NULL,
|
|
81
|
+
predecessor_generation INTEGER,
|
|
82
|
+
issued_at TEXT NOT NULL DEFAULT (${u}),
|
|
83
|
+
expires_at TEXT NOT NULL,
|
|
84
|
+
used_at TEXT,
|
|
85
|
+
revoked_at TEXT,
|
|
86
|
+
PRIMARY KEY (family_id, generation),
|
|
87
|
+
CHECK (predecessor_generation IS NULL OR (predecessor_generation > 0 AND predecessor_generation < generation))
|
|
88
|
+
) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_refresh_rotations (
|
|
89
|
+
family_id TEXT NOT NULL REFERENCES oauth_refresh_families(family_id) ON DELETE CASCADE,
|
|
90
|
+
predecessor_generation INTEGER NOT NULL,
|
|
91
|
+
request_fingerprint BLOB NOT NULL,
|
|
92
|
+
successor_generation INTEGER NOT NULL,
|
|
93
|
+
sealed_successor BLOB NOT NULL,
|
|
94
|
+
sealed_nonce BLOB NOT NULL,
|
|
95
|
+
sealed_tag BLOB NOT NULL,
|
|
96
|
+
replay_key_id TEXT NOT NULL,
|
|
97
|
+
rotated_at TEXT NOT NULL DEFAULT (${u}),
|
|
98
|
+
replay_expires_at TEXT NOT NULL,
|
|
99
|
+
PRIMARY KEY (family_id, predecessor_generation),
|
|
100
|
+
UNIQUE (family_id, successor_generation),
|
|
101
|
+
CHECK (successor_generation = predecessor_generation + 1)
|
|
102
|
+
) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_security_events (
|
|
103
|
+
event_id TEXT PRIMARY KEY,
|
|
104
|
+
family_id TEXT NOT NULL,
|
|
105
|
+
event_type TEXT NOT NULL CHECK (event_type IN ('reuse','binding_mismatch','manual_revoke','expiry')),
|
|
106
|
+
reason_code TEXT NOT NULL,
|
|
107
|
+
occurred_at TEXT NOT NULL DEFAULT (${u}),
|
|
108
|
+
retain_until TEXT NOT NULL
|
|
109
|
+
) STRICT`,"CREATE INDEX IF NOT EXISTS oauth_clients_inactivity_idx ON oauth_clients(status, last_used_at, client_id)","CREATE INDEX IF NOT EXISTS oauth_codes_expiry_idx ON oauth_codes(expires_at, code_digest)","CREATE INDEX IF NOT EXISTS oauth_code_exchanges_replay_expiry_idx ON oauth_code_exchanges(replay_expires_at, code_digest)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_lifecycle_idx ON oauth_refresh_families(status, expires_at, family_id)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_user_status_idx ON oauth_refresh_families(user_id, status)","CREATE INDEX IF NOT EXISTS oauth_refresh_tokens_expiry_idx ON oauth_refresh_tokens(expires_at, family_id, generation)","CREATE INDEX IF NOT EXISTS oauth_refresh_rotations_replay_expiry_idx ON oauth_refresh_rotations(replay_expires_at, family_id, predecessor_generation)","CREATE INDEX IF NOT EXISTS oauth_security_events_retention_idx ON oauth_security_events(retain_until, event_id)"],U=["CREATE INDEX IF NOT EXISTS oauth_clients_cleanup_idx ON oauth_clients(COALESCE(last_used_at,created_at), client_id)","CREATE INDEX IF NOT EXISTS oauth_codes_client_idx ON oauth_codes(client_id, code_digest)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_client_idx ON oauth_refresh_families(client_id, family_id)",`CREATE INDEX IF NOT EXISTS oauth_refresh_families_cleanup_idx
|
|
110
|
+
ON oauth_refresh_families(COALESCE(compromised_at,revoked_at,expires_at), family_id)
|
|
111
|
+
WHERE status!='active'`],g=[`CREATE TABLE IF NOT EXISTS oauth_rate_limit_buckets (
|
|
112
|
+
scope TEXT NOT NULL CHECK (length(scope) BETWEEN 1 AND 80),
|
|
113
|
+
key_digest BLOB NOT NULL CHECK (typeof(key_digest) = 'blob' AND length(key_digest) = 32),
|
|
114
|
+
window_start INTEGER NOT NULL CHECK (window_start >= 0),
|
|
115
|
+
window_seconds INTEGER NOT NULL CHECK (window_seconds BETWEEN 1 AND 604800),
|
|
116
|
+
count INTEGER NOT NULL CHECK (count >= 1),
|
|
117
|
+
expires_at INTEGER NOT NULL CHECK (expires_at = window_start + window_seconds),
|
|
118
|
+
updated_at TEXT NOT NULL DEFAULT (${u}),
|
|
119
|
+
PRIMARY KEY (scope, key_digest, window_start, window_seconds)
|
|
120
|
+
) STRICT`,`CREATE INDEX IF NOT EXISTS oauth_rate_limit_buckets_expiry_idx
|
|
121
|
+
ON oauth_rate_limit_buckets(expires_at, scope, key_digest, window_start, window_seconds)`],L=[...M,...U,...g];async function B(e){if(await p(e,"PRAGMA foreign_keys = ON"),await p(e,"PRAGMA busy_timeout = 5000",!0),(await e.execute("SELECT name FROM pragma_table_info('oauth_codes')")).rows.some(r=>String(r.name)==="code"))throw new Error("Legacy raw OAuth tables require the explicit maintenance-mode coexistence migration");let s=(await e.execute("SELECT 1 present FROM sqlite_master WHERE type='table' AND name='oauth_store_metadata'")).rows.length>0?await e.execute("SELECT schema_version FROM oauth_store_metadata WHERE id=1"):void 0,a=s?.rows[0]?.schema_version==null?void 0:Number(s.rows[0].schema_version);if(a!==void 0&&(!Number.isSafeInteger(a)||a<1||a>3))throw new Error("OAuth store schema version cannot be migrated by this runtime");let o=a===void 0?L:a===1?[...U,...g]:a===2?g:[];for(let r of o)await e.execute(r);if(a!==void 0&&a<3&&(await e.execute({sql:`UPDATE oauth_store_metadata SET schema_version=?,updated_at=${u} WHERE id=1 AND schema_version=?`,args:[3,a]})).rowsAffected!==1)throw new Error("OAuth store schema version changed during migration");await p(e,"PRAGMA optimize",!0)}async function Z(e){await p(e,"PRAGMA foreign_keys = ON"),await p(e,"PRAGMA busy_timeout = 5000",!0);let t=await e.execute("SELECT name FROM pragma_table_info('oauth_codes')");if(!t.rows.some(o=>String(o.name)==="code")){let o=t.rows.some(r=>String(r.name)==="code_digest");return await B(e),o?"current":"created"}if((await e.execute({sql:"SELECT name FROM sqlite_master WHERE type='table' AND name IN (?,?,?)",args:Object.values(C)})).rows.length>0)throw new Error("Legacy OAuth archive names already exist; refusing ambiguous migration");let a=await e.transaction("write");try{for(let[o,r]of Object.entries(C))(await a.execute({sql:"SELECT 1 present FROM sqlite_master WHERE type='table' AND name=?",args:[o]})).rows.length>0&&await a.execute({sql:`ALTER TABLE ${o} RENAME TO ${r}`,args:[]});for(let o of L)await a.execute({sql:o,args:[]});await a.commit()}finally{a.close()}return"archived_legacy"}var P={oauth_store_metadata:["id","store_id","schema_version","authority_epoch","authority_state","updated_at"],oauth_clients:["client_id","client_name","client_type","token_endpoint_auth_method","status","created_at","last_used_at","expires_at"],oauth_client_redirect_uris:["client_id","redirect_uri","redirect_kind"],oauth_codes:["code_digest","lookup_key_id","client_id","redirect_uri","code_challenge","challenge_method","user_id","scope","resource","issued_at","expires_at"],oauth_code_exchanges:["code_digest","request_fingerprint","client_id","family_id","grant_scope","grant_resource","scope","resource","sealed_refresh","sealed_nonce","sealed_tag","replay_key_id","completed_at","replay_expires_at"],oauth_refresh_families:["family_id","user_id","client_id","issuer","scope","resource","status","current_generation","created_at","expires_at","revoked_at","compromised_at"],oauth_refresh_tokens:["family_id","generation","token_digest","lookup_key_id","token_prefix","predecessor_generation","issued_at","expires_at","used_at","revoked_at"],oauth_refresh_rotations:["family_id","predecessor_generation","request_fingerprint","successor_generation","sealed_successor","sealed_nonce","sealed_tag","replay_key_id","rotated_at","replay_expires_at"],oauth_security_events:["event_id","family_id","event_type","reason_code","occurred_at","retain_until"],oauth_rate_limit_buckets:["scope","key_digest","window_start","window_seconds","count","expires_at","updated_at"]},K={oauth_clients_inactivity_idx:["status","last_used_at","client_id"],oauth_clients_cleanup_idx:[null,"client_id"],oauth_codes_expiry_idx:["expires_at","code_digest"],oauth_codes_client_idx:["client_id","code_digest"],oauth_code_exchanges_replay_expiry_idx:["replay_expires_at","code_digest"],oauth_refresh_families_lifecycle_idx:["status","expires_at","family_id"],oauth_refresh_families_user_status_idx:["user_id","status"],oauth_refresh_families_client_idx:["client_id","family_id"],oauth_refresh_families_cleanup_idx:[null,"family_id"],oauth_refresh_tokens_expiry_idx:["expires_at","family_id","generation"],oauth_refresh_rotations_replay_expiry_idx:["replay_expires_at","family_id","predecessor_generation"],oauth_security_events_retention_idx:["retain_until","event_id"],oauth_rate_limit_buckets_expiry_idx:["expires_at","scope","key_digest","window_start","window_seconds"]};async function ee(e){let t=await e.execute({sql:`SELECT name FROM sqlite_master WHERE type = 'table' AND name IN (${m.map(()=>"?").join(",")})`,args:[...m]}),n=await e.execute({sql:`SELECT name FROM sqlite_master WHERE type = 'index' AND name IN (${h.map(()=>"?").join(",")})`,args:[...h]}),s=new Set(t.rows.map(i=>String(i.name))),a=new Set(n.rows.map(i=>String(i.name))),o=await e.execute("PRAGMA foreign_keys"),r=[],d=i=>i.replace(/\bIF\s+NOT\s+EXISTS\b/gi,"").replace(/\s+/g," ").trim().toLowerCase();for(let i of m){if(!s.has(i))continue;let _=(await e.execute(`PRAGMA table_info('${i}')`)).rows.map(T=>String(T.name));JSON.stringify(_)!==JSON.stringify(P[i])&&r.push(`${i}:columns`);let c=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='table' AND name=?",args:[i]}),l=String(c.rows[0]?.sql??""),N=L.find(T=>d(T).startsWith(`create table ${i} `));(!N||d(l)!==d(N))&&r.push(`${i}:definition`)}for(let i of h){if(!a.has(i))continue;let _=(await e.execute(`PRAGMA index_info('${i}')`)).rows.map(T=>T.name==null?null:String(T.name));JSON.stringify(_)!==JSON.stringify(K[i])&&r.push(`${i}:columns`);let c=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='index' AND name=?",args:[i]}),l=String(c.rows[0]?.sql??""),N=L.find(T=>d(T).startsWith(`create index ${i} `));(!N||d(l)!==d(N))&&r.push(`${i}:definition`)}return{ok:m.every(i=>s.has(i))&&h.every(i=>a.has(i))&&Number(o.rows[0]?.foreign_keys??0)===1&&r.length===0,missingTables:m.filter(i=>!s.has(i)),missingIndexes:h.filter(i=>!a.has(i)),foreignKeysEnabled:Number(o.rows[0]?.foreign_keys??0)===1,problems:r}}export{j as a,z as b,Z as c,ee as d};
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import{e as ut,f as ir,g as ar,h as lr,i as ur}from"./chunk-6BD75VKS.js";import{a as _r}from"./chunk-U4WIJZCX.js";import{J as Fe,c as Lt,d as Ee,e as re,f as Ht,k as Vt,l as Kt,s as Qt}from"./chunk-HVQZRQRJ.js";import{b as rr,c as or,e as dt,g as ct,m as le,n as pt,o as ue,p as de,q as We}from"./chunk-JHT6A4U6.js";import{a as ae,b as Ie,c as S,e as fr}from"./chunk-63VWBMYR.js";import{c as nr,d as sr,g as dr,k as cr}from"./chunk-5LYINW7Z.js";import{b as se,d as ie,e as V,f as K,g as mr,j as X,p as gr}from"./chunk-7SR7MEU5.js";import{d as Ue,e as $e,f as Je,g as Se,h as oe,k as Ae,m as ne,o as Ge,r as Be,s as T}from"./chunk-HUNSEGUN.js";import{b as Ft,c as Ut,d as $t}from"./chunk-B4ZKPLSP.js";import{a as Zt,b as er,c as tr}from"./chunk-VVSHZV5S.js";import{b as lt,d as Jt,e as Gt,g as U,h as z,j as Bt,m as Wt,o as zt}from"./chunk-C7MGJUTU.js";import{b as Xt,c as Yt}from"./chunk-4ZVO6GX4.js";import{a as m}from"./chunk-WNUXMPVX.js";import{b as pr}from"./chunk-B3JRL45T.js";import{c as O,d as b,f as we}from"./chunk-HNNYXMSI.js";import{randomUUID as jo}from"crypto";async function Pn(e,t,r){let o=jo();return await m().execute({sql:"INSERT INTO jobs (id, user_id, query, options, status, started_at) VALUES (?, ?, ?, ?, 'running', datetime('now'))",args:[o,e,t,JSON.stringify(r)]}),o}async function On(e,t,r,o){let n=await m().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,t,r,JSON.stringify(o)]}),i=await S(e,t);if(!i)throw new Error(`getOrCreateRunningJob: row missing immediately after insert/lookup for ${e}`);return{job:i,created:n.rowsAffected===1}}async function Tn(e,t,r){await m().execute({sql:`UPDATE jobs
|
|
4
|
+
SET status = 'running', started_at = COALESCE(started_at, datetime('now'))
|
|
5
|
+
WHERE id = ? AND status = 'pending'
|
|
6
|
+
AND json_extract(options, '$.executionOwner') = ?
|
|
7
|
+
AND json_extract(options, '$.jobKind') = ?`,args:[e,t,r]});let o=await S(e);if(!(!o||o.options.executionOwner!==t||o.options.jobKind!==r))return o}async function Cn(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await m().execute({sql:`SELECT * FROM jobs
|
|
8
|
+
WHERE status = 'pending'
|
|
9
|
+
AND json_extract(options, '$.executionOwner') = 'inngest'
|
|
10
|
+
AND json_extract(options, '$.jobKind') = 'extract_url'
|
|
11
|
+
AND json_extract(options, '$.billingDebitKey') IS NOT NULL
|
|
12
|
+
AND created_at <= datetime('now', '-30 seconds')
|
|
13
|
+
AND datetime(COALESCE(json_extract(options, '$.extractUrlLastDispatchAt'), '1970-01-01')) <= datetime('now', '-30 seconds')
|
|
14
|
+
ORDER BY created_at
|
|
15
|
+
LIMIT ?`,args:[t]})).rows.map(o=>Ie(ae(o)))}async function jn(e,t){return(await m().execute({sql:`UPDATE jobs
|
|
16
|
+
SET options = json_set(options,
|
|
17
|
+
'$.extractUrlDispatchAttempts', COALESCE(json_extract(options, '$.extractUrlDispatchAttempts'), 0) + 1,
|
|
18
|
+
'$.extractUrlLastDispatchAt', ?,
|
|
19
|
+
'$.extractUrlLastDispatchError', ?)
|
|
20
|
+
WHERE id = ? AND status = 'pending'
|
|
21
|
+
AND json_extract(options, '$.executionOwner') = 'inngest'
|
|
22
|
+
AND json_extract(options, '$.jobKind') = 'extract_url'`,args:[new Date().toISOString(),t??null,e]})).rowsAffected===1}async function qn(e){return(await m().execute({sql:"SELECT * FROM jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[e]})).rows.map(r=>Ie(ae(r)))}async function yr(){let e=m(),t=await e.execute(`
|
|
23
|
+
SELECT * FROM jobs
|
|
24
|
+
WHERE status = 'pending'
|
|
25
|
+
AND COALESCE(json_extract(options, '$.executionOwner'), 'cron') NOT IN ('direct', 'inngest')
|
|
26
|
+
AND json_extract(options,'$.queueExecutionProtocol') IS NOT 0
|
|
27
|
+
ORDER BY created_at
|
|
28
|
+
LIMIT 1
|
|
29
|
+
`),r=t.rows[0]?ae(t.rows[0]):void 0;return r?(await e.execute({sql:"UPDATE jobs SET status = 'running', started_at = datetime('now') WHERE id = ? AND status = 'pending'",args:[r.id]})).rowsAffected===0?void 0:{...r,status:"running"}:void 0}async function Mn(e,t){await m().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now') WHERE id = ? AND ${ct}`,args:[JSON.stringify(t),e]})}async function Ln(e,t,r){await m().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now') WHERE id = ? AND ${ct}`,args:[t,Jt(r),e]})}async function $n(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await m().execute({sql:`SELECT * FROM jobs
|
|
30
|
+
WHERE status IN ('done', 'failed', 'cancelled')
|
|
31
|
+
AND json_extract(options, '$.executionOwner') IN ('direct', 'inngest')
|
|
32
|
+
AND json_extract(options, '$.billingDebitKey') IS NOT NULL
|
|
33
|
+
AND CAST(json_extract(options, '$.billingHoldMc') AS INTEGER) > 0
|
|
34
|
+
AND json_extract(options, '$.billingSettledAt') IS NULL
|
|
35
|
+
ORDER BY completed_at DESC
|
|
36
|
+
LIMIT ?`,args:[t]})).rows.map(o=>Ie(ae(o)))}async function br(e,t=25,r="1"){if(!/^[a-z_]+$/.test(e)||!r.trim()||r.length>8192)throw Error("Invalid intent selection");return(await m().execute({sql:`SELECT r.id,r.user_id,r.job_id FROM operation_runs r
|
|
37
|
+
JOIN operation_executions e ON e.run_id=r.id
|
|
38
|
+
WHERE r.tool=? AND r.status='running' AND e.phase='claimed'
|
|
39
|
+
AND e.expires_at_ms <= CAST(strftime('%s','now') AS INTEGER)*1000
|
|
40
|
+
AND json_extract(r.normalized_flags_json,'$._storeGateRequired') IS 1 AND (${r})
|
|
41
|
+
ORDER BY r.started_at LIMIT ?`,args:[e,Math.max(1,Math.min(100,Math.floor(t)))]})).rows.map(n=>({runId:String(n.id),userId:Number(n.user_id),jobId:String(n.job_id)}))}import{request as Fo}from"https";import{HttpsProxyAgent as Uo}from"https-proxy-agent";var ze={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 Wn=ze.source,zn=ze.retrievedAt,Mo=new Set(ze.domains);function Re(e){let t=new URL(e).hostname.toLowerCase().replace(/\.$/,"");for(let r of Mo)if(t===r||t.endsWith(`.${r}`))return"premium";return"standard"}function Ne(e){for(let t of["providerProduct","billingTier","billableEvent","unitType","source","policyVersion","effectiveAt"])if(!e[t]?.trim())throw new Error(`Provider rate ${t} is required`);if(!Number.isSafeInteger(e.numeratorUsdNanos)||e.numeratorUsdNanos<0)throw new Error("Provider rate numerator must be a non-negative safe integer");if(!Number.isSafeInteger(e.denominatorUnits)||e.denominatorUnits<1)throw new Error("Provider rate denominator must be a positive safe integer");if(Number.isNaN(Date.parse(e.effectiveAt)))throw new Error("Provider rate effectiveAt must be a date");return e}function Ve(e,t){if(Ne(e),!Number.isSafeInteger(t)||t<0)throw new Error("Billable units must be a non-negative safe integer");let r=BigInt(e.numeratorUsdNanos)*BigInt(t),o=BigInt(e.denominatorUnits),n=(r*2n+o)/(o*2n);if(n>BigInt(Number.MAX_SAFE_INTEGER))throw new Error("Provider amount exceeds safe integer range");return Number(n)}function Lo(){return Ne({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 hr(e=process.env){let t=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_CONTRACT_USD_PER_1000?.trim(),r=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_RATE_SOURCE?.trim(),o=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_RATE_POLICY_VERSION?.trim(),n=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_RATE_EFFECTIVE_AT?.trim();if(!t&&!r&&!o&&!n)return Lo();if(!t||!r||!o||!n)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP contract rate requires amount, source, policy version, and effective date");let i=Number(t);if(!Number.isFinite(i)||i<0)throw new Error("Invalid \u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP contract amount");return Ne({providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_api",billingTier:"payg",billableEvent:"successful_delivery",unitType:"request",numeratorUsdNanos:Math.round(i*1e9),denominatorUnits:1e3,source:r,policyVersion:o,effectiveAt:n})}function Ho(e){return Ne({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 Xn(e){return Ho(Re(e))}function vr(){return Ne({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 $o="https://api.\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061.com/request",Jo=8e3,Go="brd.superproxy.io",Bo="44445",Wo=10*1024*1024;async function zo(e,t){let r=new URL(`http://${t.host}:${t.port}`);r.username=t.username,r.password=t.password;let o=new Uo(r);try{return await new Promise((n,i)=>{let s=Fo(e,{agent:o,headers:{"x-unblock-data-format":"parsed"},rejectUnauthorized:!1,signal:t.signal},a=>{let l=[],u=0;a.on("data",d=>{let c=Buffer.isBuffer(d)?d:Buffer.from(d);if(u+=c.length,u>Wo){s.destroy(new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP response exceeded the maximum size"));return}l.push(c)}),a.on("end",()=>n({ok:(a.statusCode??500)>=200&&(a.statusCode??500)<300,status:a.statusCode??500,rawText:Buffer.concat(l).toString("utf8"),providerRequestId:typeof a.headers["x-response-id"]=="string"?a.headers["x-response-id"]:typeof a.headers["x-request-id"]=="string"?a.headers["x-request-id"]:null}))});s.on("error",()=>i(new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 native SERP request failed"))),s.end()})}finally{o.destroy()}}function Pr(e){let t=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_USERNAME?.trim(),r=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PASSWORD?.trim();if(t||r){if(!t||!r)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP requires both \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_USERNAME and \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PASSWORD");if(/[\u0000-\u001f\u007f]/.test(t+r))throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP native credentials contain invalid control characters");return{method:"native",username:t,password:r}}let o=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_API_KEY?.trim(),n=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_ZONE?.trim();if(!o||!n)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP requires \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_API_KEY and \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_ZONE, or complete native SERP proxy credentials; \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_API_KEY is not used for SERP");if(/\s|[\u0000-\u001f\u007f]/.test(o)||!/^[a-zA-Z0-9_-]+$/.test(n))throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API key or zone has an invalid format");return{method:"rest",apiKey:o,zone:n}}function Qe(e=process.env){try{return Pr(e),!0}catch{return!1}}function _(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)?e:null}function q(e){return Array.isArray(e)?e:[]}function Y(e){return typeof e=="string"&&e.trim()?e.trim():null}function N(e){return typeof e=="number"&&Number.isFinite(e)?e:typeof e=="string"&&e.trim()&&Number.isFinite(Number(e))?Number(e):null}function y(e,t){for(let r of t){let o=Y(e[r]);if(o)return o}return null}function pe(e){try{return new URL(e).hostname.replace(/^www\./,"")}catch{return""}}function Or(e){return{rawUrl:e,resolvedUrl:e,linkType:"plain",resolutionStatus:"not_needed"}}function Vo(e){let t=e;if(typeof t=="string")try{t=JSON.parse(t)}catch{throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API returned invalid JSON")}let r=_(t);if(!r)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API returned an invalid payload");if(typeof r.body=="string")try{let n=JSON.parse(r.body);if(_(n))return _(n)}catch{}let o=_(r.body);return o?_(o.result)??_(o.data)??o:_(r.result)??_(r.data)??r}function me(e,t){for(let o of t){let n=q(e[o]);if(n.length)return n}let r=_(e.results);if(r)for(let o of t){let n=q(r[o]);if(n.length)return n}return[]}function ce(e,t){let r=[e,_(e.results)].filter(o=>!!o);for(let o of r)for(let n of t)if(Object.prototype.hasOwnProperty.call(o,n))return{observed:!0,rawShapeValid:Array.isArray(o[n]),rawCount:q(o[n]).length};return{observed:!1,rawShapeValid:!1,rawCount:0}}function mt(e,t){let r=[e,_(e.results)].filter(o=>!!o);for(let o of r)for(let n of t){if(!Object.prototype.hasOwnProperty.call(o,n))continue;let i=_(o[n]);return{observed:!0,rawShapeValid:i!==null,rawCount:i&&Object.keys(i).length>0?1:0}}return{observed:!1,rawShapeValid:!1,rawCount:0}}function wr(e){return me(e,["organic","organic_results","organicResults"]).flatMap((t,r)=>{let o=_(t);if(!o)return[];let n=y(o,["link","url","href"]),i=y(o,["title","name"]);if(!n||!i)return[];let s=_(o.rating)??_(o.inline_rating);return[{position:Math.max(1,Math.trunc(N(o.global_rank)??N(o.rank)??N(o.position)??r+1)),title:i,url:n,...Or(n),domain:pe(n),cite:y(o,["display_link","displayLink","cite"]),snippet:y(o,["description","snippet","text"]),isRedditStyle:pe(n)==="reddit.com",inlineRating:s?{value:String(s.value??s.rating??""),count:String(s.count??s.reviews??"")}:null}]}).sort((t,r)=>t.position-r.position)}function Er(e){return me(e,["snack_pack","local","local_results","local_pack","localPack"]).flatMap((t,r)=>{let o=_(t);if(!o)return[];let n=y(o,["title","name"]);if(!n)return[];let i=q(o.extensions??o.metadata).map(Y).filter(s=>!!s);return[{position:Math.max(1,Math.trunc(N(o.global_rank)??N(o.rank)??N(o.position)??r+1)),name:n,cid:y(o,["cid"]),rating:y(o,["rating"])??(N(o.rating)!=null?String(N(o.rating)):null),reviewCount:y(o,["reviews_cnt","reviews","review_count","reviewCount"])??(N(o.reviews_cnt)!=null?String(N(o.reviews_cnt)):N(o.reviews)!=null?String(N(o.reviews)):null),metadata:i,websiteUrl:y(o,["website","website_url","link"]),directionsUrl:y(o,["directions","directions_url"])}]})}function Tr(e){let t=_(e);return q(t?.citations??t?.sources??t?.references).flatMap(r=>{let o=_(r);if(!o)return[];let n=y(o,["link","url","href"]);return n?[{text:y(o,["title","text","name"])??pe(n),href:n,...Or(n)}]:[]})}function Ye(e,t=0){if(t>4)return[];if(Array.isArray(e))return e.flatMap(i=>Ye(i,t+1));let r=_(e);if(!r)return[];let o=y(r,["snippet","text","answer"]),n=Ye(r.texts??r.list??r.items,t+1);return[...o?[o]:[],...n]}function Sr(e,t){if(!t)return{detected:!1,text:null,citations:[]};let r=_(e.ai_overview)??_(e.aiOverview)??_(e.overview);if(!r)return{detected:!1,text:null,citations:[]};let o=y(r,["text","answer","description"])??(Ye(r.texts).join(`
|
|
42
|
+
|
|
43
|
+
`).slice(0,5e4)||null),n=Tr(r);return{detected:!!(o||n.length),text:o,citations:n}}function Ar(e,t){if(!t)return{detected:!1,text:null,citations:[]};let r=_(e.ai_mode)??_(e.aiMode);if(!r)return{detected:!1,text:null,citations:[]};let o=y(r,["text","answer","description"])??(Ye(r.texts).join(`
|
|
44
|
+
|
|
45
|
+
`).slice(0,5e4)||null),n=Tr(r);return{detected:!!(o||n.length),text:o,citations:n}}function Ir(e,t){return t?[...me(e,["videos","video_results"]),...me(e,["short_videos","shorts"])].flatMap(r=>{let o=_(r);if(!o)return[];let n=y(o,["link","url"]),i=y(o,["title","name"]);return!n||!i?[]:[{type:"video",title:i,channel:y(o,["channel","source"])??"",platform:pe(n),duration:y(o,["duration"])??"",url:n}]}):[]}function Rr(e,t){if(!t)return[];let r=_(e.forums);return[...me(e,["discussions","forums","forum_results"]),...q(r?.items)].flatMap(o=>{let n=_(o);if(!n)return[];let i=y(n,["link","url"]),s=y(n,["title","name"]);return!i||!s?[]:[{title:s,source:y(n,["source"])??pe(i),url:i}]})}function Nr(e,t){return t?me(e,["what_people_are_saying","whatPeopleSaying"]).flatMap(r=>{let o=_(r);if(!o)return[];let n=y(o,["link","url"]),i=y(o,["title","name"]);if(!n||!i)return[];let s=y(o,["platform","source"])??pe(n),a=s.toLowerCase();return[{type:a.includes("reddit")?"reddit":a.includes("facebook")?"facebook":a.includes("instagram")?"instagram":a.includes("tiktok")?"tiktok":a.includes("youtube")?"youtube":a.includes("news")?"news":"unknown",title:i,url:n,source:s,platform:s,popularComment:y(o,["comment","popular_comment"]),engagement:y(o,["engagement"])??"",date:y(o,["date"])??"",duration:y(o,["duration"]),authorNote:y(o,["author_note"])}]}):[]}var Ko={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 Ke(e,t){for(let r of[e,_(e.results)])if(r){for(let o of t)if(Object.prototype.hasOwnProperty.call(r,o))return{observed:!0,value:r[o]}}return{observed:!1,value:null}}function Xe(e,t,r){return e?t==null||Array.isArray(t)&&t.length===0?"observed_absent":Array.isArray(t)?r>0?"observed_present":"incomplete":_(t)?r>0?"observed_present":Object.keys(_(t)).length===0?"observed_absent":"incomplete":"incomplete":"unknown"}function Xo(e){let t=y(e,["answer","snippet","text"]);return t||q(e.answers).flatMap((o,n)=>{let i=_(o),s=_(i?.value),a=i?.type==="answer"?Y(s?.text):null;return a?[{prose:a,rank:N(i?.rank)??n+1,index:n}]:[]}).sort((o,n)=>o.rank-n.rank||o.index-n.index).map(o=>o.prose).join(`
|
|
46
|
+
|
|
47
|
+
`)||null}function Yo(e,t){let r={},o=[["localPack",["snack_pack","local","local_results","local_pack","localPack"],t.localPack],["forums",["discussions","forums","forum_results"],t.forums],["videos",["videos","video_results","short_videos","shorts"],t.videos],["aiOverview",["ai_overview","aiOverview","overview"],t.aiOverview],["whatPeopleSaying",["what_people_are_saying","whatPeopleSaying"],t.whatPeopleSaying],["entityIds",["knowledge","knowledge_graph","knowledgeGraph"],t.entityIds]];for(let[l,u,d]of o){let c=Ke(e,u);r[l]=Xe(c.observed,c.value,d)}let n=Ke(e,["ai_mode","aiMode"]);r.aiMode=Xe(n.observed,n.value,t.aiMode);let i=Ke(e,["people_also_ask","peopleAlsoAsk","related_questions","paa"]),s=q(i.value).slice(0,30).flatMap(l=>{let u=_(l);if(!u)return[];let d=y(u,["question","title"]);if(!d)return[];let c=Y(u.question)?Y(u.title)?.slice(0,1e3):null,p=Y(u.answer_source)?.slice(0,1e3),h=y(u,["answer_display_link","display_link"])?.slice(0,2e3);return[{question:d.slice(0,1e3),answer:Xo(u)?.slice(0,1e4)??null,url:y(u,["answer_link","link","url"])??null,...c?{sourceTitle:c}:{},...p?{sourceName:p}:{},...h?{displayLink:h}:{}}]});r.paaPreview=Xe(i.observed,i.value,s.length);let a=[];for(let[l,u]of Object.entries(Ko)){let d=Ke(e,u);if(!d.observed)continue;let c=_(d.value),h=(Array.isArray(d.value)?d.value:c&&(Array.isArray(c.items)||Array.isArray(c.posts))?[...q(c.items),...q(c.posts)]:[d.value]).slice(0,20).flatMap(f=>{let w=_(f);if(!w)return[];let k=y(w,["title","name","heading"]),H=y(w,["link","url","website"]),J=y(w,["description","snippet","text","summary","story"]);return!k&&!H&&!J?[]:[{title:k?.slice(0,1e3)??null,url:H,description:J?.slice(0,1e4)??null,position:N(w.global_rank)??N(w.rank)??N(w.position)??null}]});r[l]=Xe(d.observed,d.value,h.length);let v=Object.fromEntries(Object.entries(c??{}).slice(0,30).flatMap(([f,w])=>/^[a-zA-Z0-9_]{1,80}$/.test(f)&&(w===null||["string","number","boolean"].includes(typeof w))?[[f,typeof w=="string"?w.slice(0,2e3):w]]:[]));a.push({name:l,attributes:v,items:h})}return{status:r,paaPreview:s,additional:a}}function kr(e,t){let r=new Set,o=new Set(t.map(s=>s.cid).filter(s=>!!s)),n=new Set,i=(s,a=0)=>{if(a>6||s==null)return;if(Array.isArray(s)){for(let u of s)i(u,a+1);return}let l=_(s);if(l)for(let[u,d]of Object.entries(l)){let c=u.toLowerCase().replace(/[^a-z]/g,""),p=Y(d);p&&(c==="kgid"||c==="kgmid"||c==="mid")?r.add(p):p&&c==="cid"?o.add(p):p&&c==="gcid"?n.add(p):typeof d=="object"&&i(d,a+1)}};return i(e),{entities:[],kgIds:[...r],cids:[...o],gcids:[...n]}}function xr(e,t){let r=e instanceof Error?e.message:String(e);return t.aborted||/timeout|timed out/i.test(r)?"timeout":/captcha|recaptcha|unusual traffic|google\.com\/sorry|blocked/i.test(r)?"captcha":/invalid (?:json|payload)/i.test(r)?"invalid_payload":"provider_error"}function Dr(e){return e==="invalid_payload"?"invalid_payload":e==="captcha"?"serp_readiness":e==="timeout"||e==="provider_error"?"provider_transport":"pagination"}async function gt(e,t=process.env,r=fetch,o=zo,n){if(e.pages!==1)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP supports one page only; use Apify for two pages");let i=Pr(t),s=i.method==="native",a=Date.now(),l=Yt(),u=null,d=e.location?Kt(e.location):null;if(e.location&&!d?.canonical)throw new le("query_integrity","location_unresolved",`SERP location could not be resolved without changing the query (candidates: ${d?.ambiguousCandidates??0})`);let c=d?.canonical?Vt(d.canonical):null,p=AbortSignal.timeout(e.includeAllSerpFeatures?33e3:Jo),h=e.signal?AbortSignal.any([e.signal,p]):p,v=1,f=[],w=[],k=0,H=async g=>{let P=Date.now(),R=s?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_native_proxy":"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_rest",C=null,G=null,ye=!1,be=!1,te=null,he=null;if(l?.operationRunId&&(g===1||u))try{C=await se({runId:l.operationRunId,attemptNumber:n?n.attemptNumber+g-1:g,method:R,provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",...g===2?{parentAttemptId:u,edgeKind:"next_phase"}:n?{parentAttemptId:n.parentAttemptId,edgeKind:"provider_fallback",retryKind:"provider_fallback"}:{},normalizedFlags:{page:g,device:e.device,hasLocation:!!e.location}}),g===1&&(u=C),G=(await V({attemptId:C,provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_api",accountScope:l.operationAccountScope??"production-default",method:R,providerStatus:"started"})).id}catch(A){throw console.warn(JSON.stringify({event:"direct_serp_telemetry_start_failed",page:g,message:A instanceof Error?A.message:String(A)})),A}let x=new URLSearchParams({q:e.query,gl:e.gl,hl:e.hl,pws:"0",num:"10",...g===2?{start:"10"}:{}}),He=Ft(e.recency);He&&x.set("tbs",He),e.device==="mobile"&&x.set("brd_mobile","1"),e.includeAiOverview&&x.set("brd_ai_overview","2"),c&&x.set("uule",c),s&&x.set("brd_json","1"),k+=1;let F;try{if(i.method==="native"){let D=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_HOST?.trim()||Go,ve=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PORT?.trim()||Bo;F=await o(`https://www.google.com/search?${x}`,{username:i.username,password:i.password,host:D,port:ve,signal:h})}else{let D=await r($o,{method:"POST",headers:{Authorization:`Bearer ${i.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({zone:i.zone,url:`https://www.google.com/search?${x}`,format:"json",data_format:"parsed"}),signal:h});F={ok:D.ok,status:D.status,rawText:await D.text(),providerRequestId:D.headers.get("x-response-id")??D.headers.get("x-request-id")}}if(he=`http_${F.status}`,G&&F.providerRequestId&&await K(G,F.providerRequestId),!F.ok)throw new Error(`\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API failed with HTTP ${F.status}`);ye=!0;let A;try{A=Vo(JSON.parse(F.rawText))}catch(D){let ve=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 le("invalid_payload","invalid_provider_payload",ve)}let E=wr(A);return f.push({page:g,attempted:!0,captured:E.length>0,resultCount:E.length,requestOffset:g===2?10:0,providerRequestIdObserved:!!F.providerRequestId,...E.length===0?{failureCode:"empty_page"}:{}}),be=!0,A}catch(A){te=A;let E=xr(A,h);if(f.some(ve=>ve.page===g)||f.push({page:g,attempted:!0,captured:!1,resultCount:0,requestOffset:g===2?10:0,providerRequestIdObserved:!1,failureCode:E}),g===2)throw A;let D=A instanceof le?A.stage:Dr(E);throw A instanceof le?A:new le(D,E,A instanceof Error?A.message:String(A))}finally{let A=null;if(G&&ye)try{let E=hr(t);await X({receiptId:G,costState:"measured",units:1,unitType:"request",amountUsdNanos:Ve(E,1),rateSource:E.source,providerProduct:E.providerProduct,billingTier:E.billingTier,billableEvent:E.billableEvent,measurementSource:"provider_http_delivery",rateNumerator:E.numeratorUsdNanos,rateDenominator:E.denominatorUnits,ratePolicyVersion:E.policyVersion,rateEffectiveAt:E.effectiveAt,providerStatus:he??"delivered",providerDurationMs:Date.now()-P})}catch(E){console.warn(JSON.stringify({event:"direct_serp_receipt_finalize_failed",page:g,message:E instanceof Error?E.message:String(E)})),A=E}if(C&&await ie({attemptId:C,status:be?"succeeded":h.aborted?"timed_out":"failed",errorCode:te?xr(te,h):null,durationMs:Date.now()-P}).catch(E=>console.warn(JSON.stringify({event:"direct_serp_attempt_finish_failed",page:g,message:E instanceof Error?E.message:String(E)}))),A)throw A}};try{w.push({page:1,payload:await H(1)})}catch(g){throw g}let J=null;if(v===2)try{w.push({page:2,payload:await H(2)})}catch(g){J=g}let nt=Date.now()-a,Ce=Date.now(),I=w[0].payload,je=w.flatMap(({page:g,payload:P})=>wr(P).map(R=>({...R,position:g===2&&R.position<=10?R.position+10:R.position,sourcePage:g}))).filter((g,P,R)=>R.findIndex(C=>pt(C.url)===pt(g.url))===P),qe=e.includeLocalPack||e.includeAllSerpFeatures,W=qe?Er(I):[],fe=ce(I,["snack_pack","local","local_results","local_pack","localPack"]),xo=de({requested:qe,moduleObserved:fe.observed,rawCount:fe.rawCount,mappedCount:W.length,rawShapeValid:fe.rawShapeValid}),Nt=e.includeAiOverview||e.includeAllSerpFeatures,kt=Sr(I,Nt),xt=e.includeForums||e.includeAllSerpFeatures,Dt=Rr(I,xt),Pt=e.includeVideos||e.includeAllSerpFeatures,Ot=Ir(I,Pt),Tt=e.includeWhatPeopleSaying||e.includeAllSerpFeatures,Ct=Nr(I,Tt),st=_(I.forums),it=st&&Array.isArray(st.items)?{observed:!0,rawCount:st.items.length,rawShapeValid:!0}:ce(I,["discussions","forums","forum_results"]),at=ce(I,["videos","video_results","short_videos","shorts"]),jt={localPack:xo,forums:de({requested:xt,moduleObserved:it.observed,rawCount:it.rawCount,mappedCount:Dt.length,rawShapeValid:it.rawShapeValid}),videos:de({requested:Pt,moduleObserved:at.observed,rawCount:at.rawCount,mappedCount:Ot.length,rawShapeValid:at.rawShapeValid}),aiOverview:de({requested:Nt,moduleObserved:mt(I,["ai_overview","aiOverview","overview"]).observed,rawCount:mt(I,["ai_overview","aiOverview","overview"]).rawCount,mappedCount:kt.detected?1:0,rawShapeValid:mt(I,["ai_overview","aiOverview","overview"]).rawShapeValid}),whatPeopleSaying:de({requested:Tt,moduleObserved:ce(I,["what_people_are_saying","whatPeopleSaying"]).observed,rawCount:ce(I,["what_people_are_saying","whatPeopleSaying"]).rawCount,mappedCount:Ct.length,rawShapeValid:ce(I,["what_people_are_saying","whatPeopleSaying"]).rawShapeValid})},Do=ue(1,f),Po=f.find(g=>g.page===1)?.resultCount??0,Me=f.find(g=>g.page===2)?.resultCount??0,Oo=We({query:e.query,finalQuery:e.query,canonicalLocation:d?.canonical??null,locationResolutionSource:d?.source??"not_requested",locationAmbiguousCandidates:d?.ambiguousCandidates??0,uule:c,outboundProviderMethod:s?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_native_proxy":"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_rest"}),Le=J?Dr(f.find(g=>g.page===2)?.failureCode??"provider_error"):Object.values(jt).some(g=>g==="incomplete"||g==="unknown")?"optional_feature_parsing":null,To={pagination:{...Do,providerRequestCount:k},features:jt,queryIntegrity:Oo,failureStage:Le},qt=e.includeAllSerpFeatures?(()=>{let g=w.map(({page:P,payload:R})=>{let C=Er(R),G=Rr(R,!0),ye=Ir(R,!0),be=Nr(R,!0),te=Sr(R,!0),he=Ar(R,!0),x=kr(R,C),He=Yo(R,{localPack:C.length,forums:G.length,videos:ye.length,aiOverview:te.detected?1:0,aiMode:he.detected?1:0,whatPeopleSaying:be.length,entityIds:x.entities.length+x.kgIds.length+x.cids.length+x.gcids.length});return{page:P,...He,localPack:C,forums:G,videos:ye,whatPeopleSaying:be,aiOverview:te,aiMode:he,entityIds:x}});return{status:g[0].status,paaPreview:g.flatMap(P=>P.paaPreview),additional:g.flatMap(P=>P.additional),pages:g}})():void 0,Co=new Date().toISOString(),Mt=Date.now()-a;return{seed:e.query,location:e.location??null,extractedAt:Co,diagnostics:{phaseTimings:{providerConnectMs:nt,serpParseMs:Date.now()-Ce,totalServerMs:Mt},pagination:{requestedPages:v,capturedPages:v===2&&Me>0?2:1,page2Status:v===2?Me>0?"captured":"failed":"not_requested",page1OrganicCount:Po,page2OrganicCount:Me,...v===2&&Me===0?{failureCode:f.find(g=>g.page===2)?.failureCode==="captcha"?"captcha":f.find(g=>g.page===2)?.failureCode==="timeout"?"timeout":"empty_page"}:{}},completionStatus:"serp_only",problem:null,resultQuality:Le?"partial":"complete",degradedResult:!!Le,degradationReasons:[],retryRecommended:!!Le,serpCompleteness:To},totalQuestions:0,surface:"web",aiOverview:kt,aiMode:Ar(I,e.includeAllSerpFeatures),...qt?{fullSerpFeatures:qt}:{},whatPeopleSaying:Ct,tree:[],flat:[],videos:Ot,forums:Dt,organicResults:je,localPack:W,entityIds:kr(I,W),stats:{seed:e.query,totalQuestions:0,maxDepthReached:0,durationMs:Mt,errorCount:0}}}var Qo="scraperlink~google-search-results-serp-scraper",ke="https://api.apify.com/v2";var M=class extends Error{constructor(r,o=null,n=!1,i=null){super(r);this.runId=o;this.retrySafe=n;this.terminalStatus=i;this.name="ApifyGoogleRunError"}runId;retrySafe;terminalStatus};function xe(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:null}function De(e){return typeof e=="string"&&e.trim()?e.trim():null}function Zo(e){try{return["http:","https:"].includes(new URL(e).protocol)}catch{return!1}}function en(e){if(typeof e!="string")return e;try{return JSON.parse(e)}catch{throw new Error("Apify searchResults is not valid JSON")}}function Cr(e,t){if(!Array.isArray(e)||e.length===0)throw new Error("Apify dataset contains no search results");let r=[];for(let[i,s]of e.entries()){let a=xe(s);if(!a)throw new Error("Apify dataset contains an invalid row");let l=en(a.searchResults??a),u=xe(l),d=Array.isArray(l)?l:Array.isArray(u?.results)?u.results:Array.isArray(u?.organicResults)?u.organicResults:Array.isArray(u?.organic)?u.organic:u&&(u.position!==void 0||u.title!==void 0)?[u]:null;if(!d)throw new Error("Apify dataset search result shape is unsupported");let c=Number(a.page_number??u?.page_number??i+1);if(!Number.isInteger(c)||c<1||c>t)throw new Error("Apify dataset has an unexpected page number");r.push(...d.map(p=>({row:p,page:c})))}let o=r.map(({row:i,page:s},a)=>{let l=xe(i),u=l?.position,d=De(l?.title),c=De(l?.url??l?.link);if(!l||!d||!c||!Zo(c)||u!==void 0&&(!Number.isInteger(u)||u<1))throw new Error(`Apify search result ${a+1} is missing a valid position, URL, or title`);let p=De(l.description??l.snippet),h=typeof u=="number"?u:a%10+1;return{position:s>1&&h<=10?h+(s-1)*10:h,url:c,title:d,description:p}});if(o.length>t*10)throw new Error("Apify returned more results than requested");let n={page1:o.filter(i=>i.position<=10).length,page2:o.filter(i=>i.position>10).length};if(n.page1===0)throw new Error("Apify did not return the first result page");return{results:o,pageResultCounts:n}}async function Ze(e,t,r,o){let n=await r(e,{headers:{Authorization:`Bearer ${t}`},signal:o});if(!n.ok)throw new Error(`Apify API returned HTTP ${n.status}`);return n.json()}function _t(e){let t=xe(xe(e)?.data),r=De(t?.id),o=De(t?.status);if(!r||!o)throw new Error("Apify returned an invalid run receipt");return{id:r,status:o}}async function tn(e,t=fetch){let r=performance.now(),o=AbortSignal.timeout(9e4),n=e.signal?AbortSignal.any([e.signal,o]):o,i=e.runId,s=!1,a=null;try{if(!/^[A-Za-z0-9]+$/.test(i))throw new Error("Invalid Apify run ID");let l=_t(await Ze(`${ke}/actor-runs/${i}?waitForFinish=30`,e.token,t,n));for(;["READY","RUNNING","TIMING-OUT","ABORTING"].includes(l.status);)l=_t(await Ze(`${ke}/actor-runs/${i}?waitForFinish=30`,e.token,t,n));if(s=!0,a=l.status,l.status!=="SUCCEEDED")throw new Error(`Apify run ended with status ${l.status}`);let u=e.pages??1,d=await Ze(`${ke}/actor-runs/${i}/dataset/items?format=json`,e.token,t,n);return{query:e.query,...Cr(d,u),requestedPages:u,runId:i,elapsedMs:Math.round(performance.now()-r)}}catch(l){throw new M(l instanceof Error?l.message:String(l),i,s,a)}}async function jr(e,t,r=fetch){let o=performance.now(),n=e.query.trim(),i=e.pages??1;if(!n||n.includes(`
|
|
48
|
+
`))throw new Error("Apify search requires one nonempty query");if(i!==1&&i!==2)throw new Error("Apify search supports one or two pages");let s=t.token.trim();if(!s)throw new Error("Apify API token is required");let a=t.maxChargeUsd??.01;if(!Number.isFinite(a)||a<=0)throw new Error("Invalid Apify charge cap");let l=AbortSignal.timeout(9e4),u=e.signal?AbortSignal.any([e.signal,l]):l,d=`${ke}/actors/${Qo}/runs?maxTotalChargeUsd=${a}&restartOnError=false&waitForFinish=30`,c=null,p=!1,h=null;try{let v=await r(d,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({keyword:n,limit:i===2?"20":"10",page:1,proxy_location:"us",include_merged:!1}),signal:u});if(!v.ok)throw new Error(`Apify run start returned HTTP ${v.status}`);let f=_t(await v.json());if(c=f.id,p=!["READY","RUNNING","TIMING-OUT","ABORTING"].includes(f.status),p&&(h=f.status),f.status!=="SUCCEEDED"&&f.status!=="READY"&&f.status!=="RUNNING")throw new Error(`Apify run ended with status ${f.status}`);if(f.status==="SUCCEEDED"){let k=await Ze(`${ke}/actor-runs/${c}/dataset/items?format=json`,s,r,u);return{query:n,...Cr(k,i),requestedPages:i,runId:c,elapsedMs:Math.round(performance.now()-o)}}return{...await tn({runId:c,query:n,token:s,pages:i,signal:u},r),elapsedMs:Math.round(performance.now()-o)}}catch(v){throw v instanceof M?v:new M(v instanceof Error?v.message:String(v),c,p,h)}}var qr="apify_google_serp",Mr="apify",rn="apify_google_serp_scraperlink";async function Lr(e,t,r,o){let n=vr();await X({receiptId:e,costState:"estimated",units:t,unitType:n.unitType,amountUsdNanos:Ve(n,t),rateSource:n.source,providerProduct:n.providerProduct,billingTier:n.billingTier,billableEvent:n.billableEvent,measurementSource:"actor_run_succeeded",rateNumerator:n.numeratorUsdNanos,rateDenominator:n.denominatorUnits,ratePolicyVersion:n.policyVersion,rateEffectiveAt:n.effectiveAt,providerStatus:o,providerDurationMs:r})}async function Hr(e){let t=performance.now(),r=await se({runId:e.operationRunId,attemptNumber:e.attemptNumber,method:qr,provider:Mr,parentAttemptId:e.parentAttemptId,edgeKind:e.edgeKind,retryKind:e.retryKind,normalizedFlags:{page:1,pages:e.options.pages??1,proxyLocation:"us"}}),o=await V({attemptId:r,provider:Mr,providerProduct:rn,billingTier:"store_pay_per_event",accountScope:e.accountScope,method:qr,providerStatus:"before_actor_start"}),n=null,i=null;try{return n=await jr(e.options,{token:e.token},e.fetchImpl),await K(o.id,n.runId),await Lr(o.id,n.requestedPages,n.elapsedMs,"succeeded_estimated"),{...n,attemptId:r}}catch(s){throw i=s,n?Object.assign(new M("Apify cost tracking failed after run completion",n.runId),{attemptId:r}):(s instanceof M&&s.runId&&(await K(o.id,s.runId),s.terminalStatus==="SUCCEEDED"?await Lr(o.id,e.options.pages??1,Math.round(performance.now()-t),"succeeded_dataset_unavailable"):await mr({receiptId:o.id,units:e.options.pages??1,unitType:"page",providerStatus:"run_outcome_or_cost_pending"})),Object.assign(s instanceof Error?s:new Error(String(s)),{attemptId:r}))}finally{await ie({attemptId:r,status:i?e.options.signal?.aborted?"timed_out":"failed":"succeeded",errorCode:i?"apify_search_failed":null,durationMs:Math.round(performance.now()-t)})}}function Fr(e,t=e.requestedPages){let r=e.results.map(s=>{let a=new URL(s.url).hostname.replace(/^www\./,"");return{position:s.position,title:s.title,url:s.url,rawUrl:s.url,resolvedUrl:s.url,linkType:"plain",resolutionStatus:"not_needed",domain:a,cite:null,snippet:s.description,isRedditStyle:a==="reddit.com",inlineRating:null}}),o=t===2&&e.pageResultCounts.page2>0?2:1,n=t===2&&o===1,i=ue(t,[{page:1,attempted:!0,captured:!0,resultCount:e.pageResultCounts.page1,requestOffset:0,providerRequestIdObserved:!0},...t===2?[{page:2,attempted:!0,captured:!n,resultCount:e.pageResultCounts.page2,requestOffset:10,providerRequestIdObserved:!0,...n?{failureCode:"empty_page"}:{}}]:[]]);return{seed:e.query,location:null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:{providerConnectMs:e.elapsedMs,totalServerMs:e.elapsedMs},pagination:{requestedPages:t,capturedPages:o,page2Status:t===2?n?"failed":"captured":"not_requested",page1OrganicCount:e.pageResultCounts.page1,page2OrganicCount:e.pageResultCounts.page2},completionStatus:"serp_only",problem:null,resultQuality:n?"partial":"complete",degradedResult:n,degradationReasons:n?["page_two_missing"]:[],retryRecommended:!1,serpCompleteness:{pagination:i,features:{localPack:"not_requested",forums:"not_requested",videos:"not_requested",aiOverview:"not_requested",whatPeopleSaying:"not_requested"},queryIntegrity:We({query:e.query,finalQuery:e.query,locationResolutionSource:"not_requested",outboundProviderMethod:"default_search"}),failureStage:null}},totalQuestions:0,surface:"web",aiOverview:{detected:!1,text:null,citations:[],shareUrl:null},aiMode:{detected:!1,text:null,citations:[]},whatPeopleSaying:[],tree:[],flat:[],videos:[],forums:[],organicResults:r,localPack:[],entityIds:{entities:[],kgIds:[],cids:[],gcids:[]},stats:{seed:e.query,totalQuestions:0,maxDepthReached:0,durationMs:e.elapsedMs,errorCount:0}}}var on=12e3;function $r(e){return e.recency?Qt():e.mode==="full"&&e.pages===1?Qe():!!e.token||Qe()}async function ft(e){if(e.signal.throwIfAborted(),e.recency)return nn(e);if(e.mode==="full")return sn(e);if(!e.token)return Ur(e);let t=performance.now(),r;for(let o=1;o<=2;o++){let n=AbortSignal.any([e.signal,AbortSignal.timeout(on)]),i=e.pages;try{let s=await Hr({options:{query:e.query,pages:i,signal:n},token:e.token,operationRunId:e.operationRunId,accountScope:e.accountScope,attemptNumber:o,...r?{parentAttemptId:r,edgeKind:"same_method_retry",retryKind:"same_method"}:{}});console.info(JSON.stringify({event:"serp_provider_succeeded",provider:"apify",operationRunId:e.operationRunId,attemptNumber:o,durationMs:s.elapsedMs,resultCount:s.results.length,requestedPages:e.pages,providerRequestedPages:s.requestedPages,deliveredPages:s.pageResultCounts.page2>0?2:1,runId:s.runId}));let a=Fr(s,e.pages);return a.stats.durationMs=Math.round(performance.now()-t),a.diagnostics.phaseTimings&&(a.diagnostics.phaseTimings.totalServerMs=a.stats.durationMs),{result:a,mode:"light",deliveryProvider:"apify",deliveredPages:s.pageResultCounts.page2>0?2:1}}catch(s){r=s&&typeof s=="object"&&"attemptId"in s?String(s.attemptId):void 0;let a=s instanceof M?s:null;if(console.warn(JSON.stringify({event:"serp_provider_failed",provider:"apify",operationRunId:e.operationRunId,attemptNumber:o,runId:a?.runId??null,requestedPages:e.pages,attemptPages:i,retrySafe:a?.retrySafe===!0,error:s instanceof Error?s.message:String(s)})),e.signal.aborted||!r||a?.retrySafe!==!0)throw s}}return Ur(e,r)}async function Ur(e,t){if(e.signal.throwIfAborted(),!Qe())throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API fallback is not configured; set \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_API_KEY and \u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_ZONE, or the SERP proxy username and password");let r=performance.now(),o={query:e.query,gl:"us",hl:"en",device:"desktop",pages:1,includeAllSerpFeatures:!1,includeLocalPack:!1,includeForums:!1,includeVideos:!1,includeAiOverview:!1,includeWhatPeopleSaying:!1,signal:e.signal};console.info(JSON.stringify({event:"serp_provider_fallback",provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",operationRunId:e.operationRunId,attemptNumber:3,requestedPages:e.pages,providerRequestedPages:1}));try{let n=await gt(o,process.env,fetch,void 0,t?{attemptNumber:3,parentAttemptId:t}:void 0);if(n.organicResults.length===0)throw new Error("Search returned no organic results");if(e.pages===2){n.diagnostics.pagination={requestedPages:2,capturedPages:1,page2Status:"unavailable",page1OrganicCount:n.organicResults.length,page2OrganicCount:0},n.diagnostics.resultQuality="partial",n.diagnostics.degradedResult=!0,n.diagnostics.degradationReasons=[...new Set([...n.diagnostics.degradationReasons??[],"page_two_missing"])],n.diagnostics.retryRecommended=!1;let i=n.diagnostics;i.serpCompleteness&&(i.serpCompleteness.pagination=ue(2,i.serpCompleteness.pagination.evidence.filter(s=>s.page===1)),i.serpCompleteness.failureStage="pagination")}return n.stats.durationMs=Math.round(performance.now()-r),n.diagnostics.phaseTimings&&(n.diagnostics.phaseTimings.totalServerMs=n.stats.durationMs),console.info(JSON.stringify({event:"serp_provider_succeeded",provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",operationRunId:e.operationRunId,attemptNumber:3,durationMs:n.stats.durationMs,resultCount:n.organicResults.length,requestedPages:e.pages,providerRequestedPages:1,deliveredPages:1,resultQuality:n.diagnostics.resultQuality})),{result:n,mode:"light",deliveryProvider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",deliveredPages:1}}catch(n){throw console.warn(JSON.stringify({event:"serp_provider_failed",provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",operationRunId:e.operationRunId,attemptNumber:3,error:n instanceof Error?n.message:String(n)})),n}}async function nn(e){let t=await Fe({...e.physicalFactory?{physicalExecution:await e.physicalFactory()}:{},query:e.query,gl:"us",hl:"en",device:"desktop",pages:e.pages,recency:e.recency,serpOnly:!0,forceManagedSerp:!0,maxAttempts:2,proxyMode:"none",maxQuestions:1,depth:1,headless:!0,format:"json",outputDir:"/tmp/paa-output-api",softDeadlineMs:Date.now()+23e4,signal:e.signal,onAttemptEvent:e.onAttemptEvent});if(t.organicResults.length===0)throw new Error("Search returned no organic results");let r=t.diagnostics.pagination?.capturedPages===2?2:1;if(e.pages===2&&r===1&&(t.diagnostics.resultQuality="partial",t.diagnostics.degradedResult=!0,t.diagnostics.degradationReasons=["page_two_missing"],t.diagnostics.retryRecommended=!0),e.mode==="full"){let o=Object.fromEntries(["localPack","forums","videos","aiOverview","aiMode","whatPeopleSaying","entityIds","paaPreview","topStories"].map(n=>[n,"unsupported"]));t.fullSerpFeatures={status:o,paaPreview:[],additional:[],pages:[]}}return{result:t,mode:e.mode==="full"?"full":"light",deliveryProvider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",deliveredPages:r}}async function sn(e){if(e.pages===2){let t=await ft({...e,mode:"light",pages:2}),r=Object.fromEntries(["localPack","forums","videos","aiOverview","aiMode","whatPeopleSaying","entityIds","paaPreview","topStories"].map(n=>[n,"unsupported"]));t.result.fullSerpFeatures={status:r,paaPreview:[],additional:[],pages:[]};let o=t.result.diagnostics;return o.serpCompleteness&&(o.serpCompleteness.features={localPack:"unsupported",forums:"unsupported",videos:"unsupported",aiOverview:"unsupported",whatPeopleSaying:"unsupported"}),{...t,mode:"full"}}return an({...e,mode:"full"})}async function an(e){let t=performance.now(),r=e.mode==="full",o={query:e.query,gl:"us",hl:"en",device:"desktop",pages:1,...e.recency?{recency:e.recency}:{},includeAllSerpFeatures:r,includeLocalPack:r,includeForums:r,includeVideos:r,includeAiOverview:r,includeWhatPeopleSaying:r,signal:e.signal},n=await gt(o);if(n.organicResults.length===0)throw new Error("Search returned no organic results");return n.stats.durationMs=Math.round(performance.now()-t),n.diagnostics.phaseTimings&&(n.diagnostics.phaseTimings.totalServerMs=n.stats.durationMs),{result:n,mode:r?"full":"light",deliveryProvider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",deliveredPages:n.diagnostics.pagination?.capturedPages===2?2:1}}import{randomUUID as no}from"crypto";var Jr="2026-10-10-operation-final-settlements.1";async function Gr(e){let t=async()=>{let[r,o,n]=await Promise.all([e.execute("SELECT sql FROM sqlite_master WHERE name='operation_final_settlements'"),e.execute("PRAGMA index_info(operation_final_settlement_key)"),e.execute({sql:"SELECT 1 FROM schema_migrations WHERE version=?",args:[Jr]})]),i=String(r.rows[0]?.sql??"").replace(/\s+/g," ");return n.rows.length===1&&o.rows.map(s=>s.name).join(",")==="debit_key"&&i.includes("run_id TEXT NOT NULL REFERENCES operation_runs(id)")&&i.includes("user_id INTEGER NOT NULL CHECK (user_id > 0)")&&i.includes("final_amount_mc INTEGER NOT NULL CHECK (final_amount_mc >= 0)")&&i.includes("receipt_json TEXT NOT NULL CHECK (json_valid(receipt_json))")};if(!await t()){try{await e.batch([`CREATE TABLE IF NOT EXISTS operation_final_settlements (
|
|
49
|
+
id TEXT NOT NULL PRIMARY KEY,
|
|
50
|
+
run_id TEXT NOT NULL REFERENCES operation_runs(id),
|
|
51
|
+
user_id INTEGER NOT NULL CHECK (user_id > 0),
|
|
52
|
+
debit_key TEXT NOT NULL REFERENCES operation_debit_plans(debit_key),
|
|
53
|
+
final_amount_mc INTEGER NOT NULL CHECK (final_amount_mc >= 0),
|
|
54
|
+
refund_operation TEXT NOT NULL,source_surface TEXT NOT NULL,
|
|
55
|
+
receipt_json TEXT NOT NULL CHECK (json_valid(receipt_json)),
|
|
56
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
57
|
+
)`,"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:[Jr]}],"write")}catch(r){if(!await t().catch(()=>!1))throw r}if(!await t())throw Error("Final settlement schema is incomplete")}}var ln="(CAST(strftime('%s','now') AS INTEGER)*1000)";async function Br(e){let{claim:t,gate:r}=e;if(we({userId:t.userId,tool:r.tool,jobId:r.jobId},r),!Number.isSafeInteger(e.amountMc)||e.amountMc<0||!e.key||!e.refundOperation||!e.sourceSurface)throw Error("Invalid final settlement input");let o=b({key:e.key,amountMc:e.amountMc,refundOperation:e.refundOperation,sourceSurface:e.sourceSurface,material:e.material});if(Buffer.byteLength(o)>16*1024*1024)throw Error("Final settlement material exceeds budget");let n=m();await Gr(n),await re({userId:t.userId,runId:t.runId});let i=Ht(t.userId,r.jobId),s="settlement:"+O(`${t.runId}\0${e.key}`),a=`EXISTS(SELECT 1 FROM operation_runs r JOIN operation_executions x ON x.run_id=r.id
|
|
58
|
+
WHERE r.id=? AND r.user_id=? AND r.tool=? AND r.job_id=? AND r.status=? AND x.claim_token=? AND x.phase=? AND x.expires_at_ms>${ln}) AND (${r.sql}) AND (${i.sql})`,l=[t.runId,t.userId,r.tool,r.jobId,e.recovery?"unknown":"running",t.token,e.recovery?"unknown":"effects_started",...r.args,...i.args];try{await n.execute({sql:`INSERT OR IGNORE INTO operation_final_settlements(id,run_id,user_id,debit_key,final_amount_mc,refund_operation,source_surface,receipt_json)
|
|
59
|
+
SELECT ?,?,?,?,?,?,?,? WHERE (${a}) AND EXISTS(SELECT 1 FROM operation_debit_plans p JOIN billing_debits d ON d.idempotency_key=p.debit_key
|
|
60
|
+
WHERE p.run_id=? AND p.debit_key=? AND p.refund_operation=? AND p.source_surface=? AND d.user_id=? AND d.status='applied' AND ?>=0 AND ?<=p.amount_mc)`,args:[s,t.runId,t.userId,e.key,e.amountMc,e.refundOperation,e.sourceSurface,o,...l,t.runId,e.key,e.refundOperation,e.sourceSurface,t.userId,e.amountMc,e.amountMc]})}catch{}let u=(await n.execute({sql:`SELECT s.* FROM operation_final_settlements s WHERE s.id=? AND s.run_id=? AND s.user_id=? AND (${a})`,args:[s,t.runId,t.userId,...l]})).rows[0];if(!u||u.receipt_json!==o)throw Error("final_settlement_plan_unknown_or_conflicting");return{...t,mode:e.recovery?"compensate":"execute",settlementPlanId:s}}function et(e){return{...e,sql:`EXISTS(SELECT 1 FROM operation_final_settlements s JOIN billing_events b ON b.user_id=s.user_id
|
|
61
|
+
WHERE s.run_id=? AND s.user_id=? AND s.debit_key=? AND b.billing_class='wallet_hold_settlement' AND b.status='settled'
|
|
62
|
+
AND b.source_surface=s.source_surface AND b.amount_mc=s.final_amount_mc AND json_extract(b.metadata,'$.debitIdempotencyKey')=s.debit_key
|
|
63
|
+
AND json_extract(b.metadata,'$.refundOperation')=s.refund_operation)`,args:[e.runId,e.userId,e.key]}}var Wr="2026-10-10-outbound-delivery.1";async function tt(e){let t=async()=>{let r=(await e.execute("SELECT sql FROM sqlite_master WHERE name='outbound_deliveries'")).rows[0],o=(await e.execute({sql:"SELECT 1 FROM schema_migrations WHERE version=?",args:[Wr]})).rows,n=String(r?.sql??"").replace(/\s+/g," "),i=(await e.execute("PRAGMA index_info(outbound_delivery_job)")).rows.map(s=>s.name).join(",");return o.length===1&&i==="job_id,user_id"&&n.includes("request_json TEXT NOT NULL CHECK (json_valid(request_json))")&&n.includes("expires_at_ms INTEGER NOT NULL")&&n.includes("'accepted','unknown','expired','unavailable'")};if(!await t()){try{await e.batch([`CREATE TABLE IF NOT EXISTS outbound_deliveries (
|
|
64
|
+
id TEXT NOT NULL PRIMARY KEY,user_id INTEGER NOT NULL CHECK (user_id > 0),job_id TEXT NOT NULL,
|
|
65
|
+
parent_run_id TEXT NOT NULL REFERENCES operation_runs(id),request_json TEXT NOT NULL CHECK (json_valid(request_json)),
|
|
66
|
+
state TEXT NOT NULL CHECK (state IN ('requested','frozen','sending','accepted','unknown','expired','unavailable')),
|
|
67
|
+
expires_at_ms INTEGER NOT NULL,payload_json TEXT CHECK (payload_json IS NULL OR json_valid(payload_json)),payload_sha256 TEXT,
|
|
68
|
+
send_nonce TEXT,send_token TEXT,http_status INTEGER,receipt_json TEXT CHECK (receipt_json IS NULL OR json_valid(receipt_json)),
|
|
69
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
70
|
+
)`,"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:[Wr]}],"write")}catch(r){if(!await t().catch(()=>!1))throw r}if(!await t())throw Error("Delivery schema is incomplete")}}var Q=class extends Error{};var ge="(CAST(strftime('%s','now') AS INTEGER)*1000)",Pe=e=>`delivery:${e}`,Z=e=>b(e);async function j(e,t){let r=m();await tt(r);let o=(await r.execute({sql:`SELECT *,${ge} AS now_ms FROM outbound_deliveries WHERE id=? AND user_id=?`,args:[e,t]})).rows[0];if(!o)return null;let n=JSON.parse(String(o.request_json));if(n.id!==e||n.userId!==t||n.jobId!==o.job_id||n.parentRunId!==o.parent_run_id)throw Error("Delivery request conflicts");return{...n,state:String(o.state),expiresAtMs:Number(o.expires_at_ms),nowMs:Number(o.now_ms),payloadJson:o.payload_json==null?null:String(o.payload_json),payloadSha256:o.payload_sha256==null?null:String(o.payload_sha256),sendNonce:o.send_nonce==null?null:String(o.send_nonce),sendToken:o.send_token==null?null:String(o.send_token),httpStatus:o.http_status==null?null:Number(o.http_status),receiptJson:o.receipt_json==null?null:String(o.receipt_json)}}async function zr(e,t,r){if(we({userId:e.userId,tool:r.tool,jobId:e.jobId},r),!e.id||!e.url||!["paa-direct","paa-queue"].includes(e.profile)||!Number.isSafeInteger(e.userId)||e.userId<=0||t.runId!==e.parentRunId||t.userId!==e.userId||!/^[a-f0-9]{64}$/.test(e.fingerprint))throw Error("Invalid delivery request");let o=m();await tt(o);let n;try{await o.execute({sql:`INSERT OR IGNORE INTO outbound_deliveries(id,user_id,job_id,parent_run_id,request_json,state,expires_at_ms)
|
|
71
|
+
SELECT ?,?,?,?,?,'requested',${ge}+? WHERE (${r.sql}) AND EXISTS(SELECT 1 FROM operation_runs r JOIN operation_executions x ON x.run_id=r.id
|
|
72
|
+
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>${ge})`,args:[e.id,e.userId,e.jobId,e.parentRunId,Z(e),864e5,...r.args,t.runId,t.userId,r.tool,r.jobId,t.token]})}catch(s){n=s}let i=await j(e.id,e.userId);if(!i||Z($(i))!==Z(e))throw n??Error("Delivery request receipt is unavailable or conflicting");return i}function $(e){return{id:e.id,userId:e.userId,jobId:e.jobId,parentRunId:e.parentRunId,url:e.url,profile:e.profile,fingerprint:e.fingerprint}}async function Vr(e,t,r){let o;try{o=b(t)}catch{throw new Q("Delivery payload cannot be serialized")}let n=O(o);if(Buffer.byteLength(o)>16777216)throw new Q("Delivery payload exceeds budget");we({userId:e.userId,tool:r.tool,jobId:e.jobId},r);let i;try{await m().execute({sql:`UPDATE outbound_deliveries SET state='frozen',payload_json=?,payload_sha256=?,updated_at=datetime('now') WHERE id=? AND user_id=? AND request_json=? AND state='requested' AND expires_at_ms>${ge} AND (${r.sql})`,args:[o,n,e.id,e.userId,Z($(e)),...r.args]})}catch(a){i=a}let s=await j(e.id,e.userId);if(!s||s.payloadJson!==o||s.payloadSha256!==n)throw i??Error("Delivery payload receipt is unavailable or conflicting");return s}function Oe(e,t,r,o){return{userId:e.userId,tool:"paa_callback",jobId:e.jobId,sql:`(${t.sql}) AND EXISTS(SELECT 1 FROM outbound_deliveries d WHERE d.id=? AND d.user_id=? AND d.request_json=? AND d.state=? AND d.payload_json=? AND d.payload_sha256=? ${r==="accepted"?"":`AND d.expires_at_ms>${ge}`} ${o?"AND d.send_nonce=?":""})`,args:[...t.args,e.id,e.userId,Z($(e)),r,e.payloadJson,e.payloadSha256,...o?[o]:[]]}}async function Kr(e,t,r,o){let n=Oe(e,o,"frozen"),i=ne(t,{tool:n.tool,jobId:e.jobId}),s;try{await m().execute({sql:`UPDATE outbound_deliveries SET state='sending',send_nonce=?,send_token=?,updated_at=datetime('now') WHERE id=? AND user_id=? AND state='frozen' AND (${n.sql}) AND (${i.sql})`,args:[r,t.token,e.id,e.userId,...n.args,...i.args]})}catch(l){s=l}let a=await j(e.id,e.userId);if(!a||a.state!=="sending"||a.sendNonce!==r||a.sendToken!==t.token||a.payloadSha256!==e.payloadSha256)throw s??Error("Delivery send permission is unavailable");return a}async function Xr(e,t,r){let o=Oe(e,r,"sending",e.sendNonce),n=ne(t,{tool:o.tool,jobId:e.jobId});return(await m().execute({sql:`SELECT 1 WHERE (${o.sql}) AND (${n.sql})`,args:[...o.args,...n.args]})).rows.length===1}async function Yr(e,t){if(!e.sendNonce||!e.sendToken||!e.payloadSha256||t<200||t>=300)throw Error("Invalid endpoint acceptance");let r=b({deliveryId:e.id,idempotencyKey:e.id,payloadSha256:e.payloadSha256,httpStatus:t}),o=m(),n;try{await o.execute({sql:`UPDATE outbound_deliveries SET state='accepted',http_status=?,receipt_json=?,updated_at=datetime('now') WHERE id=? AND user_id=? AND state IN ('sending','unknown') AND send_nonce=? AND send_token=? AND payload_sha256=? AND request_json=?
|
|
73
|
+
AND EXISTS(SELECT 1 FROM operation_runs WHERE id=? AND user_id=? AND tool='paa_callback' AND job_id=?)`,args:[t,r,e.id,e.userId,e.sendNonce,e.sendToken,e.payloadSha256,Z($(e)),Pe(e.id),e.userId,e.jobId]})}catch(s){n=s}let i=await j(e.id,e.userId);if(!i||i.state!=="accepted"||i.receiptJson!==r)throw n??Error("Endpoint acceptance receipt is unavailable");return i}async function yt(e){await m().execute({sql:"UPDATE outbound_deliveries SET state='unknown',updated_at=datetime('now') WHERE id=? AND user_id=? AND request_json=? AND state='frozen' AND send_nonce IS NULL AND EXISTS(SELECT 1 FROM operation_executions x JOIN operation_runs o ON o.id=x.run_id WHERE o.id=? AND o.user_id=? AND o.tool='paa_callback' AND o.job_id=? AND x.phase IN ('effects_started','unknown'))",args:[e.id,e.userId,Z($(e)),Pe(e.id),e.userId,e.jobId]})}async function Qr(e){await m().execute({sql:"UPDATE outbound_deliveries SET state='unknown',updated_at=datetime('now') WHERE id=? AND user_id=? AND state='sending' AND send_nonce=?",args:[e.id,e.userId,e.sendNonce]})}async function rt(e,t,r){await m().execute({sql:`UPDATE outbound_deliveries SET state=?,updated_at=datetime('now') WHERE id=? AND user_id=? AND state IN ('requested','frozen') AND send_nonce IS NULL ${t==="expired"?`AND expires_at_ms<=${ge}`:""} ${r?`AND (${r.sql})`:""}`,args:[t,e.id,e.userId,...r?r.args:[]]})}async function L(e){let t=e.state==="sending"?"unknown":e.state;return await m().execute({sql:"UPDATE jobs SET options=json_set(options,'$.callbackDeliveryState',?,'$.callbackDeliveryId',?,'$.callbackDeliveryExpiresAtMs',?) WHERE id=? AND user_id=? AND callback_url=? AND json_extract(options,'$.callbackDeliveryProtocol')=1",args:[t,e.id,e.expiresAtMs,e.jobId,e.userId,e.url]}).catch(()=>{}),{state:t,deliveryId:e.id,expiresAtMs:e.expiresAtMs,...e.httpStatus?{httpStatus:e.httpStatus}:{}}}async function Zr(e=25){let t=m();return await tt(t),(await t.execute({sql:"SELECT d.id,d.user_id,d.job_id FROM outbound_deliveries d JOIN jobs j ON j.id=d.job_id AND j.user_id=d.user_id WHERE (d.state IN ('requested','frozen') OR (d.state='accepted' AND EXISTS(SELECT 1 FROM operation_executions x WHERE x.run_id='delivery:'||d.id AND x.phase<>'published'))) AND j.status IN ('done','failed','cancelled') AND json_extract(j.options,'$.executionState')='finalized' ORDER BY d.created_at LIMIT ?",args:[Math.max(1,Math.min(100,Math.floor(e)))]})).rows.map(r=>({id:String(r.id),userId:Number(r.user_id),jobId:String(r.job_id)}))}function bt(e){if(!e.callback_url||e.options.callbackDeliveryProtocol!==1)return null;let t=e.options.executionProtocol===1&&e.options.directCompletionProtocol===1&&e.options.executionOwner==="direct",r=e.options.queueExecutionProtocol===1&&e.options.executionOwner==="cron";if(!t&&!r)throw Error("Callback parent profile is unavailable");return{id:`paa-callback:${e.id}`,userId:e.user_id,jobId:e.id,parentRunId:t?`paa-execution:${e.id}`:`harvest:${e.id}`,url:e.callback_url,profile:t?"paa-direct":"paa-queue",fingerprint:String(e.options.requestFingerprint)}}async function eo(e,t,r){let o=bt(e);o&&await zr(o,t,{...r,sql:`(${r.sql}) AND EXISTS(SELECT 1 FROM jobs WHERE id=? AND user_id=? AND callback_url=? AND json_extract(options,'$.callbackDeliveryProtocol')=1 AND json_extract(options,'$.requestFingerprint')=?)`,args:[...r.args,e.id,e.user_id,e.callback_url,o.fingerprint]})}function to(e,t){let r=bt(e);return r?{...t,sql:`(${t.sql}) AND EXISTS(SELECT 1 FROM outbound_deliveries WHERE id=? AND user_id=? AND request_json=? AND state='requested')`,args:[...t.args,r.id,r.userId,b(r)]}:t}async function ro(e,t){let r=await S(e,t);if(!r?.callback_url)return{kind:"none"};let o=bt(r);if(!o)return{kind:"unavailable"};let n=await j(o.id,r.user_id);if(!n||b($(n))!==b(o))return{kind:"unavailable"};if(!["done","failed","cancelled"].includes(r.status)||r.options.executionState!=="finalized"||r.options.holdState!=="settled"||!r.options.syncCapturedAt)return{kind:"pending",record:n};let i=await T(o.parentRunId,r.user_id,o.profile==="paa-direct"?"harvest_paa":"search_serp",r.id);if(!i||i.phase!=="published")return{kind:"pending",record:n};let s=o.profile==="paa-direct"?i.flags:i.flags.intent;if(!s||s.callbackUrl!==o.url||s.requestFingerprint!==o.fingerprint||s.userId!==r.user_id||s.jobId!==r.id||r.query!==s.options?.query||b(Object.fromEntries(Object.keys(s.options).map(p=>[p,r.options[p]])))!==b(s.options)||s.hold?.userId!==r.user_id||s.hold.key!==r.options.billingDebitKey||s.hold.amountMc!==r.options.billingHoldMc||r.status!==r.options.syncTerminalStatus||r.options.syncFinalAmountMc!==r.options.billingFinalAmountMc)return{kind:"unavailable"};if(r.options.syncRequiresPhysicalReceipt===1&&(await Ee(o.parentRunId,r.user_id)).length===0)return{kind:"pending",record:n};if(await re({runId:o.parentRunId,userId:r.user_id}))return{kind:"pending",record:n};let a=O(b({result:r.result,error:r.publicError,httpStatus:r.options.syncHttpStatus,requiresPhysical:r.options.syncRequiresPhysicalReceipt})),l={jobId:r.id,requestFingerprint:s.requestFingerprint,captureSha256:a,status:r.status},u=b({...l,amountMc:Number(r.options.syncFinalAmountMc),physicalOutcome:"terminated"}),d=et({userId:r.user_id,jobId:r.id,tool:o.profile==="paa-direct"?"harvest_paa":"search_serp",runId:o.parentRunId,key:s.hold.key}),c={...d,sql:`(${d.sql}) AND EXISTS(SELECT 1 FROM jobs j JOIN operation_runs r ON r.job_id=j.id AND r.user_id=j.user_id JOIN operation_executions x ON x.run_id=r.id JOIN operation_final_settlements s ON s.run_id=r.id AND s.user_id=r.user_id
|
|
74
|
+
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=?
|
|
75
|
+
AND j.callback_url=? AND json_extract(j.options,'$.requestFingerprint')=? AND r.request_fingerprint=? AND j.query=json_extract(r.normalized_flags_json,?)
|
|
76
|
+
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))
|
|
77
|
+
AND json_extract(j.options,'$.callbackDeliveryProtocol')=1 AND json_extract(j.options,'$.executionState')='finalized' AND json_extract(j.options,'$.holdState')='settled'
|
|
78
|
+
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 ?
|
|
79
|
+
AND s.debit_key=? AND s.final_amount_mc=? AND json_extract(s.receipt_json,'$.material.captureSha256')=?)`,args:[...d.args,r.id,r.user_id,o.parentRunId,u,r.status,o.url,o.fingerprint,i.fingerprint,o.profile==="paa-direct"?"$.options.query":"$.intent.options.query",o.profile==="paa-direct"?"$.options":"$.intent.options",Number(r.options.syncFinalAmountMc),Number(r.options.syncFinalAmountMc),r.status,r.result==null?null:b(r.result),r.publicError==null?null:JSON.stringify(r.publicError),s.hold.key,Number(r.options.syncFinalAmountMc),a]};return{kind:"ready",job:r,record:n,domain:c}}var ee=e=>`harvest:${e}`,so=e=>e.profile==="direct"?"executionProtocol":e.profile==="queue"?"queueExecutionProtocol":"syncExecutionProtocol";function _e(e,t="'running'"){let r=b(e.options),o=Object.keys(JSON.parse(r)).sort();if(o.some(n=>!/^[a-zA-Z][a-zA-Z0-9]*$/.test(n)))throw Error("Invalid synchronous option key");return{userId:e.userId,tool:e.tool,jobId:e.jobId,sql:`EXISTS(SELECT 1 FROM jobs j WHERE j.id=? AND j.user_id=? AND j.status IN (${t}) AND json_extract(j.options,'$.${so(e)}')=1 AND j.query=? AND j.callback_url IS ? ${e.profile==="direct"?"AND json_extract(j.options,'$.executionOwner')='direct' AND json_extract(j.options,'$.directCompletionProtocol')=1 AND json_extract(j.options,'$.paaLeaseToken')=? AND json_extract(j.options,'$.executionRunId')=?":e.profile==="queue"?"AND json_extract(j.options,'$.executionOwner')='cron'":""} AND json_extract(j.options,'$.requestFingerprint')=? AND json_extract(j.options,'$.billingHoldMc')=? ${o.map(()=>"AND json_extract(j.options,?) IS json_extract(?,?)").join(" ")})`,args:[e.jobId,e.userId,String(e.options.query),e.callbackUrl??null,...e.profile==="direct"?[e.recordToken,`paa-execution:${e.jobId}`]:[],e.requestFingerprint,e.hold.amountMc,...o.flatMap(n=>[`$.${n}`,r,`$.${n}`])]}}function vt(e){let t=JSON.parse(b(e));if(!t.jobId||!Number.isSafeInteger(t.userId)||t.userId<=0||!["harvest_paa","search_serp"].includes(t.tool)||!Number.isSafeInteger(t.deadlineAt)||!Number.isSafeInteger(t.hold.amountMc)||t.hold.amountMc<=0||t.hold.userId!==t.userId||t.hold.key!==(t.profile==="queue"?`serp-search:${t.jobId}:hold`:`harvest-sync:${t.jobId}:charge`)||!/^[a-f0-9]{64}$/.test(t.requestFingerprint)||!t.refundOperation||!t.sourceSurface)throw Error("Invalid synchronous funded intent");if(t.profile==="queue"&&(t.tool!=="search_serp"||t.options.serpOnly!==!0||t.deadlineAt!==0||!Number.isSafeInteger(t.budgetMs)||t.budgetMs<1e3||t.budgetMs>36e5||t.hold.operation!=="serp"||t.refundOperation!=="serp_refund"||t.sourceSurface!=="serp_search"||t.hold.description!==`SERP search: ${t.options.query}`.slice(0,500)))throw Error("Invalid queued compatibility intent");return t}async function io(e){let t=await T(ee(e.id),e.user_id,e.options.serpOnly===!0?"search_serp":"harvest_paa",e.id);if(!t||t.flags.syncExecutionProtocol!==1||!t.flags.intent)return null;let r=vt(t.flags.intent);if((r.profile==="queue"?e.options.queueExecutionProtocol:e.options.syncExecutionProtocol)!==1||r.jobId!==e.id||r.userId!==e.user_id||t.fingerprint!==r.requestFingerprint)throw Error("Synchronous intent receipt conflicts");return r}async function B(e,t="held"){let r=e.options.serpOnly===!0?2:dt;return{status:503,headers:{"Retry-After":String(r)},body:{job_id:e.id,status:"running",saved_status:e.status,...z({errorCode:"response_lost",retryable:!0,chargeStatus:t==="held"?"refund_pending":void 0,details:{retry_guidance:`Wait at least ${r} 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:t,status_tool:e.options.queueExecutionProtocol===1?"harvest_paa_status":e.options.serpOnly===!0?"search_serp":"harvest_paa_status",...e.result?{result:e.result}:{}}}}async function cn(e,t){await m().execute({sql:`UPDATE jobs SET options=json_set(options,'$.executionState','unknown','$.holdState',CASE WHEN json_extract(options,'$.billingSettledAt') IS NOT NULL THEN 'settled' ELSE 'held' END) WHERE id=? AND user_id=? AND json_extract(options,'$.${so(e)}')=1 AND EXISTS(SELECT 1 FROM operation_executions x WHERE x.run_id=? AND x.claim_token=?)`,args:[e.jobId,e.userId,t.runId,t.token]})}async function oo(e,t,r,o,n,i=null,s=200,a=!0){if(!Number.isSafeInteger(o)||o<0||o>e.hold.amountMc)throw Error("Invalid captured synchronous charge");let l=r==null?null:b(r),u=i==null?null:JSON.stringify(i),d=_e(e),c;try{await m().execute({sql:`UPDATE jobs SET result=?,public_error_json=?,options=json_set(options,'$.syncCapturedAt',datetime('now'),'$.syncFinalAmountMc',?,'$.syncTerminalStatus',?,'$.syncHttpStatus',?,'$.syncRequiresPhysicalReceipt',?)
|
|
80
|
+
WHERE id=? AND user_id=? AND json_extract(options,'$.syncCapturedAt') IS NULL AND (${d.sql})
|
|
81
|
+
AND EXISTS(SELECT 1 FROM operation_runs r JOIN operation_executions x ON x.run_id=r.id WHERE r.id=? AND r.user_id=? AND x.claim_token=? AND x.phase IN ('effects_started','unknown') AND r.status IN ('running','unknown'))`,args:[l,u,o,n,s,a?1:0,e.jobId,e.userId,...d.args,t.runId,t.userId,t.token]})}catch(h){c=h}let p=await S(e.jobId,e.userId);if(!p?.options.syncCapturedAt||b({result:p.result})!==b({result:r==null?null:JSON.parse(l)})||p.options.syncFinalAmountMc!==o||p.options.syncTerminalStatus!==n||b({error:p.publicError})!==b({error:Gt(i)})||p.options.syncHttpStatus!==s||p.options.syncRequiresPhysicalReceipt!==(a?1:0))throw c??Error("synchronous_capture_receipt_unknown_or_conflicting");return p}async function ot(e,t){return{status:t?200:Number(e.options.syncHttpStatus??200),body:{job_id:e.id,status:e.status,...e.result?{result:e.result}:{},...e.publicError?{...e.publicError,error:e.publicError.message,...e.options.holdState==="settled"&&e.options.billingFinalAmountMc===0?{charge_status:"refunded"}:{}}:{},...t?{replayed:!0}:{}}}}async function ht(e,t,r,o=!1){let n=await S(e.jobId,e.userId);if(!n?.options.syncCapturedAt)throw Error("Synchronous capture is not known");if(n.options.syncRequiresPhysicalReceipt===1&&(await Ee(t.runId,t.userId)).length===0)throw Error("synchronous_physical_receipt_missing");if(await re({userId:e.userId,runId:t.runId}))throw Error("synchronous_physical_outcome_unknown");let i=Number(n.options.syncFinalAmountMc),s=String(n.options.syncTerminalStatus);if(!["done","failed","cancelled"].includes(s))throw Error("Invalid synchronous terminal receipt");let a={jobId:n.id,requestFingerprint:e.requestFingerprint,captureSha256:O(b({result:n.result,error:n.publicError,httpStatus:n.options.syncHttpStatus,requiresPhysical:n.options.syncRequiresPhysicalReceipt})),status:s},l=_e(e,"'running','done','failed','cancelled'"),u={...l,sql:`(${l.sql}) AND EXISTS(SELECT 1 FROM jobs WHERE id=? AND user_id=? AND json_extract(options,'$.syncCapturedAt') IS NOT NULL AND json_extract(options,'$.syncFinalAmountMc')=? AND json_extract(options,'$.syncTerminalStatus')=? AND json(result) IS json(?) AND public_error_json IS ? AND json_extract(options,'$.syncHttpStatus')=? AND json_extract(options,'$.syncRequiresPhysicalReceipt')=?)`,args:[...l.args,n.id,n.user_id,i,s,n.result==null?null:b(n.result),n.publicError==null?null:JSON.stringify(n.publicError),Number(n.options.syncHttpStatus),Number(n.options.syncRequiresPhysicalReceipt)]},d=await Br({claim:t,recovery:r,gate:u,key:e.hold.key,amountMc:i,refundOperation:e.refundOperation,sourceSurface:e.sourceSurface,material:a});if((await ur(e.userId,e.hold.key,e.sourceSurface)??await ar(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=et({userId:n.user_id,tool:e.tool,jobId:n.id,runId:t.runId,key:e.hold.key}),h=ne(t,{tool:e.tool,jobId:n.id,recovery:r}),v;try{await m().execute({sql:`UPDATE jobs SET status=?,completed_at=COALESCE(completed_at,datetime('now')),options=json_set(options,'$.executionState','finalized','$.holdState','settled','$.physicalOutcome','terminated','$.billingSettledAt',COALESCE(json_extract(options,'$.billingSettledAt'),datetime('now')),'$.billingFinalAmountMc',?${e.profile==="direct"?",'$.billedMc',?":""}) WHERE id=? AND user_id=? AND (${u.sql}) AND (${h.sql}) AND (${p.sql})`,args:[s,i,...e.profile==="direct"?[i]:[],n.id,n.user_id,...u.args,...h.args,...p.args]})}catch(H){v=H}let f=await S(n.id,n.user_id);if(!f||f.status!==s||f.options.billingFinalAmountMc!==i||f.options.holdState!=="settled"||b({result:f.result})!==b({result:n.result}))throw v??Error("synchronous_publication_receipt_unknown");let w={status:r?"unknown":s==="done"?"succeeded":s,json:b({...a,amountMc:i,physicalOutcome:"terminated"})};if(!(r?await Je(t,w,p):await $e(t,w)))throw Error("Synchronous execution receipt publication unknown");return ot(f,o)}async function wt(e){if(e.options.syncExecutionProtocol!==1&&e.options.queueExecutionProtocol!==1)return null;let t=await io(e);if(!t)return e.options.queueExecutionProtocol===1||await Ge(ee(e.id),e.user_id)?B(e,"unconfirmed"):null;let r=await T(ee(e.id),e.user_id,t.tool,e.id);if(r?.phase==="published"&&e.options.holdState==="settled")return ot(e,!0);if(r?.phase==="claimed"&&r.expiresAtMs<=r.nowMs&&e.status==="running"&&!e.options.syncCapturedAt)return null;if(r?.phase==="claimed"||r?.phase==="effects_started"&&r.expiresAtMs>r.nowMs)return{status:409,headers:{"Retry-After":String(t.tool==="harvest_paa"?dt:2)},body:{job_id:e.id,error:"This request is already running under the supplied Idempotency-Key.",errorCode:"idempotency_in_progress",retryable:!0,...e.result?{result:e.result}:{}}};let o=await Ue(ee(e.id),e.user_id);if(!o)return B(e);try{return await ht(t,o,!0,!0)}catch{return B(await S(e.id,e.user_id)??e,e.options.holdState==="settled"?"settled":"held")}}async function ao(e,t,r=!0){let o=await ut(t.userId,t.hold.key);if(!o||o.status!=="applied"){if(!r)throw Error("Original applied hold is unavailable");let n=await ir(t.userId,t.hold.amountMc,t.hold.operation,t.hold.description,t.hold.key);if(!n.ok)return{status:402,body:{job_id:t.jobId,error:"Insufficient balance",error_code:"insufficient_balance",balance_mc:n.balance_mc,required_mc:t.hold.amountMc}}}return await lr(e,{hold:t.hold,label:t.profile==="queue"?"original-queue-hold":"original-sync-hold",refundOperation:t.refundOperation,sourceSurface:t.sourceSurface,tool:t.tool,jobId:t.jobId}),null}async function lo(e,t,r){let o=vt(e),n,i=!1,s=!1,a=!1,l=await S(o.jobId,o.userId);try{let u=await io(l);if(u){if(u.requestFingerprint!==o.requestFingerprint)throw Error("Synchronous request conflicts");o=u}else if(o.profile==="queue"||await Ge(ee(o.jobId),o.userId)||(await ut(o.userId,o.hold.key))?.status==="applied")return B(l,"unconfirmed");if(o.profile!=="queue"&&Date.now()>=o.deadlineAt)return B(l,"unconfirmed");let d=await Ae({id:ee(o.jobId),userId:o.userId,ownerScope:`user:${o.userId}`,tool:o.tool,jobId:o.jobId,idempotencyKey:`job:${o.jobId}`,requestFingerprint:o.requestFingerprint,normalizedFlags:{syncExecutionProtocol:1,intent:o}},no(),Math.min(36e5,Math.max(1e3,(o.profile==="queue"?o.budgetMs:o.deadlineAt-Date.now())+3e4)),_e(o));if(d.kind!=="claimed")return B(l,"unconfirmed");n=d.claim;let c=await ao(n,o);if(c)return c;let p=_e(o),h=nr(o.hold),v=await S(o.jobId,o.userId),f=to(v,{...p,sql:`(${p.sql}) AND (${h.sql})`,args:[...p.args,...h.args]});if(!await Be(n,f))throw Error("Synchronous effect start unknown");if(i=!0,o.profile==="queue"){let Ce=ne(n,{tool:o.tool,jobId:o.jobId}),I=_e(o),je;try{await m().execute({sql:`UPDATE jobs SET options=json_set(options,'$.compatDeadlineAt',CAST(strftime('%s','now') AS INTEGER)*1000+?) WHERE id=? AND user_id=? AND json_extract(options,'$.compatDeadlineAt') IS NULL AND (${I.sql}) AND (${Ce.sql})`,args:[o.budgetMs,o.jobId,o.userId,...I.args,...Ce.args]})}catch(fe){je=fe}let qe=await S(o.jobId,o.userId),W=Number(qe?.options.compatDeadlineAt);if(!Number.isSafeInteger(W)||W<=Date.now())throw je??Error("Queued deadline unavailable or expired");o={...o,deadlineAt:W}}let w=0,k=n,H={claim:n,deadlineAt:o.deadlineAt,physicalFactory:async()=>Lt({claim:k,gate:f,deadlineAt:o.deadlineAt,scope:`sync-browser-${++w}`,profile:"customer-funded"})},J=await t(H);a=!0,await oo(o,n,J.result,J.amountMc,"done",null,200,o.options.serpOnly!==!0||w>0);let nt=await ht(o,n,!1);return s=!0,nt}catch(u){if(n&&i){if(!(await S(o.jobId,o.userId))?.options.syncCapturedAt&&!a){let c=await Ee(n.runId,n.userId).catch(()=>[]);if(c.length>0&&c.every(p=>p.state==="terminated"||p.state==="not_started")){let p=r(u);try{await oo(o,n,null,0,p.terminalStatus==="cancelled"?"cancelled":"failed",p.publicError,p.httpStatus);let h=await ht(o,n,!1);return s=!0,h}catch{}}}await oe(n).catch(()=>{}),await cn(o,n).catch(()=>{})}return B(await S(o.jobId,o.userId)??l)}finally{n&&!i&&await Se(n).catch(()=>{}),n&&i&&!s&&await oe(n).catch(()=>{})}}async function Et(e,t=!0){let r=vt(e);if(r.profile!=="queue")throw Error("Queue profile required");let o=!1,n=ee(r.jobId),i=await S(r.jobId,r.userId),s=async()=>({kind:"unknown",reply:i?await B(i):{status:503,body:{job_id:r.jobId,status:"pending",executionState:"unknown",hold_state:o?"held":"unconfirmed",status_tool:"harvest_paa_status",...z({errorCode:"response_lost",retryable:!0})}}});if(i&&i.options.queueExecutionProtocol!==1)return s();let a=await T(n,r.userId,r.tool,r.jobId);if(a){if(a.flags.syncExecutionProtocol!==1||b({intent:a.flags.intent})!==b({intent:r}))return s();if(["effects_started","unknown","published"].includes(a.phase)){if(!i)return s();let d=await wt(i);if(d&&d.status!==200)return{kind:"unknown",reply:d};let c=await S(r.jobId,r.userId);return c?{kind:"ready",job:c,replayed:!0}:s()}}else if(i||await Ge(n,r.userId))return s();let l={userId:r.userId,tool:r.tool,jobId:r.jobId,sql:"EXISTS(SELECT 1 FROM users WHERE id=? AND active=1)",args:[r.userId]},u;try{let d=await Ae({id:n,userId:r.userId,ownerScope:`user:${r.userId}`,tool:r.tool,jobId:r.jobId,idempotencyKey:`job:${r.jobId}`,requestFingerprint:r.requestFingerprint,normalizedFlags:{syncExecutionProtocol:1,intent:r}},no(),45e3,l);if(d.kind!=="claimed")return s();u=d.claim;let c=await ao(u,r,t);if(c)return{kind:"unfunded",reply:c};if(o=!0,!i&&(await fr(r.jobId,r.userId,String(r.options.query),{...r.options,executionOwner:"cron",queueExecutionProtocol:1,...r.callbackUrl?{callbackDeliveryProtocol:1}:{},billingHoldMc:r.hold.amountMc,billingDebitKey:r.hold.key,requestFingerprint:r.requestFingerprint},r.callbackUrl??void 0)).kind==="unknown")return s();let p=_e(r,"'pending','running','done','failed','cancelled'"),h=(await m().execute({sql:`SELECT 1 WHERE (${p.sql})`,args:p.args})).rows.length>0,v=await S(r.jobId,r.userId);return h&&v&&await eo(v,u,p),h&&v?{kind:"ready",job:v,replayed:!!(i||a)}:s()}catch{return s()}finally{u&&await Se(u).catch(()=>{})}}function uo(e){let t=JSON.parse(b(e.options)),r=t.serpOnly===!0&&!t.serpIdentity;return{profile:"queue",jobId:e.jobId,userId:e.userId,tool:"search_serp",requestFingerprint:e.requestFingerprint,options:t,callbackUrl:e.callbackUrl??null,deadlineAt:0,budgetMs:Ut(Number(t.maxQuestions??30),!0,t.mode,t.pages,!!t.recency,r).serverMs,hold:{userId:e.userId,key:`serp-search:${e.jobId}:hold`,amountMc:e.amountMc,operation:"serp",description:`SERP search: ${t.query}`.slice(0,500)},refundOperation:"serp_refund",sourceSurface:"serp_search"}}var _i=e=>Et(uo(e));async function pn(e,t){let r;try{r=await T(`harvest:${t}`,e,"search_serp",t)}catch{return{kind:"unknown",reply:{status:503,body:{job_id:t,status:"pending",executionState:"unknown",hold_state:"unconfirmed",status_tool:"harvest_paa_status",...z({errorCode:"response_lost",retryable:!0})}}}}return r?.flags.syncExecutionProtocol!==1||r.flags.intent?.profile!=="queue"?null:Et(r.flags.intent,!1)}async function co(){for(let t of await br("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 ${sr("saved.user_id","json_extract(saved.normalized_flags_json,'$.hold.key')")}))`))await S(t.jobId,t.userId)||await pn(t.userId,t.jobId);let e=(await m().execute(`SELECT j.id,j.user_id FROM jobs j JOIN operation_runs r ON r.id='harvest:'||j.id AND r.user_id=j.user_id JOIN operation_executions x ON x.run_id=r.id
|
|
82
|
+
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
|
|
83
|
+
ORDER BY j.created_at LIMIT 1`)).rows[0];return e?S(String(e.id),Number(e.user_id)):void 0}async function po(e,t){if(e.options.queueExecutionProtocol!==1)return await m().execute({sql:"UPDATE jobs SET options=json_set(options,'$.queueExecutionProtocol',0,'$.executionState','unknown','$.holdState','unconfirmed') WHERE id=? AND user_id=? AND json_extract(options,'$.queueExecutionProtocol') IS NULL",args:[e.id,e.user_id]}),{completed:!1,replayed:!1,reply:null};let r=await wt(e);if(r)return{completed:(await S(e.id,e.user_id))?.options.executionState==="finalized"&&r.status===200,replayed:!0,reply:r};let o=e.options,n=Object.fromEntries(Object.entries(o).filter(([l])=>!["executionOwner","queueExecutionProtocol","billingHoldMc","billingDebitKey","requestFingerprint","compatDeadlineAt","executionState","holdState"].includes(l))),i=uo({jobId:e.id,userId:e.user_id,options:n,requestFingerprint:String(o.requestFingerprint),amountMc:Number(o.billingHoldMc),callbackUrl:e.callback_url}),s=await lo(i,async l=>{let u={value:null},d=o.serpOnly===!0&&!o.serpIdentity,c=`harvest:${e.id}`,p=null,h=AbortSignal.timeout(Math.max(0,l.deadlineAt-Date.now()));if(d&&!$r({pages:o.pages===2?2:1,recency:o.recency==="week"||o.recency==="month"?o.recency:void 0,mode:o.mode,token:t.apifyToken}))throw Error("Search providers are not configured");let v=await t.withCostContext({op:"serp",userId:e.user_id,headlessSentOut:u,operationRunId:c,operationAccountScope:"production-default"},async()=>d?ft({query:String(o.query??e.query),pages:o.pages===2?2:1,mode:o.mode,recency:o.recency==="week"||o.recency==="month"?o.recency:void 0,token:t.apifyToken,operationRunId:c,accountScope:"production-default",signal:h,onAttemptEvent:t.onAttemptEvent,physicalFactory:l.physicalFactory}).then(k=>(p=k,k.result)):Fe({...o,physicalExecution:await l.physicalFactory(),\u006b\u0065\u0072\u006e\u0065\u006cApiKey:t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey,headless:!0,format:"json",outputDir:"/tmp/paa-output-api",signal:h,onAttemptEvent:t.onAttemptEvent}));if(d&&!p)throw Error("Search provider billing receipt is missing");let f=p,w=d?cr(f.deliveredPages,f.deliveryProvider):dr(u.value);return{result:v,amountMc:Math.min(Number(o.billingHoldMc),w)}},t.classifyFailure);return{completed:(await S(e.id,e.user_id))?.options.executionState==="finalized"&&!!(s.body.status&&["done","failed","cancelled"].includes(String(s.body.status))),replayed:!1,reply:s}}import{randomUUID as mn}from"crypto";function Te(e){return e==null?null:Number(e)===1}function mo(e){if(e==null)return null;try{return JSON.parse(String(e))}catch{return null}}function go(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:Te(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:Te(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:Te(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:Te(e.provider_captcha),provider_checked_at:e.provider_checked_at!=null?String(e.provider_checked_at):null,provider_detail:mo(e.provider_detail_json),provider_disconnect_observed:Te(e.provider_disconnect_observed),provider_disconnect_message:e.provider_disconnect_message!=null?String(e.provider_disconnect_message):null,debug:mo(e.debug_json),created_at:String(e.created_at),completed_at:e.completed_at!=null?String(e.completed_at):null}}async function _o(e){await m().execute({sql:`
|
|
84
|
+
INSERT INTO harvest_attempts (
|
|
85
|
+
id, job_id, user_id, attempt_number, max_attempts, query, location, max_questions, status, created_at
|
|
86
|
+
)
|
|
87
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'running', ?)
|
|
88
|
+
ON CONFLICT(job_id, attempt_number) DO NOTHING
|
|
89
|
+
`,args:[mn(),e.jobId,e.userId,e.attemptNumber,e.maxAttempts,e.query,e.location,e.maxQuestions,e.startedAt]})}async function fo(e){return(await m().execute({sql:`
|
|
90
|
+
UPDATE harvest_attempts SET
|
|
91
|
+
browser_provider = ?,
|
|
92
|
+
provider_session_id = ?,
|
|
93
|
+
provider_session_observed_at = COALESCE(provider_session_observed_at, ?),
|
|
94
|
+
provider_lookup_status = CASE
|
|
95
|
+
WHEN provider_lookup_status = 'complete' THEN provider_lookup_status
|
|
96
|
+
ELSE 'pending'
|
|
97
|
+
END
|
|
98
|
+
WHERE job_id = ? AND attempt_number = ? AND status = 'running'
|
|
99
|
+
`,args:[e.browserProvider,e.providerSessionId,e.observedAt,e.jobId,e.attemptNumber]})).rowsAffected===1}async function yo(e){await m().execute({sql:`
|
|
100
|
+
UPDATE harvest_attempts SET
|
|
101
|
+
status = 'finished',
|
|
102
|
+
outcome = ?,
|
|
103
|
+
\u006b\u0065\u0072\u006e\u0065\u006c_session_id = ?,
|
|
104
|
+
question_count = ?,
|
|
105
|
+
duration_ms = ?,
|
|
106
|
+
error = ?,
|
|
107
|
+
will_retry = ?,
|
|
108
|
+
\u006b\u0065\u0072\u006e\u0065\u006c_delete_started = ?,
|
|
109
|
+
\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded = ?,
|
|
110
|
+
\u006b\u0065\u0072\u006e\u0065\u006c_delete_error = ?,
|
|
111
|
+
browser_close_succeeded = ?,
|
|
112
|
+
browser_close_error = ?,
|
|
113
|
+
browser_provider = COALESCE(browser_provider, ?),
|
|
114
|
+
provider_session_id = COALESCE(provider_session_id, ?),
|
|
115
|
+
provider_lookup_status = CASE
|
|
116
|
+
WHEN provider_lookup_status = 'complete' THEN provider_lookup_status
|
|
117
|
+
ELSE COALESCE(?, provider_lookup_status)
|
|
118
|
+
END,
|
|
119
|
+
provider_status = COALESCE(provider_status, ?),
|
|
120
|
+
provider_error_code = CASE
|
|
121
|
+
WHEN provider_reason_source = 'provider_session_api' THEN provider_error_code
|
|
122
|
+
ELSE COALESCE(?, provider_error_code)
|
|
123
|
+
END,
|
|
124
|
+
provider_error_message = CASE
|
|
125
|
+
WHEN provider_reason_source = 'provider_session_api' THEN provider_error_message
|
|
126
|
+
ELSE COALESCE(?, provider_error_message)
|
|
127
|
+
END,
|
|
128
|
+
provider_reason_source = CASE
|
|
129
|
+
WHEN provider_reason_source = 'provider_session_api' THEN provider_reason_source
|
|
130
|
+
ELSE COALESCE(?, provider_reason_source)
|
|
131
|
+
END,
|
|
132
|
+
provider_duration_ms = COALESCE(provider_duration_ms, ?),
|
|
133
|
+
provider_bandwidth_bytes = COALESCE(provider_bandwidth_bytes, ?),
|
|
134
|
+
provider_captcha = COALESCE(provider_captcha, ?),
|
|
135
|
+
provider_checked_at = COALESCE(provider_checked_at, ?),
|
|
136
|
+
provider_detail_json = COALESCE(provider_detail_json, ?),
|
|
137
|
+
provider_disconnect_observed = COALESCE(provider_disconnect_observed, ?),
|
|
138
|
+
provider_disconnect_message = COALESCE(provider_disconnect_message, ?),
|
|
139
|
+
debug_json = ?,
|
|
140
|
+
completed_at = ?
|
|
141
|
+
WHERE job_id = ? AND attempt_number = ?
|
|
142
|
+
`,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:bo(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 bo(e,t=4096){let r=JSON.stringify(e);return r.length<=t?r:JSON.stringify({truncated:!0})}async function hi(e){return(await m().execute({sql:`
|
|
143
|
+
UPDATE harvest_attempts SET
|
|
144
|
+
provider_lookup_status = ?,
|
|
145
|
+
provider_status = ?,
|
|
146
|
+
provider_error_code = ?,
|
|
147
|
+
provider_error_message = ?,
|
|
148
|
+
provider_reason_source = ?,
|
|
149
|
+
provider_duration_ms = ?,
|
|
150
|
+
provider_bandwidth_bytes = ?,
|
|
151
|
+
provider_captcha = ?,
|
|
152
|
+
provider_checked_at = ?,
|
|
153
|
+
provider_detail_json = ?
|
|
154
|
+
WHERE id = ?
|
|
155
|
+
AND job_id = ?
|
|
156
|
+
AND user_id = ?
|
|
157
|
+
AND browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
|
|
158
|
+
AND provider_session_id = ?
|
|
159
|
+
AND COALESCE(provider_lookup_status, '') <> 'complete'
|
|
160
|
+
`,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:bo(e.detail),e.attemptId,e.jobId,e.userId,e.providerSessionId]})).rowsAffected===1}async function vi(e=25){let t=Math.max(1,Math.min(100,Math.trunc(e)));return(await m().execute({sql:`
|
|
161
|
+
SELECT * FROM harvest_attempts
|
|
162
|
+
WHERE browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
|
|
163
|
+
AND provider_session_id IS NOT NULL
|
|
164
|
+
AND provider_lookup_status IN ('pending', 'temporary_error')
|
|
165
|
+
ORDER BY COALESCE(provider_checked_at, created_at) ASC
|
|
166
|
+
LIMIT ?
|
|
167
|
+
`,args:[t]})).rows.map(o=>go(o))}async function ho(e,t){return(t==null?await m().execute({sql:"SELECT * FROM harvest_attempts WHERE job_id = ? ORDER BY attempt_number ASC",args:[e]}):await m().execute({sql:`
|
|
168
|
+
SELECT ha.*
|
|
169
|
+
FROM harvest_attempts ha
|
|
170
|
+
INNER JOIN jobs j ON j.id = ha.job_id
|
|
171
|
+
WHERE ha.job_id = ? AND j.user_id = ?
|
|
172
|
+
ORDER BY ha.attempt_number ASC
|
|
173
|
+
`,args:[e,t]})).rows.map(o=>go(o))}import{createHash as Ri}from"crypto";var gn=1e9;function St(e){return e==="timeout"?"timed_out":e==="request_aborted"?"cancelled":e==="browser_session_interrupted"?"interrupted":e==="captcha"||e==="proxy_tunnel_failed"||e==="proxy_unavailable"||e==="location_mismatch"||e==="error"?"failed":"succeeded"}function _n(e){return e==="\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061":"\u006b\u0065\u0072\u006e\u0065\u006c"}function vo(e,t,r=0){let o=new Map,n=null;return async i=>{if(e)try{if(i.type==="started"){let a=r+i.attemptNumber;if(a>1&&!n){let c=(await gr(e))?.attempts.at(-1);n=c?.id==null?null:String(c.id)}let l=await se({runId:e,attemptNumber:a,method:i.method,provider:i.provider,parentAttemptId:a===1?null:n,edgeKind:a===1?null:r>0&&i.attemptNumber===1?"durable_resume":i.retryKind==="provider_fallback"?"provider_fallback":"same_method_retry",retryKind:a===1?null:r>0&&i.attemptNumber===1?"durable_resume":i.retryKind,retryReason:a===1?null:r>0&&i.attemptNumber===1?"durable_worker_resume":i.retryReason,retryOwner:a===1?null:r>0&&i.attemptNumber===1?"durable_reconciler":"harvest",normalizedFlags:{maxAttempts:i.maxAttempts,maxQuestions:i.maxQuestions,hasLocation:!!i.location,plannedProvider:i.provider,planReason:i.planReason??null,planTimeoutMs:i.planTimeoutMs??null},startedAt:i.startedAt}),u=await V({attemptId:l,provider:i.provider,providerProduct:i.provider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser_api":"\u006b\u0065\u0072\u006e\u0065\u006c_browser",billingTier:i.provider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?Re("https://www.google.com/search"):null,accountScope:t,method:i.method,providerStatus:"started"});o.set(i.attemptNumber,{attemptId:l,receiptId:u.id,plannedProvider:i.provider,observedProvider:null,providerMismatch:!1,method:i.method,startedAtMs:Date.parse(i.startedAt),billingMode:null}),n=l;return}let s=o.get(i.attemptNumber);if(!s)throw new Error(`Missing operation attempt state for attempt ${i.attemptNumber}`);if(i.type==="provider_session_started"){let a=_n(i.provider);if(s.observedProvider=a,s.billingMode=i.billingMode??null,a!==s.plannedProvider){s.providerMismatch=!0,await X({receiptId:s.receiptId,costState:"unavailable",providerStatus:"provider_mismatch",errorCode:"provider_mismatch",errorMessage:`Planned ${s.plannedProvider}; observed ${a}`,finalizedAt:i.observedAt});let l=a==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser":"\u006b\u0065\u0072\u006e\u0065\u006c_browser",u=await V({attemptId:s.attemptId,provider:a,providerProduct:a==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser_api":"\u006b\u0065\u0072\u006e\u0065\u006c_browser",billingTier:a==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?Re("https://www.google.com/search"):null,accountScope:t,method:l,providerStatus:"observed_provider_mismatch"});s.receiptId=u.id,s.method=l}await K(s.receiptId,i.providerSessionId);return}if(await ie({attemptId:s.attemptId,status:s.providerMismatch?"failed":St(i.outcome),errorCode:s.providerMismatch?"provider_mismatch":St(i.outcome)==="succeeded"?null:i.outcome,errorMessage:i.error,durationMs:i.durationMs,endedAt:i.completedAt}),(s.observedProvider??s.plannedProvider)==="\u006b\u0065\u0072\u006e\u0065\u006c"){let a=s.billingMode==="headful",l=s.billingMode==="headless"||s.billingMode==="headful"?tr(i.durationMs,a):null;await X({receiptId:s.receiptId,costState:"estimated",units:i.durationMs/1e3,unitType:"wall_open_second",amountUsdNanos:l==null?null:Math.round(l*gn),providerProduct:"\u006b\u0065\u0072\u006e\u0065\u006c_browser",billingTier:s.billingMode,billableEvent:"provider_active_gb_second",measurementSource:"wall_open_time_proxy",rateSource:l!=null?`${er};\u006b\u0065\u0072\u006e\u0065\u006c_usd_per_second:${Zt}`:null,providerStatus:s.providerMismatch?"provider_mismatch":i.outcome,providerDurationMs:i.durationMs,errorCode:s.providerMismatch?"provider_mismatch":St(i.outcome)==="succeeded"?null:i.outcome,errorMessage:i.error,finalizedAt:i.completedAt})}}catch(s){console.warn(JSON.stringify({event:"operation_attempt_telemetry_failed",operation_run_id:e,attempt_number:i.attemptNumber,message:s instanceof Error?s.message:String(s)}))}}}function wo(e,t,r=null,o="production-default",n=0){let i=vo(r,o,n);return async s=>{if(await i(s),s.type==="started"){await _o({jobId:e,userId:t,attemptNumber:s.attemptNumber,maxAttempts:s.maxAttempts,query:s.query,location:s.location,maxQuestions:s.maxQuestions,startedAt:s.startedAt});return}if(s.type==="provider_session_started"){await fo({jobId:e,attemptNumber:s.attemptNumber,browserProvider:s.provider,providerSessionId:s.providerSessionId,observedAt:s.observedAt});return}await yo({jobId:e,attemptNumber:s.attemptNumber,outcome:s.outcome,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:s.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:s.questionCount,durationMs:s.durationMs,error:s.error,willRetry:s.willRetry,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:s.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:s.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:s.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError,browserCloseSucceeded:s.cleanup.browserCloseSucceeded,browserCloseError:s.cleanup.browserCloseError,browserProvider:s.cleanup.provider??null,providerSessionId:s.cleanup.providerSessionId??null,providerLookupStatus:s.cleanup.providerSessionId?"pending":"not_applicable",providerErrorCode:s.cleanup.providerDisconnectObserved?"browser_session_interrupted":null,providerErrorMessage:s.cleanup.providerDisconnectMessage??null,providerReasonSource:s.cleanup.providerDisconnectObserved?"client_runtime":null,providerDisconnectObserved:s.cleanup.providerDisconnectObserved??!1,providerDisconnectMessage:s.cleanup.providerDisconnectMessage??null,debug:s.debug,completedAt:s.completedAt})}}function fn(e){return e instanceof Error?e.message:String(e)}function yn(e,t){return e instanceof DOMException&&(e.name==="TimeoutError"||e.name==="AbortError")?!0:/timeout|timed out|Timeout \d+ms exceeded|deadline/i.test(t)}function bn(e){return/captcha|recaptcha|unusual traffic|google\.com\/sorry|blocked/i.test(e)}function hn(e){return/ERR_TUNNEL_CONNECTION_FAILED|ERR_PROXY_CONNECTION_FAILED|ERR_SOCKS_CONNECTION_FAILED|tunnel connection failed|proxy connection failed|transport error: proxy/i.test(e)}function vn(e){return/proxy unavailable|proxy_unavailable|connection_test_failed|did not return a proxy id|configured fallback/i.test(e)}function wn(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 En(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 At(e){let t=fn(e);return e instanceof Wt?{error_code:"request_aborted",error_type:"request_aborted",message:U("request_aborted"),retryable:!0,httpStatus:408,terminalStatus:"cancelled"}:e instanceof Bt||bn(t)?{error_code:"captcha_exhausted",error_type:"captcha",message:U("captcha_exhausted"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:_r(e,t)?{error_code:"vendor_unavailable",error_type:"service_unavailable",message:U("vendor_unavailable"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:e instanceof zt?{error_code:"location_mismatch",error_type:"location_mismatch",message:U("location_mismatch"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:hn(t)?{error_code:"proxy_tunnel_failed",error_type:"connection",message:U("proxy_tunnel_failed"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:vn(t)?{error_code:"proxy_unavailable",error_type:"connection",message:U("proxy_unavailable"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:En(t)?{error_code:"browser_session_interrupted",error_type:"extraction",message:U("browser_session_interrupted"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:yn(e,t)?{error_code:"harvest_timeout",error_type:"timeout",message:U("harvest_timeout"),retryable:!0,httpStatus:504,terminalStatus:"failed"}:wn(t)?{error_code:"service_unavailable",error_type:"service_unavailable",message:lt,retryable:!0,httpStatus:503,terminalStatus:"failed"}:{error_code:"extraction_failed",error_type:"extraction",message:lt,retryable:!1,httpStatus:500,terminalStatus:"failed"}}function qi(e){return JSON.stringify({error_code:e.error_code,error_type:e.error_type,message:e.message,retryable:e.retryable})}function Eo(e,t={}){let r=z({errorCode:e.error_code,errorType:e.error_type,retryable:e.retryable,retryAfterSeconds:t.retryAfterSeconds,chargeStatus:t.chargeStatus,details:t.details});return{error:r.message,...r}}function So(e,t={}){let{error:r,...o}=Eo(e,t);return o}function Mi(e,t={}){let r=At(e);return{body:Eo(r,t),status:r.httpStatus}}import{randomUUID as Ao}from"crypto";var Sn=3e4;async function Io(e,t,r){if(!e.receiptJson)return;let o=Pe(e.id);if((await T(o,e.userId,"paa_callback",e.jobId))?.phase==="published")return;if(r){if(await $e(r,{status:"succeeded",json:e.receiptJson}))return;await oe(r)}let i=await Ue(o,e.userId);i&&await Je(i,{status:"unknown",json:e.receiptJson},Oe(e,t,"accepted"))}function An(e){return!!(e.payloadJson&&e.payloadSha256===O(e.payloadJson)&&e.sendNonce&&e.sendToken&&e.httpStatus&&e.httpStatus>=200&&e.httpStatus<300&&e.receiptJson===b({deliveryId:e.id,idempotencyKey:e.id,payloadSha256:e.payloadSha256,httpStatus:e.httpStatus}))}async function Ro(e){let t=e.record,r,o=!1;try{if(t=await j(t.id,t.userId)??t,t.state==="accepted")return An(t)?(await Io(t,e.domain).catch(()=>{}),L(t)):{state:"unavailable",deliveryId:t.id};if(["sending","unknown","expired","unavailable"].includes(t.state))return L(t);if(t.expiresAtMs<=t.nowMs)return await rt(t,"expired"),L(await j(t.id,t.userId));if(t.payloadJson||(t=await Vr(t,await e.compose(),e.domain)),!t.payloadJson||t.payloadSha256!==O(t.payloadJson))throw Error("Delivery payload conflicts");let n=Oe(t,e.domain,"frozen"),i=Pe(t.id),s={version:1,purpose:"outbound-callback",request:$(t),payloadSha256:t.payloadSha256},a=await Ae({id:i,userId:t.userId,ownerScope:`user:${t.userId}`,tool:"paa_callback",jobId:t.jobId,idempotencyKey:t.id,requestFingerprint:O(b(s)),normalizedFlags:s},Ao(),Sn,n);if(a.kind!=="claimed"){let u=await T(i,t.userId,"paa_callback",t.jobId);if(u&&["effects_started","unknown","published"].includes(u.phase)){await yt(t),u.phase==="published"&&await rt(t,"unavailable",n);let d=await j(t.id,t.userId);return d?L(d):{state:"unknown",deliveryId:t.id}}return{state:"pending",deliveryId:t.id,expiresAtMs:t.expiresAtMs}}if(r=a.claim,!await e.validate(t.url))return L(t);if(!await Be(r,n))throw Error("Delivery effects start is unconfirmed");if(o=!0,t=await Kr(t,r,Ao(),e.domain),!await Xr(t,r,e.domain))throw Error("Delivery authority was lost before send");let l=await fetch(t.url,{method:"POST",headers:{"content-type":"application/json","idempotency-key":t.id},body:t.payloadJson,redirect:"error",signal:AbortSignal.timeout(1e4)});if(!l.ok||l.status<200||l.status>=300)throw Error("Recipient acceptance is unconfirmed");return t=await Yr(t,l.status),await Io(t,e.domain,r).catch(()=>{}),L(t)}catch(n){if(n instanceof Q&&await rt(t,"unavailable",e.domain).catch(()=>{}),r){let s=await T(r.runId,r.userId,"paa_callback",t.jobId).catch(()=>null);(o||s?.phase==="effects_started"||s?.phase==="unknown")&&await oe(r).catch(()=>{})}t.sendNonce?await Qr(t).catch(()=>{}):await yt(t).catch(()=>{});let i=await j(t.id,t.userId).catch(()=>null);return i?L(i):{state:"unknown",deliveryId:t.id}}finally{r&&!o&&await Se(r).catch(()=>{})}}async function It(e,t){let r=await ro(e,t);return r.kind==="none"?{state:"none"}:r.kind==="unavailable"?{state:"unavailable"}:r.kind==="pending"?(await L(r.record),{state:"pending",deliveryId:r.record.id,expiresAtMs:r.record.expiresAtMs}):Ro({record:r.record,domain:r.domain,validate:async o=>{let n=await pr(o,{field:"callback_url",requireHttps:!0});return!n.error&&n.parsed?.href===o&&!n.parsed.username&&!n.parsed.password},compose:async()=>{let o=(await ot(r.job,!1)).body;return{...o,...o.result?{result:or(o.result)}:{},...r.record.profile==="paa-queue"?{attempts:rr(await ho(r.job.id,r.job.user_id))}:{}}}})}async function Qi(e=25){let t=0,r=0,o=await Zr(e);for(let n of o)try{(await It(n.jobId,n.userId)).state==="accepted"?t++:r++}catch{r++}return{checked:o.length,accepted:t,pending:r}}var No=2,Rt=0;async function ko(){let e=await co(),t=e?void 0:await yr(),r=e??(t?await S(t.id,Number(t.user_id)):void 0);if(!r)return{claimed:!1};let o=Date.now();Rt++;try{let n=await po(r,{\u006b\u0065\u0072\u006e\u0065\u006cApiKey:$t(),apifyToken:process.env.APIFY_API_TOKEN?.trim(),onAttemptEvent:wo(r.id,r.user_id,`harvest:${r.id}`),withCostContext:Xt,classifyFailure:i=>{let s=At(i);return{publicError:So(s),httpStatus:s.httpStatus,terminalStatus:s.terminalStatus}}});return n.completed&&r.callback_url&&await It(r.id,r.user_id).catch(()=>{}),{claimed:!0,jobId:r.id,completed:n.completed,durationMs:Date.now()-o}}finally{Rt--}}async function la(e){let t=[];for(let r=0;r<e.maxJobs&&!(Date.now()>=e.deadlineMs);r++){let o=await ko();if(t.push(o),!o.claimed)break}return t}function ua(){setInterval(async()=>{Rt>=No||ko()},2e3),console.log(`[worker] started \u2014 polling every 2s, max ${No} concurrent`)}export{Pn as a,On as b,Tn as c,Cn as d,jn as e,qn as f,Mn as g,Ln as h,Br as i,et as j,Re as k,Ve as l,Ho as m,Xn as n,hi as o,vi as p,ho as q,At as r,qi as s,So as t,Mi as u,eo as v,to as w,B as x,cn as y,oo as z,ot as A,ht as B,wt as C,lo as D,It as E,Qi as F,$n as G,br as H,$r as I,ft as J,_i as K,pn as L,wo as M,ko as N,la as O,ua as P};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import{c as b}from"./chunk-5LYINW7Z.js";import{g as y,i as f}from"./chunk-C7MGJUTU.js";var h={\u006b\u0065\u0072\u006e\u0065\u006c:"browserRuntime"},E=/error|message/i,x=(new RegExp("(?:spending|billing|organization|account).{0,80}(?:cap|limit|blocked|disabled)|(?:quota|capacity).{0,40}(?:reached|exceeded)|https?:\\/\\/\\S*(?:dashboard|on\u006b\u0065\u0072\u006e\u0065\u006c)", "i")),T=/\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,N=new Set(["\u006b\u0065\u0072\u006e\u0065\u006c_session_id","browser_session_id","\u006b\u0065\u0072\u006e\u0065\u006cSessionId","browserSessionId","sessionId","\u006b\u0065\u0072\u006e\u0065\u006c_delete_started","session_cleanup_started","\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted","sessionCleanupStarted","\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded","session_cleanup_succeeded","\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded","sessionCleanupSucceeded","\u006b\u0065\u0072\u006e\u0065\u006c_delete_error","session_cleanup_error","\u006b\u0065\u0072\u006e\u0065\u006cDeleteError","sessionCleanupError","\u006b\u0065\u0072\u006e\u0065\u006cProxyId","proxyId","requestedProxyIdSuffix","retrievedProxyIdSuffix","provider","providerName","service","serviceName","vendor","vendorName","organization","organizationId","accountId","browser_provider","provider_session_id","provider_session_observed_at","provider_lookup_status","provider_status","provider_error_code","provider_error_message","provider_reason_source","provider_duration_ms","provider_bandwidth_bytes","provider_captcha","provider_checked_at","provider_detail","provider_detail_json","provider_disconnect_observed","provider_disconnect_message","browserProvider","providerSessionId","providerLookupStatus","providerStatus","providerErrorCode","providerErrorMessage","providerReasonSource","providerDurationMs","providerBandwidthBytes","providerCaptcha","providerCheckedAt","providerDetail","providerDisconnectObserved","providerDisconnectMessage"]),O=new Set(["hosted_url","hostedUrl","live_view_url","liveViewUrl","cdp_ws_url","cdpWsUrl","browser_live_view_url"]),L=(new RegExp("\\b(?:wss?|https?):\\/\\/[^\\s\"'<>]*\\bon\u006b\u0065\u0072\u006e\u0065\u006c\\.com[^\\s\"'<>]*", "gi"));function k(e){return e.replace(L,"[browser-service]")}var D=new Set(["\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api","\u006b\u0065\u0072\u006e\u0065\u006c","local"]),j=new Set(["pending","complete","not_found","unavailable_credentials","temporary_error","invalid_payload","not_applicable"]),q=new Set(["active","running","complete","completed","failed","closed","stopped","terminated","timed_out"]),F=new Set(["provider_session_api","client_runtime","extractor","unknown"]),U=new Set(["browser_disconnected","worker_disconnect","job_killed","cdp_cmd_timeout","network_inactivity_timeout","session_timeout","client_timeout","navigate_domains_limit","cdp_error","browser_session_interrupted","provider_detail_pending","provider_lookup_unavailable","provider_reported_no_error","provider_session_not_found","provider_invalid_json","provider_invalid_payload","provider_lookup_timeout","provider_lookup_network_error","unknown"]),M=new Set(["browser_provider","provider_session_id","provider_lookup_status","provider_status","provider_error_code","provider_error_message","provider_reason_source","provider_duration_ms","provider_bandwidth_bytes","provider_captcha","provider_checked_at","provider_detail","provider_detail_json","provider_disconnect_observed","provider_disconnect_message"]),$=512,z=320;function p(e,r){return typeof e=="string"&&r.has(e)?e:null}function H(e){return typeof e!="string"?null:U.has(e)||/^provider_http_(?:429|5\d\d)$/.test(e)?e:null}function Q(e){return typeof e!="string"||e.length<1||e.length>$||/^(?:authorization|bearer|password|secret|token|api[_-]?key|account)/i.test(e)?null:/^[A-Za-z0-9._:-]+$/.test(e)&&!e.includes("://")?e:null}function R(e){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=0?e:null}function A(e){if(typeof e!="string"||e.length>40)return null;let r=Date.parse(e);return Number.isFinite(r)&&new Date(r).toISOString()===e?e:null}function C(e){if(typeof e!="string")return null;let r=e.replace(/[\u0000-\u001f\u007f]+/g," ").replace(/\s+/g," ").trim();if(!r||r.startsWith("{")||r.startsWith("["))return null;let t=r.replace(/\b(?:wss?|https?):\/\/\S+/gi,"[redacted endpoint]").replace(/\b(?:authorization|proxy-authorization)\s*:\s*(?:Bearer\s+)?\S+/gi,"[redacted credential]").replace(/\bBearer\s+\S+/gi,"[redacted credential]").replace(/\b(?:api[_-]?key|password|secret|token|account[_-]?id)\s*[=:]\s*[^\s,;]+/gi,"[redacted credential]").replace(/\b(?:account|organization)\s+(?:id\s+)?[A-Za-z0-9_-]{4,}/gi,"[redacted account]");return k(t).slice(0,z)}function w(e){return typeof e=="boolean"?e:null}function V(e){return{browser_provider:p(e.browser_provider,D),provider_session_id:Q(e.provider_session_id),provider_session_observed_at:A(e.provider_session_observed_at),provider_lookup_status:p(e.provider_lookup_status,j),provider_status:p(e.provider_status,q),provider_error_code:H(e.provider_error_code),provider_error_message:C(e.provider_error_message),provider_reason_source:p(e.provider_reason_source,F),provider_duration_ms:R(e.provider_duration_ms),provider_bandwidth_bytes:R(e.provider_bandwidth_bytes),provider_captcha:w(e.provider_captcha),provider_checked_at:A(e.provider_checked_at),provider_disconnect_observed:w(e.provider_disconnect_observed),provider_disconnect_message:C(e.provider_disconnect_message)}}function l(e,r=""){if(typeof e=="string"){let t=k(e);return E.test(r)&&(x.test(e)||T.test(e))?t=y("service_unavailable"):E.test(r)&&(t=f(t)),t}if(Array.isArray(e))return e.map(t=>l(t,r));if(e!==null&&typeof e=="object"){let t={};for(let[n,o]of Object.entries(e)){if(N.has(n))continue;let i=h[n]??n;if(O.has(n)){t[i]=null;continue}t[i]=l(o,n)}return t}return e}function Y(e){return e.map(r=>{if(r===null||typeof r!="object"||Array.isArray(r))return l(r);let t=r,n=l(t);return Object.keys(t).some(i=>M.has(i))?{...n,...V(t)}:n})}function X(e){let r=e?.diagnostics;if(!r)return e;let t=r.serpCompleteness,n=t?.queryIntegrity;return!r.debug&&!n?e:{...e,diagnostics:{...r,...r.debug?{debug:l(r.debug)}:{},...n?{serpCompleteness:{...t,queryIntegrity:{...n,outboundProviderMethod:"search"}}}:{}}}}var ee="strftime('%Y-%m-%dT%H:%M:%fZ','now')",_="julianday('now')";var oe=20,m="(json_extract(options,'$.executionOwner')='direct' AND json_extract(options,'$.serpOnly') IS NOT 1)",se=`NOT COALESCE(${m},0) AND json_extract(options,'$.syncExecutionProtocol') IS NOT 1 AND json_extract(options,'$.queueExecutionProtocol') IS NULL`,ie=`${m} AND julianday(json_extract(options,'$.paaLeaseExpiresAt')) > ${_}`,ae=`${m} AND (
|
|
2
|
+
(json_extract(options,'$.paaLeaseExpiresAt') IS NOT NULL AND COALESCE(julianday(json_extract(options,'$.paaLeaseExpiresAt')),0) <= ${_})
|
|
3
|
+
OR (json_extract(options,'$.paaLeaseExpiresAt') IS NULL AND julianday(started_at) <= julianday('now','-15 minutes'))
|
|
4
|
+
)`;function ue(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 de(e,r){return!r||r.jobId!==e||!Number.isSafeInteger(r.userId)||r.userId<=0||!Number.isSafeInteger(r.recoveryCount)||r.recoveryCount<0||r.leaseToken!==null&&(typeof r.leaseToken!="string"||r.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:[r.userId,r.leaseToken,r.recoveryCount,r.resultJson]}}function le(e,r,t){let n={userId:e.user_id,tool:"harvest_paa",jobId:e.id,sql:"0",args:[]},o=e.options.requestFingerprint;if(e.options.executionProtocol!==1||e.options.executionOwner!=="direct"||e.options.serpOnly===!0||typeof o!="string"||!/^[a-f0-9]{64}$/.test(o)||!r||t.userId!==e.user_id||t.key!==e.options.billingDebitKey||t.amountMc!==e.options.billingHoldMc)return n;let i=b(t);return{...n,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')) > ${_}
|
|
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,o,r,t.key,t.amountMc,...i.args]}}import{createHash as B}from"crypto";var G=["observed_present","observed_absent","incomplete","not_requested","unknown","unsupported"],J=["provider_transport","invalid_payload","serp_readiness","query_integrity","pagination","optional_feature_parsing","unknown"],P=class extends Error{stage;failureCode;constructor(r,t,n){super(n),this.name="SerpExtractionError",this.stage=r,this.failureCode=t}};function g(e){return B("sha256").update(e).digest("hex")}function W(e){return e.normalize("NFKC").toLocaleLowerCase("en-US").split(/[^\p{L}\p{N}]+/u).filter(Boolean).slice(0,64)}function _e(e){try{let r=new URL(e);return r.hash="",r.pathname.length>1&&(r.pathname=r.pathname.replace(/\/+$/,"")),r.toString()}catch{return e.trim()}}function ge(e,r){let t=e===2?[1,2]:[1],n=r.filter(s=>s.attempted).map(s=>s.page),o=r.filter(s=>s.captured&&s.resultCount>0).map(s=>s.page),i=r.find(s=>s.failureCode);return{status:t.every(s=>o.includes(s))?"complete":"incomplete",requestedPages:t,attemptedPages:n,capturedPages:o,pageResultCounts:t.map(s=>({page:s,resultCount:r.find(S=>S.page===s)?.resultCount??0})),providerRequestCount:n.length,evidence:r,failureCode:i?.failureCode??null}}function Se(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 me(e){let r=g(e.query),t=e.finalQuery==null?null:g(e.finalQuery),n=e.locationResolutionSource==="unresolved";return{status:t!==null&&t!==r?"query_mismatch":n?"unresolved_location":"matched",queryHash:r,normalizedQueryTokens:W(e.query),canonicalLocation:e.canonicalLocation??null,locationResolutionSource:e.locationResolutionSource,locationAmbiguousCandidates:Math.max(0,Math.trunc(e.locationAmbiguousCandidates??0)),uulePresent:!!e.uule,uuleHash:e.uule?g(e.uule):null,outboundProviderMethod:e.outboundProviderMethod,finalQueryHash:t}}function ve(e){return g(JSON.stringify(Object.fromEntries(Object.entries(e).filter(([r,t])=>r!=="requestFingerprint"&&t!==void 0).sort(([r],[t])=>r.localeCompare(t)))))}function c(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function v(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.trunc(e):0}function u(e,r){return typeof e=="string"&&e.length<=r?e:null}function ye(e){let r=c(e),t=c(r.pagination),n=c(r.features),o=c(r.queryIntegrity),i=a=>Array.isArray(a)?a.filter(d=>d===1||d===2).slice(0,2):[],s=i(t.requestedPages);if(s.length===0)return null;let S=new Set(G),I=new Set(J);return{pagination:{status:t.status==="complete"?"complete":"incomplete",requestedPages:s,attemptedPages:i(t.attemptedPages),capturedPages:i(t.capturedPages),pageResultCounts:Array.isArray(t.pageResultCounts)?t.pageResultCounts.slice(0,2).map(a=>{let d=c(a);return{page:d.page===2?2:1,resultCount:v(d.resultCount)}}):[],providerRequestCount:v(t.providerRequestCount),failureCode:u(t.failureCode,100)},features:Object.fromEntries(["localPack","forums","videos","aiOverview","whatPeopleSaying","aiMode","paaPreview","entityIds"].map(a=>[a,S.has(String(n[a]))?n[a]:"unknown"])),queryIntegrity:{status:["matched","unresolved_location","query_mismatch"].includes(String(o.status))?o.status:"query_mismatch",queryHash:u(o.queryHash,64)??"",normalizedQueryTokens:Array.isArray(o.normalizedQueryTokens)?o.normalizedQueryTokens.slice(0,64).flatMap(a=>typeof a=="string"?[a.slice(0,100)]:[]):[],canonicalLocation:u(o.canonicalLocation,500),locationResolutionSource:u(o.locationResolutionSource,100)??"unknown",locationAmbiguousCandidates:v(o.locationAmbiguousCandidates),uulePresent:o.uulePresent===!0,uuleHash:u(o.uuleHash,64),outboundProviderMethod:"search",finalQueryHash:u(o.finalQueryHash,64)},failureStage:I.has(String(r.failureStage))?r.failureStage:null}}export{l as a,Y as b,X as c,ee as d,oe as e,m as f,se as g,ie as h,ae as i,ue as j,de as k,le as l,P as m,_e as n,ge as o,Se as p,me as q,ve as r,ye as s};
|