mcp-scraper 0.96.2 → 0.97.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -1
- package/README.md +12 -18
- package/dist/actions-NCZNPYEY.js +1 -0
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.js +26 -27
- package/dist/bin/mcp-scraper-core.js +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.js +1 -1
- package/dist/bin/paa-harvest.js +1 -1
- package/dist/bundle-XR6XKYJM.js +1 -0
- package/dist/chunk-4P3LZNVA.js +954 -0
- package/dist/chunk-6FAMBNHY.js +1 -0
- package/dist/chunk-A4UASMEQ.js +1 -0
- package/dist/chunk-AMYPXA2F.js +930 -0
- package/dist/{chunk-HUNSEGUN.js → chunk-ANQ4JJVI.js} +43 -29
- package/dist/chunk-B5Y26E3A.js +1 -0
- package/dist/{chunk-WP3QS4CJ.js → chunk-EYGA6LOU.js} +1 -1
- package/dist/{chunk-HVQZRQRJ.js → chunk-GLCR4KJI.js} +16 -37
- package/dist/{chunk-7WPCGRD7.js → chunk-JNPM3U3L.js} +41 -34
- package/dist/chunk-K3VDGJNK.js +1 -0
- package/dist/chunk-ND4WIBXT.js +16 -0
- package/dist/{chunk-ZTMQEDIB.js → chunk-NULRGHJ4.js} +1 -1
- package/dist/{chunk-DTVKZU5X.js → chunk-OOB3RKWD.js} +2 -2
- package/dist/{chunk-6BD75VKS.js → chunk-OSKCHEVM.js} +1 -1
- package/dist/{chunk-BPKTUCV7.js → chunk-PD7BI7TR.js} +1 -1
- package/dist/chunk-PKQHHCO4.js +20 -0
- package/dist/{chunk-SFUOSJ3A.js → chunk-PQRT4T2G.js} +3 -3
- package/dist/chunk-U3NV72AL.js +8 -0
- package/dist/{chunk-JHT6A4U6.js → chunk-WHVK6FUB.js} +1 -1
- package/dist/{chunk-2OKQVTQ5.js → chunk-XYUJTIPE.js} +66 -36
- package/dist/chunk-YJPFEL2E.js +1 -0
- package/dist/{chunk-SE4VKLEC.js → chunk-Z4EHBBL4.js} +1 -1
- package/dist/{core-schema-423BSTE6.js → core-schema-Y47YFKH2.js} +7 -44
- package/dist/dispatch-ILBBKOSW.js +1 -0
- package/dist/index.cjs +10 -10
- package/dist/index.js +1 -1
- package/dist/metering-YHZ46GV4.js +1 -0
- package/dist/queue-VOGXQDPR.js +1 -0
- package/dist/reconciliation-OXBG7JA2.js +1 -0
- package/dist/repository-UKDA4IWP.js +1 -0
- package/dist/{server-AEEE7E3C.js → server-6HUBN3OR.js} +918 -1196
- package/dist/settlement-3PS32LQO.js +1 -0
- package/dist/worker-NXRU3TT3.js +1 -0
- package/package.json +2 -3
- package/dist/actions-R4EJDLRO.js +0 -1
- package/dist/bundle-FCXZMIRB.js +0 -1
- package/dist/chunk-2IATUJO6.js +0 -1
- package/dist/chunk-5BKSKLHX.js +0 -1
- package/dist/chunk-5LYINW7Z.js +0 -8
- package/dist/chunk-6K7ZJYQW.js +0 -16
- package/dist/chunk-7H6YWD2L.js +0 -1
- package/dist/chunk-CORWWDHL.js +0 -1
- package/dist/chunk-H6MODA7W.js +0 -935
- package/dist/chunk-KUEMW76G.js +0 -955
- package/dist/chunk-RYX4FJVH.js +0 -1
- package/dist/chunk-UXNR3K6I.js +0 -1
- package/dist/dispatch-P7IY75LH.js +0 -1
- package/dist/metering-ZH2P62IC.js +0 -1
- package/dist/queue-AC4XKD6Z.js +0 -1
- package/dist/reconciliation-UZUZ6B74.js +0 -1
- package/dist/repository-4EC5EXVN.js +0 -1
- package/dist/settlement-6CS4JZTY.js +0 -1
- package/dist/worker-HHUU2ECG.js +0 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import{i as
|
|
2
|
-
WHERE r.id='extract-site:' || site_extract_jobs.id AND r.tool='extract_site')`,args:[]};if(e.workflow.runId!==`extract-site:${t}`||n&&(!e.phase||e.recovery))return{sql:"0",args:[]};let r=f(e.workflow,{tool:"extract_site",jobId:t,recovery:e.recovery}),a="site_extract_jobs.user_id = ?";if(!e.phase)return{sql:`(${r.sql} AND ${a})`,args:[...r.args,e.workflow.userId]};if(e.phase.userId!==e.workflow.userId)return{sql:"0",args:[]};let s=f(e.phase,{tool:"extract_site_phase",jobId:t});return{sql:`(${r.sql} AND ${a} AND ${s.sql})`,args:[...r.args,e.workflow.userId,...s.args]}}function h(t="site_extract_jobs."){return`(${
|
|
3
|
-
AND ${
|
|
1
|
+
import{i as T,m as j}from"./chunk-KXJCGV3H.js";import{n as f,r as w}from"./chunk-ANQ4JJVI.js";import{d as E,e as C,i as p}from"./chunk-C7MGJUTU.js";import{a as o}from"./chunk-WNUXMPVX.js";import{createHash as U}from"crypto";import{gunzipSync as k,gzipSync as $}from"zlib";var H=10,m=20*1024*1024;function g(t){return U("sha256").update(t).digest("hex")}function W(t){return!t.acquiredHtml||t.extractionStatus==="failed"?null:{pageId:t.pageId??g(t.archivedUrl??t.url),url:t.archivedUrl??t.url,html:t.acquiredHtml,mainHtml:t.mainHtml??"",markdown:t.bodyMarkdown,htmlSha256:t.htmlSha256??g(t.acquiredHtml),markdownSha256:t.markdownSha256??g(t.bodyMarkdown)}}function A(t){return Buffer.from(JSON.stringify({version:"site-extract-content.v1",pages:t}))}async function I(t){let e=t.pages.flatMap(i=>{let c=W(i);return c?[c]:[]}),n=new Map,r=[],a=0,s=async()=>{if(!r.length)return;let i=A(r);if(i.length>m)throw new Error(`site export content chunk exceeds ${m} bytes`);let c=g(r.map(l=>l.pageId).join("\0")).slice(0,16),u=await T({ownerId:t.ownerId,jobId:t.jobId,createdAt:t.createdAt,chunkKey:`content-${String(a).padStart(4,"0")}-${c}`,content:$(i,{level:6})});for(let l of r)n.set(l.url,{artifactId:u.artifactId,artifactSha256:u.sha256,pageId:l.pageId,uncompressedBytes:i.length});a++,r=[]};for(let i of e){let c=[...r,i];if(r.length>0&&(c.length>H||A(c).length>m)&&await s(),r.push(i),A(r).length>m)throw new Error(`page ${i.pageId} exceeds the durable content chunk limit`)}return await s(),n}function Y(t){let e=new Map;return async n=>{let r=e.get(n.artifactId);if(r&&r.digest!==n.artifactSha256)throw new Error("site export content chunk checksum mismatch");let a=r?.chunk;if(!a){let i=await j({artifactId:n.artifactId,ownerId:t});if(!i)throw new Error("site export content chunk is missing or unauthorized");if(g(i)!==n.artifactSha256)throw new Error("site export content chunk checksum mismatch");let c=k(i);if(c.length>m)throw new Error("site export content chunk exceeds its read limit");if(a=JSON.parse(c.toString("utf8")),a.version!=="site-extract-content.v1"||!Array.isArray(a.pages))throw new Error("site export content chunk has an unsupported contract");for(e.set(n.artifactId,{digest:n.artifactSha256,chunk:a});e.size>2;)e.delete(e.keys().next().value)}let s=a.pages.find(i=>i.pageId===n.pageId);if(!s)throw new Error("site export page is missing from its content chunk");if(g(s.html)!==s.htmlSha256||g(s.markdown)!==s.markdownSha256)throw new Error("site export page checksum mismatch");return s}}import{randomUUID as J}from"crypto";function x(t,e,n=!1){if(!e)return{sql:`NOT EXISTS (SELECT 1 FROM operation_executions x JOIN operation_runs r ON r.id=x.run_id
|
|
2
|
+
WHERE r.id='extract-site:' || site_extract_jobs.id AND r.tool='extract_site')`,args:[]};if(e.workflow.runId!==`extract-site:${t}`||n&&(!e.phase||e.recovery))return{sql:"0",args:[]};let r=f(e.workflow,{tool:"extract_site",jobId:t,recovery:e.recovery}),a="site_extract_jobs.user_id = ?";if(!e.phase)return{sql:`(${r.sql} AND ${a})`,args:[...r.args,e.workflow.userId]};if(e.phase.userId!==e.workflow.userId)return{sql:"0",args:[]};let s=f(e.phase,{tool:"extract_site_phase",jobId:t});return{sql:`(${r.sql} AND ${a} AND ${s.sql})`,args:[...r.args,e.workflow.userId,...s.args]}}function h(t="site_extract_jobs."){return`(${w(`${t}id`,`${t}user_id`,"extract_site")}
|
|
3
|
+
AND ${w(`${t}id`,`${t}user_id`,"extract_site_phase")})`}function y(){return w("site_extract_jobs.id","site_extract_jobs.user_id","extract_site_phase")}function D(t="site_extract_jobs."){return`(${t}status='running' OR (${t}status='pending' AND ${t}execution_generation=0 AND (
|
|
4
4
|
EXISTS (SELECT 1 FROM operation_runs r WHERE r.id='extract-site:' || ${t}id AND r.user_id=${t}user_id AND r.tool='extract_site')
|
|
5
|
-
OR COALESCE(json_extract(${t}options,'$.__websiteExecutionProtocol'),0) <> 1)))`}var q="xray_entitlement";function st(t){let e=Math.max(1,Number(t.options.effectiveMaxPages??t.options.maxPages??1)),n=Math.max(e,Number(t.options.requestedMaxPages??e)),r=n>e;return{requestedMaxPages:n,effectiveMaxPages:e,creditLimited:r,creditTruncated:r&&t.totalUrls>=e}}function it(t,e=!1){return t.successfulUrls===0?"failed":t.failedUrls>0||t.remainingUrls>0||e?"partial":"complete"}function
|
|
5
|
+
OR COALESCE(json_extract(${t}options,'$.__websiteExecutionProtocol'),0) <> 1)))`}var q="xray_entitlement";function st(t){let e=Math.max(1,Number(t.options.effectiveMaxPages??t.options.maxPages??1)),n=Math.max(e,Number(t.options.requestedMaxPages??e)),r=n>e;return{requestedMaxPages:n,effectiveMaxPages:e,creditLimited:r,creditTruncated:r&&t.totalUrls>=e}}function it(t,e=!1){return t.successfulUrls===0?"failed":t.failedUrls>0||t.remainingUrls>0||e?"partial":"complete"}function _(t){let e=Number(t.total_urls??0),n=t.attempted_urls==null,r=Number(n?t.done_urls??0:t.attempted_urls),a=Number(n?t.done_urls??0:t.successful_urls??0),s=Number(t.failed_urls??Math.max(0,r-a)),i=t.options?JSON.parse(String(t.options)):{},c=i.__websiteExecutionProtocol;delete i.__websiteExecutionProtocol;let u={id:String(t.id),userId:t.user_id!=null?Number(t.user_id):null,idempotencyKey:t.idempotency_key!=null?String(t.idempotency_key):null,requestFingerprint:t.request_fingerprint!=null?String(t.request_fingerprint):null,status:t.status!=null?String(t.status):"pending",executionGeneration:Number(t.execution_generation??0),refinalizeUntil:t.refinalize_until==null?null:String(t.refinalize_until),settlementPlan:t.settlement_plan_json?JSON.parse(String(t.settlement_plan_json)):null,settlementReceipt:t.settlement_receipt_json?JSON.parse(String(t.settlement_receipt_json)):null,dispatchClaimToken:t.dispatch_claim_token==null?null:String(t.dispatch_claim_token),dispatchClaimUntil:t.dispatch_claim_until==null?null:String(t.dispatch_claim_until),dispatchedAt:t.dispatched_at==null?null:String(t.dispatched_at),dispatchAttempts:Number(t.dispatch_attempts??0),dispatchError:t.dispatch_error==null?null:String(t.dispatch_error),startUrl:String(t.start_url??""),options:i,totalUrls:e,doneUrls:r,attemptedUrls:r,successfulUrls:a,failedUrls:s,remainingUrls:Math.max(0,e-r),artifacts:t.artifacts?JSON.parse(String(t.artifacts)):null,error:t.error!=null?String(t.error):null,publicError:C(t.public_error_json),billedMc:t.billed_mc!=null?Number(t.billed_mc):null,createdAt:String(t.created_at??""),updatedAt:String(t.updated_at??"")};return c===1&&Object.defineProperty(u,"executionProtocol",{value:1,enumerable:!1}),u}async function v(t,e){let r=await o().execute({sql:"SELECT * FROM site_extract_jobs WHERE user_id = ? AND idempotency_key = ? LIMIT 1",args:[t,e]});return r.rows[0]?_(r.rows[0]):null}async function ot(t){let n=await o().execute({sql:`INSERT OR IGNORE INTO site_extract_jobs
|
|
6
6
|
(id, user_id, status, start_url, options, idempotency_key, request_fingerprint, created_at, updated_at)
|
|
7
|
-
VALUES (?, ?, 'pending', ?, ?, ?, ?, datetime('now'), datetime('now'))`,args:[t.jobId,t.userId,t.startUrl,JSON.stringify({...t.options,__websiteExecutionProtocol:1}),t.idempotencyKey,t.requestFingerprint]}),r=await v(t.userId,t.idempotencyKey);if(!r)throw new Error("idempotent extract job was not persisted");return{job:r,created:n.rowsAffected===1,conflict:r.requestFingerprint!==t.requestFingerprint}}async function P(t){let n=await o().execute({sql:"SELECT * FROM site_extract_jobs WHERE id = ?",args:[t]});return n.rows[0]?
|
|
7
|
+
VALUES (?, ?, 'pending', ?, ?, ?, ?, datetime('now'), datetime('now'))`,args:[t.jobId,t.userId,t.startUrl,JSON.stringify({...t.options,__websiteExecutionProtocol:1}),t.idempotencyKey,t.requestFingerprint]}),r=await v(t.userId,t.idempotencyKey);if(!r)throw new Error("idempotent extract job was not persisted");return{job:r,created:n.rowsAffected===1,conflict:r.requestFingerprint!==t.requestFingerprint}}async function P(t){let n=await o().execute({sql:"SELECT * FROM site_extract_jobs WHERE id = ?",args:[t]});return n.rows[0]?_(n.rows[0]):null}async function ct(t=25){return(await o().execute({sql:`SELECT * FROM site_extract_jobs
|
|
8
8
|
WHERE billed_mc IS NULL AND status IN ('complete', 'partial', 'failed')
|
|
9
9
|
AND (next_settlement_at IS NULL OR next_settlement_at <= datetime('now'))
|
|
10
|
-
ORDER BY updated_at ASC LIMIT ?`,args:[Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(r=>
|
|
10
|
+
ORDER BY updated_at ASC LIMIT ?`,args:[Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(r=>_(r))}var N=`(
|
|
11
11
|
EXISTS (SELECT 1 FROM billing_debits d
|
|
12
12
|
WHERE d.idempotency_key = json_extract(site_extract_jobs.options, '$.debitKey')
|
|
13
13
|
AND d.user_id = site_extract_jobs.user_id AND d.status = 'applied'
|
|
@@ -25,33 +25,40 @@ import{i as j,m as T}from"./chunk-KXJCGV3H.js";import{m as f,q as b}from"./chunk
|
|
|
25
25
|
AND json_type(options, '$.xraySetupReceipt.heldMc') IN ('integer', 'real')
|
|
26
26
|
AND json_extract(options, '$.xraySetupReceipt.heldMc') = 0
|
|
27
27
|
AND json_type(options, '$.xraySetupReceipt.billedMc') IN ('integer', 'real')
|
|
28
|
-
AND json_extract(options, '$.xraySetupReceipt.billedMc') = 0))`;async function
|
|
28
|
+
AND json_extract(options, '$.xraySetupReceipt.billedMc') = 0))`;async function ut(t){let e=await o().execute({sql:`SELECT * FROM site_extract_jobs WHERE id = ? AND user_id > 0
|
|
29
29
|
AND status IN ('pending', 'running') AND billed_mc IS NULL
|
|
30
|
-
AND execution_generation = 0 AND ${
|
|
31
|
-
AND execution_generation = 0 AND dispatched_at IS NULL AND ${
|
|
30
|
+
AND execution_generation = 0 AND ${N}`,args:[t]});return e.rows[0]?_(e.rows[0]):null}async function F(t=25,e=2){let n=Math.max(1,Math.min(60,Math.round(e)));return(await o().execute({sql:`SELECT * FROM site_extract_jobs WHERE status = 'pending' AND billed_mc IS NULL
|
|
31
|
+
AND execution_generation = 0 AND dispatched_at IS NULL AND ${N}
|
|
32
32
|
AND (dispatch_claim_token IS NULL OR dispatch_claim_until <= datetime('now'))
|
|
33
33
|
AND (next_dispatch_at IS NULL OR next_dispatch_at <= datetime('now'))
|
|
34
|
-
AND updated_at <= datetime('now', ?) ORDER BY updated_at, id LIMIT ?`,args:[`-${n} minutes`,Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(a=>
|
|
34
|
+
AND updated_at <= datetime('now', ?) ORDER BY updated_at, id LIMIT ?`,args:[`-${n} minutes`,Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(a=>_(a))}async function lt(t=25){return(await o().execute({sql:`SELECT * FROM site_extract_jobs WHERE status IN ('pending', 'running') AND billed_mc IS NULL
|
|
35
|
+
AND execution_generation = 0 AND ${N}
|
|
36
|
+
AND (
|
|
37
|
+
(dispatched_at <= datetime('now', '-30 seconds') AND NOT EXISTS (SELECT 1 FROM operation_executions e WHERE e.run_id = 'extract-site:' || site_extract_jobs.id))
|
|
38
|
+
OR EXISTS (SELECT 1 FROM operation_executions e JOIN operation_runs r ON r.id = e.run_id
|
|
39
|
+
WHERE e.run_id = 'extract-site:' || site_extract_jobs.id AND r.status = 'running'
|
|
40
|
+
AND e.phase = 'claimed' AND e.expires_at_ms <= CAST((julianday('now') - 2440587.5) * 86400000 AS INTEGER))
|
|
41
|
+
) ORDER BY updated_at, id LIMIT ?`,args:[Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(n=>_(n))}async function dt(t={}){let e=t.jobId?[t.jobId]:(await F(t.limit)).map(r=>r.id),n=[];for(let r of e){let a=J(),i=(await o().execute({sql:`UPDATE site_extract_jobs SET dispatch_claim_token = ?, dispatch_claim_until = datetime('now', ?),
|
|
35
42
|
dispatch_attempts = dispatch_attempts + 1, dispatch_error = NULL, next_dispatch_at = NULL,
|
|
36
43
|
updated_at = datetime('now')
|
|
37
44
|
WHERE id = ? AND status = 'pending' AND billed_mc IS NULL AND execution_generation = 0
|
|
38
|
-
AND dispatched_at IS NULL AND ${
|
|
45
|
+
AND dispatched_at IS NULL AND ${N}
|
|
39
46
|
AND (dispatch_claim_token IS NULL OR dispatch_claim_until <= datetime('now'))
|
|
40
47
|
AND (next_dispatch_at IS NULL OR next_dispatch_at <= datetime('now'))
|
|
41
|
-
RETURNING id, dispatch_claim_token, dispatch_attempts`,args:[a,`+${Math.max(15,Math.min(3600,Math.round(t.leaseSeconds??300)))} seconds`,r]})).rows[0];i&&n.push({id:String(i.id),claimToken:String(i.dispatch_claim_token),attempts:Number(i.dispatch_attempts)})}return n}async function
|
|
48
|
+
RETURNING id, dispatch_claim_token, dispatch_attempts`,args:[a,`+${Math.max(15,Math.min(3600,Math.round(t.leaseSeconds??300)))} seconds`,r]})).rows[0];i&&n.push({id:String(i.id),claimToken:String(i.dispatch_claim_token),attempts:Number(i.dispatch_attempts)})}return n}async function _t(t,e){return(await o().execute({sql:`SELECT id FROM site_extract_jobs WHERE id = ? AND status = 'pending' AND billed_mc IS NULL
|
|
42
49
|
AND execution_generation = 0 AND dispatched_at IS NULL AND dispatch_claim_token = ?
|
|
43
|
-
AND dispatch_claim_until > datetime('now') AND ${
|
|
50
|
+
AND dispatch_claim_until > datetime('now') AND ${N}`,args:[t,e]})).rows.length===1}async function gt(t,e){return(await o().execute({sql:`UPDATE site_extract_jobs SET dispatched_at = datetime('now'), dispatch_claim_token = NULL,
|
|
44
51
|
dispatch_claim_until = NULL, next_dispatch_at = NULL, dispatch_error = NULL, updated_at = datetime('now')
|
|
45
52
|
WHERE id = ? AND execution_generation = 0 AND dispatched_at IS NULL
|
|
46
|
-
AND dispatch_claim_token = ? AND dispatch_claim_until > datetime('now')`,args:[t,e]})).rowsAffected===1}async function
|
|
53
|
+
AND dispatch_claim_token = ? AND dispatch_claim_until > datetime('now')`,args:[t,e]})).rowsAffected===1}async function pt(t,e,n,r){return(await o().execute({sql:`UPDATE site_extract_jobs SET dispatch_error = ?, next_dispatch_at = datetime('now', ?),
|
|
47
54
|
dispatch_claim_token = NULL, dispatch_claim_until = NULL, updated_at = datetime('now')
|
|
48
55
|
WHERE id = ? AND status = 'pending' AND billed_mc IS NULL AND execution_generation = 0
|
|
49
|
-
AND dispatched_at IS NULL AND dispatch_claim_token = ? AND dispatch_claim_until > datetime('now')`,args:[n.slice(0,2e3),`+${Math.max(15,Math.min(3600,Math.round(r)))} seconds`,t,e]})).rowsAffected===1}async function
|
|
56
|
+
AND dispatched_at IS NULL AND dispatch_claim_token = ? AND dispatch_claim_until > datetime('now')`,args:[n.slice(0,2e3),`+${Math.max(15,Math.min(3600,Math.round(r)))} seconds`,t,e]})).rowsAffected===1}async function Et(t,e,n=0){await o().execute({sql:`UPDATE site_extract_jobs SET
|
|
50
57
|
settlement_attempts = settlement_attempts + 1,
|
|
51
58
|
settlement_error = ?,
|
|
52
59
|
next_settlement_at = datetime('now', '+15 minutes'),
|
|
53
60
|
updated_at = datetime('now')
|
|
54
|
-
WHERE id = ? AND billed_mc IS NULL AND execution_generation = ? AND status IN ('complete', 'partial', 'failed')`,args:[p(e).slice(0,1e3),t,n]})}function
|
|
61
|
+
WHERE id = ? AND billed_mc IS NULL AND execution_generation = ? AND status IN ('complete', 'partial', 'failed')`,args:[p(e).slice(0,1e3),t,n]})}function O(t=""){return`((${t}execution_generation = 0 AND ${t}updated_at <= datetime('now', ?))
|
|
55
62
|
OR (${t}execution_generation > 0 AND ${t}refinalize_until <= datetime('now')))`}async function mt(t=25,e=60){let n=o(),r=Math.max(15,Math.min(1440,Math.round(e)));return(await n.execute({sql:`SELECT j.* FROM site_extract_jobs j
|
|
56
63
|
LEFT JOIN billing_debits d
|
|
57
64
|
ON d.idempotency_key = json_extract(j.options, '$.debitKey')
|
|
@@ -63,8 +70,8 @@ import{i as j,m as T}from"./chunk-KXJCGV3H.js";import{m as f,q as b}from"./chunk
|
|
|
63
70
|
json_extract(j.options, '$.debitKey') IS NULL
|
|
64
71
|
OR d.idempotency_key IS NOT NULL
|
|
65
72
|
)
|
|
66
|
-
AND ${
|
|
67
|
-
ORDER BY j.updated_at ASC LIMIT ?`,args:[`-${r} minutes`,Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(s=>
|
|
73
|
+
AND ${O("j.")} AND ${h("j.")}
|
|
74
|
+
ORDER BY j.updated_at ASC LIMIT ?`,args:[`-${r} minutes`,Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(s=>_(s))}async function xt(t,e=60){let n=o(),r=Math.max(15,Math.min(1440,Math.round(e)));return(await n.execute({sql:`UPDATE site_extract_jobs
|
|
68
75
|
SET status = 'failed',
|
|
69
76
|
error = 'Background extraction attempt expired; completed pages were preserved and settlement is pending.',
|
|
70
77
|
public_error_json = ?,
|
|
@@ -72,16 +79,16 @@ import{i as j,m as T}from"./chunk-KXJCGV3H.js";import{m as f,q as b}from"./chunk
|
|
|
72
79
|
WHERE id = ?
|
|
73
80
|
AND ${D()}
|
|
74
81
|
AND billed_mc IS NULL
|
|
75
|
-
AND ${
|
|
82
|
+
AND ${O()} AND ${h()}`,args:[E({error_code:"extraction_failed",error_type:"extraction",message:"The background extraction attempt expired. Completed pages were preserved; retry after settlement completes.",retryable:!0,charge_status:"refund_pending"}),t,`-${r} minutes`]})).rowsAffected===1}async function Nt(t){let e=await o().execute({sql:`UPDATE site_extract_jobs
|
|
76
83
|
SET status = 'running', execution_generation = execution_generation + 1,
|
|
77
84
|
refinalize_until = datetime('now', '+60 minutes'), updated_at = datetime('now')
|
|
78
85
|
WHERE id = ? AND (settlement_plan_json IS NULL OR billed_mc IS NOT NULL) AND (status = 'failed' OR (
|
|
79
86
|
status = 'running' AND execution_generation > 0 AND refinalize_until <= datetime('now')
|
|
80
|
-
)) RETURNING *`,args:[t]});return e.rows[0]?
|
|
81
|
-
AND execution_generation = ? AND (execution_generation = 0 OR refinalize_until > datetime('now'))`,args:[t,e]})).rows.length===1}async function
|
|
82
|
-
WHERE id = ? AND billed_mc IS NULL AND execution_generation = ? AND status IN ('complete', 'partial', 'failed')`,args:[p(e).slice(0,1e3),t,n]})}async function
|
|
87
|
+
)) RETURNING *`,args:[t]});return e.rows[0]?_(e.rows[0]):null}async function z(t,e=0){return(await o().execute({sql:`SELECT 1 FROM site_extract_jobs WHERE id = ? AND status IN ('pending', 'running')
|
|
88
|
+
AND execution_generation = ? AND (execution_generation = 0 OR refinalize_until > datetime('now'))`,args:[t,e]})).rows.length===1}async function bt(t,e,n=0){await o().execute({sql:`UPDATE site_extract_jobs SET billed_mc = 0, settlement_error = ?, updated_at = datetime('now')
|
|
89
|
+
WHERE id = ? AND billed_mc IS NULL AND execution_generation = ? AND status IN ('complete', 'partial', 'failed')`,args:[p(e).slice(0,1e3),t,n]})}async function wt(t,e,n){let r=o(),a=x(t,n);await r.execute({sql:`UPDATE site_extract_jobs
|
|
83
90
|
SET status = 'running', total_urls = MAX(total_urls, ?), updated_at = datetime('now')
|
|
84
|
-
WHERE id = ? AND status IN ('pending', 'running') AND execution_generation = 0 AND ${a.sql}`,args:[e,t,...a.args]})}async function
|
|
91
|
+
WHERE id = ? AND status IN ('pending', 'running') AND execution_generation = 0 AND ${a.sql}`,args:[e,t,...a.args]})}async function St(t,e,n){if(e.length===0)return;let r=o(),a=await P(t);if(!a||!await z(t)){if(n)throw Error("site_crawl_page_write_not_current");return}let s=x(t,n,!0);if(!(await r.execute({sql:`SELECT 1 FROM site_extract_jobs WHERE id=? AND ${s.sql}`,args:[t,...s.args]})).rows.length){if(n)throw Error("site_crawl_page_write_not_current");return}let c=a?.userId!=null?await I({ownerId:String(a.userId),jobId:t,createdAt:a.createdAt,pages:e}):new Map,u=e.map(d=>{let{discoveryLinks:M,acquiredHtml:b,mainHtml:R,...L}=d;return L.contentRef=c.get(d.archivedUrl??d.url)??d.contentRef,{sql:`INSERT INTO site_extract_pages (job_id, url, page)
|
|
85
92
|
SELECT ?, ?, ?
|
|
86
93
|
WHERE EXISTS (
|
|
87
94
|
SELECT 1 FROM site_extract_jobs
|
|
@@ -109,7 +116,7 @@ import{i as j,m as T}from"./chunk-KXJCGV3H.js";import{m as f,q as b}from"./chunk
|
|
|
109
116
|
AND json_extract(excluded.page, '$.wordCount') > 0,
|
|
110
117
|
0
|
|
111
118
|
)
|
|
112
|
-
END`,args:[t,d.archivedUrl??d.url,JSON.stringify(L),t,...s.args]}}),
|
|
119
|
+
END`,args:[t,d.archivedUrl??d.url,JSON.stringify(L),t,...s.args]}}),l,S;try{S=await r.batch([...u,{sql:`UPDATE site_extract_jobs SET
|
|
113
120
|
done_urls = (SELECT COUNT(*) FROM site_extract_pages WHERE job_id = ?),
|
|
114
121
|
attempted_urls = (SELECT COUNT(*) FROM site_extract_pages WHERE job_id = ?),
|
|
115
122
|
successful_urls = (
|
|
@@ -136,18 +143,18 @@ import{i as j,m as T}from"./chunk-KXJCGV3H.js";import{m as f,q as b}from"./chunk
|
|
|
136
143
|
END
|
|
137
144
|
),
|
|
138
145
|
updated_at = datetime('now')
|
|
139
|
-
WHERE id = ? AND status IN ('pending', 'running') AND execution_generation = 0 AND ${s.sql}`,args:[t,t,t,t,t,...s.args]}],"write")}catch(d){
|
|
146
|
+
WHERE id = ? AND status IN ('pending', 'running') AND execution_generation = 0 AND ${s.sql}`,args:[t,t,t,t,t,...s.args]}],"write")}catch(d){l=d}if(l){let d=await Promise.all(u.map(b=>r.execute({sql:"SELECT page FROM site_extract_pages WHERE job_id=? AND url=?",args:b.args.slice(0,2)})));if(!(await r.execute({sql:`SELECT 1 FROM site_extract_jobs WHERE id=? AND ${s.sql}
|
|
140
147
|
AND attempted_urls=(SELECT COUNT(*) FROM site_extract_pages WHERE job_id=?)
|
|
141
148
|
AND successful_urls=(SELECT COUNT(*) FROM site_extract_pages WHERE job_id=site_extract_jobs.id AND CASE
|
|
142
149
|
WHEN json_extract(page,'$.extractionStatus') IS NOT NULL THEN json_extract(page,'$.extractionStatus')='successful'
|
|
143
150
|
ELSE COALESCE(json_extract(page,'$.status')>=200 AND json_extract(page,'$.status')<300 AND json_extract(page,'$.wordCount')>0,0) END)
|
|
144
|
-
AND failed_urls=attempted_urls-successful_urls`,args:[t,...s.args,t]})).rows.length||d.some((
|
|
151
|
+
AND failed_urls=attempted_urls-successful_urls`,args:[t,...s.args,t]})).rows.length||d.some((b,R)=>b.rows[0]?.page!==u[R].args[2]))throw l}else if(n&&S?.at(-1)?.rowsAffected!==1)throw Error("site_crawl_page_write_not_current")}async function ft(t){return(await o().execute({sql:"SELECT page FROM site_extract_pages WHERE job_id = ? ORDER BY rowid",args:[t]})).rows.map(r=>JSON.parse(String(r.page)))}async function At(t,e=181){let n=o(),r=Math.max(1,Math.min(5001,Math.round(e)));return(await n.execute({sql:`SELECT DISTINCT CAST(images.value AS TEXT) AS url
|
|
145
152
|
FROM site_extract_pages p,
|
|
146
153
|
json_each(CASE WHEN json_valid(p.page) THEN p.page ELSE '{}' END, '$.imageLinks') images
|
|
147
154
|
WHERE p.job_id = ?
|
|
148
155
|
AND images.type = 'text'
|
|
149
156
|
AND length(CAST(images.value AS TEXT)) BETWEEN 1 AND 4096
|
|
150
|
-
LIMIT ?`,args:[t,r]})).rows.map(s=>String(s.url))}async function
|
|
157
|
+
LIMIT ?`,args:[t,r]})).rows.map(s=>String(s.url))}async function ht(t){let n=await o().execute({sql:`SELECT COUNT(*) AS n FROM site_extract_pages
|
|
151
158
|
WHERE job_id = ? AND CASE
|
|
152
159
|
WHEN json_extract(page, '$.extractionStatus') IS NOT NULL
|
|
153
160
|
THEN json_extract(page, '$.extractionStatus') = 'successful'
|
|
@@ -157,26 +164,26 @@ import{i as j,m as T}from"./chunk-KXJCGV3H.js";import{m as f,q as b}from"./chunk
|
|
|
157
164
|
AND json_extract(page, '$.wordCount') > 0,
|
|
158
165
|
0
|
|
159
166
|
)
|
|
160
|
-
END`,args:[t]});return Number(n.rows[0]?.n??0)}async function
|
|
167
|
+
END`,args:[t]});return Number(n.rows[0]?.n??0)}async function Dt(t,e,n,r=null,a=!1,s=null,i=0,c){let u=o(),l=x(t,c,!0);return(await u.execute({sql:`UPDATE site_extract_jobs
|
|
161
168
|
SET status = ?, artifacts = ?, error = ?, public_error_json = ?, updated_at = datetime('now')
|
|
162
169
|
WHERE id = ? AND execution_generation = ? AND (settlement_plan_json IS NULL OR billed_mc IS NOT NULL)
|
|
163
170
|
AND (
|
|
164
171
|
(execution_generation = 0 AND (status IN ('pending', 'running') OR (? = 1 AND status = 'failed')))
|
|
165
172
|
OR (execution_generation > 0 AND status = 'running' AND refinalize_until > datetime('now'))
|
|
166
|
-
) AND (execution_generation > 0 OR ${
|
|
173
|
+
) AND (execution_generation > 0 OR ${l.sql})`,args:[n,JSON.stringify(e??[]),r?p(r).slice(0,2e3):null,E(s),t,i,a?1:0,...l.args]})).rowsAffected===1}async function Rt(t,e,n,r=0,a){let s=x(t,a);return(await o().execute({sql:`UPDATE site_extract_jobs
|
|
167
174
|
SET status = 'failed', error = ?, public_error_json = ?, updated_at = datetime('now')
|
|
168
175
|
WHERE id = ? AND status IN ('pending', 'running') AND execution_generation = ?
|
|
169
176
|
AND (execution_generation = 0 OR refinalize_until > datetime('now'))
|
|
170
|
-
AND (execution_generation > 0 OR (${s.sql} AND ${
|
|
177
|
+
AND (execution_generation > 0 OR (${s.sql} AND ${y()}))`,args:[p(e).slice(0,2e3),E(n),t,r,...s.args]})).rowsAffected===1}async function Lt(t,e,n){await o().execute({sql:`UPDATE site_extract_jobs
|
|
171
178
|
SET status = 'failed', billed_mc = 0, error = ?, public_error_json = ?, updated_at = datetime('now')
|
|
172
|
-
WHERE id = ? AND status = 'pending' AND billed_mc IS NULL`,args:[p(e).slice(0,2e3),
|
|
179
|
+
WHERE id = ? AND status = 'pending' AND billed_mc IS NULL`,args:[p(e).slice(0,2e3),E(n),t]})}async function Ct(t){return await o().execute({sql:`UPDATE site_extract_jobs SET settlement_plan_json = ?, updated_at = datetime('now')
|
|
173
180
|
WHERE id = ? AND user_id = ? AND execution_generation = ? AND status = ?
|
|
174
|
-
AND billed_mc IS NULL AND settlement_plan_json IS NULL`,args:[JSON.stringify(t),t.jobId,t.userId,t.generation,t.status]}),P(t.jobId)}async function
|
|
181
|
+
AND billed_mc IS NULL AND settlement_plan_json IS NULL`,args:[JSON.stringify(t),t.jobId,t.userId,t.generation,t.status]}),P(t.jobId)}async function Tt(t,e){let n=t.billingClass===q?"not_charged":e.netChargeMc>0?"charged":e.refundMc>0?"refunded":"not_charged";await o().execute({sql:`UPDATE site_extract_jobs SET billed_mc = ?, settlement_receipt_json = ?,
|
|
175
182
|
public_error_json = CASE WHEN json_valid(public_error_json) THEN json_set(public_error_json, '$.charge_status', ?) ELSE public_error_json END,
|
|
176
183
|
updated_at = datetime('now')
|
|
177
184
|
WHERE id = ? AND user_id = ? AND execution_generation = ? AND status = ?
|
|
178
|
-
AND billed_mc IS NULL AND settlement_plan_json = ?`,args:[e.netChargeMc,JSON.stringify(e),n,t.jobId,t.userId,t.generation,t.status,JSON.stringify(t)]})}async function jt(t,e,n,r,a,s=0){let{settleExtractJobCharge:i}=await import("./settlement-
|
|
185
|
+
AND billed_mc IS NULL AND settlement_plan_json = ?`,args:[e.netChargeMc,JSON.stringify(e),n,t.jobId,t.userId,t.generation,t.status,JSON.stringify(t)]})}async function jt(t,e,n,r,a,s=0){let{settleExtractJobCharge:i}=await import("./settlement-3PS32LQO.js");return i(t,e,n,r,a,s)}var B=25;async function*It(t){let e=o(),n=0;for(;;){let r=await e.execute({sql:`SELECT rowid AS cursor_id, page
|
|
179
186
|
FROM site_extract_pages
|
|
180
187
|
WHERE job_id = ? AND rowid > ?
|
|
181
188
|
ORDER BY rowid
|
|
182
|
-
LIMIT ${B}`,args:[t,n]});if(!r.rows.length)return;if(n=Number(r.rows.at(-1)?.cursor_id??n),!Number.isSafeInteger(n)||n<=0)throw new Error("site extract page cursor is invalid");yield r.rows.map(a=>JSON.parse(String(a.page)))}}export{Y as a,q as b,st as c,it as d,v as e,ot as f,P as g,ct as h,
|
|
189
|
+
LIMIT ${B}`,args:[t,n]});if(!r.rows.length)return;if(n=Number(r.rows.at(-1)?.cursor_id??n),!Number.isSafeInteger(n)||n<=0)throw new Error("site extract page cursor is invalid");yield r.rows.map(a=>JSON.parse(String(a.page)))}}export{Y as a,q as b,st as c,it as d,v as e,ot as f,P as g,ct as h,ut as i,lt as j,dt as k,_t as l,gt as m,pt as n,Et as o,mt as p,xt as q,Nt as r,z as s,bt as t,wt as u,St as v,ft as w,At as x,ht as y,Dt as z,Rt as A,Lt as B,Ct as C,Tt as D,jt as E,B as F,It as G};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as w,b as u,c as _,d as l,e as h,m as g,p}from"./chunk-7SR7MEU5.js";import{k as c,m}from"./chunk-ANQ4JJVI.js";import{b as I,c as s}from"./chunk-4ZVO6GX4.js";async function R(e){let r=s(),n=!r?.operationRunId,o=r?.operationRunId??(await c({userId:r?.userId??null,ownerScope:r?.userId!=null?`user:${r.userId}`:"system:unscoped",tool:e.tool,normalizedFlags:{subOperation:r?.subOp??null},deploymentCommit:process.env.VERCEL_GIT_COMMIT_SHA?.trim()||process.env.GIT_COMMIT_SHA?.trim()||null})).id,a=n?null:await p(o),i=a?.attempts.at(-1),t=e.parentAttemptId??(e.retryKind&&i?String(i.id):r?.operationRootAttemptId),b=e.edgeKind??(e.retryKind==="same_method"?"same_method_retry":e.retryKind==="provider_fallback"?"provider_fallback":void 0),d=t?await _({runId:o,parentAttemptId:t,edgeKind:b??"parallel_child",method:e.method,provider:e.provider,retryKind:e.retryKind,retryReason:e.retryReason}):await u({runId:o,attemptNumber:(a?.attempts.length??0)+1,method:e.method,provider:e.provider,...i?{parentAttemptId:String(i.id),edgeKind:b??"next_phase",retryKind:e.retryKind??null,retryReason:e.retryReason??null}:{}}),y;try{y=(await h({attemptId:d,provider:e.provider,providerProduct:e.providerProduct,billingTier:e.billingTier,accountScope:r?.operationAccountScope??"production-default",method:e.method,providerStatus:"started"})).id}catch(f){throw await w({tool:e.tool,method:e.method,phase:"pending_receipt_create",errorCode:f instanceof Error?f.name:"UnknownError",runId:o,attemptId:d}).catch(()=>{}),await l({attemptId:d,status:"failed",errorCode:"pending_receipt_create_failed",durationMs:0}).catch(()=>{}),f}return{runId:o,attemptId:d,receiptId:y,ownsRun:n,startedAtMs:Date.now()}}async function S(e,r,n){await l({attemptId:e.attemptId,status:r,errorCode:n??null,durationMs:Date.now()-e.startedAtMs}),e.ownsRun&&await m({runId:e.runId,status:r,failureClass:n??null})}async function T(e,r){let n=s(),o=null,a=Date.now();if(n?.operationRunId&&n.operationRootAttemptId)try{o=await _({runId:n.operationRunId,parentAttemptId:n.operationRootAttemptId,edgeKind:"parallel_child",method:e})}catch(t){console.warn(JSON.stringify({event:"local_cost_phase_start_failed",method:e,message:t instanceof Error?t.message:String(t)}))}let i="failed";try{let t=await r();return i="succeeded",t}finally{o&&await l({attemptId:o,status:i,durationMs:Date.now()-a,errorCode:i==="failed"?"local_phase_failed":null}).catch(t=>console.warn(JSON.stringify({event:"local_cost_phase_finish_failed",method:e,message:t instanceof Error?t.message:String(t)})))}}async function M(e,r){let n=s()?.operationRunId;n&&await g({runId:n,billingTable:"billing_debits",billingKey:e,relation:"debit",amountMc:r}).catch(o=>console.warn(JSON.stringify({event:"cost_billing_link_failed",message:o instanceof Error?o.message:String(o)})))}async function K(e,r){let n=s();if(n?.operationRunId)return I({...n,op:e.op,userId:e.userId},r);let o=null,a=null;try{o=(await c({userId:e.userId,ownerScope:`user:${e.userId}`,tool:e.tool,normalizedFlags:e.normalizedFlags,deploymentCommit:process.env.VERCEL_GIT_COMMIT_SHA?.trim()||process.env.GIT_COMMIT_SHA?.trim()||null})).id,e.billingDebitKey&&await g({runId:o,billingTable:"billing_debits",billingKey:e.billingDebitKey,relation:"debit"}).catch(t=>console.warn(JSON.stringify({event:"cost_billing_link_failed",tool:e.tool,message:t instanceof Error?t.message:String(t)}))),a=await u({runId:o,attemptNumber:1,method:`${e.tool}_root`,normalizedFlags:e.normalizedFlags})}catch(t){console.warn(JSON.stringify({event:"logical_cost_run_start_failed",tool:e.tool,message:t instanceof Error?t.message:String(t)}))}let i="failed";try{let t=await I({...n,op:e.op,userId:e.userId,operationRunId:o,operationRootAttemptId:a},r);return i=t instanceof Response&&t.status>=400?"failed":"succeeded",t}finally{o&&a?await v({runId:o,rootAttemptId:a,status:i,failureClass:i==="failed"?"operation_failed":null}).catch(t=>console.warn(JSON.stringify({event:"logical_cost_run_finish_failed",tool:e.tool,message:t instanceof Error?t.message:String(t)}))):o&&await m({runId:o,status:i,failureClass:i==="failed"?"operation_failed":null}).catch(()=>{})}}async function O(e){let r=await c({...e.jobId?{id:`extract-url:${e.jobId}`,idempotencyKey:`job:${e.jobId}`,requestFingerprint:e.jobId,jobId:e.jobId}:{},userId:e.userId,ownerScope:`user:${e.userId}`,tool:"extract_url",normalizedFlags:e.normalizedFlags,deploymentCommit:process.env.VERCEL_GIT_COMMIT_SHA?.trim()||process.env.GIT_COMMIT_SHA?.trim()||null}),n=r.replayed?await p(r.id):null,o=n?.attempts[0]?.id==null?await u({runId:r.id,attemptNumber:1,method:"extract_url_root",normalizedFlags:e.normalizedFlags}):String(n.attempts[0].id);return e.billingDebitKey&&await g({runId:r.id,billingTable:"billing_debits",billingKey:e.billingDebitKey,relation:"debit"}),{runId:r.id,rootAttemptId:o}}async function v(e){let r=await p(e.runId),n=r?.attempts.find(o=>String(o.id)===e.rootAttemptId);n?.status==="running"&&await l({attemptId:e.rootAttemptId,status:e.status,errorCode:e.failureClass??null,durationMs:Math.max(0,Date.now()-Date.parse(String(n.started_at)))}),r?.run.status==="running"&&await m({runId:e.runId,status:e.status,failureClass:e.failureClass??null})}export{R as a,S as b,T as c,M as d,K as e,O as f,v as g};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import{a as s}from"./chunk-EYGA6LOU.js";var _={message:"User scheduling and automatic cleanup have been removed. Memory, video and connected services run through the native runtime; manual workflows, full-file delivery, reusable templates and existing credits remain available. SDK templates now live in the artifacts namespace. PAA progress checks remain at least 20 seconds apart."};var i={reset:"\x1B[0m",cyan:"\x1B[36m",lime:"\x1B[32m",amber:"\x1B[33m",red:"\x1B[31m",muted:"\x1B[90m",bold:"\x1B[1m"};function r(t,e,n){return n?`${i[e]}${t}${i.reset}`:t}function o(t,e,n){let a=t.padEnd(9," ");return` ${r(a,"muted",n)} ${e.join(r(" . ","muted",n))}`}function b(t){let e=t.color??!0,n=t.apiKeyConfigured?"$MCP_SCRAPER_API_KEY":"sk_live_your_key",a=String.raw`
|
|
2
|
+
__ __ ____ ____
|
|
3
|
+
| \/ |/ ___| _ \
|
|
4
|
+
| |\/| | | | |_) |
|
|
5
|
+
| | | | |___| __/
|
|
6
|
+
|_| |_|\____|_|
|
|
7
|
+
|
|
8
|
+
____ ____ ____ _ ____ _____ ____
|
|
9
|
+
/ ___| / ___| _ \ / \ | _ \| ____| _ \
|
|
10
|
+
\___ \| | | |_) | / _ \ | |_) | _| | |_) |
|
|
11
|
+
___) | |___| _ < / ___ \| __/| |___| _ <
|
|
12
|
+
|____/ \____|_| \_\/_/ \_\_| |_____|_| \_\
|
|
13
|
+
`,c=[`MCP_SCRAPER_API_KEY=${n} npx -y -p mcp-scraper@latest \\`," mcp-scraper-cli agent install claude --apply"].join(`
|
|
14
|
+
`),l=["[mcp_servers.mcp-scraper]",'command = "npx"','args = ["-y", "-p", "mcp-scraper@latest", "mcp-scraper"]',`env = { MCP_SCRAPER_API_KEY = "${n}" }`].join(`
|
|
15
|
+
`);return[r(`mcp-scraper v${t.version}`,"bold",e),r("> mcp-scraper-install","muted",e),r(a,"amber",e),`${r("MCP Scraper Agent","cyan",e)} . v${t.version} . mcpscraper.dev`,"1/1 install surfaces ready",r(`Newest in v${t.version}: ${_.message}`,"lime",e),"",`${r("Tools","cyan",e)} ${r(`(${s.inventory.totalTools} MCP tools)`,"muted",e)}`,o("search",["harvest_paa","search_serp","maps_search","maps_place_intel"],e),o("extract",["extract_url","map_site_urls","extract_site","audit_site","directory_workflow"],e),o("build",["create_editorial_reading_room","rank_tracker_workflow","portable HTML"],e),o("media",["youtube_harvest","youtube_transcribe","facebook_reels_inventory","facebook_ad_search","facebook_page_intel","facebook_ad_transcribe","facebook_video_transcribe","tiktok_video_transcribe","instagram_profile_content","instagram_media_download","reddit_thread"],e),o("browser",["serp_identity_create","serp_identity_list","browser_open","browser_profile_connect","browser_profile_list","browser_close","browser_screenshot","browser_read","browser_locate","browser_replay_mark","browser_replay_annotate"],e),o("connect",["list_service_connections","describe_service_connection_tool","import_service_connection_to_memory","export_connected_service_data","renew_connected_data_download","read_service_connection","call_service_connection_action"],e),o("commons",["commons_search_entities","commons_get_entity_linkset","commons_prepare_entity","commons_submit_entity","commons_prepare_publication","commons_claim_publication","commons_publish_editorial","commons_get_publication"],e),o("account",["credits_info","reports","MCP resources"],e),o("memory",["memory-put","memory-get","memory-search","list-vaults","record-fact","list_artifact_templates"],e),`${r("Workflows","cyan",e)} ${r("(MCP + CLI + API)","muted",e)}`,o("route",["workflow_list","workflow_suggest","workflow_run","workflow_step","workflow_status","workflow_artifact_read"],e),o("seo",["directory","agent-packet","competitive audit","map/serp comparison","PAA/AIO briefs"],e),"",r("Usage tips:","amber",e),"Run mcp-scraper-install for this visible card. Run mcp-scraper-cli for setup utilities and subcommands.","Run mcp-scraper in a human terminal to print this card; MCP clients get the same command as a silent stdio server.","Explicit card command: npx -y -p mcp-scraper@latest mcp-scraper-install","Hosted browser sessions use direct/no-proxy egress by default.","Customer auth setup: run browser_profile_connect, send the watch_url, let the user sign in, then call browser_profile_list until AUTHENTICATED.","Connected account ranges: call export_connected_service_data once. It handles Gmail, Calendar, Zoom, and Resend pagination; do not loop read_service_connection over individual records.","Connected account RAG: call import_service_connection_to_memory for one bounded approved read. It writes a redacted, untrusted snapshot to a stable Memory path and embeds it for search.","Stack logins / reconnect: run browser_profile_connect again with the same profile name and another domain to add accounts or refresh a login.","Start with workflow_suggest for broad jobs like market analysis, ICP research, CRO audits, brand briefs, content gaps, and AI visibility.","For MCP clients, use mcp-scraper so one install can mix SERP, Maps, browser, reports, and saved MCP resources.","If you hit the concurrency limit, add 2 browsers for $5/month with mcp-scraper-cli billing concurrency checkout.","",`${r("Ready.","lime",e)} Install the combined MCP server with one command:`,"",r("Setup doctor","amber",e),"npx -y -p mcp-scraper@latest mcp-scraper-cli doctor","",r("Hosted profile setup","amber",e),'In your MCP client, call browser_profile_connect with email="seo@example.com" and domain="chatgpt.com".',"Give the returned watch_url to the user. After they sign in, call browser_profile_list, then browser_open with the returned profile. Add more logins by calling browser_profile_connect again with the same profile and a new domain.","",r("Claude Code one-command setup","amber",e),c,"Then fully exit Claude Code and open a new Claude terminal. Check with: claude mcp list","",r("Codex config","amber",e),l,"",r("Claude Desktop Extension","amber",e),"Download: https://mcpscraper.dev/downloads/mcp-scraper.mcpb","",r("Safety note:","muted",e),"mcp-scraper prints this card only when stdin/stdout are an interactive TTY. In MCP clients it writes only JSON-RPC to stdout.","Use --stdio or MCP_SCRAPER_FORCE_STDIO=1 to force server mode from a terminal.",""].join(`
|
|
16
|
+
`)}export{b as a};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as ot}from"./chunk-U4WIJZCX.js";import{
|
|
1
|
+
import{a as ot}from"./chunk-U4WIJZCX.js";import{G as fe,a as Qe,c as Ve}from"./chunk-JNPM3U3L.js";import{g as Ke,h as Ze}from"./chunk-KXJCGV3H.js";import{c as st}from"./chunk-JMZIDHYQ.js";import{c as tt,e as nt,f as rt,g as it}from"./chunk-CNSVZTTT.js";import{c as et}from"./chunk-K3VDGJNK.js";import{h as Ge}from"./chunk-C7MGJUTU.js";import{a as se}from"./chunk-WNUXMPVX.js";import{createWriteStream as ae,mkdtempSync as Yt,mkdirSync as le,readFileSync as Wt,readdirSync as Gt,rmSync as Kt,statSync as Zt,writeFileSync as y}from"fs";import{createHash as W}from"crypto";import{join as l}from"path";import{tmpdir as Qt}from"os";import{createGzip as Vt}from"zlib";import{once as G}from"events";import{finished as ue}from"stream/promises";import{ZipFile as en}from"yazl";import tn from"p-limit";var vt=new Set(["browser_navigation_blocked","browser_navigation_failed","browser_timeout","browser_session_failed","browser_result_missing"]);function Mt(e){return e instanceof Error?e.code:void 0}function At(e){return e instanceof Error?e.message:String(e)}function at(e){let r=e?.match(/^browser_http_(\d+)$/);return r?Number(r[1]):null}function It(e){return e===404?"page_not_found":e===403?"page_forbidden":e===429?"page_rate_limited":e>=500&&e<=599?"page_server_error":"page_http_error"}function Rt(e){let r=At(e),i=Mt(e);if(ot(e,r))return{errorCode:"vendor_unavailable",httpStatus:null,retryable:!0};let a=at(i)??at(r.match(/^(browser_http_\d+)/)?.[1]);return a!=null?{errorCode:It(a),httpStatus:a,retryable:a===429||a>=500}:i==="browser_challenge_unresolved"||/^browser_challenge_unresolved/.test(r)?{errorCode:"bot_check_unresolved",httpStatus:null,retryable:!0}:i==="browser_response_too_large"||/exceeds \d+ byte limit/i.test(r)?{errorCode:"page_too_large",httpStatus:null,retryable:!1}:/browser (?:has been )?closed|context closed|target page, context or browser has been closed|session closed/i.test(r)?{errorCode:"browser_session_interrupted",httpStatus:null,retryable:!0}:vt.has(i??"")||/timeout|navigation_failed|ERR_/i.test(r)?{errorCode:"page_unreachable",httpStatus:null,retryable:!0}:{errorCode:"extraction_failed",httpStatus:null,retryable:!1}}function lt(e,r){switch(e){case"page_not_found":return`The page could not be found (HTTP ${r??404}). It may have been moved or deleted.`;case"page_forbidden":return`The site refused the request (HTTP ${r??403}).`;case"page_rate_limited":return"The site is rate-limiting requests right now (HTTP 429). Retrying after a short wait usually works.";case"page_server_error":return`The page's own server returned an error (HTTP ${r}). This is on the target site's side, not something a retry here can fix.`;case"page_http_error":return`The page returned an unexpected HTTP ${r} response.`;case"bot_check_unresolved":return"This site has automated-traffic protection (a bot/CAPTCHA check) that could not be resolved in time. Some sites are simply not extractable this way.";case"page_too_large":return"The page is larger than we can safely process.";case"page_unreachable":return"The page did not respond in time, or the connection could not be completed.";case"browser_session_interrupted":return"The browser session closed before extraction completed. A retry uses a fresh browser session.";case"vendor_unavailable":return"MCP Scraper's internal browser services require MCP Scraper team attention. Servers or IPs are down until this is fixed \u2014 this is not caused by your request. Please retry in a few minutes.";case"extraction_failed":return"The page could not be extracted. Check retryable before attempting it again; contact support if this persists for the same URL."}}function on(e,r={}){let i=lt(e.errorCode,e.httpStatus);return{...Ge({errorCode:e.errorCode,retryable:e.retryable,chargeStatus:r.chargeStatus,details:{...r.details??{},...e.httpStatus!=null?{http_status:e.httpStatus}:{}}}),message:i,error:i}}function an(e){return e.httpStatus===404?404:e.httpStatus===403?403:e.httpStatus===429?429:e.httpStatus!=null&&e.httpStatus>=500&&e.httpStatus<=599?500:e.httpStatus!=null?502:e.errorCode==="vendor_unavailable"?503:502}var Dt="wayback_capture_missing";function Me(e,r){if(e==null)return{failureCode:null,failureReason:null};if(e===Dt)return{failureCode:e,failureReason:r??null};let i=new Error(r??e);i.code=e;let a=Rt(i);return{failureCode:a.errorCode,failureReason:lt(a.errorCode,a.httpStatus)}}import{createHash as Ie}from"crypto";import{neon as $t}from"@neondatabase/serverless";import{waitUntil as Ut}from"@vercel/functions";var jt="jina",ye=null,ut=!1;function be(){return(process.env.JINA_EMBED_MODEL??"jina-embeddings-v5-omni-small").trim()}function _e(){return Number((process.env.JINA_EMBED_DIM??"1024").trim())}function Ae(){return!!(process.env.JINA_API_KEY?.trim()&&process.env.MEMORY_DATABASE_URL?.trim())}function oe(){if(ye)return ye;let e=process.env.MEMORY_DATABASE_URL?.trim();if(!e)throw new Error("MEMORY_DATABASE_URL is not set; Commons semantic search needs the shared Postgres.");return ye=$t(e),ye}async function mt(){if(ut)return;let e=_e();await oe().query("CREATE EXTENSION IF NOT EXISTS vector"),await oe().query(`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS commons_index_vectors (
|
|
3
3
|
document_id TEXT PRIMARY KEY,
|
|
4
4
|
entity_id TEXT NOT NULL,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{$ as E,B as R,D as
|
|
2
|
-
`).filter(t=>t.startsWith("data:")).map(t=>t.slice(5).trim()).filter(Boolean);if(!s.length)return JSON.parse(r);for(let t of s){let e=JSON.parse(t);if(e.result||e.error)return e}throw new Error("hosted MCP returned no JSON-RPC result")}function l(r){return{content:[{type:"text",text:JSON.stringify({ok:!1,error:r})}],isError:!0}}var p=class{baseUrl;apiKey;constructor(s,t){this.baseUrl=s.replace(/\/$/,""),this.apiKey=t}async callMemoryTool(s,t){let e=I.get(s);if(!e)return l(`unknown memory tool: ${s}`);try{let n=await fetch(`${this.baseUrl}/mcp`,{method:"POST",headers:{"content-type":"application/json",accept:"application/json, text/event-stream","x-api-key":this.apiKey},body:JSON.stringify({jsonrpc:"2.0",id:`memory:${e}`,method:"tools/call",params:{name:e,arguments:t}})}),i=await n.text();if(!n.ok)return l(`hosted memory ${e} failed (HTTP ${n.status})`);let o=N(i);return o.error?l(o.error.message??`hosted memory ${e} failed`):o.result??l(`hosted memory ${e} returned no result`)}catch(n){return l(n instanceof Error?n.message:`hosted memory ${e} call failed`)}}};function M(r,s){if(s.length===0)throw new Error("Restricted MCP tool allowlist must contain at least one tool name");let t=new Set;for(let o of s){if(typeof o!="string"||o.trim()!==o||o.length===0)throw new Error("Restricted MCP tool allowlist contains a malformed tool name");if(t.has(o))throw new Error(`Restricted MCP tool allowlist contains duplicate tool name: ${o}`);t.add(o)}let e=new Set,n=r,i=n.registerTool.bind(r);return n.registerTool=(o,a,m)=>{if(t.has(o))return e.add(o),i(o,a,m)},{assertComplete(){let o=[...t].filter(a=>!e.has(a));if(o.length>0)throw new Error(`Restricted MCP tool allowlist contains unknown or unavailable tool names: ${o.join(", ")}`)},registeredToolNames(){return[...e]}}}import{Client as b,StreamableHTTPClientTransport as k}from"@modelcontextprotocol/client";var $=new Set(["artifact_read","artifact_describe","artifact_download","report_artifact_read"]),A=()=>({content:[{type:"text",text:"Retained file storage is unavailable. Preserve the artifactId and retry retrieval; do not repeat acquisition."}],isError:!0});function O(r,s,t={}){return async(e,n)=>{if(!$.has(e))return A();let i=new b({name:"mcp-scraper-artifact-client",version:c},{versionNegotiation:{mode:"auto"}}),o=AbortSignal.timeout(3e4);try{let a=new k(new URL(`${r.replace(/\/$/,"")}/mcp`),{requestInit:{signal:o,headers:{Authorization:`Bearer ${s}`,"x-api-key":s,...t.localNetworkAccess?{"x-mcp-scraper-local-network":"1"}:{}}}});return await i.connect(a,{signal:o,timeout:3e4}),await i.callTool({name:e,arguments:n},{signal:o,timeout:3e4})}catch{return A()}finally{await i.close().catch(()=>{})}}}var G=new Set(["paa","serp","browser-agent","
|
|
1
|
+
import{$ as E,B as R,D as v,Fa as C,Ga as P,Y as S,_ as T,ha as w,ja as h,ka as _,la as y,x as f,y as u,z as g}from"./chunk-4P3LZNVA.js";import{a as x}from"./chunk-ND4WIBXT.js";import{a as c}from"./chunk-6FAMBNHY.js";import{readFileSync as L}from"fs";import{homedir as B}from"os";import{join as U}from"path";import{serveStdio as Y}from"@modelcontextprotocol/server/stdio";import{McpServer as J}from"@modelcontextprotocol/server";var I=new Map(_.map(r=>[r.upstreamName,r.id]));function N(r){let s=r.split(`
|
|
2
|
+
`).filter(t=>t.startsWith("data:")).map(t=>t.slice(5).trim()).filter(Boolean);if(!s.length)return JSON.parse(r);for(let t of s){let e=JSON.parse(t);if(e.result||e.error)return e}throw new Error("hosted MCP returned no JSON-RPC result")}function l(r){return{content:[{type:"text",text:JSON.stringify({ok:!1,error:r})}],isError:!0}}var p=class{baseUrl;apiKey;constructor(s,t){this.baseUrl=s.replace(/\/$/,""),this.apiKey=t}async callMemoryTool(s,t){let e=I.get(s);if(!e)return l(`unknown memory tool: ${s}`);try{let n=await fetch(`${this.baseUrl}/mcp`,{method:"POST",headers:{"content-type":"application/json",accept:"application/json, text/event-stream","x-api-key":this.apiKey},body:JSON.stringify({jsonrpc:"2.0",id:`memory:${e}`,method:"tools/call",params:{name:e,arguments:t}})}),i=await n.text();if(!n.ok)return l(`hosted memory ${e} failed (HTTP ${n.status})`);let o=N(i);return o.error?l(o.error.message??`hosted memory ${e} failed`):o.result??l(`hosted memory ${e} returned no result`)}catch(n){return l(n instanceof Error?n.message:`hosted memory ${e} call failed`)}}};function M(r,s){if(s.length===0)throw new Error("Restricted MCP tool allowlist must contain at least one tool name");let t=new Set;for(let o of s){if(typeof o!="string"||o.trim()!==o||o.length===0)throw new Error("Restricted MCP tool allowlist contains a malformed tool name");if(t.has(o))throw new Error(`Restricted MCP tool allowlist contains duplicate tool name: ${o}`);t.add(o)}let e=new Set,n=r,i=n.registerTool.bind(r);return n.registerTool=(o,a,m)=>{if(t.has(o))return e.add(o),i(o,a,m)},{assertComplete(){let o=[...t].filter(a=>!e.has(a));if(o.length>0)throw new Error(`Restricted MCP tool allowlist contains unknown or unavailable tool names: ${o.join(", ")}`)},registeredToolNames(){return[...e]}}}import{Client as b,StreamableHTTPClientTransport as k}from"@modelcontextprotocol/client";var $=new Set(["artifact_read","artifact_describe","artifact_download","report_artifact_read"]),A=()=>({content:[{type:"text",text:"Retained file storage is unavailable. Preserve the artifactId and retry retrieval; do not repeat acquisition."}],isError:!0});function O(r,s,t={}){return async(e,n)=>{if(!$.has(e))return A();let i=new b({name:"mcp-scraper-artifact-client",version:c},{versionNegotiation:{mode:"auto"}}),o=AbortSignal.timeout(3e4);try{let a=new k(new URL(`${r.replace(/\/$/,"")}/mcp`),{requestInit:{signal:o,headers:{Authorization:`Bearer ${s}`,"x-api-key":s,...t.localNetworkAccess?{"x-mcp-scraper-local-network":"1"}:{}}}});return await i.connect(a,{signal:o,timeout:3e4}),await i.callTool({name:e,arguments:n},{signal:o,timeout:3e4})}catch{return A()}finally{await i.close().catch(()=>{})}}}var G=new Set(["paa","serp","browser-agent","artifact-templates","memory"]);function K(){let s=[process.env.MCP_SCRAPER_KEY_PATH?.trim(),U(B(),".mcp-scraper-key")].filter(Boolean);for(let t of s)try{let e=L(t,"utf8").trim();if(e)return e}catch{}}function j(r,s={}){let t=s.toolsets??G,e=process.env.MCP_SCRAPER_BASE_URL?.trim()||process.env.MCP_BASE_URL?.trim()||"https://mcpscraper.dev",n=R(),i=v({deploymentProfile:n,transportProfile:"stdio",baseUrl:e,explicitlyEnabled:process.env.MCP_SCRAPER_ALLOW_PRIVATE_NETWORK==="1"}),o=process.env.BROWSER_AGENT_CONSOLE_URL?.trim()||e,a=new J({name:"mcp-scraper",version:c},{instructions:u,cacheHints:{"server/discover":{ttlMs:3e5,cacheScope:"private"},"tools/list":{ttlMs:3e5,cacheScope:"private"},"prompts/list":{ttlMs:3e5,cacheScope:"private"},"resources/list":{ttlMs:3e5,cacheScope:"private"},"resources/templates/list":{ttlMs:3e5,cacheScope:"private"},"resources/read":{ttlMs:6e4,cacheScope:"private"}}});g(a);let m=s.allowedToolNames?M(a,s.allowedToolNames):void 0,d=s.httpExecutor??new w(e,r,{localNetworkAccess:i,analyticsIdentity:()=>E(a.server.getClientVersion()?.name)});return t.has("paa")&&T(a,d,{ownerId:S(r),deploymentProfile:n,transportProfile:"stdio",baseUrl:e,localNetworkAccess:i,taskHandleSecret:r,remoteArtifactAccess:O(e,r,{localNetworkAccess:i})}),t.has("serp")&&f(a,d,{exposeDevelopmentDiagnostics:n==="development"||n==="test"}),t.has("browser-agent")&&h(a,{baseUrl:e,apiKey:r,consoleBaseUrl:o}),t.has("artifact-templates")&&P(a,new C(e,r)),t.has("memory")&&y(a,new p(e,r)),m?.assertComplete(),a}function Re(r={}){let s=process.argv.includes("--stdio")||process.env.MCP_SCRAPER_FORCE_STDIO==="1",t=!!(process.stdin.isTTY&&process.stdout.isTTY),e=process.argv.includes("--help")||process.argv.includes("-h");if(!s&&(t||e)){let i=process.argv.includes("--no-color")||process.env.NO_COLOR!==void 0||process.env.FORCE_COLOR==="0"||!process.stdout.isTTY;process.stdout.write(x({version:c,color:!i,apiKeyConfigured:!!process.env.MCP_SCRAPER_API_KEY?.trim()}),()=>process.exit(0));return}let n=(process.env.MCP_SCRAPER_API_KEY??process.env.MCP_SCRAPER_KEY??process.env.MCP_API_KEY??K())?.trim();n||(process.stderr.write(`MCP_SCRAPER_API_KEY env var or ~/.mcp-scraper-key is required
|
|
3
3
|
`),process.exit(1)),Y(()=>j(n,r),{legacy:"serve",onerror(i){process.stderr.write(`${i.message}
|
|
4
4
|
`)}})}export{Re as a};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as _,b as N,c as I}from"./chunk-
|
|
1
|
+
import{a as _,b as N,c as I}from"./chunk-U3NV72AL.js";import{a as u}from"./chunk-WNUXMPVX.js";var y="2026-06-26 21:58:03";var k="+3 months";function D(t){return{sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, expires_at)
|
|
2
2
|
SELECT ?, legacy.balance_mc, legacy.balance_mc, 'migration', datetime('now', ?)
|
|
3
3
|
FROM (
|
|
4
4
|
SELECT COALESCE(SUM(amount_mc), 0) AS balance_mc
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as D,c as A,d as T,e as C,f as w,g as p}from"./chunk-
|
|
1
|
+
import{a as D,c as A,d as T,e as C,f as w,g as p}from"./chunk-OSKCHEVM.js";import{C as k,D as x,E as v,b as E,g,y as I}from"./chunk-JNPM3U3L.js";import{e as P,f as S}from"./chunk-U3NV72AL.js";import{a as _}from"./chunk-WNUXMPVX.js";import{randomUUID as O}from"crypto";var L=class{constructor(t,r,i){this.userId=t;this.sourceSurface=r;this.fence=i;if(i&&i.userId!==t)throw Error("Billing scope principal differs from execution claim")}userId;sourceSurface;fence;identity=`debit:${O()}`;charges=new Map;pending=new Map;compensating=new Set;closing=!1;async debit(t,r,i,c,a){if(this.closing||this.compensating.has(t))throw Error("Billing scope is compensating; new charges are forbidden");let s=this.charges.get(t);if(s?.outcome==="pending")throw Error("Named debit outcome is pending; reconcile before retrying");if(s?.outcome==="funded"&&s.amountMc!==r)throw Error("An applied debit amount cannot change");let o={key:s?.key??`${this.identity}:${t}`,amountMc:r,operation:i,description:c,refundOperation:a,outcome:"pending"};if(s&&(s.operation!==i||s.description!==c||s.refundOperation!==a))throw Error("Named charge identity cannot change");this.charges.set(t,o);let u=(async()=>{if(this.fence){let f=await A(this.fence,{label:t,amountMc:r,operation:i,description:c,refundOperation:a,sourceSurface:this.sourceSurface});if(o.key=f.key,this.closing||this.compensating.has(t))throw Error("Billing scope began compensating while planning")}return this.fence?w(this.userId,r,i,c,o.key,this.fence):w(this.userId,r,i,c,o.key)})();this.pending.set(t,u);try{let f=await u;return o.outcome=f.ok?"funded":"unfunded",{...f,billingKey:o.key}}finally{this.pending.delete(t)}}async compensate(t){this.compensating.add(t),await this.pending.get(t)?.catch(()=>{});try{this.fence&&await this.loadDurablePlans();let r=this.charges.get(t);if(!r)return"not_charged";let i=await C(this.userId,r.key);return i?i.amountMc!==r.amountMc||i.operation!==r.operation||i.description!==r.description?"refund_pending":i.status==="claimed"?this.fence?.mode==="compensate"||r.outcome==="unfunded"?"not_charged":"refund_pending":i.status!=="applied"?"refund_pending":(this.fence?await p(this.userId,r.key,0,r.refundOperation,`${this.sourceSurface} failed`,this.sourceSurface,this.fence):await p(this.userId,r.key,0,r.refundOperation,`${this.sourceSurface} failed`,this.sourceSurface)).final_amount_mc===0?"refunded":"refund_pending":this.fence?.mode==="compensate"||r.outcome==="unfunded"?"not_charged":"refund_pending"}catch{return"refund_pending"}}async compensateAll(){if(this.closing=!0,await Promise.allSettled([...this.pending.values()]),this.fence)try{await this.loadDurablePlans()}catch{return"refund_pending"}let t=await Promise.all([...this.charges.keys()].map(r=>this.compensate(r)));return t.includes("refund_pending")?"refund_pending":t.includes("refunded")?"refunded":"not_charged"}async loadDurablePlans(){if(this.fence)for(let t of await T(this.fence)){let r=this.charges.get(t.label);if(t.sourceSurface!==this.sourceSurface)throw Error("Persisted billing source differs from scope");this.charges.set(t.label,{key:t.key,amountMc:t.amountMc,operation:t.operation,description:t.description,refundOperation:t.refundOperation,outcome:r?.key===t.key?r.outcome:"pending"})}}};async function H(e){if(!Number.isSafeInteger(e.userId)||e.userId<=0||!Number.isSafeInteger(e.refundMc)||e.refundMc<0)throw Error("invalid_legacy_refund");await _().batch([e.admission,{sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, expires_at)
|
|
2
2
|
SELECT ?, ?, ?, ?, ? WHERE changes() = 1 AND ? > 0 AND datetime(?) > datetime('now')`,args:[e.userId,e.refundMc,e.refundMc,e.operation,e.expiresAt,e.refundMc,e.expiresAt]},{sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ? AND ? > 0 AND changes() = 1",args:[e.refundMc,e.userId,e.refundMc]},{sql:`INSERT INTO ledger (user_id, amount_mc, operation, description)
|
|
3
3
|
SELECT ?, ?, ?, ? WHERE ? > 0 AND changes() = 1`,args:[e.userId,e.refundMc,e.operation,e.description,e.refundMc]},e.acknowledgment],"write")}function J(e){return e.status==="complete"||e.status==="partial"||e.status==="failed"}function y(e,t,r){return e.userId===t&&(e.executionGeneration??0)===r&&J(e)}function W(e){let t=e.options.xraySetupReceipt;return e.options.heldMc===0&&e.options.debitKey==null&&t?.billingClass===E&&t.consumesMcpScraperCredits===!1&&t.heldMc===0&&t.billedMc===0}function b(e,t){if(!e||!y(e,t.userId,t.generation)||JSON.stringify(e.settlementPlan)!==JSON.stringify(t))return null;let r=e.settlementReceipt;return!r||r.jobId!==t.jobId||r.userId!==t.userId||r.generation!==t.generation||e.billedMc!==r.netChargeMc?null:r}async function Q(e,t,r,i,c,a=0){let s=await g(e);if(!s||!y(s,t,a))throw Error("extract_settlement_identity_or_terminal_conflict");if(s.billedMc!=null)return s.settlementReceipt??null;let o=Number(s.options.heldMc??0);if(![o,r,i].every(d=>Number.isSafeInteger(d)&&d>=0)||r+i!==o)throw Error("extract_settlement_amount_conflict");let u=String(s.options.billingClass??"credits");if(u===E&&!W(s))throw Error("xray_extract_zero_charge_finalization_rejected");let f={version:1,jobId:e,userId:t,generation:a,status:s.status,heldMc:o,debitKey:typeof s.options.debitKey=="string"?s.options.debitKey:null,billingClass:u,netChargeMc:i,refundMc:r,reference:c},l;try{l=await k(f)}catch(d){if(l=await g(e).catch(()=>null),!l?.settlementPlan||!y(l,t,a))throw d}if(!l||!y(l,t,a)||!l.settlementPlan)throw Error("extract_settlement_admission_conflict");let n=l.settlementPlan;if(n.jobId!==e||n.userId!==t||n.generation!==a||n.status!==l.status||n.heldMc!==o||n.debitKey!==f.debitKey||n.billingClass!==u)throw Error("extract_settlement_plan_conflict");let N=b(l,n);if(N)return N;let m={version:1,jobId:e,userId:t,generation:a,netChargeMc:n.netChargeMc,refundMc:0,expiredRefundMc:0};try{if(u===E)await x(n,m);else if(n.debitKey){let d=await p(t,n.debitKey,n.netChargeMc,S.EXTRACT_SITE_REFUND,n.reference,"extract_site");m.netChargeMc=d.final_amount_mc,m.refundMc=d.refund_mc,m.expiredRefundMc=d.expired_refund_mc??0,await x(n,m)}else{let h=await _().execute({sql:"SELECT datetime(created_at, ?) AS expires_at FROM site_extract_jobs WHERE id = ?",args:[D,e]}),R=[e,t,a,n.status,JSON.stringify(n)];await H({userId:t,refundMc:n.refundMc,expiresAt:String(h.rows[0]?.expires_at),operation:S.EXTRACT_SITE_REFUND,description:n.reference,admission:{sql:`UPDATE site_extract_jobs SET billed_mc = -1
|
|
4
4
|
WHERE id = ? AND user_id = ? AND execution_generation = ? AND status = ?
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
var a="2026-10-10-operation-physical-attempts.1",s="operation_physical_attempts";async function r(t){let[i,_,p,E,c]=await Promise.all([t.execute(`PRAGMA table_info(${s})`),t.execute("PRAGMA index_info(operation_physical_identity)"),t.execute(`PRAGMA foreign_key_list(${s})`),t.execute("SELECT name,sql FROM sqlite_master WHERE name IN ('operation_physical_attempts','operation_physical_unresolved','operation_physical_identity')"),t.execute({sql:"SELECT 1 FROM schema_migrations WHERE version=?",args:[a]})]),n=e=>String(E.rows.find(o=>o.name===e)?.sql??"").replace(/\s+/g," ");return["id","parent_run_id","user_id","controller_token","claim_token","scope","attempt_number","provider","profile","intent_json","state","effects_json","resources_json","created_at","updated_at"].every(e=>i.rows.some(o=>o.name===e&&Number(o.notnull)===1))&&i.rows.some(e=>e.name==="id"&&Number(e.pk)===1)&&i.rows.some(e=>e.name==="receipt_json")&&_.rows.map(e=>e.name).join(",")==="parent_run_id,scope,attempt_number"&&p.rows.some(e=>e.table==="operation_runs"&&e.from==="parent_run_id"&&e.to==="id"&&e.on_delete==="CASCADE")&&n(s).includes("state IN ('prepared','effects_started','terminated','not_started','unknown')")&&n(s).includes("CHECK (json_valid(intent_json))")&&n(s).includes("CHECK (json_valid(effects_json))")&&n(s).includes("CHECK (json_valid(resources_json))")&&n(s).includes("CHECK (receipt_json IS NULL OR json_valid(receipt_json))")&&n(s).includes("CHECK ((state IN ('terminated','not_started','unknown') AND receipt_json IS NOT NULL)")&&n("operation_physical_identity").includes("CREATE UNIQUE INDEX")&&n("operation_physical_unresolved").includes("CREATE UNIQUE INDEX")&&n("operation_physical_unresolved").includes("WHERE state IN ('prepared','effects_started','unknown')")&&c.rows.length===1}async function l(t){if(!await r(t)){try{await t.batch([`CREATE TABLE IF NOT EXISTS operation_physical_attempts (
|
|
2
|
+
id TEXT NOT NULL PRIMARY KEY,
|
|
3
|
+
parent_run_id TEXT NOT NULL REFERENCES operation_runs(id) ON DELETE CASCADE,
|
|
4
|
+
user_id INTEGER NOT NULL CHECK (user_id > 0),
|
|
5
|
+
controller_token TEXT NOT NULL,
|
|
6
|
+
claim_token TEXT NOT NULL,
|
|
7
|
+
scope TEXT NOT NULL,
|
|
8
|
+
attempt_number INTEGER NOT NULL CHECK (attempt_number > 0),
|
|
9
|
+
provider TEXT NOT NULL CHECK (length(provider) BETWEEN 1 AND 100),
|
|
10
|
+
profile TEXT NOT NULL CHECK (profile IN ('customer-funded','funded-parent')),
|
|
11
|
+
intent_json TEXT NOT NULL CHECK (json_valid(intent_json)),
|
|
12
|
+
state TEXT NOT NULL CHECK (state IN ('prepared','effects_started','terminated','not_started','unknown')),
|
|
13
|
+
effects_json TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(effects_json)),
|
|
14
|
+
resources_json TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(resources_json)),
|
|
15
|
+
receipt_json TEXT CHECK (receipt_json IS NULL OR json_valid(receipt_json)),
|
|
16
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
17
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
18
|
+
CHECK ((state IN ('terminated','not_started','unknown') AND receipt_json IS NOT NULL)
|
|
19
|
+
OR (state IN ('prepared','effects_started') AND receipt_json IS NULL))
|
|
20
|
+
)`,"CREATE UNIQUE INDEX IF NOT EXISTS operation_physical_identity ON operation_physical_attempts(parent_run_id,scope,attempt_number)","CREATE UNIQUE INDEX IF NOT EXISTS operation_physical_unresolved ON operation_physical_attempts(parent_run_id) WHERE state IN ('prepared','effects_started','unknown')",{sql:"INSERT OR IGNORE INTO schema_migrations(version) VALUES (?)",args:[a]}],"write")}catch(i){if(!await r(t).catch(()=>!1))throw i}if(!await r(t))throw Error("Physical attempt schema is incomplete")}}export{l as a};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as M,b as q,f as L}from"./chunk-
|
|
1
|
+
import{a as M,b as q,f as L}from"./chunk-OSKCHEVM.js";import{A as ge,f as I,h as F,s as b,v as J,w as pe,x as _e,y as H}from"./chunk-U3NV72AL.js";import{g as j}from"./chunk-VVSHZV5S.js";import{b as $}from"./chunk-4ZVO6GX4.js";import{a as l}from"./chunk-WNUXMPVX.js";import{createHash as O,randomUUID as Oe}from"crypto";import{Client as tt,StreamableHTTPClientTransport as nt}from"@modelcontextprotocol/client";import{randomUUID as Q}from"crypto";import{createHash as Y,randomBytes as W,scryptSync as fe,timingSafeEqual as We}from"crypto";function Ee(){return"sk_"+W(24).toString("hex")}function ye(e){let t=W(16).toString("hex"),n=fe(e,t,64);return`${t}:${n.toString("hex")}`}function Ct(e,t){let[n,i]=t.split(":"),r=Buffer.from(i,"hex"),o=fe(e,n,64);return We(r,o)}function K(e){return{id:Number(e.id),email:String(e.email),name:e.name!=null?String(e.name):null,api_key:String(e.api_key),key_active:Number(e.key_active??1),password_hash:e.password_hash!=null?String(e.password_hash):null,created_at:String(e.created_at),active:Number(e.active),stripe_customer_id:e.stripe_customer_id!=null?String(e.stripe_customer_id):null,balance_mc:Number(e.balance_mc??0),extra_concurrency_slots:Number(e.extra_concurrency_slots??0),concurrency_stripe_sub_id:e.concurrency_stripe_sub_id!=null?String(e.concurrency_stripe_sub_id):null,concurrency_pack_quantity:Number(e.concurrency_pack_quantity??0),subscription_concurrency:Number(e.subscription_concurrency??0),subscription_tier:e.subscription_tier!=null?String(e.subscription_tier):null,subscription_id:e.subscription_id!=null?String(e.subscription_id):null,memory_plan:e.memory_plan!=null?String(e.memory_plan):"free",memory_subscription_id:e.memory_subscription_id!=null?String(e.memory_subscription_id):null,memory_provisioned:Number(e.memory_provisioned??0)}}async function X(e){let t=await l().execute({sql:"SELECT * FROM users WHERE email = ? AND active = 1",args:[e]});return t.rows[0]?K(t.rows[0]):void 0}async function St(e){let t=await l().execute({sql:"SELECT * FROM users WHERE api_key = ? AND active = 1 AND key_active = 1",args:[e]});return t.rows[0]?K(t.rows[0]):void 0}async function Nt(e){let t=await l().execute({sql:"SELECT * FROM users WHERE id = ? AND active = 1",args:[e]});return t.rows[0]?K(t.rows[0]):void 0}async function ht(e,t){await l().execute({sql:"UPDATE users SET password_hash = ? WHERE id = ?",args:[ye(t),e]})}async function Rt(e){let t=l(),[n,i,r,o,s]=await Promise.all([t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ?",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'failed'",args:[e]}),t.execute({sql:"SELECT COALESCE(SUM(json_extract(result, '$.totalQuestions')), 0) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT MAX(created_at) as t FROM jobs WHERE user_id = ?",args:[e]})]);return{total:Number(n.rows[0]?.n??0),done:Number(i.rows[0]?.n??0),failed:Number(r.rows[0]?.n??0),totalQuestions:Number(o.rows[0]?.n??0),lastUsed:s.rows[0]?.t!=null?String(s.rows[0].t):null}}async function At(e,t,n,i){let r=l(),o=Ee(),s=n??W(6).toString("hex"),a=ye(s);return{id:(await r.execute({sql:"INSERT INTO users (email, name, api_key, password_hash, stripe_customer_id) VALUES (?, ?, ?, ?, ?)",args:[e,t??null,o,a,i??null]})).lastInsertRowid,email:e,name:t,api_key:o,password:s}}async function xt(e,t,n,i){let r=Math.floor(Date.now()/1e3),o=Math.floor(r/i)*i,s=Y("sha256").update(t).digest("hex"),d=await l().execute({sql:`
|
|
2
2
|
INSERT INTO rate_limits (scope, key_hash, window_start, count)
|
|
3
3
|
VALUES (?, ?, ?, 1)
|
|
4
4
|
ON CONFLICT(scope, key_hash, window_start)
|
|
@@ -138,7 +138,7 @@ import{a as M,b as q,f as L}from"./chunk-6BD75VKS.js";import{o as b,r as J,s as
|
|
|
138
138
|
FROM users u
|
|
139
139
|
LEFT JOIN credit_lots l ON l.user_id = u.id
|
|
140
140
|
WHERE u.id = ?
|
|
141
|
-
GROUP BY u.id, u.balance_mc`,args:[e]})).rows[0];if(!s)return 0;if(Number(s.lot_count??0)===0&&(await q(Number(e)),(await n.execute({sql:"SELECT 1 FROM credit_lots WHERE user_id = ? LIMIT 1",args:[e]})).rows.length>0))continue;let a=Number(s.cached_balance_mc??0),d=Number(s.projected_balance_mc??0);if(a===d||(await n.execute({sql:"UPDATE users SET balance_mc = ? WHERE id = ? AND balance_mc = ?",args:[d,e,a]})).rowsAffected===1)return d}let i=await n.execute({sql:"SELECT balance_mc FROM users WHERE id = ? LIMIT 1",args:[e]});return Number(i.rows[0]?.balance_mc??0)}var N="connected_usage",Ge="
|
|
141
|
+
GROUP BY u.id, u.balance_mc`,args:[e]})).rows[0];if(!s)return 0;if(Number(s.lot_count??0)===0&&(await q(Number(e)),(await n.execute({sql:"SELECT 1 FROM credit_lots WHERE user_id = ? LIMIT 1",args:[e]})).rows.length>0))continue;let a=Number(s.cached_balance_mc??0),d=Number(s.projected_balance_mc??0);if(a===d||(await n.execute({sql:"UPDATE users SET balance_mc = ? WHERE id = ? AND balance_mc = ?",args:[d,e,a]})).rowsAffected===1)return d}let i=await n.execute({sql:"SELECT balance_mc FROM users WHERE id = ? LIMIT 1",args:[e]});return Number(i.rows[0]?.balance_mc??0)}var N="connected_usage",Ge="native_worker",Ve=E.object({toolName:E.string().trim().min(1).max(200).optional(),operationKind:E.enum(["read","action","sync","export","proxy","other"]).optional(),outcome:E.enum(["success","error","partial"]).optional(),requestId:E.string().trim().min(1).max(200).optional(),occurrenceId:E.string().trim().min(1).max(200).optional(),scheduleId:E.string().trim().min(1).max(200).optional(),nangoOperationId:E.string().trim().min(1).max(200).optional(),startedAt:E.string().datetime({offset:!0}).optional(),completedAt:E.string().datetime({offset:!0}).optional()}).strict(),$e=E.object({identity:E.string().trim().min(1).max(320),idempotencyKey:E.string().trim().min(1).max(500),ratePolicyVersion:E.string().trim().min(1).max(100),connectionId:E.string().trim().min(1).max(500),providerConfigKey:E.string().trim().min(1).max(200),functionRuns:E.number().int().safe().nonnegative(),proxyRequests:E.number().int().safe().nonnegative(),computeMilliseconds:E.number().int().safe().nonnegative(),sourceSurface:E.enum(["main_mcp","native_worker","mastra_scheduler","nango_reconciliation"]).default(Ge),metadata:Ve.optional()}).strict(),je=E.object({identity:E.string().trim().min(1).max(320),ratePolicyVersion:E.string().trim().min(1).max(100)}).strict(),T=class extends Error{constructor(n,i,r,o={}){super(i);this.code=n;this.httpStatus=r;this.details=o;this.name="ConnectedUsageBillingError"}code;httpStatus;details};function oe(e){return Xe("sha256").update(e).digest("hex")}function Je(e){return`connected-usage:${oe(e)}`}function Ye(e){return`connected-usage-debit:${oe(e)}`}function ze(e){return e.trim().toLowerCase()}async function Ne(e){let t=await X(ze(e));if(!t)throw new T("user_not_found","billing identity was not found",404);return t}function Qe(e){let t={toolName:e.metadata.toolName??null,operationKind:e.metadata.operationKind??null,outcome:e.metadata.outcome??null,requestId:e.metadata.requestId??null,occurrenceId:e.metadata.occurrenceId??null,scheduleId:e.metadata.scheduleId??null,nangoOperationId:e.metadata.nangoOperationId??null,startedAt:e.metadata.startedAt??null,completedAt:e.metadata.completedAt??null};return oe(JSON.stringify({ratePolicyVersion:b,connectionId:e.connectionId,providerConfigKey:e.providerConfigKey,usage:e.usage,sourceSurface:e.sourceSurface,metadata:t}))}function P(e){let t=JSON.stringify(e);if(t.length>4e3)throw new T("invalid_request","connected usage metadata is too large",400);return t}function se(e){try{let t=JSON.parse(e.metadata??"");if(t.contract!=="connected_usage_receipt"||t.ratePolicyVersion!==b||typeof t.fingerprint!="string"||typeof t.connectionId!="string"||typeof t.providerConfigKey!="string"||!t.usage||!t.charge)throw new Error("invalid connected usage receipt metadata");return t}catch{throw new T("idempotency_key_conflict","the idempotency key is already bound to an incompatible billing receipt",409)}}async function ne(e){let t=await l().execute({sql:"SELECT id, user_id, billing_class, source_surface, status, amount_mc, metadata FROM billing_events WHERE idempotency_key = ? LIMIT 1",args:[e]});return t.rows[0]?t.rows[0]:null}async function he(e,t){return(await l().execute({sql:`SELECT 1
|
|
142
142
|
FROM billing_events
|
|
143
143
|
WHERE user_id = ?
|
|
144
144
|
AND billing_class = ?
|
|
@@ -156,4 +156,4 @@ import{a as M,b as q,f as L}from"./chunk-6BD75VKS.js";import{o as b,r as J,s as
|
|
|
156
156
|
FROM billing_events
|
|
157
157
|
WHERE user_id = ? AND billing_class = ? AND status IN ('settled', 'cost_pending')
|
|
158
158
|
ORDER BY created_at DESC
|
|
159
|
-
LIMIT ?`,args:[e,N,Math.max(1,Math.min(250,Math.round(t)))]}),i=[];for(let r of n.rows){let o=r;try{let s=se(o);i.push({id:o.id,createdAt:String(o.created_at??""),status:o.status==="settled"?"settled":"cost_pending",connectionId:s.connectionId,providerConfigKey:s.providerConfigKey,amountMc:s.charge.amountMc,credits:s.charge.credits,usage:s.usage,costBreakdown:Ae(s.usage,s.charge),metadata:s.safeMetadata})}catch{}}return i}function ue(e){return e.annotations?.readOnlyHint===!0?"read":e.annotations?.readOnlyHint===!1?"action":/^(get|list|search|query|read|download|fetch|find|lookup|inspect|describe|check)-/i.test(e.name)?"read":"action"}function xe(e){return new Map(Object.entries(e??{}).map(([t,n])=>[t,[...new Set(n.map(i=>i.trim()).filter(Boolean))].sort()]))}function B(e){let t=xe(e.requiredPermissionsByTool),n=xe(e.requiredFeaturesByTool),i=new Set(e.grantedPermissions??[]),r=new Set(e.enabledFeatures??[]),o=new Set(e.adminBlockedTools??[]),s=new Map;for(let a of e.tools){let d=ue(a),c=t.get(a.name)??[],u=n.get(a.name)??[],p=c.filter(w=>!i.has(w)),f=u.filter(w=>!r.has(w)),y=e.connectionActive?o.has(a.name)?"admin_blocked":d==="action"&&!e.actionsEnabled?"actions_disabled":c.length>0&&e.permissionVerification==="unavailable"?"permission_verification_unavailable":p.length>0?"missing_permission":f.length>0?"missing_app_feature":null:"inactive_connection";s.set(a.name,{name:a.name,classification:d,requiredPermissions:c,requiredFeatures:u,available:y===null,blockedReason:y,missingPermissions:p,missingFeatures:f})}return s}function de(e,t){let n=e.get(t);if(!n)throw new Error("connected_tool_policy_missing");return n}var it="https://api.nango.dev/mcp",rt=2e4,ot=24e4,Ie=100,st=20,at=360*60*1e3,ct=new Set(["stripe_revenue","salesforce","pipedrive"]),ut="2026-07-16.1",dt="f037859ec80c2ea2fac6e4a67c1a59f3200dd22d3642c97789b9bb3236723d3e",g=class extends Error{status;code;retryable;retryAfterMs;constructor(t,n,i,r=n===429||n>=500,o=null){super(t),this.name="MainNangoTransportError",this.status=n,this.code=i,this.retryable=r,this.retryAfterMs=o}};function G(e){return typeof e=="string"&&ct.has(e.normalize("NFKC").trim().toLowerCase())}function Le(e){if(G(e))throw new g("This provider integration is not currently available.",409,"provider_unavailable",!1)}function lt(e){if(e instanceof Error)return e.message;if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return""}}function Ue(e){let t=e.match(/retry[_ -]?after[_ -]?ms[^0-9]{0,20}(\d{1,7})/i);if(t)return Math.min(Math.max(Number(t[1]),1e3),6e4);let n=e.match(/retry[_ -]?after[^0-9]{0,20}(\d{1,4})/i);return n?Math.min(Math.max(Number(n[1]),1)*1e3,6e4):null}function De(e){if(e instanceof g)return e;let t=lt(e),n=e&&typeof e=="object"?e:null;return n?.code===-32001||n?.name==="RequestTimeout"||/Request timed out|RequestTimeout|Maximum total timeout exceeded/i.test(t)?new g("The connected service operation timed out before returning a result. Retry failed items or use a smaller batch.",503,"mcp_request_timeout",!0):/SERVICE_DISABLED|accessNotConfigured/i.test(t)?new g("The provider API required by this connection is disabled. Enable it in the provider project, wait for propagation, then retry.",409,"provider_api_disabled",!1):/PERMISSION_DENIED|insufficientPermissions|insufficient permission/i.test(t)?new g("The connected account does not have permission to run this provider operation.",403,"missing_provider_permission",!1):/RESOURCE_EXHAUSTED|rate.?limit|status["']?\s*:\s*429/i.test(t)?new g("The connected provider is temporarily rate limited.",429,"upstream_rate_limited",!0,Ue(t)):/UNAUTHENTICATED|invalid_grant|status["']?\s*:\s*401/i.test(t)?new g("The service connection requires reconnection.",409,"connection_inactive",!1):new g("The service connection is temporarily unavailable.",503,"connection_transport_unavailable")}async function mt(e,t,n){return e.callTool({name:t,arguments:n},{timeout:ot})}function _(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function m(e){return typeof e=="string"&&e.trim()?e.trim():null}function le(e,t){if(Array.isArray(e))return e;let n=_(e);if(Array.isArray(n?.[t]))return n[t];if(Array.isArray(n?.data))return n.data;let i=_(n?.data);return Array.isArray(i?.[t])?i[t]:[]}function Pe(){let e=process.env.NANGO_SECRET_KEY?.trim();if(!e)throw new g("Nango is not configured.",503,"nango_not_configured");return e}function ke(){try{return new URL(process.env.NANGO_MCP_URL?.trim()||it)}catch{throw new g("Nango MCP URL is invalid.",503,"nango_invalid_url")}}async function A(e,t={}){let n=new URL(e,`${ke().origin}/`);for(let[s,a]of Object.entries(t.query??{}))a!==void 0&&n.searchParams.set(s,String(a));let i;try{i=await fetch(n,{method:t.method??"GET",headers:{authorization:`Bearer ${Pe()}`,accept:"application/json",...t.body?{"content-type":"application/json"}:{},...t.headers},body:t.body?JSON.stringify(t.body):void 0,signal:AbortSignal.timeout(rt)})}catch{throw new g("Nango is temporarily unavailable.",503,"connection_transport_unavailable")}let r=await i.text(),o={};try{o=r?JSON.parse(r):{}}catch{throw new g("Nango returned an invalid response.",502,"nango_invalid_response")}if(!i.ok){let s=i.status===400||i.status===403||i.status===404||i.status===409||i.status===429||i.status===503?i.status:502;throw new g(s===429?"The connected provider is temporarily rate limited.":"Nango request failed.",s,s===429?"upstream_rate_limited":s===404?"connection_not_found":"connection_transport_unavailable",s===429||s>=500,s===429?Ue(`retry-after: ${i.headers.get("retry-after")??""}`):null)}return o}function k(e){let t=m(e);return t?t.normalize("NFKC").toLowerCase():null}function pt(e,t){let n=_(e),i=_(n?.tags),r=_(n?.end_user),o=k(t);if(!o)return!1;let s=[k(i?.end_user_email),k(r?.email)].filter(d=>!!d);if(s.some(d=>d!==o))return!1;let a=[k(i?.end_user_id),k(r?.id)].filter(d=>!!d&&d.includes("@"));return a.some(d=>d!==o)?!1:s.length>0?s.includes(o):a.includes(o)}function _t(e){let t=_(e),n=m(t?.connection_id),i=m(t?.provider_config_key);if(!n||!i)return null;let o=(Array.isArray(t?.errors)?t.errors:[]).some(s=>m(_(s)?.type)==="auth");return{upstreamConnectionId:n,providerConfigKey:i,provider:m(t?.provider)??i,label:null,lifecycleStatus:o?"needs_reauth":"connected",reconnectRequired:o,createdAt:m(t?.created_at)??m(t?.created),updatedAt:m(t?.updated_at)}}var gt=new Set(["facebook","github-getting-started","google-analytics","google-calendar","google-drive","google-mail","google-search-console","linkedin","meta-marketing-api","slack","twitter-v2","xero","youtube","zoom"]);function ft(e){let t=m(e);return t||(typeof e=="number"&&Number.isFinite(e)?String(e):null)}function R(e){let t=m(e)?.toLowerCase()??null;return t&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)?t:null}function v(e){return e.id||e.email||e.name?e:null}async function h(e){return A(`/proxy${e.path}`,{query:e.query,headers:{"connection-id":e.upstreamConnectionId,"provider-config-key":e.providerConfigKey,...e.baseUrlOverride?{"base-url-override":e.baseUrlOverride}:{}}})}var Et=[{method:"GET",pattern:/^\/gmail\/v1\/users\/me\/messages$/},{method:"GET",pattern:/^\/gmail\/v1\/users\/me\/messages\/[A-Za-z0-9_-]+$/},{method:"GET",pattern:/^\/gmail\/v1\/users\/me\/messages\/[A-Za-z0-9_-]+\/attachments\/[A-Za-z0-9_-]+$/},{method:"GET",pattern:/^\/gmail\/v1\/users\/me\/labels$/},{method:"POST",pattern:/^\/gmail\/v1\/users\/me\/messages\/batchModify$/},{method:"POST",pattern:/^\/gmail\/v1\/users\/me\/messages\/batchDelete$/},{method:"POST",pattern:/^\/gmail\/v1\/users\/me\/messages\/send$/},{method:"POST",pattern:/^\/gmail\/v1\/users\/me\/messages\/[A-Za-z0-9_-]+\/(?:trash|untrash)$/}],yt=new Set(["q","maxResults","pageToken","format","metadataHeaders","fields"]);async function Ln(e){let t=await V(e.identity,e.connectionId);if(t.providerConfigKey!=="google-mail")throw new g("Service connection not found.",404,"connection_not_found",!1);if(!Et.some(d=>d.method===e.method&&d.pattern.test(e.path)))throw new g("The Gmail provider operation is not allowed.",403,"tool_not_allowed",!1);if(Object.keys(e.query??{}).some(d=>!yt.has(d)))throw new g("The Gmail provider query is not allowed.",400,"invalid_request",!1);let n=e.method==="POST";if(n&&!t.actionsEnabled)throw new g("Actions are disabled for this service connection.",403,"actions_disabled",!1);await ae({identity:e.identity,ratePolicyVersion:b});let i=e.requestId?.trim()||Oe(),r=`main-gmail-proxy:${O("sha256").update(e.identity.toLowerCase()).update("\0").update(t.id).update("\0").update(e.method).update("\0").update(e.path).update("\0").update(i).digest("hex")}`,o=performance.now(),s,a;try{s=await A(`/proxy${e.path}`,{method:e.method,query:e.query,body:e.body,headers:{"connection-id":t.upstreamConnectionId,"provider-config-key":"google-mail","base-url-override":"https://gmail.googleapis.com"}})}catch(d){a=d}if(await ce({identity:e.identity,idempotencyKey:r,ratePolicyVersion:b,connectionId:t.id,providerConfigKey:t.providerConfigKey,functionRuns:0,proxyRequests:1,computeMilliseconds:Math.max(0,Math.round(performance.now()-o)),sourceSurface:"main_mcp",metadata:{operationKind:n?"action":"read",outcome:a?"error":"success",requestId:i.length<=200?i:O("sha256").update(i).digest("hex")}}),a)throw De(a);return s}async function bt(e){let t=(n,i,r)=>h({...e,path:n,query:i,baseUrlOverride:r});try{if(e.providerConfigKey==="google-mail"){let n=_(await t("/gmail/v1/users/me/profile",void 0,"https://gmail.googleapis.com")),i=R(n?.emailAddress);return v({id:i,email:i,name:null})}if(e.providerConfigKey==="google-drive"){let n=_(await t("/drive/v3/about",{fields:"user(permissionId,displayName,emailAddress)"},"https://www.googleapis.com")),i=_(n?.user);return v({id:m(i?.permissionId),email:R(i?.emailAddress),name:m(i?.displayName)})}if(e.providerConfigKey==="google-calendar"){let n=_(await t("/calendar/v3/calendars/primary",void 0,"https://www.googleapis.com")),i=m(n?.id);return v({id:i,email:R(i),name:m(n?.summary)})}if(e.providerConfigKey==="youtube"){let n=_(await t("/youtube/v3/channels",{part:"snippet",mine:"true",maxResults:1},"https://www.googleapis.com")),i=Array.isArray(n?.items)?_(n.items[0]):null;return v({id:m(i?.id),email:null,name:m(_(i?.snippet)?.title)})}}catch{}try{let n=_(await t("/v1/userinfo",void 0,"https://openidconnect.googleapis.com"));return v({id:m(n?.sub),email:n?.email_verified===!1?null:R(n?.email),name:m(n?.name)})}catch{return null}}async function Tt(e){if(!gt.has(e.providerConfigKey))return null;if(e.providerConfigKey.startsWith("google-")||e.providerConfigKey==="youtube")return bt(e);try{if(e.providerConfigKey==="github-getting-started"){let t=_(await h({...e,path:"/user"}));return v({id:ft(t?.id),email:R(t?.email),name:m(t?.name)??m(t?.login)})}if(e.providerConfigKey==="slack"){let t=_(await h({...e,path:"/api/auth.test"}));return v({id:m(t?.user_id),email:null,name:[m(t?.user),m(t?.team)].filter(Boolean).join(" \xB7 ")||null})}if(e.providerConfigKey==="zoom"){let t=_(await h({...e,path:"/v2/users/me"})),n=[m(t?.first_name),m(t?.last_name)].filter(Boolean).join(" ");return v({id:m(t?.id),email:R(t?.email),name:m(t?.display_name)??(n||null)})}if(e.providerConfigKey==="linkedin"){let t=_(await h({...e,path:"/v2/userinfo"}));return v({id:m(t?.sub),email:t?.email_verified===!1?null:R(t?.email),name:m(t?.name)})}if(e.providerConfigKey==="meta-marketing-api"||e.providerConfigKey==="facebook"){let t=_(await h({...e,path:"/me",query:{fields:"id,name,email"}}));return v({id:m(t?.id),email:R(t?.email),name:m(t?.name)})}if(e.providerConfigKey==="twitter-v2"){let t=_(await h({...e,path:"/2/users/me",query:{"user.fields":"id,name,username"}})),n=_(t?.data);return v({id:m(n?.id),email:null,name:m(n?.username)??m(n?.name)})}if(e.providerConfigKey==="xero"){let t=await h({...e,path:"/connections"}),n=Array.isArray(t)?_(t[0]):null;return v({id:m(n?.tenantId),email:null,name:m(n?.tenantName)})}}catch{return null}return null}async function Un(e,t={}){let n=[];for(let a=0;a<st;a+=1){let d=await A("/connections",{query:{limit:Ie,page:a}}),c=le(d,"connections");if(n.push(...c),c.length<Ie)break}let i=n.filter(a=>pt(a,e)).map(_t).filter(a=>a!==null),o=(await ee(e,i)).filter(a=>!G(a.providerConfigKey));if(t.resolveProviderIdentity===!1)return o;let s=new Map(i.map(a=>[`${a.providerConfigKey}\0${a.upstreamConnectionId}`,a]));return await Promise.all(o.map(async a=>{if(a.lifecycleStatus!=="connected"||!a.upstreamConnectionId)return;let d=s.get(`${a.providerConfigKey}\0${a.upstreamConnectionId}`);if(!d)return;let c=d.updatedAt??d.createdAt??a.lifecycleStatus,u=!!(a.providerAccountId||a.providerAccountEmail||a.providerAccountName),p=a.providerIdentityCheckedAt?Date.parse(`${a.providerIdentityCheckedAt.replace(" ","T")}Z`):Number.NaN,f=!u&&Number.isFinite(p)&&Date.now()-p<at;if(a.providerIdentitySourceUpdatedAt===c&&(u||f))return;let y=await Tt({upstreamConnectionId:a.upstreamConnectionId,providerConfigKey:a.providerConfigKey});await we({connectionId:a.id,providerAccountId:y?.id,providerAccountEmail:y?.email,providerAccountName:y?.name,sourceUpdatedAt:c})})),(await ee(e,i)).filter(a=>!G(a.providerConfigKey))}async function Dn(){let[e,t]=await Promise.all([A("/integrations"),A("/providers")]),n=new Map;for(let i of le(t,"providers")){let r=_(i),o=m(r?.name);r&&o&&n.set(o,r)}return le(e,"integrations").flatMap(i=>{let r=_(i),o=m(r?.unique_key)??m(r?.id),s=m(r?.provider);if(!o||!s||G(o))return[];let a=n.get(s);return[{id:o,provider:s,displayName:m(r?.display_name)??m(a?.display_name)??o,authMode:m(a?.auth_mode),categories:Array.isArray(a?.categories)?a.categories:[],docsUrl:m(a?.docs),logoUrl:m(r?.logo),safeDefaultAllowedTools:[],actionTools:[],setupStatus:"ready"}]})}function Me(e){let n={linkedin:"openid profile email w_member_social","github-getting-started":"repo workflow read:org read:user user:email","google-drive":"openid profile email https://www.googleapis.com/auth/drive","google-search-console":"openid profile email https://www.googleapis.com/auth/webmasters.readonly https://www.googleapis.com/auth/webmasters"}[e];return n?{[e]:{connection_config:{oauth_scopes_override:n}}}:void 0}function qe(e){let t=_(e),n=_(t?.data)??t,i=m(n?.connect_link);if(!i)throw new g("Nango did not return a connect link.",502,"nango_missing_connect_link");return{connectLink:i,expiresAt:m(n?.expires_at)}}async function Pn(e,t){Le(t);let n=Me(t);return qe(await A("/connect/sessions",{method:"POST",body:{tags:{end_user_id:e,end_user_email:e},allowed_integrations:[t],...n?{integrations_config_defaults:n}:{}}}))}async function kn(e,t){let n=await V(e,t,!0),i=Me(n.providerConfigKey);return qe(await A("/connect/sessions/reconnect",{method:"POST",body:{connection_id:n.upstreamConnectionId,integration_id:n.providerConfigKey,tags:{end_user_id:e,end_user_email:e},...i?{integrations_config_defaults:i}:{}}}))}async function Mn(e,t){let n=await Fe(e,t);try{await A(`/connections/${encodeURIComponent(n.upstreamConnectionId)}`,{method:"DELETE",query:{provider_config_key:n.providerConfigKey}})}catch(i){if(!(i instanceof g)||i.status!==404)throw i}}async function Fe(e,t){let n=await S(e,t);if(!n||n.transport!=="nango"||!n.upstreamConnectionId)throw new g("Service connection not found.",404,"connection_not_found",!1);return n}async function V(e,t,n=!1){let i=await Fe(e,t);if(Le(i.providerConfigKey),i.lifecycleStatus!=="connected"&&!(n&&i.lifecycleStatus==="needs_reauth"))throw new g("Service connection requires reconnection.",409,"connection_inactive",!1);return i}async function me(e,t){let n=new nt(ke(),{requestInit:{headers:{Authorization:`Bearer ${Pe()}`,"connection-id":e.upstreamConnectionId,"provider-config-key":e.providerConfigKey}}}),i=new tt({name:"mcp-scraper-integrations",version:"1.0.0"},{capabilities:{}});try{await i.connect(n);let r=await t(i);return await te({connectionId:e.id,operationalStatus:"available",evidenceSource:"nango_mcp"}),r}catch(r){let o=De(r);throw await te({connectionId:e.id,operationalStatus:o.code==="connection_transport_unavailable"?"unavailable":"degraded",failureCode:o.code,retryable:o.retryable,evidenceSource:"nango_mcp"}).catch(()=>{}),o}finally{await i.close().catch(()=>{})}}async function qn(e,t){let n=await V(e,t);(n.provider??n.providerConfigKey)==="google-search-console"&&await me(n,async r=>{if(!(await r.listTools()).tools.some(s=>s.name==="list-sites"))throw new g("The Search Console health-check tool is unavailable.",404,"live_tool_missing",!1);await r.callTool({name:"list-sites",arguments:{}})})}async function He(e,t){let n=await V(e,t),r=(await me(n,u=>u.listTools())).tools.flatMap(u=>{let p=_(u.inputSchema);return!u.name||!p?[]:[{name:u.name,...u.title?{title:u.title}:{},...u.description?{description:u.description}:{},inputSchema:p,..._(u.outputSchema)?{outputSchema:_(u.outputSchema)}:{},..._(u.annotations)?{annotations:_(u.annotations)}:{}}]}),o=B({tools:r,connectionActive:n.lifecycleStatus==="connected",actionsEnabled:n.actionsEnabled}),s=[...o.values()].filter(u=>u.classification==="read").map(u=>u.name),a=[...o.values()].filter(u=>u.classification==="action").map(u=>u.name),d=O("sha256").update(JSON.stringify(r.map(u=>({name:u.name,inputSchema:u.inputSchema})))).digest("hex");return await ve(n.id,s,a,d),{connection:await S(e,n.id)??{...n,readTools:s,actionTools:a,toolRevision:d},tools:r}}async function Fn(e){let{connection:t,tools:n}=await He(e.identity,e.connectionId),i=n.find(f=>f.name===e.tool);if(!i)throw new g("The requested provider tool is unavailable.",404,"live_tool_missing",!1);let r=de(B({tools:n,connectionActive:t.lifecycleStatus==="connected",actionsEnabled:t.actionsEnabled}),i.name);if(r.classification!==e.classification)throw new g("The provider tool classification does not match this operation.",403,"tool_not_allowed",!1);if(!r.available&&r.blockedReason==="actions_disabled")throw new g("Actions are disabled for this service connection.",403,"actions_disabled",!1);if(!r.available)throw new g("The provider tool is not authorized for this connection.",403,"tool_not_allowed",!1);await ae({identity:e.identity,ratePolicyVersion:b});let o=e.requestId?.trim()||Oe(),s=`main-nango:${O("sha256").update(e.identity.toLowerCase()).update("\0").update(t.id).update("\0").update(e.tool).update("\0").update(o).digest("hex")}`,a=new Date,d=performance.now(),c,u;try{c=await me(t,f=>mt(f,e.tool,e.input))}catch(f){u=f}let p=new Date;if(await ce({identity:e.identity,idempotencyKey:s,ratePolicyVersion:b,connectionId:t.id,providerConfigKey:t.providerConfigKey,functionRuns:1,proxyRequests:0,computeMilliseconds:Math.max(0,Math.round(performance.now()-d)),sourceSurface:"main_mcp",metadata:{toolName:e.tool,operationKind:e.operationKind??e.classification,outcome:u?"error":"partial",requestId:o.length<=200?o:O("sha256").update(o).digest("hex"),startedAt:a.toISOString(),completedAt:p.toISOString()}}),u)throw u;return c}async function Hn(e,t,n){let{connection:i,tools:r}=await He(e,t),o=r.find(u=>u.name===n);if(!o)throw new g("The requested provider tool is unavailable.",404,"live_tool_missing",!1);let s=de(B({tools:r,connectionActive:i.lifecycleStatus==="connected",actionsEnabled:i.actionsEnabled}),o.name),a=ue(o),d=s.available,c={name:o.name,...o.title?{title:o.title}:{},...o.description?{description:o.description}:{},inputSchema:o.inputSchema,...o.outputSchema?{outputSchema:o.outputSchema}:{},...o.annotations?{annotations:o.annotations}:{}};return{...c,classification:a,callable:d,blockedReason:s.blockedReason,requiredPermissions:s.requiredPermissions,missingPermissions:s.missingPermissions,requiredFeatures:s.requiredFeatures,missingFeatures:s.missingFeatures,transport:"nango",providerConfigKey:i.providerConfigKey,providerContractVersion:ut,providerContractHash:dt,protocolVersion:null,schemaSource:"live_tools_list",schemaHash:O("sha256").update(JSON.stringify(c)).digest("hex"),fetchedAt:new Date().toISOString()}}export{an as a,cn as b,un as c,dn as d,ln as e,mn as f,pn as g,D as h,Ct as i,K as j,X as k,St as l,Nt as m,ht as n,Rt as o,At as p,xt as q,It as r,Ot as s,Lt as t,Ut as u,Dt as v,Pt as w,kt as x,Mt as y,Qt as z,$e as A,je as B,T as C,ae as D,ce as E,Cn as F,Kt as G,C as H,Ke as I,S as J,Xt as K,Bt as L,Gt as M,Vt as N,$t as O,g as P,G as Q,Le as R,Ln as S,Un as T,Dn as U,Pn as V,kn as W,Mn as X,qn as Y,He as Z,Fn as _,Hn as $};
|
|
159
|
+
LIMIT ?`,args:[e,N,Math.max(1,Math.min(250,Math.round(t)))]}),i=[];for(let r of n.rows){let o=r;try{let s=se(o);i.push({id:o.id,createdAt:String(o.created_at??""),status:o.status==="settled"?"settled":"cost_pending",connectionId:s.connectionId,providerConfigKey:s.providerConfigKey,amountMc:s.charge.amountMc,credits:s.charge.credits,usage:s.usage,costBreakdown:Ae(s.usage,s.charge),metadata:s.safeMetadata})}catch{}}return i}function ue(e){return e.annotations?.readOnlyHint===!0?"read":e.annotations?.readOnlyHint===!1?"action":/^(get|list|search|query|read|download|fetch|find|lookup|inspect|describe|check)-/i.test(e.name)?"read":"action"}function xe(e){return new Map(Object.entries(e??{}).map(([t,n])=>[t,[...new Set(n.map(i=>i.trim()).filter(Boolean))].sort()]))}function B(e){let t=xe(e.requiredPermissionsByTool),n=xe(e.requiredFeaturesByTool),i=new Set(e.grantedPermissions??[]),r=new Set(e.enabledFeatures??[]),o=new Set(e.adminBlockedTools??[]),s=new Map;for(let a of e.tools){let d=ue(a),c=t.get(a.name)??[],u=n.get(a.name)??[],p=c.filter(w=>!i.has(w)),f=u.filter(w=>!r.has(w)),y=e.connectionActive?o.has(a.name)?"admin_blocked":d==="action"&&!e.actionsEnabled?"actions_disabled":c.length>0&&e.permissionVerification==="unavailable"?"permission_verification_unavailable":p.length>0?"missing_permission":f.length>0?"missing_app_feature":null:"inactive_connection";s.set(a.name,{name:a.name,classification:d,requiredPermissions:c,requiredFeatures:u,available:y===null,blockedReason:y,missingPermissions:p,missingFeatures:f})}return s}function de(e,t){let n=e.get(t);if(!n)throw new Error("connected_tool_policy_missing");return n}var it="https://api.nango.dev/mcp",rt=2e4,ot=24e4,Ie=100,st=20,at=360*60*1e3,ct=new Set(["stripe_revenue","salesforce","pipedrive"]),ut="2026-07-16.1",dt="f037859ec80c2ea2fac6e4a67c1a59f3200dd22d3642c97789b9bb3236723d3e",g=class extends Error{status;code;retryable;retryAfterMs;constructor(t,n,i,r=n===429||n>=500,o=null){super(t),this.name="MainNangoTransportError",this.status=n,this.code=i,this.retryable=r,this.retryAfterMs=o}};function G(e){return typeof e=="string"&&ct.has(e.normalize("NFKC").trim().toLowerCase())}function Le(e){if(G(e))throw new g("This provider integration is not currently available.",409,"provider_unavailable",!1)}function lt(e){if(e instanceof Error)return e.message;if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return""}}function Ue(e){let t=e.match(/retry[_ -]?after[_ -]?ms[^0-9]{0,20}(\d{1,7})/i);if(t)return Math.min(Math.max(Number(t[1]),1e3),6e4);let n=e.match(/retry[_ -]?after[^0-9]{0,20}(\d{1,4})/i);return n?Math.min(Math.max(Number(n[1]),1)*1e3,6e4):null}function De(e){if(e instanceof g)return e;let t=lt(e),n=e&&typeof e=="object"?e:null;return n?.code===-32001||n?.name==="RequestTimeout"||/Request timed out|RequestTimeout|Maximum total timeout exceeded/i.test(t)?new g("The connected service operation timed out before returning a result. Retry failed items or use a smaller batch.",503,"mcp_request_timeout",!0):/SERVICE_DISABLED|accessNotConfigured/i.test(t)?new g("The provider API required by this connection is disabled. Enable it in the provider project, wait for propagation, then retry.",409,"provider_api_disabled",!1):/PERMISSION_DENIED|insufficientPermissions|insufficient permission/i.test(t)?new g("The connected account does not have permission to run this provider operation.",403,"missing_provider_permission",!1):/RESOURCE_EXHAUSTED|rate.?limit|status["']?\s*:\s*429/i.test(t)?new g("The connected provider is temporarily rate limited.",429,"upstream_rate_limited",!0,Ue(t)):/UNAUTHENTICATED|invalid_grant|status["']?\s*:\s*401/i.test(t)?new g("The service connection requires reconnection.",409,"connection_inactive",!1):new g("The service connection is temporarily unavailable.",503,"connection_transport_unavailable")}async function mt(e,t,n){return e.callTool({name:t,arguments:n},{timeout:ot})}function _(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function m(e){return typeof e=="string"&&e.trim()?e.trim():null}function le(e,t){if(Array.isArray(e))return e;let n=_(e);if(Array.isArray(n?.[t]))return n[t];if(Array.isArray(n?.data))return n.data;let i=_(n?.data);return Array.isArray(i?.[t])?i[t]:[]}function Pe(){let e=process.env.NANGO_SECRET_KEY?.trim();if(!e)throw new g("Nango is not configured.",503,"nango_not_configured");return e}function ke(){try{return new URL(process.env.NANGO_MCP_URL?.trim()||it)}catch{throw new g("Nango MCP URL is invalid.",503,"nango_invalid_url")}}async function A(e,t={}){let n=new URL(e,`${ke().origin}/`);for(let[s,a]of Object.entries(t.query??{}))a!==void 0&&n.searchParams.set(s,String(a));let i;try{i=await fetch(n,{method:t.method??"GET",headers:{authorization:`Bearer ${Pe()}`,accept:"application/json",...t.body?{"content-type":"application/json"}:{},...t.headers},body:t.body?JSON.stringify(t.body):void 0,signal:AbortSignal.timeout(rt)})}catch{throw new g("Nango is temporarily unavailable.",503,"connection_transport_unavailable")}let r=await i.text(),o={};try{o=r?JSON.parse(r):{}}catch{throw new g("Nango returned an invalid response.",502,"nango_invalid_response")}if(!i.ok){let s=i.status===400||i.status===403||i.status===404||i.status===409||i.status===429||i.status===503?i.status:502;throw new g(s===429?"The connected provider is temporarily rate limited.":"Nango request failed.",s,s===429?"upstream_rate_limited":s===404?"connection_not_found":"connection_transport_unavailable",s===429||s>=500,s===429?Ue(`retry-after: ${i.headers.get("retry-after")??""}`):null)}return o}function k(e){let t=m(e);return t?t.normalize("NFKC").toLowerCase():null}function pt(e,t){let n=_(e),i=_(n?.tags),r=_(n?.end_user),o=k(t);if(!o)return!1;let s=[k(i?.end_user_email),k(r?.email)].filter(d=>!!d);if(s.some(d=>d!==o))return!1;let a=[k(i?.end_user_id),k(r?.id)].filter(d=>!!d&&d.includes("@"));return a.some(d=>d!==o)?!1:s.length>0?s.includes(o):a.includes(o)}function _t(e){let t=_(e),n=m(t?.connection_id),i=m(t?.provider_config_key);if(!n||!i)return null;let o=(Array.isArray(t?.errors)?t.errors:[]).some(s=>m(_(s)?.type)==="auth");return{upstreamConnectionId:n,providerConfigKey:i,provider:m(t?.provider)??i,label:null,lifecycleStatus:o?"needs_reauth":"connected",reconnectRequired:o,createdAt:m(t?.created_at)??m(t?.created),updatedAt:m(t?.updated_at)}}var gt=new Set(["facebook","github-getting-started","google-analytics","google-calendar","google-drive","google-mail","google-search-console","linkedin","meta-marketing-api","slack","twitter-v2","xero","youtube","zoom"]);function ft(e){let t=m(e);return t||(typeof e=="number"&&Number.isFinite(e)?String(e):null)}function R(e){let t=m(e)?.toLowerCase()??null;return t&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)?t:null}function v(e){return e.id||e.email||e.name?e:null}async function h(e){return A(`/proxy${e.path}`,{query:e.query,headers:{"connection-id":e.upstreamConnectionId,"provider-config-key":e.providerConfigKey,...e.baseUrlOverride?{"base-url-override":e.baseUrlOverride}:{}}})}var Et=[{method:"GET",pattern:/^\/gmail\/v1\/users\/me\/messages$/},{method:"GET",pattern:/^\/gmail\/v1\/users\/me\/messages\/[A-Za-z0-9_-]+$/},{method:"GET",pattern:/^\/gmail\/v1\/users\/me\/messages\/[A-Za-z0-9_-]+\/attachments\/[A-Za-z0-9_-]+$/},{method:"GET",pattern:/^\/gmail\/v1\/users\/me\/labels$/},{method:"POST",pattern:/^\/gmail\/v1\/users\/me\/messages\/batchModify$/},{method:"POST",pattern:/^\/gmail\/v1\/users\/me\/messages\/batchDelete$/},{method:"POST",pattern:/^\/gmail\/v1\/users\/me\/messages\/send$/},{method:"POST",pattern:/^\/gmail\/v1\/users\/me\/messages\/[A-Za-z0-9_-]+\/(?:trash|untrash)$/}],yt=new Set(["q","maxResults","pageToken","format","metadataHeaders","fields"]);async function Ln(e){let t=await V(e.identity,e.connectionId);if(t.providerConfigKey!=="google-mail")throw new g("Service connection not found.",404,"connection_not_found",!1);if(!Et.some(d=>d.method===e.method&&d.pattern.test(e.path)))throw new g("The Gmail provider operation is not allowed.",403,"tool_not_allowed",!1);if(Object.keys(e.query??{}).some(d=>!yt.has(d)))throw new g("The Gmail provider query is not allowed.",400,"invalid_request",!1);let n=e.method==="POST";if(n&&!t.actionsEnabled)throw new g("Actions are disabled for this service connection.",403,"actions_disabled",!1);await ae({identity:e.identity,ratePolicyVersion:b});let i=e.requestId?.trim()||Oe(),r=`main-gmail-proxy:${O("sha256").update(e.identity.toLowerCase()).update("\0").update(t.id).update("\0").update(e.method).update("\0").update(e.path).update("\0").update(i).digest("hex")}`,o=performance.now(),s,a;try{s=await A(`/proxy${e.path}`,{method:e.method,query:e.query,body:e.body,headers:{"connection-id":t.upstreamConnectionId,"provider-config-key":"google-mail","base-url-override":"https://gmail.googleapis.com"}})}catch(d){a=d}if(await ce({identity:e.identity,idempotencyKey:r,ratePolicyVersion:b,connectionId:t.id,providerConfigKey:t.providerConfigKey,functionRuns:0,proxyRequests:1,computeMilliseconds:Math.max(0,Math.round(performance.now()-o)),sourceSurface:"main_mcp",metadata:{operationKind:n?"action":"read",outcome:a?"error":"success",requestId:i.length<=200?i:O("sha256").update(i).digest("hex")}}),a)throw De(a);return s}async function bt(e){let t=(n,i,r)=>h({...e,path:n,query:i,baseUrlOverride:r});try{if(e.providerConfigKey==="google-mail"){let n=_(await t("/gmail/v1/users/me/profile",void 0,"https://gmail.googleapis.com")),i=R(n?.emailAddress);return v({id:i,email:i,name:null})}if(e.providerConfigKey==="google-drive"){let n=_(await t("/drive/v3/about",{fields:"user(permissionId,displayName,emailAddress)"},"https://www.googleapis.com")),i=_(n?.user);return v({id:m(i?.permissionId),email:R(i?.emailAddress),name:m(i?.displayName)})}if(e.providerConfigKey==="google-calendar"){let n=_(await t("/calendar/v3/calendars/primary",void 0,"https://www.googleapis.com")),i=m(n?.id);return v({id:i,email:R(i),name:m(n?.summary)})}if(e.providerConfigKey==="youtube"){let n=_(await t("/youtube/v3/channels",{part:"snippet",mine:"true",maxResults:1},"https://www.googleapis.com")),i=Array.isArray(n?.items)?_(n.items[0]):null;return v({id:m(i?.id),email:null,name:m(_(i?.snippet)?.title)})}}catch{}try{let n=_(await t("/v1/userinfo",void 0,"https://openidconnect.googleapis.com"));return v({id:m(n?.sub),email:n?.email_verified===!1?null:R(n?.email),name:m(n?.name)})}catch{return null}}async function Tt(e){if(!gt.has(e.providerConfigKey))return null;if(e.providerConfigKey.startsWith("google-")||e.providerConfigKey==="youtube")return bt(e);try{if(e.providerConfigKey==="github-getting-started"){let t=_(await h({...e,path:"/user"}));return v({id:ft(t?.id),email:R(t?.email),name:m(t?.name)??m(t?.login)})}if(e.providerConfigKey==="slack"){let t=_(await h({...e,path:"/api/auth.test"}));return v({id:m(t?.user_id),email:null,name:[m(t?.user),m(t?.team)].filter(Boolean).join(" \xB7 ")||null})}if(e.providerConfigKey==="zoom"){let t=_(await h({...e,path:"/v2/users/me"})),n=[m(t?.first_name),m(t?.last_name)].filter(Boolean).join(" ");return v({id:m(t?.id),email:R(t?.email),name:m(t?.display_name)??(n||null)})}if(e.providerConfigKey==="linkedin"){let t=_(await h({...e,path:"/v2/userinfo"}));return v({id:m(t?.sub),email:t?.email_verified===!1?null:R(t?.email),name:m(t?.name)})}if(e.providerConfigKey==="meta-marketing-api"||e.providerConfigKey==="facebook"){let t=_(await h({...e,path:"/me",query:{fields:"id,name,email"}}));return v({id:m(t?.id),email:R(t?.email),name:m(t?.name)})}if(e.providerConfigKey==="twitter-v2"){let t=_(await h({...e,path:"/2/users/me",query:{"user.fields":"id,name,username"}})),n=_(t?.data);return v({id:m(n?.id),email:null,name:m(n?.username)??m(n?.name)})}if(e.providerConfigKey==="xero"){let t=await h({...e,path:"/connections"}),n=Array.isArray(t)?_(t[0]):null;return v({id:m(n?.tenantId),email:null,name:m(n?.tenantName)})}}catch{return null}return null}async function Un(e,t={}){let n=[];for(let a=0;a<st;a+=1){let d=await A("/connections",{query:{limit:Ie,page:a}}),c=le(d,"connections");if(n.push(...c),c.length<Ie)break}let i=n.filter(a=>pt(a,e)).map(_t).filter(a=>a!==null),o=(await ee(e,i)).filter(a=>!G(a.providerConfigKey));if(t.resolveProviderIdentity===!1)return o;let s=new Map(i.map(a=>[`${a.providerConfigKey}\0${a.upstreamConnectionId}`,a]));return await Promise.all(o.map(async a=>{if(a.lifecycleStatus!=="connected"||!a.upstreamConnectionId)return;let d=s.get(`${a.providerConfigKey}\0${a.upstreamConnectionId}`);if(!d)return;let c=d.updatedAt??d.createdAt??a.lifecycleStatus,u=!!(a.providerAccountId||a.providerAccountEmail||a.providerAccountName),p=a.providerIdentityCheckedAt?Date.parse(`${a.providerIdentityCheckedAt.replace(" ","T")}Z`):Number.NaN,f=!u&&Number.isFinite(p)&&Date.now()-p<at;if(a.providerIdentitySourceUpdatedAt===c&&(u||f))return;let y=await Tt({upstreamConnectionId:a.upstreamConnectionId,providerConfigKey:a.providerConfigKey});await we({connectionId:a.id,providerAccountId:y?.id,providerAccountEmail:y?.email,providerAccountName:y?.name,sourceUpdatedAt:c})})),(await ee(e,i)).filter(a=>!G(a.providerConfigKey))}async function Dn(){let[e,t]=await Promise.all([A("/integrations"),A("/providers")]),n=new Map;for(let i of le(t,"providers")){let r=_(i),o=m(r?.name);r&&o&&n.set(o,r)}return le(e,"integrations").flatMap(i=>{let r=_(i),o=m(r?.unique_key)??m(r?.id),s=m(r?.provider);if(!o||!s||G(o))return[];let a=n.get(s);return[{id:o,provider:s,displayName:m(r?.display_name)??m(a?.display_name)??o,authMode:m(a?.auth_mode),categories:Array.isArray(a?.categories)?a.categories:[],docsUrl:m(a?.docs),logoUrl:m(r?.logo),safeDefaultAllowedTools:[],actionTools:[],setupStatus:"ready"}]})}function Me(e){let n={linkedin:"openid profile email w_member_social","github-getting-started":"repo workflow read:org read:user user:email","google-drive":"openid profile email https://www.googleapis.com/auth/drive","google-search-console":"openid profile email https://www.googleapis.com/auth/webmasters.readonly https://www.googleapis.com/auth/webmasters"}[e];return n?{[e]:{connection_config:{oauth_scopes_override:n}}}:void 0}function qe(e){let t=_(e),n=_(t?.data)??t,i=m(n?.connect_link);if(!i)throw new g("Nango did not return a connect link.",502,"nango_missing_connect_link");return{connectLink:i,expiresAt:m(n?.expires_at)}}async function Pn(e,t){Le(t);let n=Me(t);return qe(await A("/connect/sessions",{method:"POST",body:{tags:{end_user_id:e,end_user_email:e},allowed_integrations:[t],...n?{integrations_config_defaults:n}:{}}}))}async function kn(e,t){let n=await V(e,t,!0),i=Me(n.providerConfigKey);return qe(await A("/connect/sessions/reconnect",{method:"POST",body:{connection_id:n.upstreamConnectionId,integration_id:n.providerConfigKey,tags:{end_user_id:e,end_user_email:e},...i?{integrations_config_defaults:i}:{}}}))}async function Mn(e,t){let n=await Fe(e,t);try{await A(`/connections/${encodeURIComponent(n.upstreamConnectionId)}`,{method:"DELETE",query:{provider_config_key:n.providerConfigKey}})}catch(i){if(!(i instanceof g)||i.status!==404)throw i}}async function Fe(e,t){let n=await S(e,t);if(!n||n.transport!=="nango"||!n.upstreamConnectionId)throw new g("Service connection not found.",404,"connection_not_found",!1);return n}async function V(e,t,n=!1){let i=await Fe(e,t);if(Le(i.providerConfigKey),i.lifecycleStatus!=="connected"&&!(n&&i.lifecycleStatus==="needs_reauth"))throw new g("Service connection requires reconnection.",409,"connection_inactive",!1);return i}async function me(e,t){let n=new nt(ke(),{requestInit:{headers:{Authorization:`Bearer ${Pe()}`,"connection-id":e.upstreamConnectionId,"provider-config-key":e.providerConfigKey}}}),i=new tt({name:"mcp-scraper-integrations",version:"1.0.0"},{capabilities:{}});try{await i.connect(n);let r=await t(i);return await te({connectionId:e.id,operationalStatus:"available",evidenceSource:"nango_mcp"}),r}catch(r){let o=De(r);throw await te({connectionId:e.id,operationalStatus:o.code==="connection_transport_unavailable"?"unavailable":"degraded",failureCode:o.code,retryable:o.retryable,evidenceSource:"nango_mcp"}).catch(()=>{}),o}finally{await i.close().catch(()=>{})}}async function qn(e,t){let n=await V(e,t);(n.provider??n.providerConfigKey)==="google-search-console"&&await me(n,async r=>{if(!(await r.listTools()).tools.some(s=>s.name==="list-sites"))throw new g("The Search Console health-check tool is unavailable.",404,"live_tool_missing",!1);await r.callTool({name:"list-sites",arguments:{}})})}async function He(e,t){let n=await V(e,t),r=(await me(n,u=>u.listTools())).tools.flatMap(u=>{let p=_(u.inputSchema);return!u.name||!p?[]:[{name:u.name,...u.title?{title:u.title}:{},...u.description?{description:u.description}:{},inputSchema:p,..._(u.outputSchema)?{outputSchema:_(u.outputSchema)}:{},..._(u.annotations)?{annotations:_(u.annotations)}:{}}]}),o=B({tools:r,connectionActive:n.lifecycleStatus==="connected",actionsEnabled:n.actionsEnabled}),s=[...o.values()].filter(u=>u.classification==="read").map(u=>u.name),a=[...o.values()].filter(u=>u.classification==="action").map(u=>u.name),d=O("sha256").update(JSON.stringify(r.map(u=>({name:u.name,inputSchema:u.inputSchema})))).digest("hex");return await ve(n.id,s,a,d),{connection:await S(e,n.id)??{...n,readTools:s,actionTools:a,toolRevision:d},tools:r}}async function Fn(e){let{connection:t,tools:n}=await He(e.identity,e.connectionId),i=n.find(f=>f.name===e.tool);if(!i)throw new g("The requested provider tool is unavailable.",404,"live_tool_missing",!1);let r=de(B({tools:n,connectionActive:t.lifecycleStatus==="connected",actionsEnabled:t.actionsEnabled}),i.name);if(r.classification!==e.classification)throw new g("The provider tool classification does not match this operation.",403,"tool_not_allowed",!1);if(!r.available&&r.blockedReason==="actions_disabled")throw new g("Actions are disabled for this service connection.",403,"actions_disabled",!1);if(!r.available)throw new g("The provider tool is not authorized for this connection.",403,"tool_not_allowed",!1);await ae({identity:e.identity,ratePolicyVersion:b});let o=e.requestId?.trim()||Oe(),s=`main-nango:${O("sha256").update(e.identity.toLowerCase()).update("\0").update(t.id).update("\0").update(e.tool).update("\0").update(o).digest("hex")}`,a=new Date,d=performance.now(),c,u;try{c=await me(t,f=>mt(f,e.tool,e.input))}catch(f){u=f}let p=new Date;if(await ce({identity:e.identity,idempotencyKey:s,ratePolicyVersion:b,connectionId:t.id,providerConfigKey:t.providerConfigKey,functionRuns:1,proxyRequests:0,computeMilliseconds:Math.max(0,Math.round(performance.now()-d)),sourceSurface:"main_mcp",metadata:{toolName:e.tool,operationKind:e.operationKind??e.classification,outcome:u?"error":"partial",requestId:o.length<=200?o:O("sha256").update(o).digest("hex"),startedAt:a.toISOString(),completedAt:p.toISOString()}}),u)throw u;return c}async function Hn(e,t,n){let{connection:i,tools:r}=await He(e,t),o=r.find(u=>u.name===n);if(!o)throw new g("The requested provider tool is unavailable.",404,"live_tool_missing",!1);let s=de(B({tools:r,connectionActive:i.lifecycleStatus==="connected",actionsEnabled:i.actionsEnabled}),o.name),a=ue(o),d=s.available,c={name:o.name,...o.title?{title:o.title}:{},...o.description?{description:o.description}:{},inputSchema:o.inputSchema,...o.outputSchema?{outputSchema:o.outputSchema}:{},...o.annotations?{annotations:o.annotations}:{}};return{...c,classification:a,callable:d,blockedReason:s.blockedReason,requiredPermissions:s.requiredPermissions,missingPermissions:s.missingPermissions,requiredFeatures:s.requiredFeatures,missingFeatures:s.missingFeatures,transport:"nango",providerConfigKey:i.providerConfigKey,providerContractVersion:ut,providerContractHash:dt,protocolVersion:null,schemaSource:"live_tools_list",schemaHash:O("sha256").update(JSON.stringify(c)).digest("hex"),fetchedAt:new Date().toISOString()}}export{Ct as a,K as b,X as c,St as d,Nt as e,ht as f,Rt as g,At as h,xt as i,It as j,Ot as k,Lt as l,Ut as m,Dt as n,Pt as o,kt as p,Mt as q,an as r,cn as s,un as t,dn as u,ln as v,mn as w,pn as x,D as y,Qt as z,$e as A,je as B,T as C,ae as D,ce as E,Cn as F,Kt as G,C as H,Ke as I,S as J,Xt as K,Bt as L,Gt as M,Vt as N,$t as O,g as P,G as Q,Le as R,Ln as S,Un as T,Dn as U,Pn as V,kn as W,Mn as X,qn as Y,He as Z,Fn as _,Hn as $};
|