mcp-scraper 0.89.4 → 0.89.6
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 +27 -1
- package/README.md +1 -1
- package/dist/{analytics-repository-5CAFUXYD.js → analytics-repository-4UA3WI3U.js} +1 -1
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- 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/{chunk-K7KMLT33.js → chunk-3H7HU5JI.js} +1 -1
- package/dist/{chunk-J7EVLE6H.js → chunk-C6JXNOSF.js} +1 -1
- package/dist/chunk-CULFQBFR.js +1 -0
- package/dist/chunk-D6BTAT5Y.js +1 -0
- package/dist/{chunk-HYQDXTS7.js → chunk-FKSTNWP6.js} +1 -1
- package/dist/{chunk-DMCYIWB3.js → chunk-FVSXX43Z.js} +1 -1
- package/dist/{chunk-OBDMJCCF.js → chunk-G6GAIXXA.js} +2 -2
- package/dist/{chunk-CYOEMHTB.js → chunk-H2I63VAD.js} +1 -1
- package/dist/chunk-H3QW5U67.js +41 -0
- package/dist/chunk-ISZIA6NE.js +820 -0
- package/dist/{chunk-S7RA23GR.js → chunk-KKI2SNB2.js} +1 -1
- package/dist/{chunk-OXFWXWQG.js → chunk-PPOI4C3Q.js} +1 -1
- package/dist/{chunk-EN66HBAW.js → chunk-VZTFJLOK.js} +1 -1
- package/dist/{chunk-D4NOJAUN.js → chunk-WUVMD6ZX.js} +1 -1
- package/dist/{chunk-VEJQ4XPI.js → chunk-WXOLIRFJ.js} +1 -1
- package/dist/chunk-Y3ITV2OK.js +19 -0
- package/dist/{chunk-Z27SYWYD.js → chunk-YCZKKSTT.js} +1 -1
- package/dist/{chunk-Z66Z2HV4.js → chunk-YQ5U5C2X.js} +121 -73
- package/dist/{chunk-QN3QHTVK.js → chunk-Z45GM22P.js} +190 -190
- package/dist/db-IZ5UF33U.js +1 -0
- package/dist/{extract-bundle-TXH3VNXH.js → extract-bundle-BTZQJTYV.js} +1 -1
- package/dist/gmail-service-ZZDF52KK.js +1 -0
- package/dist/index.cjs +19 -19
- package/dist/index.js +1 -1
- package/dist/{lead-list-enrichment-repository-G7Z5DQZR.js → lead-list-enrichment-repository-K4H5DMSF.js} +1 -1
- package/dist/{location-data-repository-TEXZ3I2N.js → location-data-repository-KALKE3FG.js} +1 -1
- package/dist/{server-RORLM2FG.js → server-YVNOU3RK.js} +727 -1546
- package/dist/{site-extract-repository-MBSCAP4D.js → site-extract-repository-FTTIOWAL.js} +1 -1
- package/dist/stripe-event-worker-CURL3RYL.js +1 -0
- package/dist/{worker-SUCJKWU2.js → worker-MUHILD2W.js} +1 -1
- package/package.json +1 -1
- package/dist/chunk-2O3UYISB.js +0 -59
- package/dist/chunk-RNDORDA2.js +0 -1
- package/dist/db-NLGNTQC3.js +0 -1
- package/dist/gmail-service-J2DWSQJX.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as _,i as c}from"./chunk-
|
|
1
|
+
import{g as _,i as c}from"./chunk-YQ5U5C2X.js";var g={\u006b\u0065\u0072\u006e\u0065\u006c:"browserRuntime"},a=/error|message/i,w=(new RegExp("(?:spending|billing|organization|account).{0,80}(?:cap|limit|blocked|disabled)|(?:quota|capacity).{0,40}(?:reached|exceeded)|https?:\\/\\/\\S*(?:dashboard|on\u006b\u0065\u0072\u006e\u0065\u006c)", "i")),E=/\b(?:ENOENT|ENOTDIR|EACCES|EPERM|EISDIR|EMFILE|ENFILE)\b|\b(?:mkdir|open|stat|lstat|readFile|writeFile)\s+['"]?(?:\/|[A-Za-z]:\\)|(?:^|[\s'"])(?:\/Users|\/home|\/tmp|\/var|\/private|\/opt|\/srv|\/root)\//i,k=new Set(["\u006b\u0065\u0072\u006e\u0065\u006c_session_id","browser_session_id","\u006b\u0065\u0072\u006e\u0065\u006cSessionId","browserSessionId","sessionId","\u006b\u0065\u0072\u006e\u0065\u006c_delete_started","session_cleanup_started","\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted","sessionCleanupStarted","\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded","session_cleanup_succeeded","\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded","sessionCleanupSucceeded","\u006b\u0065\u0072\u006e\u0065\u006c_delete_error","session_cleanup_error","\u006b\u0065\u0072\u006e\u0065\u006cDeleteError","sessionCleanupError","\u006b\u0065\u0072\u006e\u0065\u006cProxyId","proxyId","requestedProxyIdSuffix","retrievedProxyIdSuffix","provider","providerName","service","serviceName","vendor","vendorName","organization","organizationId","accountId","browser_provider","provider_session_id","provider_session_observed_at","provider_lookup_status","provider_status","provider_error_code","provider_error_message","provider_reason_source","provider_duration_ms","provider_bandwidth_bytes","provider_captcha","provider_checked_at","provider_detail","provider_detail_json","provider_disconnect_observed","provider_disconnect_message","browserProvider","providerSessionId","providerLookupStatus","providerStatus","providerErrorCode","providerErrorMessage","providerReasonSource","providerDurationMs","providerBandwidthBytes","providerCaptcha","providerCheckedAt","providerDetail","providerDisconnectObserved","providerDisconnectMessage"]),S=new Set(["hosted_url","hostedUrl","live_view_url","liveViewUrl","cdp_ws_url","cdpWsUrl","browser_live_view_url"]),f=(new RegExp("\\b(?:wss?|https?):\\/\\/[^\\s\"'<>]*\\bon\u006b\u0065\u0072\u006e\u0065\u006c\\.com[^\\s\"'<>]*", "gi"));function b(e){return e.replace(f,"[browser-service]")}var R=new Set(["\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api","\u006b\u0065\u0072\u006e\u0065\u006c","local"]),m=new Set(["pending","complete","not_found","unavailable_credentials","temporary_error","invalid_payload","not_applicable"]),h=new Set(["active","running","complete","completed","failed","closed","stopped","terminated","timed_out"]),I=new Set(["provider_session_api","client_runtime","extractor","unknown"]),y=new Set(["browser_disconnected","worker_disconnect","job_killed","cdp_cmd_timeout","network_inactivity_timeout","session_timeout","client_timeout","navigate_domains_limit","cdp_error","browser_session_interrupted","provider_detail_pending","provider_lookup_unavailable","provider_reported_no_error","provider_session_not_found","provider_invalid_json","provider_invalid_payload","provider_lookup_timeout","provider_lookup_network_error","unknown"]),T=new Set(["browser_provider","provider_session_id","provider_lookup_status","provider_status","provider_error_code","provider_error_message","provider_reason_source","provider_duration_ms","provider_bandwidth_bytes","provider_captcha","provider_checked_at","provider_detail","provider_detail_json","provider_disconnect_observed","provider_disconnect_message"]),P=512,A=320;function t(e,r){return typeof e=="string"&&r.has(e)?e:null}function O(e){return typeof e!="string"?null:y.has(e)||/^provider_http_(?:429|5\d\d)$/.test(e)?e:null}function D(e){return typeof e!="string"||e.length<1||e.length>P||/^(?:authorization|bearer|password|secret|token|api[_-]?key|account)/i.test(e)?null:/^[A-Za-z0-9._:-]+$/.test(e)&&!e.includes("://")?e:null}function p(e){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=0?e:null}function l(e){if(typeof e!="string"||e.length>40)return null;let r=Date.parse(e);return Number.isFinite(r)&&new Date(r).toISOString()===e?e:null}function u(e){if(typeof e!="string")return null;let r=e.replace(/[\u0000-\u001f\u007f]+/g," ").replace(/\s+/g," ").trim();if(!r||r.startsWith("{")||r.startsWith("["))return null;let o=r.replace(/\b(?:wss?|https?):\/\/\S+/gi,"[redacted endpoint]").replace(/\b(?:authorization|proxy-authorization)\s*:\s*(?:Bearer\s+)?\S+/gi,"[redacted credential]").replace(/\bBearer\s+\S+/gi,"[redacted credential]").replace(/\b(?:api[_-]?key|password|secret|token|account[_-]?id)\s*[=:]\s*[^\s,;]+/gi,"[redacted credential]").replace(/\b(?:account|organization)\s+(?:id\s+)?[A-Za-z0-9_-]{4,}/gi,"[redacted account]");return b(o).slice(0,A)}function v(e){return typeof e=="boolean"?e:null}function N(e){return{browser_provider:t(e.browser_provider,R),provider_session_id:D(e.provider_session_id),provider_session_observed_at:l(e.provider_session_observed_at),provider_lookup_status:t(e.provider_lookup_status,m),provider_status:t(e.provider_status,h),provider_error_code:O(e.provider_error_code),provider_error_message:u(e.provider_error_message),provider_reason_source:t(e.provider_reason_source,I),provider_duration_ms:p(e.provider_duration_ms),provider_bandwidth_bytes:p(e.provider_bandwidth_bytes),provider_captcha:v(e.provider_captcha),provider_checked_at:l(e.provider_checked_at),provider_disconnect_observed:v(e.provider_disconnect_observed),provider_disconnect_message:u(e.provider_disconnect_message)}}function i(e,r=""){if(typeof e=="string"){let o=b(e);return a.test(r)&&(w.test(e)||E.test(e))?o=_("service_unavailable"):a.test(r)&&(o=c(o)),o}if(Array.isArray(e))return e.map(o=>i(o,r));if(e!==null&&typeof e=="object"){let o={};for(let[n,d]of Object.entries(e)){if(k.has(n))continue;let s=g[n]??n;if(S.has(n)){o[s]=null;continue}o[s]=i(d,n)}return o}return e}function L(e){return e.map(r=>{if(r===null||typeof r!="object"||Array.isArray(r))return i(r);let o=r,n=i(o);return Object.keys(o).some(s=>T.has(s))?{...n,...N(o)}:n})}function C(e){let r=e?.diagnostics;return r?.debug?{...e,diagnostics:{...r,debug:i(r.debug)}}:e}export{i as a,L as b,C as c};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as Q,d as Se}from"./chunk-
|
|
1
|
+
import{a as Q,d as Se}from"./chunk-YCZKKSTT.js";import{createHash as pe,createHmac as Yt,randomBytes as P,randomUUID as y}from"crypto";import{Pool as Wt}from"pg";var ct=[[/perplexity/i,"llm","Perplexity"],[/chatgpt|chat\.openai|openai/i,"llm","ChatGPT"],[/claude|anthropic/i,"llm","Claude"],[/\bgrok\b|xai/i,"llm","Grok"],[/ai[ _-]?overview|google[ _-]?ai|\bsge\b|gemini/i,"llm","Google AI Overview"],[/instagram/i,"social","Instagram"],[/facebook|\bfb\b|meta/i,"social","Facebook"],[/linkedin/i,"social","LinkedIn"],[/tiktok/i,"social","TikTok"],[/youtube|youtu\.be/i,"social","YouTube"],[/twitter|x\.com/i,"social","X"],[/\bg2\b|g2\.com/i,"review","G2"],[/trustpilot/i,"review","Trustpilot"],[/\bbbb\b|better business bureau/i,"review","BBB"],[/capterra/i,"review","Capterra"],[/yelp/i,"review","Yelp"],[/google|bing|duckduckgo|yahoo/i,"search","Search"]];function q(e,t=240){return typeof e=="string"&&e.trim()?e.trim().slice(0,t):null}function Ce(e){try{return e?new URL(e).hostname.replace(/^www\./,""):""}catch{return""}}function Re(e){let t=e.properties??{},i=q(e.source,180)||Ce(e.referrer)||"(direct)",n=q(e.medium,180)||(i==="(direct)"?"(none)":"referral"),s=e.clickIds??{},a=`${i} ${n} ${Ce(e.referrer)}`,r=i==="(direct)"?"direct":/email|newsletter/i.test(n)?"email":"referral",o=i==="(direct)"?"Direct":i;for(let[d,_,u]of ct)if(d.test(a)){r=_,o=u;break}return s.fbclid?(r="social",o=/instagram/i.test(a)?"Instagram":"Facebook"):s.ttclid?(r="social",o="TikTok"):s.rdt_cid?(r="social",o="Reddit"):s.gclid||s.gbraid||s.wbraid?(r="search",o="Google"):s.msclkid&&(r="search",o="Microsoft Ads"),{channelFamily:r,platform:o,source:i,medium:n,campaign:q(e.campaign),campaignId:q(t.campaign_id??t.utm_id),adSetId:q(t.adset_id??t.ad_set_id??t.adgroup_id??t.ad_group_id),adId:q(t.ad_id),creativeId:q(t.creative_id),placement:q(t.placement),term:q(t.utm_term),content:q(t.utm_content)}}import{createHash as yt,randomUUID as ee}from"crypto";import{createCipheriv as _t,createDecipheriv as ut,createHmac as fe,randomBytes as Et,scryptSync as lt,timingSafeEqual as Nt}from"crypto";var Z="xray1";function mt(){return process.env.ANALYTICS_RESTRICTED_DATA_SECRET?.trim()||Q()}function _e(e){return lt(mt(),`xray-restricted:${e}:v1`,32)}function De(e,t){let i=t.trim().slice(0,80);if(!i)throw new Error("analytics encryption purpose required");let n=Et(12),s=_t("aes-256-gcm",_e(i),n);s.setAAD(Buffer.from(`${Z}:${i}`,"utf8"));let a=Buffer.concat([s.update(e,"utf8"),s.final()]),r=s.getAuthTag();return[Z,Buffer.from(i,"utf8").toString("base64url"),n.toString("base64url"),r.toString("base64url"),a.toString("base64url")].join(".")}function Ue(e,t){try{let[i,n,s,a,r]=e.split(".");if(i!==Z||!n||!s||!a||!r)return null;let o=Buffer.from(n,"base64url").toString("utf8");if(o!==t)return null;let d=ut("aes-256-gcm",_e(o),Buffer.from(s,"base64url"));return d.setAAD(Buffer.from(`${Z}:${o}`,"utf8")),d.setAuthTag(Buffer.from(a,"base64url")),Buffer.concat([d.update(Buffer.from(r,"base64url")),d.final()]).toString("utf8")}catch{return null}}function bi(e,t){return fe("sha256",_e(`identity:${e}`)).update(t.trim().toLowerCase()).digest("hex")}function hi(e,t,i,n){return fe("sha256",n).update(`${e}.${t}.${i}`).digest("hex")}function xi(e,t){if(!e||e.length!==t.length)return!1;try{return Nt(Buffer.from(e),Buffer.from(t))}catch{return!1}}var we="enhanced_matching",pt=90,Tt=10,H=class extends Error{constructor(i,n,s){super(n);this.code=i;this.status=s;this.name="AnalyticsIdentityProfileError"}code;status};function te(e,t){return e?.trim().replace(/\s+/g," ").slice(0,t)||null}function Lt(e){if(!e)return null;let[t,i]=e.split("@");return!t||!i?null:`${t.slice(0,1)}${"*".repeat(Math.min(6,Math.max(2,t.length-1)))}@${i}`}function At(e){if(!e)return null;let t=e.replace(/\D/g,"");return t.length<4?null:`***-***-${t.slice(-4)}`}function ue(e){return yt("sha256").update(e).digest("hex")}async function ie(e,t){if(!t.signals.length)return;let i=t.signals.map(a=>a.kind),n=t.signals.map(a=>a.valueHmac);if((await e.query(`SELECT 1 FROM analytics_identity_tombstones
|
|
2
2
|
WHERE site_id=$1 AND (kind,value_hmac) IN (
|
|
3
3
|
SELECT * FROM unnest($2::text[],$3::text[])
|
|
4
4
|
) LIMIT 1`,[t.siteId,i,n])).rowCount)throw new H("analytics_identity_deleted","This identity cannot be automatically recreated.",410)}async function ne(e,t){let i=te(t.displayName,160),n=te(t.email,320)?.toLowerCase()??null,s=te(t.phone,40);if(!i&&!n&&!s)return!1;let r=(await e.query(`SELECT p.public_ref FROM analytics_people p
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{t as r}from"./chunk-YQ5U5C2X.js";import{createHash as b,randomUUID as O}from"crypto";var p="mcp-scraper/lead-list-enrichment.requested",A=new Set(["complete","partial","empty","failed","cancelled"]),U=new Set(["complete","failed","cancelled"]),T=10,g=360,S=60,h=null,m=null;function o(e,t,s){let n=e.trim();if(!n||n.length>s)throw new Error(`${t} is required and must be ${s} characters or fewer`);return n}function d(e,t){if(!Number.isSafeInteger(e)||e<0)throw new Error(`${t} must be a non-negative safe integer`);return e}function u(e){if(e==null)return null;try{return JSON.parse(String(e))}catch{return null}}function R(e){let t=new WeakSet,s=n=>{if(n===null||typeof n=="string"||typeof n=="boolean")return n;if(typeof n=="number"){if(!Number.isFinite(n))throw new Error("canonical fingerprint input must contain finite numbers");return Object.is(n,-0)?0:n}if(Array.isArray(n))return n.map(s);if(typeof n=="object"){if(t.has(n))throw new Error("canonical fingerprint input must not be cyclic");t.add(n);let i={};for(let _ of Object.keys(n).sort()){let c=n[_];c!==void 0&&(i[_]=s(c))}return t.delete(n),i}throw new Error(`canonical fingerprint input contains unsupported ${typeof n}`)};return JSON.stringify(s(e))}function y(e){return b("sha256").update(R(e)).digest("hex")}function I(e){return b("sha256").update(R(e)).digest("hex")}function j(){return{mapsAttempts:0,pageAttempts:0,pageSuccesses:0,serpSearches:0}}function E(e){let t=u(e.input_json);if(!t)throw new Error(`lead list enrichment job ${String(e.id??"")} has invalid durable input`);return{id:String(e.id),userId:Number(e.user_id),idempotencyKey:String(e.idempotency_key),requestFingerprint:String(e.request_fingerprint),input:t,status:String(e.status),totalRows:Number(e.total_rows??0),doneRows:Number(e.done_rows??0),failedRows:Number(e.failed_rows??0),cancelledRows:Number(e.cancelled_rows??0),usage:{mapsAttempts:Number(e.maps_attempts??0),pageAttempts:Number(e.page_attempts??0),pageSuccesses:Number(e.page_successes??0),serpSearches:Number(e.serp_searches??0)},concurrencyLockId:e.concurrency_lock_id==null?null:String(e.concurrency_lock_id),debitKey:String(e.debit_key),holdMc:Number(e.hold_mc??0),billedMc:e.billed_mc==null?null:Number(e.billed_mc),result:u(e.result_json),csvArtifact:u(e.csv_artifact_json),xlsxArtifact:u(e.xlsx_artifact_json),warnings:u(e.warnings_json)??[],cancelRequestedAt:e.cancel_requested_at==null?null:String(e.cancel_requested_at),errorCode:e.error_code==null?null:String(e.error_code),errorMessage:e.error_message==null?null:String(e.error_message),retryable:e.retryable==null?null:Number(e.retryable)===1,createdAt:String(e.created_at??""),startedAt:e.started_at==null?null:String(e.started_at),completedAt:e.completed_at==null?null:String(e.completed_at),updatedAt:String(e.updated_at??"")}}function w(e){return{jobId:String(e.job_id),ordinal:Number(e.ordinal),inputDigest:String(e.input_digest),status:String(e.status),result:u(e.result_json),usage:{mapsAttempts:Number(e.maps_attempts??0),pageAttempts:Number(e.page_attempts??0),pageSuccesses:Number(e.page_successes??0),serpSearches:Number(e.serp_searches??0)},errorCode:e.error_code==null?null:String(e.error_code),errorMessage:e.error_message==null?null:String(e.error_message),retryable:Number(e.retryable??0)===1,durationMs:Number(e.duration_ms??0),startedAt:e.started_at==null?null:String(e.started_at),completedAt:e.completed_at==null?null:String(e.completed_at),updatedAt:String(e.updated_at??"")}}function M(e){return{id:String(e.id),jobId:String(e.job_id),eventName:p,status:String(e.status),attempts:Number(e.attempts??0),claimToken:e.locked_by==null?null:String(e.locked_by),lockedUntil:e.locked_until==null?null:String(e.locked_until),nextAttemptAt:e.next_attempt_at==null?null:String(e.next_attempt_at),lastError:e.last_error==null?null:String(e.last_error),createdAt:String(e.created_at??""),dispatchedAt:e.dispatched_at==null?null:String(e.dispatched_at),updatedAt:String(e.updated_at??"")}}async function a(){let e=r();return h!==e&&(h=e,m=null),m||(m=(async()=>{await e.execute(`CREATE TABLE IF NOT EXISTS lead_list_enrichment_jobs (
|
|
2
2
|
id TEXT PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id), idempotency_key TEXT NOT NULL,
|
|
3
3
|
request_fingerprint TEXT NOT NULL, input_json TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'initializing',
|
|
4
4
|
total_rows INTEGER NOT NULL DEFAULT 0, done_rows INTEGER NOT NULL DEFAULT 0,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{t as _}from"./chunk-YQ5U5C2X.js";import{AsyncLocalStorage as N}from"async_hooks";var C="MCP_SCRAPER_ALLOW_HEADLESS_HARVEST_TEST",d=new N;function D(e,t){return d.run(e,t)}function l(){return d.getStore()}import{randomUUID as T}from"crypto";var p=166667e-10,L=.0001333336,h=new Set(["serp","fb_search","fb_ad","instagram"]),A=.00111,R=4,g=4e-4;function n(e,t){let r=process.env[e]?.trim();if(!r)return t;let o=Number(r);return Number.isFinite(o)&&o>=0?o:t}var m=n("NANGO_USD_PER_CONNECTION_MONTH",1),U=n("NANGO_USD_PER_FUNCTION_RUN",1e-4),O=n("NANGO_USD_PER_PROXY_REQUEST",1e-4),S=n("NANGO_USD_PER_COMPUTE_SEC",2e-4),b=n("\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_BROWSER_USD_PER_GB",8);function u(e,t){return Math.max(0,e)/1e3*(t?L:p)}function i(e,t){return e==="fal_wizper"?Math.max(0,t)/R*A:e==="deepinfra_qwen"?Math.max(0,t)/1e3*g:e==="openrouter"||e==="mcp_memory_video"||e==="mcp_memory_ai"?Math.max(0,t):e==="nango_connection"?Math.max(0,t)*m:e==="nango_function_run"?Math.max(0,t)*U:e==="nango_proxy_request"?Math.max(0,t)*O:e==="nango_compute"?Math.max(0,t)*S:e==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser_api"?Math.max(0,t)/1e9*b:0}var E=!1,s=null;async function c(){if(!E)return s||(s=x().finally(()=>{s=null}),s)}async function x(){let e=_(),t=await e.execute(`
|
|
2
2
|
SELECT
|
|
3
3
|
(SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name IN ('\u006b\u0065\u0072\u006e\u0065\u006c_session_log', 'vendor_usage_log', 'cost_probe_runs')) = 3
|
|
4
4
|
AND (SELECT COUNT(*) FROM pragma_table_info('\u006b\u0065\u0072\u006e\u0065\u006c_session_log') WHERE name IN ('proxy_source', 'proxy_type', 'method')) = 3
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as j,b as T,c as P,d as C,f as S}from"./chunk-TMB56NCA.js";import{W as w}from"./chunk-MZN4U5BL.js";import{
|
|
1
|
+
import{a as j,b as T,c as P,d as C,f as S}from"./chunk-TMB56NCA.js";import{W as w}from"./chunk-MZN4U5BL.js";import{Gb as N,Pb as D,d as m,e as I,i as u,t as s}from"./chunk-YQ5U5C2X.js";import{createHash as W}from"crypto";import{gunzipSync as $,gzipSync as q}from"zlib";var y="site-extracts/",L=10080*60*1e3,H=900*1e3;function U(){return process.env.SITE_EXTRACT_ARTIFACT_READ_WRITE_TOKEN?.trim()||process.env.PRIVATE_ARTIFACT_READ_WRITE_TOKEN?.trim()||process.env.CONNECTED_DATA_READ_WRITE_TOKEN?.trim()||process.env.CONNECTED_DATA_BLOB_READ_WRITE_TOKEN?.trim()||null}function v(){return process.env.VERCEL==="1"||process.env.NODE_ENV==="production"}function p(){return{prefix:y,artifactTtlMs:L,downloadTtlMs:H,token:U()}}function h(t){return j(t,y)}async function V(t){let e=await P({policy:p(),ownerId:t.ownerId,artifactKey:`${t.jobId}.zip`,createdAt:t.createdAt,filename:`${t.jobId}-site-export.zip`,contentType:"application/zip",content:t.content});return{key:e.artifactId,url:e.downloadUrl??"",bytes:e.bytes,contentType:e.contentType,filename:e.filename,sha256:e.sha256,expiresAt:e.expiresAt,downloadUrlExpiresAt:e.downloadUrlExpiresAt,kind:"bundle"}}async function G(t){let e=await T({policy:p(),ownerId:t.ownerId,scopeSegments:[t.jobId,"images"],artifactKey:`${t.imageId}.bin`,createdAt:new Date,filename:t.filename,contentType:t.contentType,content:t.content});return{key:e.artifactId,url:e.downloadUrl??"",bytes:e.bytes,contentType:e.contentType,filename:e.filename,sha256:e.sha256,expiresAt:e.expiresAt,downloadUrlExpiresAt:e.downloadUrlExpiresAt,kind:"image",imageId:t.imageId,sourceUrl:t.sourceUrl,sourcePage:t.sourcePage}}async function O(t){return T({policy:p(),ownerId:t.ownerId,scopeSegments:[t.jobId,"content"],artifactKey:`${t.chunkKey}.json.gz`,createdAt:t.createdAt,filename:`${t.chunkKey}.json.gz`,contentType:"application/gzip",content:t.content})}async function Q(t){return C({policy:p(),artifactId:t.artifactId,ownerId:t.ownerId})}async function J(t){return S({policy:p(),artifactId:t,maxBytes:50*1024*1024})}async function Z(t){return h(t.artifactId)!==t.ownerId?null:J(t.artifactId)}async function k(t){return h(t.artifactId)!==t.ownerId?null:S({policy:p(),artifactId:t.artifactId,maxBytes:25*1024*1024})}async function tt(t){return h(t.artifactId)!==t.ownerId?null:S({policy:p(),artifactId:t.artifactId,maxBytes:10*1024*1024})}async function et(t={}){let e=t.now??new Date,n=U();if(!n)return{deleted:0,store:v()?"none":"local"};if(!t.force&&!(e.getUTCHours()===3&&e.getUTCMinutes()===21))return{deleted:0,store:"private-vercel-blob",skipped:!0};let r=e.getTime()-L,{list:i,del:a}=await import("@vercel/blob"),o,c=0;for(let d=0;d<20;d+=1){let l=await i({prefix:y,token:n,limit:1e3,cursor:o}),f=l.blobs.filter(A=>new Date(A.uploadedAt).getTime()<=r);if(f.length>0&&(await a(f.map(A=>A.pathname),{token:n}),c+=f.length),!l.hasMore||!l.cursor)break;o=l.cursor}return{deleted:c,store:"private-vercel-blob"}}var F=10,b=20*1024*1024;function E(t){return W("sha256").update(t).digest("hex")}function B(t){return!t.acquiredHtml||t.extractionStatus==="failed"?null:{pageId:t.pageId??E(t.archivedUrl??t.url),url:t.archivedUrl??t.url,html:t.acquiredHtml,mainHtml:t.mainHtml??"",markdown:t.bodyMarkdown,htmlSha256:t.htmlSha256??E(t.acquiredHtml),markdownSha256:t.markdownSha256??E(t.bodyMarkdown)}}function R(t){return Buffer.from(JSON.stringify({version:"site-extract-content.v1",pages:t}))}async function M(t){let e=t.pages.flatMap(o=>{let c=B(o);return c?[c]:[]}),n=new Map,r=[],i=0,a=async()=>{if(!r.length)return;let o=R(r);if(o.length>b)throw new Error(`site export content chunk exceeds ${b} bytes`);let c=E(r.map(l=>l.pageId).join("\0")).slice(0,16),d=await O({ownerId:t.ownerId,jobId:t.jobId,createdAt:t.createdAt,chunkKey:`content-${String(i).padStart(4,"0")}-${c}`,content:q(o,{level:6})});for(let l of r)n.set(l.url,{artifactId:d.artifactId,artifactSha256:d.sha256,pageId:l.pageId,uncompressedBytes:o.length});i++,r=[]};for(let o of e){let c=[...r,o];if(r.length>0&&(c.length>F||R(c).length>b)&&await a(),r.push(o),R(r).length>b)throw new Error(`page ${o.pageId} exceeds the durable content chunk limit`)}return await a(),n}function it(t){let e=new Map;return async n=>{let r=e.get(n.artifactId);if(!r){let a=await k({artifactId:n.artifactId,ownerId:t});if(!a)throw new Error("site export content chunk is missing or unauthorized");if(E(a)!==n.artifactSha256)throw new Error("site export content chunk checksum mismatch");let o=$(a);if(o.length>b)throw new Error("site export content chunk exceeds its read limit");if(r=JSON.parse(o.toString("utf8")),r.version!=="site-extract-content.v1"||!Array.isArray(r.pages))throw new Error("site export content chunk has an unsupported contract");for(e.set(n.artifactId,r);e.size>2;)e.delete(e.keys().next().value)}let i=r.pages.find(a=>a.pageId===n.pageId);if(!i)throw new Error("site export page is missing from its content chunk");if(E(i.html)!==i.htmlSha256||E(i.markdown)!==i.markdownSha256)throw new Error("site export page checksum mismatch");return i}}var g="xray_entitlement";function pt(t){let e=Math.max(1,Number(t.options.effectiveMaxPages??t.options.maxPages??1)),n=Math.max(e,Number(t.options.requestedMaxPages??e)),r=n>e;return{requestedMaxPages:n,effectiveMaxPages:e,creditLimited:r,creditTruncated:r&&t.totalUrls>=e}}function Et(t,e=!1){return t.successfulUrls===0?"failed":t.failedUrls>0||t.remainingUrls>0||e?"partial":"complete"}function _(t){let e=Number(t.total_urls??0),n=t.attempted_urls==null,r=Number(n?t.done_urls??0:t.attempted_urls),i=Number(n?t.done_urls??0:t.successful_urls??0),a=Number(t.failed_urls??Math.max(0,r-i));return{id:String(t.id),userId:t.user_id!=null?Number(t.user_id):null,idempotencyKey:t.idempotency_key!=null?String(t.idempotency_key):null,requestFingerprint:t.request_fingerprint!=null?String(t.request_fingerprint):null,status:t.status!=null?String(t.status):"pending",startUrl:String(t.start_url??""),options:t.options?JSON.parse(String(t.options)):{},totalUrls:e,doneUrls:r,attemptedUrls:r,successfulUrls:i,failedUrls:a,remainingUrls:Math.max(0,e-r),artifacts:t.artifacts?JSON.parse(String(t.artifacts)):null,error:t.error!=null?String(t.error):null,publicError:I(t.public_error_json),billedMc:t.billed_mc!=null?Number(t.billed_mc):null,createdAt:String(t.created_at??""),updatedAt:String(t.updated_at??"")}}async function mt(t,e,n,r){await s().execute({sql:`INSERT INTO site_extract_jobs (id, user_id, status, start_url, options, created_at, updated_at)
|
|
2
2
|
VALUES (?, ?, 'pending', ?, ?, datetime('now'), datetime('now'))`,args:[t,e,n,JSON.stringify(r)]})}async function K(t,e){let r=await s().execute({sql:"SELECT * FROM site_extract_jobs WHERE user_id = ? AND idempotency_key = ? LIMIT 1",args:[t,e]});return r.rows[0]?_(r.rows[0]):null}async function gt(t){let n=await s().execute({sql:`INSERT OR IGNORE INTO site_extract_jobs
|
|
3
3
|
(id, user_id, status, start_url, options, idempotency_key, request_fingerprint, created_at, updated_at)
|
|
4
4
|
VALUES (?, ?, 'pending', ?, ?, ?, ?, datetime('now'), datetime('now'))`,args:[t.jobId,t.userId,t.startUrl,JSON.stringify(t.options),t.idempotencyKey,t.requestFingerprint]}),r=await K(t.userId,t.idempotencyKey);if(!r)throw new Error("idempotent extract job was not persisted");return{job:r,created:n.rowsAffected===1,conflict:r.requestFingerprint!==t.requestFingerprint}}async function x(t){let n=await s().execute({sql:"SELECT * FROM site_extract_jobs WHERE id = ?",args:[t]});return n.rows[0]?_(n.rows[0]):null}async function _t(t){return(await s().execute({sql:"SELECT * FROM site_extract_jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[t]})).rows.map(r=>_(r))}async function xt(t=25){return(await s().execute({sql:`SELECT * FROM site_extract_jobs
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import{f as F,h as V,i as re,j as ae,l as $}from"./chunk-YCZKKSTT.js";import{W as R,e as U,q as _,t as G,u as ne,v as oe,w as M,y as ie}from"./chunk-MZN4U5BL.js";import{b as K,h as L}from"./chunk-WUVMD6ZX.js";import{Ob as D,Q as te,Tb as x,t as C}from"./chunk-YQ5U5C2X.js";import{createHash as Te,randomUUID as Ne}from"crypto";import{z as f}from"zod";async function at(e,t){!Number.isFinite(t)||t<=0||await K({op:R.CONNECTED_ACCOUNT_FEE,userId:Number(e)},()=>L({vendor:"nango_connection",units:t,unitType:"connection_month"}))}async function se(e,t){let n=[{vendor:"nango_function_run",units:t.functionRuns,unitType:"function_run"},{vendor:"nango_proxy_request",units:t.proxyRequests,unitType:"proxy_request"},{vendor:"nango_compute",units:t.computeMilliseconds/1e3,unitType:"compute_second"}];await K({op:R.CONNECTED_USAGE,userId:Number(e)},async()=>{for(let o of n)!Number.isFinite(o.units)||o.units<=0||await L(o)})}var E="connected_usage",Re="mastra_scheduler",Ie=f.object({toolName:f.string().trim().min(1).max(200).optional(),operationKind:f.enum(["read","action","sync","export","proxy","other"]).optional(),outcome:f.enum(["success","error","partial"]).optional(),requestId:f.string().trim().min(1).max(200).optional(),occurrenceId:f.string().trim().min(1).max(200).optional(),scheduleId:f.string().trim().min(1).max(200).optional(),nangoOperationId:f.string().trim().min(1).max(200).optional(),startedAt:f.string().datetime({offset:!0}).optional(),completedAt:f.string().datetime({offset:!0}).optional()}).strict(),Ae=f.object({identity:f.string().trim().min(1).max(320),idempotencyKey:f.string().trim().min(1).max(500),ratePolicyVersion:f.string().trim().min(1).max(100),connectionId:f.string().trim().min(1).max(500),providerConfigKey:f.string().trim().min(1).max(200),functionRuns:f.number().int().safe().nonnegative(),proxyRequests:f.number().int().safe().nonnegative(),computeMilliseconds:f.number().int().safe().nonnegative(),sourceSurface:f.enum(["main_mcp","mastra_scheduler","nango_reconciliation"]).default(Re),metadata:Ie.optional()}).strict(),Pe=f.object({identity:f.string().trim().min(1).max(320),ratePolicyVersion:f.string().trim().min(1).max(100)}).strict(),h=class extends Error{constructor(n,o,a,i={}){super(o);this.code=n;this.httpStatus=a;this.details=i;this.name="ConnectedUsageBillingError"}code;httpStatus;details};function z(e){return Te("sha256").update(e).digest("hex")}function xe(e){return`connected-usage:${z(e)}`}function Ue(e){return`connected-usage-debit:${z(e)}`}function Me(e){return e.trim().toLowerCase()}async function ce(e){let t=await te(Me(e));if(!t)throw new h("user_not_found","billing identity was not found",404);return t}function Oe(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 z(JSON.stringify({ratePolicyVersion:_,connectionId:e.connectionId,providerConfigKey:e.providerConfigKey,usage:e.usage,sourceSurface:e.sourceSurface,metadata:t}))}function A(e){let t=JSON.stringify(e);if(t.length>4e3)throw new h("invalid_request","connected usage metadata is too large",400);return t}function W(e){try{let t=JSON.parse(e.metadata??"");if(t.contract!=="connected_usage_receipt"||t.ratePolicyVersion!==_||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 h("idempotency_key_conflict","the idempotency key is already bound to an incompatible billing receipt",409)}}async function H(e){let t=await C().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 de(e,t){return(await C().execute({sql:`SELECT 1
|
|
2
|
+
FROM billing_events
|
|
3
|
+
WHERE user_id = ?
|
|
4
|
+
AND billing_class = ?
|
|
5
|
+
AND status = 'cost_pending'
|
|
6
|
+
${t?"AND idempotency_key <> ?":""}
|
|
7
|
+
LIMIT 1`,args:t?[e,E,t]:[e,E]})).rows.length>0}function ke(e){let t="connected-usage:",n=e.startsWith(t)?e.slice(t.length):"";return/^[a-f0-9]{64}$/.test(n)?`connected-usage-debit:${n}`:null}async function qe(e){let t=await C().execute({sql:`SELECT id, user_id, idempotency_key, billing_class, source_surface, status, amount_mc, metadata
|
|
8
|
+
FROM billing_events
|
|
9
|
+
WHERE user_id = ? AND billing_class = ? AND status = 'cost_pending'
|
|
10
|
+
ORDER BY created_at ASC
|
|
11
|
+
LIMIT 10`,args:[e.id,E]});for(let n of t.rows){let o=n,a=String(o.idempotency_key??""),i=ke(a),s;try{s=W(o)}catch{return}if(!i||Number(o.user_id)!==e.id||o.billing_class!==E||Number(o.amount_mc)!==s.charge.amountMc||s.charge.amountMc>0&&!(await D(e.id,s.charge.amountMc,R.CONNECTED_USAGE,`connected-usage:${s.providerConfigKey}`,i)).ok)return;let r={...s};delete r.reason,await C().execute({sql:`UPDATE billing_events
|
|
12
|
+
SET status = 'settled', metadata = ?, settled_at = datetime('now')
|
|
13
|
+
WHERE idempotency_key = ? AND user_id = ? AND billing_class = ? AND status = 'cost_pending'`,args:[A(r),a,e.id,E]})}}function ue(e){if(e!==_)throw new h("rate_policy_mismatch","connected usage receipt rate policy does not match the active policy",409,{expectedRatePolicyVersion:_})}async function Y(e){let t=Pe.safeParse(e);if(!t.success)throw new h("invalid_request","invalid connected usage preflight request",400);ue(t.data.ratePolicyVersion);let n=await ce(t.data.identity);if(await qe(n),await de(n.id))throw new h("pending_cost","a previous connected usage receipt has unresolved cost",409);let o=await x(n.id,n.balance_mc);if(o<M)throw new h("insufficient_credits","the wallet cannot cover the minimum connected function charge",402,{balanceMc:o,requiredMc:M});return{allowed:!0,ratePolicyVersion:_,minimumMc:M,minimumCredits:G,balanceMc:o}}function B(e,t,n,o,a){let i=W(e);if(Number(e.user_id)!==t||e.billing_class!==E||e.source_surface!==n||Number(e.amount_mc)!==a||i.fingerprint!==o)throw new h("idempotency_key_conflict","the idempotency key is already bound to different connected usage",409);return i}function le(e,t){return[{key:"function_runs",label:"Connected function runs",quantity:e.functionRuns,quantityUnit:"function_run",rateCredits:G,rateUnit:"function_run",amountMc:t.functionRunMc,credits:t.functionRunMc/U},{key:"proxy_requests",label:"Connected proxy requests",quantity:e.proxyRequests,quantityUnit:"proxy_request",rateCredits:ne,rateUnit:"proxy_request",amountMc:t.proxyRequestMc,credits:t.proxyRequestMc/U},{key:"compute",label:"Connected function compute",quantity:e.computeMilliseconds,quantityUnit:"millisecond",rateCredits:oe,rateUnit:"compute_second",amountMc:t.computeMc,credits:t.computeMc/U}]}function J(e,t,n,o){let a=e.status==="cost_pending"?t.reason:void 0;return{id:e.id,status:e.status==="settled"?"settled":"cost_pending",ratePolicyVersion:_,connectionId:t.connectionId,providerConfigKey:t.providerConfigKey,amountMc:t.charge.amountMc,credits:t.charge.credits,functionRunMc:t.charge.functionRunMc,proxyRequestMc:t.charge.proxyRequestMc,computeMc:t.charge.computeMc,usage:t.usage,costBreakdown:le(t.usage,t.charge),balanceMc:n,...a?{reason:a}:{},duplicate:o}}async function j(e){let t=Ae.safeParse(e);if(!t.success)throw new h("invalid_request","invalid connected usage settlement request",400,{fields:[...new Set(t.error.issues.map(v=>v.path.join(".")).filter(Boolean))]});let n=t.data;ue(n.ratePolicyVersion);let o=await ce(n.identity),a={functionRuns:n.functionRuns,proxyRequests:n.proxyRequests,computeMilliseconds:n.computeMilliseconds},i=ie(a),s=n.metadata??{},r=Oe({connectionId:n.connectionId,providerConfigKey:n.providerConfigKey,usage:a,sourceSurface:n.sourceSurface,metadata:s}),u={contract:"connected_usage_receipt",ratePolicyVersion:_,fingerprint:r,connectionId:n.connectionId,providerConfigKey:n.providerConfigKey,usage:a,charge:i,safeMetadata:s},p=xe(n.idempotencyKey);if(await de(o.id,p))throw new h("pending_cost","a previous connected usage receipt has unresolved cost",409);let d=await C().execute({sql:`INSERT OR IGNORE INTO billing_events
|
|
14
|
+
(id, user_id, idempotency_key, billing_class, source_surface, status, amount_mc, metadata)
|
|
15
|
+
VALUES (?, ?, ?, ?, ?, 'settling', ?, ?)`,args:[Ne(),o.id,p,E,n.sourceSurface,i.amountMc,A(u)]}),g=await H(p);if(!g)throw new Error("connected usage receipt insert completed without a readable event");let y=B(g,o.id,n.sourceSurface,r,i.amountMc),b=d.rowsAffected===0;if(g.status==="settled")return J(g,y,await x(o.id,o.balance_mc),!0);if(!["settling","cost_pending"].includes(g.status))throw new h("idempotency_key_conflict","the connected usage receipt has an incompatible status",409);if(g.status==="cost_pending"&&await C().execute({sql:"UPDATE billing_events SET status = 'settling', metadata = ? WHERE idempotency_key = ? AND status = 'cost_pending'",args:[A(u),p]}),i.amountMc===0)await C().execute({sql:"UPDATE billing_events SET status = 'settled', settled_at = datetime('now') WHERE idempotency_key = ? AND status = 'settling'",args:[p]});else{let v=await D(o.id,i.amountMc,R.CONNECTED_USAGE,`connected-usage:${n.providerConfigKey}`,Ue(n.idempotencyKey));if(!v.ok){let Se={...u,reason:"insufficient_credits"};if(await C().execute({sql:"UPDATE billing_events SET status = 'cost_pending', metadata = ? WHERE idempotency_key = ? AND status = 'settling'",args:[A(Se),p]}),g=await H(p),!g)throw new Error("connected usage pending receipt was lost");return y=B(g,o.id,n.sourceSurface,r,i.amountMc),J(g,y,v.balance_mc,b||v.duplicate)}await C().execute({sql:"UPDATE billing_events SET status = 'settled', metadata = ?, settled_at = datetime('now') WHERE idempotency_key = ? AND status IN ('settling', 'cost_pending')",args:[A(u),p]}),v.duplicate||await se(o.id,a)}if(g=await H(p),!g)throw new Error("connected usage settlement completed without an event receipt");return y=B(g,o.id,n.sourceSurface,r,i.amountMc),J(g,y,await x(o.id,o.balance_mc),b)}async function pt(e,t=100){let n=await C().execute({sql:`SELECT id, user_id, billing_class, source_surface, status, amount_mc, metadata, created_at
|
|
16
|
+
FROM billing_events
|
|
17
|
+
WHERE user_id = ? AND billing_class = ? AND status IN ('settled', 'cost_pending')
|
|
18
|
+
ORDER BY created_at DESC
|
|
19
|
+
LIMIT ?`,args:[e,E,Math.max(1,Math.min(250,Math.round(t)))]}),o=[];for(let a of n.rows){let i=a;try{let s=W(i);o.push({id:i.id,createdAt:String(i.created_at??""),status:i.status==="settled"?"settled":"cost_pending",connectionId:s.connectionId,providerConfigKey:s.providerConfigKey,amountMc:s.charge.amountMc,credits:s.charge.credits,usage:s.usage,costBreakdown:le(s.usage,s.charge),metadata:s.safeMetadata})}catch{}}return o}import{createHash as I,randomUUID as ge}from"crypto";import{Client as De,StreamableHTTPClientTransport as Ke}from"@modelcontextprotocol/client";function Q(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 me(e){return new Map(Object.entries(e??{}).map(([t,n])=>[t,[...new Set(n.map(o=>o.trim()).filter(Boolean))].sort()]))}function O(e){let t=me(e.requiredPermissionsByTool),n=me(e.requiredFeaturesByTool),o=new Set(e.grantedPermissions??[]),a=new Set(e.enabledFeatures??[]),i=new Set(e.adminBlockedTools??[]),s=new Map;for(let r of e.tools){let u=Q(r),p=t.get(r.name)??[],d=n.get(r.name)??[],g=p.filter(v=>!o.has(v)),y=d.filter(v=>!a.has(v)),b=e.connectionActive?i.has(r.name)?"admin_blocked":u==="action"&&!e.actionsEnabled?"actions_disabled":p.length>0&&e.permissionVerification==="unavailable"?"permission_verification_unavailable":g.length>0?"missing_permission":y.length>0?"missing_app_feature":null:"inactive_connection";s.set(r.name,{name:r.name,classification:u,requiredPermissions:p,requiredFeatures:d,available:b===null,blockedReason:b,missingPermissions:g,missingFeatures:y})}return s}function Z(e,t){let n=e.get(t);if(!n)throw new Error("connected_tool_policy_missing");return n}var Le="https://api.nango.dev/mcp",Ge=2e4,Fe=24e4,pe=100,Ve=20,$e=360*60*1e3,He=new Set(["stripe_revenue","salesforce","pipedrive"]),Be="2026-07-16.1",Je="f037859ec80c2ea2fac6e4a67c1a59f3200dd22d3642c97789b9bb3236723d3e",m=class extends Error{status;code;retryable;retryAfterMs;constructor(t,n,o,a=n===429||n>=500,i=null){super(t),this.name="MainNangoTransportError",this.status=n,this.code=o,this.retryable=a,this.retryAfterMs=i}};function k(e){return typeof e=="string"&&He.has(e.normalize("NFKC").trim().toLowerCase())}function fe(e){if(k(e))throw new m("This provider integration is not currently available.",409,"provider_unavailable",!1)}function ze(e){if(e instanceof Error)return e.message;if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return""}}function ye(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 _e(e){if(e instanceof m)return e;let t=ze(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 m("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 m("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 m("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 m("The connected provider is temporarily rate limited.",429,"upstream_rate_limited",!0,ye(t)):/UNAUTHENTICATED|invalid_grant|status["']?\s*:\s*401/i.test(t)?new m("The service connection requires reconnection.",409,"connection_inactive",!1):new m("The service connection is temporarily unavailable.",503,"connection_transport_unavailable")}async function We(e,t,n){return e.callTool({name:t,arguments:n},{timeout:Fe})}function l(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function c(e){return typeof e=="string"&&e.trim()?e.trim():null}function X(e,t){if(Array.isArray(e))return e;let n=l(e);if(Array.isArray(n?.[t]))return n[t];if(Array.isArray(n?.data))return n.data;let o=l(n?.data);return Array.isArray(o?.[t])?o[t]:[]}function he(){let e=process.env.NANGO_SECRET_KEY?.trim();if(!e)throw new m("Nango is not configured.",503,"nango_not_configured");return e}function we(){try{return new URL(process.env.NANGO_MCP_URL?.trim()||Le)}catch{throw new m("Nango MCP URL is invalid.",503,"nango_invalid_url")}}async function N(e,t={}){let n=new URL(e,`${we().origin}/`);for(let[s,r]of Object.entries(t.query??{}))r!==void 0&&n.searchParams.set(s,String(r));let o;try{o=await fetch(n,{method:t.method??"GET",headers:{authorization:`Bearer ${he()}`,accept:"application/json",...t.body?{"content-type":"application/json"}:{},...t.headers},body:t.body?JSON.stringify(t.body):void 0,signal:AbortSignal.timeout(Ge)})}catch{throw new m("Nango is temporarily unavailable.",503,"connection_transport_unavailable")}let a=await o.text(),i={};try{i=a?JSON.parse(a):{}}catch{throw new m("Nango returned an invalid response.",502,"nango_invalid_response")}if(!o.ok){let s=o.status===400||o.status===403||o.status===404||o.status===409||o.status===429||o.status===503?o.status:502;throw new m(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?ye(`retry-after: ${o.headers.get("retry-after")??""}`):null)}return i}function P(e){let t=c(e);return t?t.normalize("NFKC").toLowerCase():null}function Ye(e,t){let n=l(e),o=l(n?.tags),a=l(n?.end_user),i=P(t);if(!i)return!1;let s=[P(o?.end_user_email),P(a?.email)].filter(u=>!!u);if(s.some(u=>u!==i))return!1;let r=[P(o?.end_user_id),P(a?.id)].filter(u=>!!u&&u.includes("@"));return r.some(u=>u!==i)?!1:s.length>0?s.includes(i):r.includes(i)}function je(e){let t=l(e),n=c(t?.connection_id),o=c(t?.provider_config_key);if(!n||!o)return null;let i=(Array.isArray(t?.errors)?t.errors:[]).some(s=>c(l(s)?.type)==="auth");return{upstreamConnectionId:n,providerConfigKey:o,provider:c(t?.provider)??o,label:null,lifecycleStatus:i?"needs_reauth":"connected",reconnectRequired:i,createdAt:c(t?.created_at)??c(t?.created),updatedAt:c(t?.updated_at)}}var Qe=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 Ze(e){let t=c(e);return t||(typeof e=="number"&&Number.isFinite(e)?String(e):null)}function T(e){let t=c(e)?.toLowerCase()??null;return t&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)?t:null}function w(e){return e.id||e.email||e.name?e:null}async function S(e){return N(`/proxy${e.path}`,{query:e.query,headers:{"connection-id":e.upstreamConnectionId,"provider-config-key":e.providerConfigKey,...e.baseUrlOverride?{"base-url-override":e.baseUrlOverride}:{}}})}var Xe=[{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)$/}],et=new Set(["q","maxResults","pageToken","format","metadataHeaders","fields"]);async function bt(e){let t=await q(e.identity,e.connectionId);if(t.providerConfigKey!=="google-mail")throw new m("Service connection not found.",404,"connection_not_found",!1);if(!Xe.some(u=>u.method===e.method&&u.pattern.test(e.path)))throw new m("The Gmail provider operation is not allowed.",403,"tool_not_allowed",!1);if(Object.keys(e.query??{}).some(u=>!et.has(u)))throw new m("The Gmail provider query is not allowed.",400,"invalid_request",!1);let n=e.method==="POST";if(n&&!t.actionsEnabled)throw new m("Actions are disabled for this service connection.",403,"actions_disabled",!1);await Y({identity:e.identity,ratePolicyVersion:_});let o=e.requestId?.trim()||ge(),a=`main-gmail-proxy:${I("sha256").update(e.identity.toLowerCase()).update("\0").update(t.id).update("\0").update(e.method).update("\0").update(e.path).update("\0").update(o).digest("hex")}`,i=performance.now(),s,r;try{s=await N(`/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(u){r=u}if(await j({identity:e.identity,idempotencyKey:a,ratePolicyVersion:_,connectionId:t.id,providerConfigKey:t.providerConfigKey,functionRuns:0,proxyRequests:1,computeMilliseconds:Math.max(0,Math.round(performance.now()-i)),sourceSurface:"main_mcp",metadata:{operationKind:n?"action":"read",outcome:r?"error":"success",requestId:o.length<=200?o:I("sha256").update(o).digest("hex")}}),r)throw _e(r);return s}async function tt(e){let t=(n,o,a)=>S({...e,path:n,query:o,baseUrlOverride:a});try{if(e.providerConfigKey==="google-mail"){let n=l(await t("/gmail/v1/users/me/profile",void 0,"https://gmail.googleapis.com")),o=T(n?.emailAddress);return w({id:o,email:o,name:null})}if(e.providerConfigKey==="google-drive"){let n=l(await t("/drive/v3/about",{fields:"user(permissionId,displayName,emailAddress)"},"https://www.googleapis.com")),o=l(n?.user);return w({id:c(o?.permissionId),email:T(o?.emailAddress),name:c(o?.displayName)})}if(e.providerConfigKey==="google-calendar"){let n=l(await t("/calendar/v3/calendars/primary",void 0,"https://www.googleapis.com")),o=c(n?.id);return w({id:o,email:T(o),name:c(n?.summary)})}if(e.providerConfigKey==="youtube"){let n=l(await t("/youtube/v3/channels",{part:"snippet",mine:"true",maxResults:1},"https://www.googleapis.com")),o=Array.isArray(n?.items)?l(n.items[0]):null;return w({id:c(o?.id),email:null,name:c(l(o?.snippet)?.title)})}}catch{}try{let n=l(await t("/v1/userinfo",void 0,"https://openidconnect.googleapis.com"));return w({id:c(n?.sub),email:n?.email_verified===!1?null:T(n?.email),name:c(n?.name)})}catch{return null}}async function nt(e){if(!Qe.has(e.providerConfigKey))return null;if(e.providerConfigKey.startsWith("google-")||e.providerConfigKey==="youtube")return tt(e);try{if(e.providerConfigKey==="github-getting-started"){let t=l(await S({...e,path:"/user"}));return w({id:Ze(t?.id),email:T(t?.email),name:c(t?.name)??c(t?.login)})}if(e.providerConfigKey==="slack"){let t=l(await S({...e,path:"/api/auth.test"}));return w({id:c(t?.user_id),email:null,name:[c(t?.user),c(t?.team)].filter(Boolean).join(" \xB7 ")||null})}if(e.providerConfigKey==="zoom"){let t=l(await S({...e,path:"/v2/users/me"})),n=[c(t?.first_name),c(t?.last_name)].filter(Boolean).join(" ");return w({id:c(t?.id),email:T(t?.email),name:c(t?.display_name)??(n||null)})}if(e.providerConfigKey==="linkedin"){let t=l(await S({...e,path:"/v2/userinfo"}));return w({id:c(t?.sub),email:t?.email_verified===!1?null:T(t?.email),name:c(t?.name)})}if(e.providerConfigKey==="meta-marketing-api"||e.providerConfigKey==="facebook"){let t=l(await S({...e,path:"/me",query:{fields:"id,name,email"}}));return w({id:c(t?.id),email:T(t?.email),name:c(t?.name)})}if(e.providerConfigKey==="twitter-v2"){let t=l(await S({...e,path:"/2/users/me",query:{"user.fields":"id,name,username"}})),n=l(t?.data);return w({id:c(n?.id),email:null,name:c(n?.username)??c(n?.name)})}if(e.providerConfigKey==="xero"){let t=await S({...e,path:"/connections"}),n=Array.isArray(t)?l(t[0]):null;return w({id:c(n?.tenantId),email:null,name:c(n?.tenantName)})}}catch{return null}return null}async function Et(e,t={}){let n=[];for(let r=0;r<Ve;r+=1){let u=await N("/connections",{query:{limit:pe,page:r}}),p=X(u,"connections");if(n.push(...p),p.length<pe)break}let o=n.filter(r=>Ye(r,e)).map(je).filter(r=>r!==null),i=(await F(e,o)).filter(r=>!k(r.providerConfigKey));if(t.resolveProviderIdentity===!1)return i;let s=new Map(o.map(r=>[`${r.providerConfigKey}\0${r.upstreamConnectionId}`,r]));return await Promise.all(i.map(async r=>{if(r.lifecycleStatus!=="connected"||!r.upstreamConnectionId)return;let u=s.get(`${r.providerConfigKey}\0${r.upstreamConnectionId}`);if(!u)return;let p=u.updatedAt??u.createdAt??r.lifecycleStatus,d=!!(r.providerAccountId||r.providerAccountEmail||r.providerAccountName),g=r.providerIdentityCheckedAt?Date.parse(`${r.providerIdentityCheckedAt.replace(" ","T")}Z`):Number.NaN,y=!d&&Number.isFinite(g)&&Date.now()-g<$e;if(r.providerIdentitySourceUpdatedAt===p&&(d||y))return;let b=await nt({upstreamConnectionId:r.upstreamConnectionId,providerConfigKey:r.providerConfigKey});await ae({connectionId:r.id,providerAccountId:b?.id,providerAccountEmail:b?.email,providerAccountName:b?.name,sourceUpdatedAt:p})})),(await F(e,o)).filter(r=>!k(r.providerConfigKey))}async function St(){let[e,t]=await Promise.all([N("/integrations"),N("/providers")]),n=new Map;for(let o of X(t,"providers")){let a=l(o),i=c(a?.name);a&&i&&n.set(i,a)}return X(e,"integrations").flatMap(o=>{let a=l(o),i=c(a?.unique_key)??c(a?.id),s=c(a?.provider);if(!i||!s||k(i))return[];let r=n.get(s);return[{id:i,provider:s,displayName:c(a?.display_name)??c(r?.display_name)??i,authMode:c(r?.auth_mode),categories:Array.isArray(r?.categories)?r.categories:[],docsUrl:c(r?.docs),logoUrl:c(a?.logo),safeDefaultAllowedTools:[],actionTools:[],setupStatus:"ready"}]})}function Ce(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 ve(e){let t=l(e),n=l(t?.data)??t,o=c(n?.connect_link);if(!o)throw new m("Nango did not return a connect link.",502,"nango_missing_connect_link");return{connectLink:o,expiresAt:c(n?.expires_at)}}async function Tt(e,t){fe(t);let n=Ce(t);return ve(await N("/connect/sessions",{method:"POST",body:{tags:{end_user_id:e,end_user_email:e},allowed_integrations:[t],...n?{integrations_config_defaults:n}:{}}}))}async function Nt(e,t){let n=await q(e,t,!0),o=Ce(n.providerConfigKey);return ve(await N("/connect/sessions/reconnect",{method:"POST",body:{connection_id:n.upstreamConnectionId,integration_id:n.providerConfigKey,tags:{end_user_id:e,end_user_email:e},...o?{integrations_config_defaults:o}:{}}}))}async function Rt(e,t){let n=await be(e,t);try{await N(`/connections/${encodeURIComponent(n.upstreamConnectionId)}`,{method:"DELETE",query:{provider_config_key:n.providerConfigKey}})}catch(o){if(!(o instanceof m)||o.status!==404)throw o}}async function be(e,t){let n=await V(e,t);if(!n||n.transport!=="nango"||!n.upstreamConnectionId)throw new m("Service connection not found.",404,"connection_not_found",!1);return n}async function q(e,t,n=!1){let o=await be(e,t);if(fe(o.providerConfigKey),o.lifecycleStatus!=="connected"&&!(n&&o.lifecycleStatus==="needs_reauth"))throw new m("Service connection requires reconnection.",409,"connection_inactive",!1);return o}async function ee(e,t){let n=new Ke(we(),{requestInit:{headers:{Authorization:`Bearer ${he()}`,"connection-id":e.upstreamConnectionId,"provider-config-key":e.providerConfigKey}}}),o=new De({name:"mcp-scraper-integrations",version:"1.0.0"},{capabilities:{}});try{await o.connect(n);let a=await t(o);return await $({connectionId:e.id,operationalStatus:"available",evidenceSource:"nango_mcp"}),a}catch(a){let i=_e(a);throw await $({connectionId:e.id,operationalStatus:i.code==="connection_transport_unavailable"?"unavailable":"degraded",failureCode:i.code,retryable:i.retryable,evidenceSource:"nango_mcp"}).catch(()=>{}),i}finally{await o.close().catch(()=>{})}}async function It(e,t){let n=await q(e,t);(n.provider??n.providerConfigKey)==="google-search-console"&&await ee(n,async a=>{if(!(await a.listTools()).tools.some(s=>s.name==="list-sites"))throw new m("The Search Console health-check tool is unavailable.",404,"live_tool_missing",!1);await a.callTool({name:"list-sites",arguments:{}})})}async function Ee(e,t){let n=await q(e,t),a=(await ee(n,d=>d.listTools())).tools.flatMap(d=>{let g=l(d.inputSchema);return!d.name||!g?[]:[{name:d.name,...d.title?{title:d.title}:{},...d.description?{description:d.description}:{},inputSchema:g,...l(d.outputSchema)?{outputSchema:l(d.outputSchema)}:{},...l(d.annotations)?{annotations:l(d.annotations)}:{}}]}),i=O({tools:a,connectionActive:n.lifecycleStatus==="connected",actionsEnabled:n.actionsEnabled}),s=[...i.values()].filter(d=>d.classification==="read").map(d=>d.name),r=[...i.values()].filter(d=>d.classification==="action").map(d=>d.name),u=I("sha256").update(JSON.stringify(a.map(d=>({name:d.name,inputSchema:d.inputSchema})))).digest("hex");return await re(n.id,s,r,u),{connection:await V(e,n.id)??{...n,readTools:s,actionTools:r,toolRevision:u},tools:a}}async function At(e){let{connection:t,tools:n}=await Ee(e.identity,e.connectionId),o=n.find(y=>y.name===e.tool);if(!o)throw new m("The requested provider tool is unavailable.",404,"live_tool_missing",!1);let a=Z(O({tools:n,connectionActive:t.lifecycleStatus==="connected",actionsEnabled:t.actionsEnabled}),o.name);if(a.classification!==e.classification)throw new m("The provider tool classification does not match this operation.",403,"tool_not_allowed",!1);if(!a.available&&a.blockedReason==="actions_disabled")throw new m("Actions are disabled for this service connection.",403,"actions_disabled",!1);if(!a.available)throw new m("The provider tool is not authorized for this connection.",403,"tool_not_allowed",!1);await Y({identity:e.identity,ratePolicyVersion:_});let i=e.requestId?.trim()||ge(),s=`main-nango:${I("sha256").update(e.identity.toLowerCase()).update("\0").update(t.id).update("\0").update(e.tool).update("\0").update(i).digest("hex")}`,r=new Date,u=performance.now(),p,d;try{p=await ee(t,y=>We(y,e.tool,e.input))}catch(y){d=y}let g=new Date;if(await j({identity:e.identity,idempotencyKey:s,ratePolicyVersion:_,connectionId:t.id,providerConfigKey:t.providerConfigKey,functionRuns:1,proxyRequests:0,computeMilliseconds:Math.max(0,Math.round(performance.now()-u)),sourceSurface:"main_mcp",metadata:{toolName:e.tool,operationKind:e.operationKind??e.classification,outcome:d?"error":"partial",requestId:i.length<=200?i:I("sha256").update(i).digest("hex"),startedAt:r.toISOString(),completedAt:g.toISOString()}}),d)throw d;return p}async function Pt(e,t,n){let{connection:o,tools:a}=await Ee(e,t),i=a.find(d=>d.name===n);if(!i)throw new m("The requested provider tool is unavailable.",404,"live_tool_missing",!1);let s=Z(O({tools:a,connectionActive:o.lifecycleStatus==="connected",actionsEnabled:o.actionsEnabled}),i.name),r=Q(i),u=s.available,p={name:i.name,...i.title?{title:i.title}:{},...i.description?{description:i.description}:{},inputSchema:i.inputSchema,...i.outputSchema?{outputSchema:i.outputSchema}:{},...i.annotations?{annotations:i.annotations}:{}};return{...p,classification:r,callable:u,blockedReason:s.blockedReason,requiredPermissions:s.requiredPermissions,missingPermissions:s.missingPermissions,requiredFeatures:s.requiredFeatures,missingFeatures:s.missingFeatures,transport:"nango",providerConfigKey:o.providerConfigKey,providerContractVersion:Be,providerContractHash:Je,protocolVersion:null,schemaSource:"live_tools_list",schemaHash:I("sha256").update(JSON.stringify(p)).digest("hex"),fetchedAt:new Date().toISOString()}}export{at as a,Ae as b,Pe as c,h as d,Y as e,j as f,pt as g,m as h,k as i,fe as j,bt as k,Et as l,St as m,Tt as n,Nt as o,Rt as p,It as q,Ee as r,At as s,Pt as t};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{Q as p,t as o}from"./chunk-YQ5U5C2X.js";import{createHmac as T,timingSafeEqual as y}from"crypto";var N=()=>process.env.NODE_ENV==="production"||process.env.VERCEL==="1";function S(){let e=process.env.SESSION_SECRET?.trim();if(e)return e;if(N())throw new Error("SESSION_SECRET is not set \u2014 add it to your Vercel env vars (see src/api/env.ts)");return"dev-secret-change-me"}var v=()=>S();function m(e,t){if(e.length!==t.length)return!1;try{return y(Buffer.from(e,"hex"),Buffer.from(t,"hex"))}catch{return!1}}function L(e){let t=String(e),n=T("sha256",v()).update(t).digest("hex");return`${t}.${n}`}function I(e){let t=e.lastIndexOf(".");if(t===-1)return null;let n=e.slice(0,t),r=e.slice(t+1),i=T("sha256",v()).update(n).digest("hex");if(!m(r,i))return null;let s=parseInt(n);return isNaN(s)?null:s}import{randomUUID as _}from"crypto";function x(e,t,n){return e.lifecycleStatus==="connected"&&e.actionsEnabled&&t.includes(e.providerConfigKey)&&e.actionTools.includes(n)}var a=null,u=null;function c(){let e=o();return a&&u===e||(u=e,a=(async()=>{let t=e;await t.execute(`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS service_connections (
|
|
3
3
|
id TEXT PRIMARY KEY,
|
|
4
4
|
user_id INTEGER NOT NULL REFERENCES users(id),
|