mcp-scraper 0.97.1 → 0.98.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.
Files changed (104) hide show
  1. package/CHANGELOG.md +5 -2442
  2. package/README.md +16 -412
  3. package/dist/bin/api-server.js +3 -2
  4. package/dist/bin/mcp-scraper-cli.js +33 -27
  5. package/dist/bin/mcp-scraper-core.js +9 -1
  6. package/dist/bin/mcp-scraper-install.js +17 -2
  7. package/dist/bin/mcp-stdio-server.js +9 -1
  8. package/dist/bin/paa-harvest.js +8 -1
  9. package/dist/index.cjs +5 -21830
  10. package/dist/index.d.ts +14 -607
  11. package/dist/index.js +5 -39
  12. package/dist/transport.d.ts +35 -0
  13. package/package.json +11 -51
  14. package/THIRD_PARTY_NOTICES.html +0 -203
  15. package/dist/actions-5X5CQAKO.js +0 -1
  16. package/dist/artifacts-4ZDNP2JW.js +0 -1
  17. package/dist/artifacts-N62OPIT5.js +0 -1
  18. package/dist/artifacts-PSADD5OC.js +0 -1
  19. package/dist/artifacts-RUR3OHAK.js +0 -1
  20. package/dist/blob-store-GIH26EDO.js +0 -1
  21. package/dist/bundle-GS657HXG.js +0 -1
  22. package/dist/chunk-24YDQ3EO.js +0 -5
  23. package/dist/chunk-2L7CHN5N.js +0 -4
  24. package/dist/chunk-3F7AFM53.js +0 -1
  25. package/dist/chunk-4AEW53RU.js +0 -954
  26. package/dist/chunk-4HZXATHB.js +0 -27
  27. package/dist/chunk-4YZ74SJ6.js +0 -1
  28. package/dist/chunk-4ZVO6GX4.js +0 -1
  29. package/dist/chunk-55ZANTHL.js +0 -3
  30. package/dist/chunk-5RQWFYXY.js +0 -930
  31. package/dist/chunk-5TQINRZN.js +0 -12
  32. package/dist/chunk-5UQAL7HV.js +0 -41
  33. package/dist/chunk-6D25Q5BR.js +0 -21728
  34. package/dist/chunk-6N5EC7ZO.js +0 -1
  35. package/dist/chunk-7POHNTVW.js +0 -1
  36. package/dist/chunk-7SR7MEU5.js +0 -62
  37. package/dist/chunk-ANQ4JJVI.js +0 -71
  38. package/dist/chunk-B3JRL45T.js +0 -1
  39. package/dist/chunk-B4ZKPLSP.js +0 -1
  40. package/dist/chunk-B5Y26E3A.js +0 -1
  41. package/dist/chunk-C3JWX6KM.js +0 -10
  42. package/dist/chunk-C7MGJUTU.js +0 -1
  43. package/dist/chunk-CNSVZTTT.js +0 -13
  44. package/dist/chunk-EYGA6LOU.js +0 -1
  45. package/dist/chunk-F3M7INSN.js +0 -41
  46. package/dist/chunk-FLAWC5PF.js +0 -5
  47. package/dist/chunk-FM7BX2LU.js +0 -159
  48. package/dist/chunk-HCK6PLM3.js +0 -3
  49. package/dist/chunk-HNNYXMSI.js +0 -1
  50. package/dist/chunk-IFPION5D.js +0 -121
  51. package/dist/chunk-IPQOBOFY.js +0 -1
  52. package/dist/chunk-J7XDXIB6.js +0 -163
  53. package/dist/chunk-JHDD6R3O.js +0 -8
  54. package/dist/chunk-JMZIDHYQ.js +0 -2
  55. package/dist/chunk-K3VDGJNK.js +0 -1
  56. package/dist/chunk-KBZY2OGP.js +0 -11
  57. package/dist/chunk-KJQXUZ4Y.js +0 -4
  58. package/dist/chunk-KXJCGV3H.js +0 -1
  59. package/dist/chunk-NALXKTUU.js +0 -1
  60. package/dist/chunk-NNOX3FYG.js +0 -198
  61. package/dist/chunk-NQFTETVC.js +0 -189
  62. package/dist/chunk-OILOHQNL.js +0 -2
  63. package/dist/chunk-OLYPLX5C.js +0 -1
  64. package/dist/chunk-P6CDR3RM.js +0 -1
  65. package/dist/chunk-PKQHHCO4.js +0 -20
  66. package/dist/chunk-QCBCOEH5.js +0 -1
  67. package/dist/chunk-QER2ELZP.js +0 -1
  68. package/dist/chunk-RDHGQ2WZ.js +0 -1
  69. package/dist/chunk-SDQW7IJN.js +0 -1
  70. package/dist/chunk-SEZETSB3.js +0 -1
  71. package/dist/chunk-SJNSTO3C.js +0 -42
  72. package/dist/chunk-TZYITYL4.js +0 -2
  73. package/dist/chunk-UIOSADPB.js +0 -1718
  74. package/dist/chunk-UNEJYZ4T.js +0 -102
  75. package/dist/chunk-UUJYICAJ.js +0 -1
  76. package/dist/chunk-VVSHZV5S.js +0 -73
  77. package/dist/chunk-WNUXMPVX.js +0 -1
  78. package/dist/chunk-XNTAHMPA.js +0 -218
  79. package/dist/chunk-ZDECILF6.js +0 -16
  80. package/dist/chunk-ZNPGM3XE.js +0 -4
  81. package/dist/compatibility-UPPKZ4KY.js +0 -1
  82. package/dist/contracts-GUXGFCVV.js +0 -1
  83. package/dist/core-schema-Y47YFKH2.js +0 -899
  84. package/dist/direct-completion-ZVPPEBDU.js +0 -1
  85. package/dist/dispatch-GRMMPKQD.js +0 -1
  86. package/dist/editorial-reading-room/assets/app.js +0 -433
  87. package/dist/editorial-reading-room/assets/index.html +0 -139
  88. package/dist/editorial-reading-room/assets/styles.css +0 -1091
  89. package/dist/index.d.cts +0 -607
  90. package/dist/jobs-NRZHGQ7I.js +0 -1
  91. package/dist/media-artifacts-67CJWI7O.js +0 -1
  92. package/dist/metering-YHZ46GV4.js +0 -1
  93. package/dist/migrations-3AKEC5QE.js +0 -1
  94. package/dist/queue-2VKW7SGH.js +0 -1
  95. package/dist/reconciliation-QC6SILLR.js +0 -1
  96. package/dist/report-artifact-offload-PQNFDNPL.js +0 -1
  97. package/dist/repository-CYXVMYAI.js +0 -1
  98. package/dist/repository-UKDA4IWP.js +0 -1
  99. package/dist/server-EYMJROPX.js +0 -5544
  100. package/dist/settlement-47EUTSGX.js +0 -1
  101. package/dist/vendor-errors-647LSH6H.js +0 -1
  102. package/dist/worker-AWJF7UYR.js +0 -1
  103. package/public/.well-known/xray-install.json +0 -183
  104. package/public/agent-install.md +0 -200
@@ -1,41 +0,0 @@
1
- import{c as ot}from"./chunk-JMZIDHYQ.js";import{G as fe,a as Ve,c as et}from"./chunk-NQFTETVC.js";import{g as Ze,h as Qe}from"./chunk-KXJCGV3H.js";import{b as Ge}from"./chunk-C3JWX6KM.js";import{c as nt,e as rt,f as it,g as st}from"./chunk-CNSVZTTT.js";import{c as tt}from"./chunk-K3VDGJNK.js";import{h as Ke}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(Ge(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{...Ke({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
- CREATE TABLE IF NOT EXISTS commons_index_vectors (
3
- document_id TEXT PRIMARY KEY,
4
- entity_id TEXT NOT NULL,
5
- document_type TEXT NOT NULL,
6
- title TEXT NOT NULL,
7
- embedding vector(${e}) NOT NULL,
8
- model TEXT NOT NULL,
9
- updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
10
- )
11
- `),await oe().query("CREATE INDEX IF NOT EXISTS commons_index_vectors_entity ON commons_index_vectors(entity_id)"),ut=!0}async function we(e){let r=process.env.JINA_API_KEY?.trim();if(!r)throw new Error("JINA_API_KEY is not set; Commons semantic search cannot embed.");if(!e.length)return[];let i=await fetch("https://api.jina.ai/v1/embeddings",{method:"POST",headers:{authorization:`Bearer ${r}`,"content-type":"application/json"},body:JSON.stringify({model:be(),dimensions:_e(),input:e.map(p=>({text:p.slice(0,8e3)}))}),signal:AbortSignal.timeout(6e4)});if(!i.ok)throw new Error(`Jina embedding request failed with HTTP ${i.status}: ${(await i.text()).slice(0,200)}`);let s=((await i.json()).data??[]).map(p=>p.embedding);if(s.length!==e.length)throw new Error(`Jina returned ${s.length} embeddings for ${e.length} inputs.`);return s}var Nt=60*6e4;async function Lt(e=50){if(!Ae())return{claimed:0,embedded:0,failed:0,remaining:0};await mt();let r=Math.max(1,Math.min(200,Math.floor(e))),a=(await se().execute({sql:`SELECT id, entity_id, document_type, title, text FROM commons_index_documents
12
- WHERE embedding_status = 'queued' OR (embedding_status = 'failed' AND updated_at < ?)
13
- ORDER BY updated_at ASC LIMIT ?`,args:[new Date(Date.now()-Nt).toISOString(),r]})).rows;if(!a.length)return{claimed:0,embedded:0,failed:0,remaining:await ct()};let s=0,p=0,M=be();try{let h=await we(a.map(S=>`${S.title}
14
-
15
- ${S.text}`));for(let[S,_]of a.entries()){let C=`[${h[S].join(",")}]`;await oe().query(`INSERT INTO commons_index_vectors (document_id, entity_id, document_type, title, embedding, model, updated_at)
16
- VALUES ($1, $2, $3, $4, $5::vector, $6, now())
17
- ON CONFLICT (document_id) DO UPDATE SET entity_id = EXCLUDED.entity_id, document_type = EXCLUDED.document_type,
18
- title = EXCLUDED.title, embedding = EXCLUDED.embedding, model = EXCLUDED.model, updated_at = now()`,[_.id,_.entity_id,_.document_type,_.title,C,M]),await se().execute({sql:`UPDATE commons_index_documents SET embedding_status = 'indexed', embedding_provider = ?, embedding_model = ?,
19
- vector_ref = ?, indexed_at = ?, error = NULL WHERE id = ?`,args:[jt,M,_.id,new Date().toISOString(),_.id]}),s+=1}}catch(h){p=a.length-s;let S=(h instanceof Error?h.message:String(h)).slice(0,500);for(let _ of a.slice(s))await se().execute({sql:"UPDATE commons_index_documents SET embedding_status = 'failed', error = ?, updated_at = ? WHERE id = ?",args:[S,new Date().toISOString(),_.id]}).catch(()=>{})}return{claimed:a.length,embedded:s,failed:p,remaining:await ct()}}function dn(){Ae()&&Ut(Lt(10).catch(e=>{console.error("[commons/embeddings] immediate embed failed; the scheduled drain will retry",e instanceof Error?e.message:String(e))}))}async function ct(){let e=await se().execute("SELECT COUNT(*) AS n FROM commons_index_documents WHERE embedding_status IN ('queued', 'failed')");return Number(e.rows[0]?.n??0)}async function pn(e,r=40){let i=new Map;if(!Ae()||!e.trim())return i;await mt();let[a]=await we([e]);if(!a)return i;let s=await oe().query(`SELECT entity_id, MAX(1 - (embedding <=> $1::vector)) AS score
20
- FROM commons_index_vectors GROUP BY entity_id ORDER BY score DESC LIMIT $2`,[`[${a.join(",")}]`,Math.max(1,Math.min(100,r))]);for(let p of s)i.set(String(p.entity_id),Number(p.score));return i}var Ot=500,Bt=.9,qt=1e4,Ft=5e4;function Se(e,r){let i=10**r;return Math.round(e*i)/i}function Jt(e,r){if(e.length===0||e.length!==r.length)throw new Error("Similarity vectors must have the same non-zero dimension.");let i=0,a=0,s=0;for(let p=0;p<e.length;p++)i+=e[p]*r[p],a+=e[p]*e[p],s+=r[p]*r[p];return a===0||s===0?0:Math.max(-1,Math.min(1,i/(Math.sqrt(a)*Math.sqrt(s))))}function Ht(e){let r=Ie("sha256");for(let i of[...e].sort((a,s)=>a.url.localeCompare(s.url)))r.update(i.url),r.update("\0"),r.update(i.contentHash),r.update("\0");return r.digest("hex")}function dt(e){let r=e.replace(/!\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/\[([^\]]+)\]\([^)]*\)/g,"$1").replace(/https?:\/\/\S+/gi," ").replace(/&(?:amp|nbsp|quot|#39);/gi," ").replace(/[#>*_`~|\\-]+/g," ").replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim().toLowerCase();return r.length>=12?r:null}function zt(e){let r=e.map(h=>h.bodyMarkdown.split(/\n{2,}/).map(S=>S.trim()).filter(Boolean)),i=e.length>=4?Math.max(3,Math.ceil(e.length*.5)):null,a=new Map;for(let h of r){let S=new Set(h.map(dt).filter(_=>!!_));for(let _ of S)a.set(_,(a.get(_)??0)+1)}let s=new Set;if(i!=null)for(let[h,S]of a)S>=i&&s.add(h);let p=0;return{texts:e.map((h,S)=>{let _=[];for(let P of r[S]){let I=dt(P);if(I&&s.has(I)){p+=P.length;continue}_.push(P)}let C=_.join(`
21
-
22
- `).trim(),v=C.length>=60?C:h.bodyMarkdown;return`${h.title?.trim()||"Untitled page"}
23
-
24
- ${v}`}),minimumPageCount:i,removedBlockSignatures:s.size,removedCharacters:p}}var Re=class{parent;constructor(r){this.parent=Array.from({length:r},(i,a)=>a)}find(r){let i=this.parent[r];return i!==r&&(this.parent[r]=this.find(i)),this.parent[r]}union(r,i){let a=this.find(r),s=this.find(i);a!==s&&(this.parent[s]=a)}};async function pt(e,r={}){let i=e.filter(o=>o.bodyMarkdown.trim().length>0).slice(0,Ot),a=Number.isFinite(r.threshold)?r.threshold:Bt,s=Number.isFinite(r.maxPairs)?r.maxPairs:qt,p=Math.max(0,Math.min(1,a)),M=Math.max(1,Math.min(Ft,Math.floor(s))),h=r.model??be(),S=r.dimensions??_e(),_=r.embedTexts??we,C=zt(i),v=[],P=new Map,I=[];for(let[o,f]of i.entries()){let w=f.contentHash||Ie("sha256").update(f.bodyMarkdown).digest("hex"),k=P.get(w);k==null&&(k=v.length,P.set(w,k),v.push(C.texts[o])),I.push(k)}let D=[];for(let o=0;o<v.length;o+=64)D.push(...await _(v.slice(o,o+64)));if(D.length!==v.length)throw new Error(`Embedding provider returned ${D.length} vectors for ${v.length} unique page bodies.`);let K=I.map(o=>D[o]),ce=new Re(i.length),L=[],O=[];for(let o=0;o<i.length;o++)for(let f=o+1;f<i.length;f++){let w=Jt(K[o],K[f]);L.push(w),!(w<p)&&(O.push({source:o,target:f,score:w}),ce.union(o,f))}O.sort((o,f)=>f.score-o.score||i[o.source].url.localeCompare(i[f.source].url)||i[o.target].url.localeCompare(i[f.target].url));let R=[...L].sort((o,f)=>o-f),U=o=>R.length?Se(R[Math.floor((R.length-1)*o)],6):null,j=new Map;for(let o=0;o<i.length;o++){let f=ce.find(o),w=j.get(f)??[];w.push(o),j.set(f,w)}let B=new Map,J=[...j.values()].filter(o=>o.length>1).sort((o,f)=>f.length-o.length||i[o[0]].url.localeCompare(i[f[0]].url)).map((o,f)=>{let w=`cluster-${String(f+1).padStart(3,"0")}`;for(let k of o)B.set(k,w);return{clusterId:w,pageCount:o.length,urls:o.map(k=>i[k].url).sort()}}),H=O.slice(0,M).map((o,f)=>{let w=i[o.source],k=i[o.target],q=Se(o.score,6);return{sourceUrl:w.url,sourceTitle:w.title,targetUrl:k.url,targetTitle:k.title,similarity:q,similarityPercent:Se(q*100,2),corpusPercentile:R.length<=1?100:Se((1-f/(R.length-1))*100,2),exactContentDuplicate:!!(w.contentHash&&w.contentHash===k.contentHash),sourceWordCount:w.wordCount,targetWordCount:k.wordCount,clusterId:B.get(o.source)??null}}),z=Ht(i),me=Ie("sha256").update(JSON.stringify({corpusSha256:z,model:h,dimensions:S,threshold:p,maxPairs:M,boilerplateRemoval:{method:"corpus_repeated_markdown_blocks",minimumPageCount:C.minimumPageCount,removedBlockSignatures:C.removedBlockSignatures}})).digest("hex");return{generatedAt:new Date().toISOString(),provider:"jina",model:h,dimensions:S,threshold:p,requestedMaxPairs:M,comparedPages:i.length,possiblePairs:i.length*Math.max(0,i.length-1)/2,qualifyingPairs:O.length,returnedPairs:H.length,pairsTruncated:O.length>H.length,corpusSha256:z,analysisSha256:me,scoreDistribution:{min:U(0),p25:U(.25),median:U(.5),p75:U(.75),p90:U(.9),max:U(1)},boilerplateRemoval:{method:"corpus_repeated_markdown_blocks",minimumPageCount:C.minimumPageCount,removedBlockSignatures:C.removedBlockSignatures,removedCharacters:C.removedCharacters},rows:H,clusters:J}}import{basename as Xt}from"path";function Y(e){return e.split("#")[0].replace(/\/$/,"")}function De(e){let r=e.replace(/^www\./,"").toLowerCase(),i=r.split(".");return i.length<=2?r:i.slice(-2).join(".")}function gt(e,r){try{let i=new URL(e);return Xt(i.pathname).replace(/[^a-zA-Z0-9._-]/g,"_").slice(0,80)||`image-${r}`}catch{return`image-${r}`}}function ht(){let e=new Map;return r=>{let i=r.replace(/^https?:\/\//,"").replace(/[^a-zA-Z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)||"page",a=e.get(i)??0;return e.set(i,a+1),a?`${i}-${a}`:i}}function ft(e){let r=e==null?"":String(e);return/[",\r\n]/.test(r)?`"${r.replace(/"/g,'""')}"`:r}function yt(e){return{source_url:e.sourceUrl,source_title:e.sourceTitle,target_url:e.targetUrl,target_title:e.targetTitle,similarity:e.similarity,similarity_percent:e.similarityPercent,corpus_percentile:e.corpusPercentile,exact_content_duplicate:e.exactContentDuplicate,source_word_count:e.sourceWordCount,target_word_count:e.targetWordCount,cluster_id:e.clusterId}}var $e=20,Ue=500,nn=8,bt=10*1024*1024,_t=100*1024*1024,je=25e4;async function Fn(e,r={}){let i=e.options.downloadImages===!0;if(e.userId==null)throw new Error("site extract artifact owner is missing");let a=Ve(String(e.userId)),s=Yt(l(Qt(),"extract-bundle-"));le(s,{recursive:!0}),i&&le(l(s,"images"),{recursive:!0});let p=e.options.captureRenderedDom===!0,M=e.options.semanticSimilarity===!0;p&&le(l(s,"rendered-dom"),{recursive:!0});try{let h=[],S=[],_=[],C=ht(),v=[],P=e.options.waybackTimeline,I=new Map;for await(let n of fe(e.id))for(let t of n){I.set(Y(t.url),t.status),h.push({url:t.url,status:t.status,title:t.title,titleLength:t.titleLength,titlePixels:t.titlePixels,metaDescription:t.metaDescription,metaDescLength:t.metaDescLength,h1:t.h1,h1_2:t.h1_2,h2Count:t.h2Count,extractionStatus:t.extractionStatus,indexable:t.indexable,indexabilityReason:t.indexabilityReason,canonicalUrl:t.canonicalUrl?t.url:null,wordCount:t.wordCount,contentHash:t.contentHash,imagesMissingAlt:t.imagesMissingAlt,schemaTypes:t.schemaTypes.length>0?["present"]:[],outlinks:[]});let u=t.pageId??W("sha256").update(t.archivedUrl??t.url).digest("hex"),E=l(s,"pages",u);le(E,{recursive:!0});let d=t.contentRef?await a(t.contentRef):null,g=d?.html??null,c=d?.markdown??t.bodyMarkdown??null;if(M&&t.extractionStatus==="successful"&&c?.trim()&&S.push({url:t.url,title:t.title,bodyMarkdown:c,contentHash:t.contentHash,wordCount:t.wordCount}),p&&g!=null){let We=`rendered-dom/${C(t.url)}.html.txt`;y(l(s,We),g),_.push({url:t.url,path:We,bytes:Buffer.byteLength(g),truncated:t.renderedDomTruncated===!0,sanitized:t.renderedDomSanitized===!0})}let m=g==null?null:`pages/${u}/page.html`,b=c==null?null:`pages/${u}/page.md`,x=c==null||!t.archiveRequestedMonth?null:`pages/${t.archiveRequestedMonth}/${u}.md`;g!=null&&m&&y(l(s,m),g),c!=null&&b&&y(l(s,b),c),c!=null&&x&&(le(l(s,"pages",t.archiveRequestedMonth),{recursive:!0}),y(l(s,x),c));let{bodyMarkdown:A,contentRef:ne,discoveryLinks:re,...Ct}=t,ie={version:"site-export-page.v1",...Ct,pageId:u,content:{htmlPath:m,markdownPath:b,htmlBytes:g==null?0:Buffer.byteLength(g),markdownBytes:c==null?0:Buffer.byteLength(c),htmlSha256:g==null?null:W("sha256").update(g).digest("hex"),markdownSha256:c==null?null:W("sha256").update(c).digest("hex")}},Xe=JSON.stringify(ie,null,2),Ye=`pages/${u}/page.json`;y(l(s,Ye),Xe),v.push({pageId:u,url:t.archivedUrl??t.url,jsonPath:Ye,htmlPath:m,markdownPath:b,legacyMarkdownPath:x,jsonSha256:W("sha256").update(Xe).digest("hex"),htmlSha256:ie.content.htmlSha256,markdownSha256:ie.content.markdownSha256,htmlBytes:ie.content.htmlBytes,markdownBytes:ie.content.markdownBytes})}let D=Vt(),K=ae(l(s,"links.jsonl.gz"));D.pipe(K);let ce=async n=>{D.write(n)||await G(D,"drain")},L=ae(l(s,"schema.jsonl")),O=async n=>{L.write(n)||await G(L,"drain")},R=ae(l(s,"failures.jsonl")),U=async n=>{R.write(n)||await G(R,"drain")},j=new Map,B=new Map,J=new Map,H=new Map,z=new Map,me=new Set,o=0,f=0,w=0,k=0,q=0,xe=!1,Ee="";try{Ee=De(new URL(e.startUrl).hostname)}catch{Ee=""}let wt=tn(nn),Ne=[],Le=[],Oe=[],Z=0,de=0,ke=0,St=n=>ke+n>_t?!1:(ke+=n,!0);for await(let n of fe(e.id))for(let t of n){if(t.schema?.length&&await O(JSON.stringify({url:t.url,schema:t.schema})+`
25
- `),t.extractionStatus==="failed"){let{failureCode:d,failureReason:g}=Me(t.failureCode,t.failureReason);await U(JSON.stringify({url:t.url,status:t.status,via:t.via,failureCode:d,failureReason:g,fetchAttempts:t.fetchAttempts??[]})+`
26
- `)}if(t.imageLinks?.length)for(let[d,g]of t.imageLinks.entries()){let c=W("sha256").update(`${t.url}\0${g}`).digest("hex"),m={imageId:c,sourcePage:t.url,sourceUrl:g,path:null,status:"not_requested",mimeType:null,bytes:null,sha256:null,failureCode:null,failureReason:null,artifactId:null};if(Le.push(m),!i)continue;if(d>=$e){m.status="skipped_page_limit",m.failureCode="page_image_limit",m.failureReason=`Only the first ${$e} image candidates are downloaded per page.`;continue}if(Z>=Ue){m.status="skipped_site_limit",m.failureCode="site_image_limit",m.failureReason=`Only the first ${Ue} image candidates are downloaded per site.`;continue}Z++;let b=`${c}-${gt(g,d)}`,x=l(s,"images");Ne.push(wt(()=>ot(g,x,b,{expectedType:"image",maxBytes:bt,consumeBytes:St})).then(async A=>{let ne=Wt(A.savedPath),re=await Qe({ownerId:String(e.userId),jobId:e.id,imageId:c,filename:b,contentType:A.mimeType??"application/octet-stream",content:ne,sourceUrl:g,sourcePage:t.url});Oe.push(re),m.status="downloaded",m.path=`images/${b}`,m.artifactId=re.key,m.mimeType=A.mimeType,m.bytes=A.sizeBytes,m.sha256=W("sha256").update(ne).digest("hex")},A=>{de++,m.status="failed",m.failureCode="image_download_failed",m.failureReason=(A instanceof Error?A.message:String(A)).replace(/\s+/g," ").slice(0,500)}))}let u=Y(t.url),E={int:0,ext:0};for(let d of t.outlinks??[]){let g=(d.rel??"").split(/\s+/).includes("nofollow"),c=Y(d.href),m=I.get(c)??null;if(await ce(JSON.stringify({from:t.url,to:d.href,anchor:d.anchor,rel:d.rel,internal:d.internal,nofollow:g,targetStatus:m})+`
27
- `),k++,q>=je){xe=!0;continue}if(q++,d.internal){if(E.int++,o++,j.has(c)||j.set(c,new Set),j.get(c).add(u),d.anchor){B.has(c)||B.set(c,new Map);let b=B.get(c);b.set(d.anchor,(b.get(d.anchor)??0)+1)}!g&&(I.get(c)===200||!I.has(c))&&(J.has(u)||J.set(u,new Set),J.get(u).add(c)),m!=null&&m>=400&&(w++,me.add(t.url))}else{E.ext++;let b="";try{b=De(new URL(d.href).hostname)}catch{continue}if(!b||b===Ee)continue;f++;let x=z.get(b)??{links:0,nofollow:0,pages:new Set};x.links++,g&&x.nofollow++,x.pages.add(t.url),z.set(b,x)}}H.set(t.url,E)}let xt=Promise.all([ue(K),ue(L),ue(R)]);D.end(),L.end(),R.end(),await xt,await Promise.all(Ne);let X=new Map,Pe=Y(e.startUrl);X.set(Pe,0);let Te=[Pe];for(;Te.length>0;){let n=Te.shift(),t=X.get(n);for(let u of J.get(n)??[])X.has(u)||(X.set(u,t+1),Te.push(u))}let Q=new Map;for(let n of h){let t=Y(n.url),u=j.get(t)??new Set,E=B.get(t),d=E?[...E.entries()].sort((c,m)=>m[1]-c[1]).slice(0,3).map(c=>c[0]):[],g=H.get(n.url)??{int:0,ext:0};Q.set(n.url,{url:n.url,inlinks:u.size,uniqueInlinks:u.size,outlinksInternal:g.int,outlinksExternal:g.ext,crawlDepth:X.has(t)?X.get(t):null,orphan:u.size===0&&t!==Pe,topAnchors:d})}let Be=it(h,Q,me),V=st(e.startUrl,h,Be,Q),ee=et(e),F={jobId:e.id,startUrl:e.startUrl,status:e.successfulUrls===0?"failed":e.failedUrls>0||e.remainingUrls>0||ee.creditTruncated?"partial":"complete",...ee,discovered:e.totalUrls,attempted:e.attemptedUrls,successful:e.successfulUrls,failed:e.failedUrls,remaining:e.remainingUrls,linkAnalysis:{truncated:xe,analyzedEdges:q,streamedEdges:k,edgeCap:je},generatedAt:new Date().toISOString()};V=["## Crawl delivery",`- Discovered: ${F.discovered}`,`- Attempted: ${F.attempted}`,`- Successful: ${F.successful}`,`- Failed: ${F.failed}`,`- Remaining: ${F.remaining}`,`- Requested page cap: ${ee.requestedMaxPages}`,`- Funded page cap: ${ee.effectiveMaxPages}`,`- Credit-truncated: ${ee.creditTruncated?"yes":"no"}`,`- Link analysis: ${q}/${k} edges${xe?` (capped at ${je})`:""}`,"",V].join(`
28
- `),r.imageAudit&&(V+=`
29
-
30
- ${nt(r.imageAudit)}`);let pe=[...Q.values()],qe=n=>Math.round(n*10)/10,te={zero:0,oneToTwo:0,threeToTen:0,elevenPlus:0},Fe=0,Je=0;for(let n of pe)Fe+=n.inlinks,Je+=n.outlinksInternal+n.outlinksExternal,n.inlinks===0?te.zero++:n.inlinks<=2?te.oneToTwo++:n.inlinks<=10?te.threeToTen++:te.elevenPlus++;let Ce=[...z.entries()].map(([n,t])=>({domain:n,links:t.links,nofollow:t.nofollow,pages:t.pages.size})).sort((n,t)=>t.links-n.links),ve={summary:{internal:{totalLinks:o,pages:h.length,orphans:pe.filter(n=>n.orphan).length,brokenInternal:w,avgInlinks:h.length?qe(Fe/h.length):0,avgOutlinks:h.length?qe(Je/h.length):0,distribution:te,topByInlinks:[...pe].sort((n,t)=>t.inlinks-n.inlinks).slice(0,20).map(n=>({url:n.url,inlinks:n.inlinks,outlinksInternal:n.outlinksInternal,outlinksExternal:n.outlinksExternal}))},external:{totalLinks:f,uniqueDomains:Ce.length,topDomains:Ce.slice(0,20)}},externalDomains:Ce},ge=ae(l(s,"pages.jsonl")),Et=new Map(v.map(n=>[n.pageId,n])),$=P?ae(l(s,"capture-matrix.jsonl")):null,He=new Set,ze=(n,t)=>{let u=t;try{u=new URL(t).href}catch{}return`${n??""}\0${u}`};for await(let n of fe(e.id))for(let t of n){let u=t.extractionStatus==="failed"?Me(t.failureCode,t.failureReason):{failureCode:null,failureReason:null},{bodyMarkdown:E,schema:d,outlinks:g,contentRef:c,...m}=t,b=Q.get(t.url),x=t.pageId?Et.get(t.pageId):void 0,A={...m,...t.extractionStatus==="failed"?u:{},representations:x?{jsonPath:x.jsonPath,htmlPath:x.htmlPath,markdownPath:x.markdownPath,jsonSha256:x.jsonSha256,htmlSha256:x.htmlSha256,markdownSha256:x.markdownSha256,htmlBytes:x.htmlBytes,markdownBytes:x.markdownBytes}:null,inlinks:b?.inlinks??0,crawlDepth:b?.crawlDepth??null,orphan:b?.orphan??!1};if(ge.write(JSON.stringify(A)+`
31
- `)||await G(ge,"drain"),$){let ne=ze(t.archiveRequestedMonth,t.originalUrl??t.url);He.add(ne);let re={requestedMonth:t.archiveRequestedMonth??null,captureTimestamp:t.archiveTimestamp??null,originalUrl:t.originalUrl??t.url,archivedUrl:t.archivedUrl??null,status:t.extractionStatus==="successful"?"captured":"failed",httpStatus:t.status,contentHash:t.contentHash||null,wordCount:t.wordCount,failureCode:u.failureCode,failureReason:u.failureReason};$.write(JSON.stringify(re)+`
32
- `)||await G($,"drain")}}if($&&P?.timeline?.urls){let n=P.timeline,t=n.urls,u=(()=>{if(n.months?.length)return[...new Set(n.months)].sort();if(!n.from||!n.to)return[];let E=[],d=new Date(`${n.from}-01T00:00:00Z`),g=new Date(`${n.to}-01T00:00:00Z`);for(;d<=g&&E.length<60;)E.push(`${d.getUTCFullYear()}-${String(d.getUTCMonth()+1).padStart(2,"0")}`),d.setUTCMonth(d.getUTCMonth()+(n.intervalMonths??1));return E})();for(let E of u)for(let d of t)He.has(ze(E,d))||$.write(JSON.stringify({requestedMonth:E,captureTimestamp:null,originalUrl:d,archivedUrl:null,status:"missing",httpStatus:null,contentHash:null,wordCount:0,failureCode:"wayback_capture_missing",failureReason:"No successful HTML capture was available in the requested month."})+`
33
- `)||await G($,"drain")}let kt=ue(ge),Pt=$?ue($):Promise.resolve();if(ge.end(),$?.end(),await Promise.all([kt,Pt]),p&&y(l(s,"rendered-dom","manifest.jsonl"),_.map(n=>JSON.stringify(n)).join(`
34
- `)),M){let n=await pt(S,{threshold:Number(e.options.similarityThreshold??void 0),maxPairs:Number(e.options.similarityMaxPairs??void 0),embedTexts:r.embedSimilarityTexts}),t=n.rows.map(yt),u=t.length>0?Object.keys(t[0]):["source_url","source_title","target_url","target_title","similarity","similarity_percent","corpus_percentile","exact_content_duplicate","source_word_count","target_word_count","cluster_id"],E=[u.join(","),...t.map(m=>u.map(b=>ft(m[b]??null)).join(","))].join(`
35
- `)+`
36
- `,{rows:d,clusters:g,...c}=n;y(l(s,"similarity-table.csv"),E),y(l(s,"similarity.jsonl"),t.map(m=>JSON.stringify(m)).join(`
37
- `)),y(l(s,"similarity-table-schema.json"),JSON.stringify({tableNameSuggestion:`site_similarity_${new URL(e.startUrl).hostname.replace(/[^a-z0-9]+/gi,"_").replace(/^_+|_+$/g,"").toLowerCase()}`,defaultSort:[{column:"similarity",direction:"desc"}],columns:{source_url:"text",source_title:"text",target_url:"text",target_title:"text",similarity:"number",similarity_percent:"number",corpus_percentile:"number",exact_content_duplicate:"boolean",source_word_count:"integer",target_word_count:"integer",cluster_id:"text"}},null,2)),y(l(s,"similarity-summary.json"),JSON.stringify(c,null,2)),y(l(s,"content-clusters.json"),JSON.stringify(n.clusters,null,2)),V+=["","## Rendered content similarity",`- Compared pages: ${n.comparedPages}`,`- Raw cosine threshold: ${n.threshold}`,`- Corpus score distribution: min ${n.scoreDistribution.min??"n/a"} / median ${n.scoreDistribution.median??"n/a"} / p90 ${n.scoreDistribution.p90??"n/a"} / max ${n.scoreDistribution.max??"n/a"}`,`- Qualifying pairs: ${n.qualifyingPairs}`,`- Returned table rows: ${n.returnedPairs}${n.pairsTruncated?" (capped)":""}`,`- Multi-page clusters: ${n.clusters.length}`,`- Embedding model: ${n.model} (${n.dimensions} dimensions)`,`- Corpus boilerplate removed: ${n.boilerplateRemoval.removedBlockSignatures} repeated block signatures / ${n.boilerplateRemoval.removedCharacters} characters`,`- Corpus SHA-256: ${n.corpusSha256}`].join(`
38
- `)}y(l(s,"report.md"),V),y(l(s,"crawl-summary.json"),JSON.stringify(F,null,2)),y(l(s,"images-manifest.jsonl"),Le.map(n=>JSON.stringify(n)).join(`
39
- `)),y(l(s,"manifest.json"),JSON.stringify({version:"site-export.v1",jobId:e.id,startUrl:e.startUrl,generatedAt:F.generatedAt,outputProfile:{json:!0,html:!0,markdown:!0,imageManifest:!0,imageBytes:i},pages:[...v].sort((n,t)=>n.pageId.localeCompare(t.pageId)),imagesManifestPath:"images-manifest.jsonl",download:"This ZIP is the complete human export. AI clients should use site_export_read and site_export_image."},null,2)),P&&y(l(s,"wayback-manifest.json"),JSON.stringify({rootUrl:P.rootUrl??e.startUrl,requested:P.timeline??null,maxPagesPerSnapshot:P.maxPagesPerSnapshot??null,captureMatrix:"capture-matrix.jsonl"},null,2)),y(l(s,"issues.json"),JSON.stringify(Be,null,2)),y(l(s,"link-metrics.jsonl"),pe.map(n=>JSON.stringify(n)).join(`
40
- `)),y(l(s,"link-report.md"),rt(ve)),y(l(s,"links-summary.json"),JSON.stringify(ve.summary,null,2)),y(l(s,"external-domains.json"),JSON.stringify(ve.externalDomains,null,2)),r.imageAudit&&(y(l(s,"images.jsonl"),r.imageAudit.rows.map(n=>JSON.stringify(n)).join(`
41
- `)),y(l(s,"images-summary.json"),JSON.stringify(r.imageAudit.summary,null,2))),r.seoAudit&&y(l(s,"seo-audit.json"),JSON.stringify(r.seoAudit,null,2)),r.branding&&y(l(s,"branding.json"),JSON.stringify(r.branding,null,2)),i&&y(l(s,"images-download-summary.json"),JSON.stringify({queued:Z,downloaded:Z-de,failed:de,downloadedBytes:ke,perPageCap:$e,perSiteCap:Ue,perFileByteCap:bt,totalByteCap:_t},null,2));let T=[{name:"manifest.json",type:"application/json"},{name:"images-manifest.jsonl",type:"application/x-ndjson"},{name:"report.md",type:"text/markdown"},{name:"crawl-summary.json",type:"application/json"},{name:"failures.jsonl",type:"application/x-ndjson"},{name:"schema.jsonl",type:"application/x-ndjson"},{name:"issues.json",type:"application/json"},{name:"pages.jsonl",type:"application/x-ndjson"},{name:"links.jsonl.gz",type:"application/gzip"},{name:"link-metrics.jsonl",type:"application/x-ndjson"},{name:"link-report.md",type:"text/markdown"},{name:"links-summary.json",type:"application/json"},{name:"external-domains.json",type:"application/json"}];if(p){T.push({name:"rendered-dom/manifest.jsonl",type:"application/x-ndjson"});for(let n of _)T.push({name:n.path,type:"text/plain"})}M&&(T.push({name:"similarity-table.csv",type:"text/csv"}),T.push({name:"similarity.jsonl",type:"application/x-ndjson"}),T.push({name:"similarity-table-schema.json",type:"application/json"}),T.push({name:"similarity-summary.json",type:"application/json"}),T.push({name:"content-clusters.json",type:"application/json"})),P&&(T.push({name:"wayback-manifest.json",type:"application/json"}),T.push({name:"capture-matrix.jsonl",type:"application/x-ndjson"})),r.imageAudit&&(T.push({name:"images.jsonl",type:"application/x-ndjson"}),T.push({name:"images-summary.json",type:"application/json"})),r.seoAudit&&T.push({name:"seo-audit.json",type:"application/json"}),r.branding&&T.push({name:"branding.json",type:"application/json"}),i&&T.push({name:"images-download-summary.json",type:"application/json"});let N=new en,Tt=Ze({ownerId:String(e.userId),jobId:e.id,createdAt:new Date,content:N.outputStream});for(let n of T)N.addFile(l(s,n.name),n.name);let he=[...v].sort((n,t)=>n.pageId.localeCompare(t.pageId));for(let n of he)n.markdownPath&&N.addFile(l(s,n.markdownPath),n.markdownPath);for(let n of he)n.legacyMarkdownPath&&N.addFile(l(s,n.legacyMarkdownPath),n.legacyMarkdownPath);for(let n of he)n.htmlPath&&N.addFile(l(s,n.htmlPath),n.htmlPath);for(let n of he)N.addFile(l(s,n.jsonPath),n.jsonPath);if(i&&Z>de){let n=l(s,"images");for(let t of Gt(n,{recursive:!0})){let u=l(n,t);Zt(u).isFile()&&N.addFile(u,`images/${t.split("\\").join("/")}`)}}return N.end(),[await tt("export_packaging",()=>Tt),...Oe]}finally{Kt(s,{recursive:!0,force:!0})}}export{Rt as a,on as b,an as c,Me as d,Ae as e,Lt as f,dn as g,ct as h,pn as i,je as j,Fn as k};
@@ -1,5 +0,0 @@
1
- import{e as l}from"./chunk-C7MGJUTU.js";import{a as o}from"./chunk-WNUXMPVX.js";function c(t){return{id:String(t.id),user_id:Number(t.user_id),status:String(t.status),query:String(t.query),options:String(t.options),callback_url:t.callback_url!=null?String(t.callback_url):null,result:t.result!=null?String(t.result):null,error:t.error!=null?String(t.error):null,public_error_json:t.public_error_json!=null?String(t.public_error_json):null,created_at:String(t.created_at),started_at:t.started_at!=null?String(t.started_at):null,completed_at:t.completed_at!=null?String(t.completed_at):null}}function g(t){let{public_error_json:r,...e}=t;return{...e,options:JSON.parse(t.options),result:t.result?JSON.parse(t.result):null,publicError:l(r)}}async function a(t,r){let e=o(),n=r?await e.execute({sql:"SELECT * FROM jobs WHERE id = ? AND user_id = ?",args:[t,r]}):await e.execute({sql:"SELECT * FROM jobs WHERE id = ?",args:[t]});return n.rows[0]?g(c(n.rows[0])):void 0}async function b(t,r,e,n,s){if(!/^[a-zA-Z0-9-]{1,100}$/.test(t))throw new Error("job id is invalid");await o().execute({sql:"INSERT INTO jobs (id, user_id, query, options, callback_url) VALUES (?, ?, ?, ?, ?)",args:[t,r,e,JSON.stringify(n),s??null]})}async function _(t,r,e,n,s){let u=Number(r);if(!Number.isSafeInteger(u)||u<=0||typeof n.requestFingerprint!="string"||!/^[a-f0-9]{64}$/.test(n.requestFingerprint))throw new Error("Job receipt requires a principal and request fingerprint");try{return await b(t,r,e,n,s),{kind:"created",jobId:t}}catch{let i;try{i=await a(t,r)}catch{return{kind:"unknown",jobId:t}}return!i||i.query!==e||i.callback_url!==(s??null)||i.options.requestFingerprint!==n.requestFingerprint||i.options.billingDebitKey!==n.billingDebitKey||i.options.billingHoldMc!==n.billingHoldMc?{kind:"unknown",jobId:t}:{kind:"recovered",jobId:t,job:i}}}async function f(t,r,e){let n=Number(r);if(!Number.isSafeInteger(n)||n<=0||!/^[a-f0-9]{64}$/.test(e))throw new Error("Job dispatch receipt requires a principal and request fingerprint");try{if((await o().execute({sql:`UPDATE jobs SET options=json_set(options,'$.dispatchRequestedAt',strftime('%Y-%m-%dT%H:%M:%fZ','now'))
2
- WHERE id=? AND user_id=? AND json_extract(options,'$.requestFingerprint')=?
3
- AND json_extract(options,'$.dispatchRequestedAt') IS NULL`,args:[t,r,e]})).rowsAffected===1)return!0}catch{}let s=await a(t,r).catch(()=>{});return s?.options.requestFingerprint===e&&typeof s.options.dispatchRequestedAt=="string"}async function m(t,r,e=new Date().toISOString()){if(!Number.isSafeInteger(r)||r<0)throw new Error("job billed amount must be a non-negative integer");return(await o().execute({sql:`UPDATE jobs
4
- SET options = json_set(options, '$.billingSettledAt', ?, '$.billedMc', ?)
5
- WHERE id = ?`,args:[e,r,t]})).rowsAffected===1}export{c as a,g as b,a as c,b as d,_ as e,f,m as g};
@@ -1,159 +0,0 @@
1
- import{a as M,b as q,f as L}from"./chunk-XNTAHMPA.js";import{b as I,d as F,o as b,r as J,s as pe,t as _e,u as H,w as ge}from"./chunk-4YZ74SJ6.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
- INSERT INTO rate_limits (scope, key_hash, window_start, count)
3
- VALUES (?, ?, ?, 1)
4
- ON CONFLICT(scope, key_hash, window_start)
5
- DO UPDATE SET count = count + 1, updated_at = datetime('now')
6
- RETURNING count
7
- `,args:[e,s,o]}),c=Number(d.rows[0]?.count);if(!Number.isSafeInteger(c)||c<1)throw new Error("Rate-limit bucket mutation did not return a valid count");return{allowed:c<=n,count:c,remaining:Math.max(0,n-c),resetSeconds:Math.max(1,o+i-r)}}async function It(e){let t=W(32).toString("hex"),n=Y("sha256").update(t).digest("hex"),i=new Date(Date.now()+3600*1e3).toISOString();return await l().execute({sql:"INSERT INTO password_reset_tokens (token, user_id, expires_at) VALUES (?, ?, ?)",args:[n,e,i]}),t}async function Ot(e){let t=l(),n=Y("sha256").update(e).digest("hex"),r=(await t.execute({sql:"SELECT user_id, expires_at, used FROM password_reset_tokens WHERE token = ?",args:[n]})).rows[0];return!r||Number(r.used)||new Date(String(r.expires_at))<new Date?null:(await t.execute({sql:"UPDATE password_reset_tokens SET used = 1 WHERE token = ?",args:[n]}),Number(r.user_id))}async function Lt(e){let t=Ee();return await l().execute({sql:"UPDATE users SET api_key = ?, key_active = 1 WHERE id = ?",args:[t,e]}),t}async function Ut(e){await l().execute({sql:"UPDATE users SET key_active = 0 WHERE id = ?",args:[e]})}async function Dt(){return(await l().execute("SELECT id, email, name, created_at, active FROM users ORDER BY created_at DESC")).rows.map(t=>K({...t,api_key:"",key_active:1}))}async function Pt(e){await l().execute({sql:"UPDATE users SET active = 0 WHERE id = ?",args:[e]})}async function kt(){let e=await l().execute("SELECT COUNT(*) as n FROM users WHERE active = 1");return Number(e.rows[0]?.n??0)}async function Mt(){return(await l().execute("SELECT id FROM users WHERE active = 1")).rows.map(t=>Number(t.id))}function Kt(e,t,n){return e.lifecycleStatus==="connected"&&e.actionsEnabled&&t.includes(e.providerConfigKey)&&e.actionTools.includes(n)}var U=null,z=null;function C(){let e=l();return U&&z===e||(z=e,U=(async()=>{let t=e;await t.execute(`
8
- CREATE TABLE IF NOT EXISTS service_connections (
9
- id TEXT PRIMARY KEY,
10
- user_id INTEGER NOT NULL REFERENCES users(id),
11
- provider_config_key TEXT NOT NULL,
12
- provider TEXT,
13
- transport TEXT NOT NULL,
14
- upstream_connection_id TEXT,
15
- label TEXT,
16
- user_label TEXT,
17
- provider_account_id TEXT,
18
- provider_account_email TEXT,
19
- provider_account_name TEXT,
20
- provider_identity_checked_at TEXT,
21
- provider_identity_source_updated_at TEXT,
22
- lifecycle_status TEXT NOT NULL DEFAULT 'pending',
23
- operational_status TEXT NOT NULL DEFAULT 'unknown',
24
- reconnect_required INTEGER NOT NULL DEFAULT 0,
25
- actions_enabled INTEGER NOT NULL DEFAULT 0,
26
- read_tools_json TEXT NOT NULL DEFAULT '[]',
27
- action_tools_json TEXT NOT NULL DEFAULT '[]',
28
- tool_revision TEXT,
29
- last_checked_at TEXT,
30
- last_successful_call_at TEXT,
31
- last_failure_at TEXT,
32
- last_failure_code TEXT,
33
- last_failure_retryable INTEGER,
34
- consecutive_failures INTEGER NOT NULL DEFAULT 0,
35
- vault_name TEXT,
36
- table_name TEXT,
37
- legacy_owner_identity TEXT,
38
- created_at TEXT NOT NULL DEFAULT (datetime('now')),
39
- updated_at TEXT NOT NULL DEFAULT (datetime('now')),
40
- UNIQUE(user_id, provider_config_key, upstream_connection_id)
41
- )
42
- `);try{await t.execute("ALTER TABLE service_connections ADD COLUMN user_label TEXT")}catch{}try{await t.execute("ALTER TABLE service_connections ADD COLUMN provider_account_id TEXT")}catch{}try{await t.execute("ALTER TABLE service_connections ADD COLUMN provider_account_email TEXT")}catch{}try{await t.execute("ALTER TABLE service_connections ADD COLUMN provider_account_name TEXT")}catch{}try{await t.execute("ALTER TABLE service_connections ADD COLUMN provider_identity_checked_at TEXT")}catch{}try{await t.execute("ALTER TABLE service_connections ADD COLUMN provider_identity_source_updated_at TEXT")}catch{}await t.execute("CREATE INDEX IF NOT EXISTS service_connections_user_updated ON service_connections(user_id, updated_at DESC)"),await t.execute("CREATE INDEX IF NOT EXISTS service_connections_upstream ON service_connections(provider_config_key, upstream_connection_id)"),await t.execute(`
43
- CREATE TABLE IF NOT EXISTS service_connection_health_events (
44
- id TEXT PRIMARY KEY,
45
- connection_id TEXT NOT NULL REFERENCES service_connections(id) ON DELETE CASCADE,
46
- operational_status TEXT NOT NULL,
47
- failure_code TEXT,
48
- retryable INTEGER,
49
- evidence_source TEXT NOT NULL,
50
- created_at TEXT NOT NULL DEFAULT (datetime('now'))
51
- )
52
- `),await t.execute("CREATE INDEX IF NOT EXISTS service_connection_health_events_connection ON service_connection_health_events(connection_id, created_at DESC)"),await t.execute(`
53
- CREATE TABLE IF NOT EXISTS service_connection_action_audit (
54
- id TEXT PRIMARY KEY,
55
- connection_id TEXT NOT NULL REFERENCES service_connections(id) ON DELETE CASCADE,
56
- user_id INTEGER NOT NULL REFERENCES users(id),
57
- tool TEXT NOT NULL,
58
- request_id TEXT NOT NULL,
59
- status TEXT NOT NULL,
60
- error_code TEXT,
61
- created_at TEXT NOT NULL DEFAULT (datetime('now')),
62
- UNIQUE(user_id, request_id)
63
- )
64
- `);try{await t.execute("ALTER TABLE service_connection_action_audit ADD COLUMN request_digest TEXT")}catch{}try{await t.execute("ALTER TABLE service_connection_action_audit ADD COLUMN result_json TEXT")}catch{}})().catch(t=>{throw U=null,z=null,t})),U}function be(e){if(typeof e!="string")return[];try{let t=JSON.parse(e);return Array.isArray(t)?t.filter(n=>typeof n=="string"):[]}catch{return[]}}function Te(e){return{id:String(e.id),userId:Number(e.user_id),providerConfigKey:String(e.provider_config_key),provider:typeof e.provider=="string"?e.provider:null,transport:e.transport==="remote_mcp"?"remote_mcp":e.transport==="credential_reference"?"credential_reference":"nango",upstreamConnectionId:typeof e.upstream_connection_id=="string"?e.upstream_connection_id:null,label:typeof e.label=="string"?e.label:null,userLabel:typeof e.user_label=="string"?e.user_label:null,providerAccountId:typeof e.provider_account_id=="string"?e.provider_account_id:null,providerAccountEmail:typeof e.provider_account_email=="string"?e.provider_account_email:null,providerAccountName:typeof e.provider_account_name=="string"?e.provider_account_name:null,providerIdentityCheckedAt:typeof e.provider_identity_checked_at=="string"?e.provider_identity_checked_at:null,providerIdentitySourceUpdatedAt:typeof e.provider_identity_source_updated_at=="string"?e.provider_identity_source_updated_at:null,lifecycleStatus:String(e.lifecycle_status),operationalStatus:String(e.operational_status),reconnectRequired:Number(e.reconnect_required)===1,actionsEnabled:Number(e.actions_enabled)===1,readTools:be(e.read_tools_json),actionTools:be(e.action_tools_json),toolRevision:typeof e.tool_revision=="string"?e.tool_revision:null,lastCheckedAt:typeof e.last_checked_at=="string"?e.last_checked_at:null,lastSuccessfulCallAt:typeof e.last_successful_call_at=="string"?e.last_successful_call_at:null,lastFailureAt:typeof e.last_failure_at=="string"?e.last_failure_at:null,lastFailureCode:typeof e.last_failure_code=="string"?e.last_failure_code:null,lastFailureRetryable:e.last_failure_retryable===null||e.last_failure_retryable===void 0?null:Number(e.last_failure_retryable)===1,consecutiveFailures:Number(e.consecutive_failures??0),vaultName:typeof e.vault_name=="string"?e.vault_name:null,tableName:typeof e.table_name=="string"?e.table_name:null,createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}async function Z(e){let t=await X(e.normalize("NFKC").trim().toLowerCase());if(!t)throw new Error("service_connection_user_not_found");return Number(t.id)}async function ee(e,t){await C();let n=l(),i=await Z(e);for(let r of t)await n.execute({sql:`
65
- INSERT INTO service_connections (
66
- id, user_id, provider_config_key, provider, transport, upstream_connection_id,
67
- label, lifecycle_status, reconnect_required, actions_enabled, legacy_owner_identity, created_at, updated_at
68
- ) VALUES (?, ?, ?, ?, 'nango', ?, ?, ?, ?, 1, ?, COALESCE(?, datetime('now')), COALESCE(?, datetime('now')))
69
- ON CONFLICT(user_id, provider_config_key, upstream_connection_id) DO UPDATE SET
70
- provider = excluded.provider,
71
- label = COALESCE(excluded.label, service_connections.label),
72
- lifecycle_status = excluded.lifecycle_status,
73
- reconnect_required = excluded.reconnect_required,
74
- updated_at = excluded.updated_at
75
- `,args:[Q(),i,r.providerConfigKey,r.provider,r.upstreamConnectionId,r.label,r.lifecycleStatus,r.reconnectRequired?1:0,e,r.createdAt,r.updatedAt]});return Ke(e,"nango")}async function Ke(e,t){await C();let n=await Z(e);return(await l().execute({sql:`SELECT * FROM service_connections WHERE user_id = ?${t?" AND transport = ?":""} AND lifecycle_status <> 'disconnected' ORDER BY updated_at DESC`,args:t?[n,t]:[n]})).rows.map(r=>Te(r))}async function S(e,t){await C();let n=await Z(e),r=(await l().execute({sql:"SELECT * FROM service_connections WHERE id = ? AND user_id = ? LIMIT 1",args:[t,n]})).rows[0];return r?Te(r):null}async function ve(e,t,n,i){await C(),await l().execute({sql:"UPDATE service_connections SET read_tools_json = ?, action_tools_json = ?, tool_revision = ?, updated_at = datetime('now') WHERE id = ?",args:[JSON.stringify(t),JSON.stringify(n),i,e]})}async function we(e){await C(),await l().execute({sql:`
76
- UPDATE service_connections SET
77
- provider_account_id = ?, provider_account_email = ?, provider_account_name = ?,
78
- provider_identity_checked_at = datetime('now'), provider_identity_source_updated_at = ?,
79
- updated_at = datetime('now')
80
- WHERE id = ?
81
- `,args:[e.providerAccountId??null,e.providerAccountEmail?.toLowerCase()??null,e.providerAccountName??null,e.sourceUpdatedAt,e.connectionId]})}async function Xt(e,t,n){let i=await S(e,t);if(!i||i.lifecycleStatus==="disconnected")throw new Error("service_connection_not_found");return await l().execute({sql:"UPDATE service_connections SET user_label = ?, updated_at = datetime('now') WHERE id = ? AND user_id = ?",args:[n,t,i.userId]}),n}async function te(e){await C();let t=new Date().toISOString();await l().execute({sql:`
82
- UPDATE service_connections SET
83
- operational_status = ?, last_checked_at = ?,
84
- last_successful_call_at = CASE WHEN ? = 'available' THEN ? ELSE last_successful_call_at END,
85
- last_failure_at = CASE WHEN ? IN ('degraded', 'unavailable') THEN ? ELSE NULL END,
86
- last_failure_code = ?, last_failure_retryable = ?,
87
- consecutive_failures = CASE WHEN ? = 'available' THEN 0 ELSE consecutive_failures + 1 END,
88
- updated_at = datetime('now')
89
- WHERE id = ?
90
- `,args:[e.operationalStatus,t,e.operationalStatus,t,e.operationalStatus,t,e.failureCode??null,e.retryable==null?null:e.retryable?1:0,e.operationalStatus,e.connectionId]}),await l().execute({sql:"INSERT INTO service_connection_health_events (id, connection_id, operational_status, failure_code, retryable, evidence_source) VALUES (?, ?, ?, ?, ?, ?)",args:[Q(),e.connectionId,e.operationalStatus,e.failureCode??null,e.retryable==null?null:e.retryable?1:0,e.evidenceSource]})}async function Bt(e,t,n){let i=await S(e,t);if(!i||i.lifecycleStatus==="disconnected")throw new Error("service_connection_not_found");return await l().execute({sql:"UPDATE service_connections SET actions_enabled = ?, updated_at = datetime('now') WHERE id = ? AND user_id = ?",args:[n?1:0,t,i.userId]}),n}async function Gt(e,t){let n=await S(e,t);if(!n)throw new Error("service_connection_not_found");await l().execute({sql:"UPDATE service_connections SET lifecycle_status = 'disconnected', operational_status = 'unknown', reconnect_required = 0, updated_at = datetime('now') WHERE id = ? AND user_id = ?",args:[t,n.userId]});let i=await l().execute({sql:"SELECT COUNT(*) AS count FROM service_connections WHERE user_id = ? AND transport = 'nango' AND lifecycle_status = 'connected'",args:[n.userId]});return Number(i.rows[0]?.count??0)}async function Vt(e){await C();let t=await S(e.identity,e.connectionId);if(!t)throw new Error("service_connection_not_found");await l().execute({sql:"UPDATE service_connection_action_audit SET status = ?, error_code = ?, result_json = ? WHERE user_id = ? AND request_id = ? AND connection_id = ?",args:[e.status,e.errorCode??null,e.result===void 0?null:JSON.stringify(e.result),t.userId,e.requestId,t.id]})}async function $t(e){await C();let t=await S(e.identity,e.connectionId);if(!t)throw new Error("service_connection_not_found");let n=await l().execute({sql:"INSERT OR IGNORE INTO service_connection_action_audit (id, connection_id, user_id, tool, request_id, status, request_digest) VALUES (?, ?, ?, ?, ?, 'started', ?)",args:[Q(),t.id,t.userId,e.tool,e.requestId,e.requestDigest]});if(Number(n.rowsAffected??0)===1)return{claimed:!0};let r=(await l().execute({sql:"SELECT connection_id, tool, status, error_code, request_digest, result_json FROM service_connection_action_audit WHERE user_id = ? AND request_id = ? LIMIT 1",args:[t.userId,e.requestId]})).rows[0],o=String(r?.connection_id??"")!==t.id||String(r?.tool??"")!==e.tool||String(r?.request_digest??"")!==e.requestDigest,s;if(!o&&typeof r?.result_json=="string")try{s=JSON.parse(r.result_json)}catch{s=void 0}return{claimed:!1,status:String(r?.status??"unknown"),errorCode:typeof r?.error_code=="string"?r.error_code:null,conflict:o,...s!==void 0?{result:s}:{}}}import{createHash as Xe,randomUUID as Be}from"crypto";import{z as E}from"zod";async function Qt(e,t){!Number.isFinite(t)||t<=0||await $({op:I.CONNECTED_ACCOUNT_FEE,userId:Number(e)},()=>j({vendor:"nango_connection",units:t,unitType:"connection_month"}))}async function Ce(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 $({op:I.CONNECTED_USAGE,userId:Number(e)},async()=>{for(let i of n)!Number.isFinite(i.units)||i.units<=0||await j(i)})}import{randomUUID as Se}from"crypto";async function an(){let e=l(),t=await e.execute({sql:`SELECT id
91
- FROM credit_lots
92
- WHERE remaining_mc > 0
93
- AND never_expires = 0
94
- AND expires_at <= datetime('now')
95
- LIMIT 500`});if(t.rows.length===0)return{expired_lots:0,expired_mc:0};let n=[],i=[];for(let c of t.rows){let u=Number(c.id),p=Se();n.push({token:p,insertResultIndex:i.length}),i.push({sql:`INSERT OR IGNORE INTO credit_lot_expirations (lot_id, user_id, amount_mc, claim_token)
96
- SELECT id, user_id, remaining_mc, ?
97
- FROM credit_lots
98
- WHERE id = ?
99
- AND remaining_mc > 0
100
- AND never_expires = 0
101
- AND expires_at <= datetime('now')`,args:[p,u]}),i.push({sql:`UPDATE credit_lots
102
- SET remaining_mc = 0
103
- WHERE id = ?
104
- AND EXISTS (
105
- SELECT 1 FROM credit_lot_expirations
106
- WHERE lot_id = ? AND claim_token = ?
107
- )`,args:[u,u,p]}),i.push({sql:`INSERT INTO ledger (user_id, amount_mc, operation, description)
108
- SELECT user_id, -amount_mc, 'credit_expired', 'credits expired'
109
- FROM credit_lot_expirations
110
- WHERE lot_id = ? AND claim_token = ?`,args:[u,p]})}let r=await e.batch(i,"write"),o=n.filter(c=>r[c.insertResultIndex]?.rowsAffected===1).map(c=>c.token);if(o.length===0)return{expired_lots:0,expired_mc:0};let s=o.map(()=>"?").join(", "),a=await e.execute({sql:`SELECT user_id, amount_mc
111
- FROM credit_lot_expirations
112
- WHERE claim_token IN (${s})`,args:o}),d=new Set(a.rows.map(c=>Number(c.user_id)));for(let c of d)await D(c);return{expired_lots:a.rows.length,expired_mc:a.rows.reduce((c,u)=>c+Number(u.amount_mc),0)}}async function cn(e,t,n,i,r,o){let s=l();await q(e);let a=o?.neverExpires;if(a===void 0&&t>0){let p=await s.execute({sql:"SELECT subscription_tier FROM users WHERE id = ? LIMIT 1",args:[e]});a=String(p.rows[0]?.subscription_tier??"").startsWith("sonic")}let d=a?"9999-12-31 23:59:59":null;if(r){let p=[{sql:"INSERT OR IGNORE INTO ledger (user_id, amount_mc, operation, description, stripe_pi) VALUES (?, ?, ?, ?, ?)",args:[e,t,n,i??null,r]}];t>0&&p.push({sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
113
- SELECT ?, ?, ?, ?, ?, COALESCE(?, datetime('now', ?)), ?
114
- WHERE changes() = 1`,args:[e,t,t,n,r,d,M,a?1:0]}),p.push({sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ? AND changes() = 1",args:[t,e]}),await s.batch(p,"write");let f=await s.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(f.rows[0]?.balance_mc??0)}let c=[];t>0&&c.push({sql:"INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires) VALUES (?, ?, ?, ?, ?, COALESCE(?, datetime('now', ?)), ?)",args:[e,t,t,n,null,d,M,a?1:0]}),c.push({sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ?",args:[t,e]}),c.push({sql:"INSERT INTO ledger (user_id, amount_mc, operation, description, stripe_pi) VALUES (?, ?, ?, ?, ?)",args:[e,t,n,i??null,null]}),await s.batch(c,"write");let u=await s.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(u.rows[0]?.balance_mc??0)}async function un(e,t,n,i,r,o){if(!Number.isSafeInteger(t)||t<=0)throw new Error("idempotent credit amount must be a positive integer");if(!r||r.length>500)throw new Error("idempotent credit key is required and must be bounded");let s=l();await q(e);let a=o?.neverExpires;if(a===void 0){let y=await s.execute({sql:"SELECT subscription_tier FROM users WHERE id = ? LIMIT 1",args:[e]});a=String(y.rows[0]?.subscription_tier??"").startsWith("sonic")}let d=a?"9999-12-31 23:59:59":null,c=async()=>{let y=await s.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(y.rows[0]?.balance_mc??0)},u;try{u=await s.batch([{sql:"INSERT OR IGNORE INTO billing_credits (idempotency_key, user_id, amount_mc, operation, description, status) VALUES (?, ?, ?, ?, ?, 'claimed')",args:[r,e,t,n,i]},{sql:"UPDATE billing_credits SET status = 'applying' WHERE idempotency_key = ? AND user_id = ? AND amount_mc = ? AND operation = ? AND description = ? AND status = 'claimed'",args:[r,e,t,n,i]},{sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
115
- SELECT user_id, amount_mc, amount_mc, operation, NULL, COALESCE(?, datetime('now', ?)), ?
116
- FROM billing_credits
117
- WHERE idempotency_key = ? AND status = 'applying'`,args:[d,M,a?1:0,r]},{sql:`UPDATE users
118
- SET balance_mc = balance_mc + COALESCE((
119
- SELECT amount_mc FROM billing_credits WHERE idempotency_key = ? AND status = 'applying'
120
- ), 0)
121
- WHERE id = ?`,args:[r,e]},{sql:"INSERT INTO ledger (user_id, amount_mc, operation, description) SELECT user_id, amount_mc, operation, description FROM billing_credits WHERE idempotency_key = ? AND status = 'applying'",args:[r]},{sql:"UPDATE billing_credits SET status = 'applied', applied_at = datetime('now') WHERE idempotency_key = ? AND status = 'applying'",args:[r]}],"write")}catch(y){try{let x=(await s.execute({sql:"SELECT user_id, amount_mc, operation, description FROM billing_credits WHERE idempotency_key = ? AND status = 'applied' LIMIT 1",args:[r]})).rows[0];if(x&&Number(x.user_id)===e&&Number(x.amount_mc)===t&&String(x.operation)===n&&String(x.description)===i)return{ok:!0,balance_mc:await c(),duplicate:!0}}catch{}throw y}let f=(await s.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_credits WHERE idempotency_key = ? LIMIT 1",args:[r]})).rows[0];if(!f||Number(f.user_id)!==e||Number(f.amount_mc)!==t||String(f.operation)!==n||String(f.description)!==i)throw new Error("idempotent credit key conflicts with another credit");return{ok:String(f.status)==="applied",balance_mc:await c(),duplicate:u[1]?.rowsAffected===0&&String(f.status)==="applied"}}async function dn(e,t){return(await l().execute({sql:"SELECT 1 FROM ledger WHERE user_id = ? AND operation = ? LIMIT 1",args:[e,t]})).rows.length>0}async function ln(e,t,n,i){let r=`debit:${Se()}`,o=await L(e,t,n,i??"",r);return{ok:o.ok,balance_mc:o.balance_mc,billingKey:r}}async function mn(e,t=50){return(await l().execute({sql:"SELECT * FROM ledger WHERE user_id = ? ORDER BY created_at DESC LIMIT ?",args:[e,t]})).rows.map(i=>({id:Number(i.id),user_id:Number(i.user_id),amount_mc:Number(i.amount_mc),operation:String(i.operation),description:i.description!=null?String(i.description):null,stripe_pi:i.stripe_pi!=null?String(i.stripe_pi):null,created_at:String(i.created_at)}))}async function pn(e,t,n){let i=l(),r=n.refund.map(()=>"?").join(", "),o=n.grant.map(()=>"?").join(", "),s=n.purchase.map(()=>"?").join(", "),a=await i.execute({sql:`SELECT
122
- COALESCE(SUM(CASE WHEN amount_mc < 0 AND operation NOT IN (${r}) THEN -amount_mc ELSE 0 END), 0) AS spent_mc,
123
- COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${r}) THEN amount_mc ELSE 0 END), 0) AS refunded_mc,
124
- COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${o}) THEN amount_mc ELSE 0 END), 0) AS granted_mc,
125
- COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${s}) THEN amount_mc ELSE 0 END), 0) AS purchased_mc,
126
- COALESCE(SUM(amount_mc), 0) AS net_mc
127
- FROM ledger WHERE user_id = ? AND created_at >= ?`,args:[...n.refund,...n.refund,...n.grant,...n.purchase,e,t]}),d=await i.execute({sql:`SELECT operation, -SUM(amount_mc) AS mc, COUNT(*) AS count
128
- FROM ledger
129
- WHERE user_id = ? AND created_at >= ? AND amount_mc < 0 AND operation NOT IN (${r})
130
- GROUP BY operation
131
- ORDER BY mc DESC, operation ASC`,args:[e,t,...n.refund]}),c=a.rows[0];return{spent_mc:Number(c?.spent_mc??0),refunded_mc:Number(c?.refunded_mc??0),granted_mc:Number(c?.granted_mc??0),purchased_mc:Number(c?.purchased_mc??0),net_mc:Number(c?.net_mc??0),by_operation:d.rows.map(u=>({operation:String(u.operation),mc:Number(u.mc),count:Number(u.count)}))}}async function D(e,t){let n=l();for(let r=0;r<8;r+=1){let s=(await n.execute({sql:`SELECT
132
- u.balance_mc AS cached_balance_mc,
133
- COUNT(l.id) AS lot_count,
134
- COALESCE(SUM(CASE
135
- WHEN l.remaining_mc > 0
136
- AND (l.never_expires = 1 OR l.expires_at > datetime('now'))
137
- THEN l.remaining_mc ELSE 0 END), 0) AS projected_balance_mc
138
- FROM users u
139
- LEFT JOIN credit_lots l ON l.user_id = u.id
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="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
- FROM billing_events
143
- WHERE user_id = ?
144
- AND billing_class = ?
145
- AND status = 'cost_pending'
146
- ${t?"AND idempotency_key <> ?":""}
147
- LIMIT 1`,args:t?[e,N,t]:[e,N]})).rows.length>0}function Ze(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 et(e){let t=await l().execute({sql:`SELECT id, user_id, idempotency_key, billing_class, source_surface, status, amount_mc, metadata
148
- FROM billing_events
149
- WHERE user_id = ? AND billing_class = ? AND status = 'cost_pending'
150
- ORDER BY created_at ASC
151
- LIMIT 10`,args:[e.id,N]});for(let n of t.rows){let i=n,r=String(i.idempotency_key??""),o=Ze(r),s;try{s=se(i)}catch{return}if(!o||Number(i.user_id)!==e.id||i.billing_class!==N||Number(i.amount_mc)!==s.charge.amountMc||s.charge.amountMc>0&&!(await L(e.id,s.charge.amountMc,I.CONNECTED_USAGE,`connected-usage:${s.providerConfigKey}`,o)).ok)return;let a={...s};delete a.reason,await l().execute({sql:`UPDATE billing_events
152
- SET status = 'settled', metadata = ?, settled_at = datetime('now')
153
- WHERE idempotency_key = ? AND user_id = ? AND billing_class = ? AND status = 'cost_pending'`,args:[P(a),r,e.id,N]})}}function Re(e){if(e!==b)throw new T("rate_policy_mismatch","connected usage receipt rate policy does not match the active policy",409,{expectedRatePolicyVersion:b})}async function ae(e){let t=je.safeParse(e);if(!t.success)throw new T("invalid_request","invalid connected usage preflight request",400);Re(t.data.ratePolicyVersion);let n=await Ne(t.data.identity);if(await et(n),await he(n.id))throw new T("pending_cost","a previous connected usage receipt has unresolved cost",409);let i=await D(n.id,n.balance_mc);if(i<H)throw new T("insufficient_credits","the wallet cannot cover the minimum connected function charge",402,{balanceMc:i,requiredMc:H});return{allowed:!0,ratePolicyVersion:b,minimumMc:H,minimumCredits:J,balanceMc:i}}function ie(e,t,n,i,r){let o=se(e);if(Number(e.user_id)!==t||e.billing_class!==N||e.source_surface!==n||Number(e.amount_mc)!==r||o.fingerprint!==i)throw new T("idempotency_key_conflict","the idempotency key is already bound to different connected usage",409);return o}function Ae(e,t){return[{key:"function_runs",label:"Connected function runs",quantity:e.functionRuns,quantityUnit:"function_run",rateCredits:J,rateUnit:"function_run",amountMc:t.functionRunMc,credits:t.functionRunMc/F},{key:"proxy_requests",label:"Connected proxy requests",quantity:e.proxyRequests,quantityUnit:"proxy_request",rateCredits:pe,rateUnit:"proxy_request",amountMc:t.proxyRequestMc,credits:t.proxyRequestMc/F},{key:"compute",label:"Connected function compute",quantity:e.computeMilliseconds,quantityUnit:"millisecond",rateCredits:_e,rateUnit:"compute_second",amountMc:t.computeMc,credits:t.computeMc/F}]}function re(e,t,n,i){let r=e.status==="cost_pending"?t.reason:void 0;return{id:e.id,status:e.status==="settled"?"settled":"cost_pending",ratePolicyVersion:b,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:Ae(t.usage,t.charge),balanceMc:n,...r?{reason:r}:{},duplicate:i}}async function ce(e){let t=$e.safeParse(e);if(!t.success)throw new T("invalid_request","invalid connected usage settlement request",400,{fields:[...new Set(t.error.issues.map(w=>w.path.join(".")).filter(Boolean))]});let n=t.data;Re(n.ratePolicyVersion);let i=await Ne(n.identity),r={functionRuns:n.functionRuns,proxyRequests:n.proxyRequests,computeMilliseconds:n.computeMilliseconds},o=ge(r),s=n.metadata??{},a=Qe({connectionId:n.connectionId,providerConfigKey:n.providerConfigKey,usage:r,sourceSurface:n.sourceSurface,metadata:s}),d={contract:"connected_usage_receipt",ratePolicyVersion:b,fingerprint:a,connectionId:n.connectionId,providerConfigKey:n.providerConfigKey,usage:r,charge:o,safeMetadata:s},c=Je(n.idempotencyKey);if(await he(i.id,c))throw new T("pending_cost","a previous connected usage receipt has unresolved cost",409);let u=await l().execute({sql:`INSERT OR IGNORE INTO billing_events
154
- (id, user_id, idempotency_key, billing_class, source_surface, status, amount_mc, metadata)
155
- VALUES (?, ?, ?, ?, ?, 'settling', ?, ?)`,args:[Be(),i.id,c,N,n.sourceSurface,o.amountMc,P(d)]}),p=await ne(c);if(!p)throw new Error("connected usage receipt insert completed without a readable event");let f=ie(p,i.id,n.sourceSurface,a,o.amountMc),y=u.rowsAffected===0;if(p.status==="settled")return re(p,f,await D(i.id,i.balance_mc),!0);if(!["settling","cost_pending"].includes(p.status))throw new T("idempotency_key_conflict","the connected usage receipt has an incompatible status",409);if(p.status==="cost_pending"&&await l().execute({sql:"UPDATE billing_events SET status = 'settling', metadata = ? WHERE idempotency_key = ? AND status = 'cost_pending'",args:[P(d),c]}),o.amountMc===0)await l().execute({sql:"UPDATE billing_events SET status = 'settled', settled_at = datetime('now') WHERE idempotency_key = ? AND status = 'settling'",args:[c]});else{let w=await L(i.id,o.amountMc,I.CONNECTED_USAGE,`connected-usage:${n.providerConfigKey}`,Ye(n.idempotencyKey));if(!w.ok){let x={...d,reason:"insufficient_credits"};if(await l().execute({sql:"UPDATE billing_events SET status = 'cost_pending', metadata = ? WHERE idempotency_key = ? AND status = 'settling'",args:[P(x),c]}),p=await ne(c),!p)throw new Error("connected usage pending receipt was lost");return f=ie(p,i.id,n.sourceSurface,a,o.amountMc),re(p,f,w.balance_mc,y||w.duplicate)}await l().execute({sql:"UPDATE billing_events SET status = 'settled', metadata = ?, settled_at = datetime('now') WHERE idempotency_key = ? AND status IN ('settling', 'cost_pending')",args:[P(d),c]}),w.duplicate||await Ce(i.id,r)}if(p=await ne(c),!p)throw new Error("connected usage settlement completed without an event receipt");return f=ie(p,i.id,n.sourceSurface,a,o.amountMc),re(p,f,await D(i.id,i.balance_mc),y)}async function Cn(e,t=100){let n=await l().execute({sql:`SELECT id, user_id, billing_class, source_surface, status, amount_mc, metadata, created_at
156
- FROM billing_events
157
- WHERE user_id = ? AND billing_class = ? AND status IN ('settled', 'cost_pending')
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{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 $};
@@ -1,3 +0,0 @@
1
- import{a as w}from"./chunk-JMZIDHYQ.js";import{e as v,j as T}from"./chunk-SEZETSB3.js";import{i as I}from"./chunk-SDQW7IJN.js";import{b as y}from"./chunk-B3JRL45T.js";import{c as E}from"./chunk-OILOHQNL.js";import{createHash as L,randomBytes as N}from"crypto";import{basename as D,extname as O,join as j}from"path";import k from"p-limit";import{ZipFile as $}from"yazl";var P="page-media/",z=10080*60*1e3,W=900*1e3,_=10*1024*1024,G=45*1024*1024,X=15e5,K=25e5,V=6,B=5;function S(){return process.env.PAGE_MEDIA_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 C(){return{prefix:P,artifactTtlMs:z,downloadTtlMs:W,token:S()}}function Y(e,r){if(e.length>=3&&e[0]===255&&e[1]===216&&e[2]===255)return{mimeType:"image/jpeg",extension:"jpg"};if(e.length>=8&&e[0]===137&&e[1]===80&&e[2]===78&&e[3]===71)return{mimeType:"image/png",extension:"png"};if(e.length>=12&&String.fromCharCode(...e.slice(0,4))==="RIFF"&&String.fromCharCode(...e.slice(8,12))==="WEBP")return{mimeType:"image/webp",extension:"webp"};if(e.length>=6&&["GIF87a","GIF89a"].includes(String.fromCharCode(...e.slice(0,6))))return{mimeType:"image/gif",extension:"gif"};if(e.length>=12&&String.fromCharCode(...e.slice(4,12)).match(/^ftyp(?:avif|avis)$/))return{mimeType:"image/avif",extension:"avif"};let t=Buffer.from(e.slice(0,Math.min(e.length,1024))).toString("utf8").replace(/^\uFEFF/,"").trimStart();return(r==="image/svg+xml"||t.startsWith("<svg")||/^<\?xml[\s\S]*?<svg/i.test(t))&&/<svg[\s>]/i.test(t)?{mimeType:"image/svg+xml",extension:"svg"}:null}function H(e,r,t){if(t==="image")return Y(e,r);if(e.length>=12&&String.fromCharCode(...e.slice(4,8))==="ftyp")return{mimeType:"video/mp4",extension:"mp4"};if(e.length>=4&&e[0]===26&&e[1]===69&&e[2]===223&&e[3]===163)return{mimeType:"video/webm",extension:"webm"};if(e.length>=4&&String.fromCharCode(...e.slice(0,4))==="OggS")return t==="audio"?{mimeType:"audio/ogg",extension:"ogg"}:{mimeType:"video/ogg",extension:"ogv"};if(t==="audio"&&e.length>=3&&String.fromCharCode(...e.slice(0,3))==="ID3")return{mimeType:"audio/mpeg",extension:"mp3"};if(r&&w(r)===t){let i=r.split("/")[1]?.replace("jpeg","jpg").replace("mpeg","mp3").replace("svg+xml","svg");if(i&&/^[a-z0-9]+$/i.test(i))return{mimeType:r,extension:i}}return null}function J(e,r){let t=Buffer.from(e);if(r==="image/png"&&t.length>=24)return{width:t.readUInt32BE(16),height:t.readUInt32BE(20)};if(r==="image/gif"&&t.length>=10)return{width:t.readUInt16LE(6),height:t.readUInt16LE(8)};if(r==="image/webp"&&t.length>=30){let i=t.toString("ascii",12,16);if(i==="VP8X")return{width:1+t.readUIntLE(24,3),height:1+t.readUIntLE(27,3)};if(i==="VP8L"&&t[20]===47){let a=t.readUInt32LE(21);return{width:(a&16383)+1,height:(a>>14&16383)+1}}}if(r==="image/jpeg"){let i=2;for(;i+9<t.length;){if(t[i]!==255){i+=1;continue}let a=t[i+1];if(a===216||a===217){i+=2;continue}let o=t.readUInt16BE(i+2);if(o<2||i+o+2>t.length)break;if([192,193,194,195,197,198,199,201,202,203,205,206,207].includes(a))return{height:t.readUInt16BE(i+5),width:t.readUInt16BE(i+7)};i+=o+2}}if(r==="image/svg+xml"){let a=t.toString("utf8",0,Math.min(t.length,65536)).match(/<svg\b[^>]*>/i)?.[0]??"",o=Number(a.match(/\bwidth=["']?([\d.]+)/i)?.[1]??0),d=Number(a.match(/\bheight=["']?([\d.]+)/i)?.[1]??0);if(o>0&&d>0)return{width:Math.round(o),height:Math.round(d)};let c=a.match(/\bviewBox=["']([^"']+)["']/i)?.[1]?.trim().split(/[\s,]+/).map(Number);if(c?.length===4&&c[2]>0&&c[3]>0)return{width:Math.round(c[2]),height:Math.round(c[3])}}return null}async function Z(e){let r=Number(e.headers.get("content-length")??"");if(Number.isFinite(r)&&r>_)throw new Error("media_too_large");if(!e.body){let o=Buffer.from(await e.arrayBuffer());if(o.length>_)throw new Error("media_too_large");return o}let t=e.body.getReader(),i=[],a=0;try{for(;;){let{done:o,value:d}=await t.read();if(o)break;if(d){if(a+=d.byteLength,a>_)throw new Error("media_too_large");i.push(Buffer.from(d))}}}finally{t.releaseLock()}return Buffer.concat(i)}async function q(e,r){let t=e;for(let i=0;i<=B;i+=1){let a=await y(t,{field:"website media URL"});if(a.error||!a.parsed)throw new Error("media_url_rejected");let o=await fetch(a.parsed.href,{redirect:"manual",headers:{Accept:r==="image"?"image/*":`${r}/*`},signal:AbortSignal.timeout(15e3)});if([301,302,303,307,308].includes(o.status)){let s=o.headers.get("location");if(!s||i===B)throw new Error("media_redirect_rejected");t=new URL(s,a.parsed).href;continue}if(!o.ok)throw new Error(`media_fetch_${o.status}`);let d=await Z(o),c=o.headers.get("content-type")?.split(";")[0].trim().toLowerCase()??null,m=H(d,c,r);if(!m||w(m.mimeType)!==r)throw new Error("media_content_invalid");let f=r==="image"?J(d,m.mimeType):null;return{bytes:d,...m,finalUrl:a.parsed.href,width:f?.width??null,height:f?.height??null,sha256:L("sha256").update(d).digest("hex")}}throw new Error("media_redirect_rejected")}function Q(e){return new Promise((r,t)=>{let i=new $,a=[];i.outputStream.on("data",o=>a.push(Buffer.from(o))),i.outputStream.once("error",t),i.outputStream.once("end",()=>r(Buffer.concat(a)));for(let o of e)i.addBuffer(o.content,o.path);i.end()})}function M(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,70)||"website"}function ee(e){try{return D(new URL(e).pathname).replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)}catch{return""}}function te(e){return I(e,P)}async function me(e){return te(e.artifactId)!==e.ownerId?null:T({policy:C(),artifactId:e.artifactId,maxBytes:60*1024*1024})}async function fe(e){let r=[],t=k(V),i=new Map,a=0,o=0,d=0;await Promise.all(e.media.assets.map((n,h)=>t(async()=>{try{let l=await q(n.url,n.type);n.finalUrl=l.finalUrl,n.mimeType=l.mimeType,n.sizeBytes=l.bytes.length,n.sha256=l.sha256,n.width=l.width??n.width,n.height=l.height??n.height;let g=i.get(l.sha256);if(g){n.filename=g,n.duplicateOf=g,n.downloadStatus="downloaded",n.downloadError=null;return}if(a+l.bytes.length>G)throw new Error("archive_byte_limit_reached");a+=l.bytes.length;let u=ee(l.finalUrl),A=O(u),F=u?A?u.slice(0,-A.length):u:n.type,p=`media/${String(h+1).padStart(4,"0")}-${M(F)}.${l.extension}`;i.set(l.sha256,p),r.push({path:p,content:l.bytes}),n.filename=p,n.duplicateOf=null,n.downloadStatus="downloaded",n.downloadError=null,n.type==="image"&&d<e.maxInlineImages&&l.bytes.length<=X&&o+l.bytes.length<=K&&(n.inlinePreview={data:l.bytes.toString("base64"),mimeType:l.mimeType},o+=l.bytes.length,d+=1)}catch(l){n.finalUrl=null,n.mimeType=null,n.sizeBytes=null,n.sha256=null,n.savedPath=null,n.downloadStatus="failed",n.downloadError=l instanceof Error?l.message:"media_download_failed",n.inlinePreview=null}})));let c=e.media.assets.filter(n=>n.downloadStatus==="downloaded").length,m=e.media.assets.length-c;if(m>0&&e.media.warnings.push(`${m} media asset(s) could not be downloaded; media.jsonl contains bounded error codes.`),c===0)return{media:e.media,artifact:null};let f=e.media.assets.map(({inlinePreview:n,...h})=>h),s={pageUrl:e.pageUrl,title:e.title,extractedAt:e.extractedAt,completeness:e.media.completeness,exhausted:e.media.exhausted,stopReason:e.media.stopReason,scrollRounds:e.media.scrollRounds,staticFound:e.media.staticFound,renderedFound:e.media.renderedFound,totalFound:e.media.totalFound,retainedAfterFilteringAndVariantCollapse:e.media.assets.length,downloaded:c,failed:m,notes:["The inventory unions static-source and rendered-page discovery.","complete means rendered scrolling reached three stable document-height checks; it does not claim every interactive control was opened.","Media records preserve discovery evidence but do not assert ownership, rights, identity, or publishability."]};r.push({path:"summary.json",content:Buffer.from(JSON.stringify(s,null,2))}),r.push({path:"media.jsonl",content:Buffer.from(f.map(n=>JSON.stringify(n)).join(`
2
- `)+`
3
- `)});let R=await Q(r),U=N(6).toString("hex"),x=await v({policy:C(),ownerId:e.ownerId,artifactKey:`${U}.zip`,createdAt:new Date(e.extractedAt),filename:`${M(e.title||new URL(e.pageUrl).hostname)}-website-media.zip`,contentType:"application/zip",content:R}),b=S()?null:j(E(),"blobs",x.artifactId);return{media:e.media,artifact:{...x,localPath:b}}}export{P as a,z as b,C as c,te as d,me as e,fe as f};
@@ -1 +0,0 @@
1
- import{createHash as s}from"crypto";var e=class extends Error{constructor(r){super(r),this.name="OperationInputError"}},o=class extends Error{constructor(){super("This idempotency key was already used with different normalized inputs."),this.name="OperationIdempotencyConflictError"}};function u(t){return s("sha256").update(t).digest("hex")}function i(t){return Array.isArray(t)?t.map(i):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).sort(([r],[n])=>r.localeCompare(n)).map(([r,n])=>[r,i(n)])):t}function l(t){return JSON.stringify(i(t??{}))}function d(t,r){let n=t.trim();if(!n)throw new Error(`${r} is required`);return n}function p(t,r){if(!Number.isSafeInteger(r.userId)||r.userId<=0||r.userId!==t.userId||!r.tool||r.tool!==t.tool||!r.jobId||r.jobId!==t.jobId||typeof r.sql!="string"||!r.sql.trim()||r.sql.length>64*1024||!Array.isArray(r.args)||r.args.length>512)throw new e("Store gate must match the operation principal, tool and job")}export{e as a,o as b,u as c,l as d,d as e,p as f};
@@ -1,121 +0,0 @@
1
- import{a as I}from"./chunk-7POHNTVW.js";import{b as S}from"./chunk-4ZVO6GX4.js";import{a as R}from"./chunk-WNUXMPVX.js";import{randomUUID as X}from"crypto";import{createMiddleware as b}from"hono/factory";async function j(e){await e.execute(`CREATE TABLE IF NOT EXISTS mcp_analytics_requests (
2
- id TEXT PRIMARY KEY, parent_request_id TEXT, user_id INTEGER NOT NULL REFERENCES users(id),
3
- service TEXT NOT NULL, method TEXT NOT NULL, http_status INTEGER NOT NULL,
4
- duration_ms INTEGER NOT NULL, client_surface TEXT NOT NULL,
5
- install_channel TEXT NOT NULL, ai_client TEXT, ai_model TEXT,
6
- attribution_basis TEXT NOT NULL, started_at TEXT NOT NULL, deployment_commit TEXT
7
- )`),(await e.execute("PRAGMA table_info(mcp_analytics_requests)")).rows.some(n=>n.name==="parent_request_id")||await e.execute("ALTER TABLE mcp_analytics_requests ADD COLUMN parent_request_id TEXT"),await e.execute("CREATE INDEX IF NOT EXISTS mcp_analytics_requests_user_started ON mcp_analytics_requests(user_id, started_at)"),await e.execute("CREATE INDEX IF NOT EXISTS mcp_analytics_requests_started ON mcp_analytics_requests(started_at)")}var k=new Set(["npx","npm","sdk","frontend","mcp-stdio","mcp-http","rest"]),D=new Set(["npx","npm","mcpb","source"]),v=new Set(["claude","claude-desktop","claude-code","chatgpt","codex","cursor","gemini","other"]);function y(e,t){return e&&t.has(e.toLowerCase())?e.toLowerCase():null}function A(e,t=!1){let n=y(e.get("x-mcp-client-surface")??void 0,k),s=e.get("x-mcp-ai-model")??"";return{surface:t?"frontend":n??"unknown",installChannel:y(e.get("x-mcp-install-channel")??void 0,D)??"unknown",aiClient:y(e.get("x-mcp-ai-client")??void 0,v),aiModel:/^[a-zA-Z0-9][a-zA-Z0-9._:/-]{0,79}$/.test(s)?s:null,basis:t?"session_authenticated":n?"caller_declared":"unknown"}}async function q(e,t=50){let n;try{await Promise.race([e,new Promise((s,a)=>{n=setTimeout(()=>a(new Error("analytics_write_budget_exceeded")),t)})])}finally{n&&clearTimeout(n)}}function F(e=2){let t=0;return async n=>{if(t>=e)return!1;t++;let s=Promise.resolve().then(n).finally(()=>{t--});return await q(s),!0}}var H=F();function z(e){return b(async(t,n)=>{let s=X(),a=new Date().toISOString(),o=performance.now(),r=new URL(t.req.url).pathname,d=e(r),i=d??(r==="/mcp"?"mcp_http":"other_authenticated_http"),f={op:i,probeRunId:t.req.header("x-cost-probe-id")??null,requestId:s},_=A(t.req.raw.headers),c={};_.surface!=="unknown"&&(c["x-mcp-client-surface"]=_.surface),new URL(t.req.url).pathname==="/mcp"&&!c["x-mcp-client-surface"]&&(c["x-mcp-client-surface"]="mcp-http"),_.installChannel!=="unknown"&&(c["x-mcp-install-channel"]=_.installChannel),_.aiClient&&(c["x-mcp-ai-client"]=_.aiClient),_.aiModel&&(c["x-mcp-ai-model"]=_.aiModel);let l=t.req.header("x-mcp-parent-request-id"),N=l&&/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(l)?l:null;return I({requestId:s,headers:c},()=>S(f,async()=>{t.header("x-mcp-request-id",s);try{await n()}finally{t.header("x-mcp-request-id",s);let T=t.get("user"),x=t.get("sessionUser"),O=Number(T?.id??x?.id),w=/\/(?:jobs|status|progress|events|history|balance|usage)(?:\/|$)/.test(r);if(process.env.MCP_ANALYTICS_CAPTURE==="1"&&!w&&t.req.method!=="HEAD"&&t.req.method!=="OPTIONS"&&(d!==null||r==="/mcp"&&t.req.method==="POST")&&Number.isSafeInteger(O)&&O>0){let E=A(t.req.raw.headers,!!x?.id);new URL(t.req.url).pathname==="/mcp"&&E.surface==="unknown"&&(E.surface="mcp-http",E.basis="hosted_mcp_route");try{await H(()=>R().execute({sql:`INSERT INTO mcp_analytics_requests
8
- (id,parent_request_id,user_id,service,method,http_status,duration_ms,client_surface,install_channel,
9
- ai_client,ai_model,attribution_basis,started_at,deployment_commit)
10
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,args:[s,N,O,i,t.req.method,t.error?500:t.res.status,Math.max(0,Math.round(performance.now()-o)),E.surface,E.installChannel,E.aiClient,E.aiModel,E.basis,a,process.env.VERCEL_GIT_COMMIT_SHA??null]}))}catch{console.warn("[mcp-analytics] request observation unavailable")}}}}))})}var m=["oauth_store_metadata","oauth_clients","oauth_client_redirect_uris","oauth_codes","oauth_code_exchanges","oauth_refresh_families","oauth_refresh_tokens","oauth_refresh_rotations","oauth_security_events","oauth_rate_limit_buckets"],h=["oauth_clients_inactivity_idx","oauth_clients_cleanup_idx","oauth_codes_expiry_idx","oauth_codes_client_idx","oauth_code_exchanges_replay_expiry_idx","oauth_refresh_families_lifecycle_idx","oauth_refresh_families_user_status_idx","oauth_refresh_families_client_idx","oauth_refresh_families_cleanup_idx","oauth_refresh_tokens_expiry_idx","oauth_refresh_rotations_replay_expiry_idx","oauth_security_events_retention_idx","oauth_rate_limit_buckets_expiry_idx"],C={oauth_clients:"oauth_clients_legacy_raw",oauth_codes:"oauth_codes_legacy_raw",oauth_tokens:"oauth_tokens_legacy_raw"},u="strftime('%Y-%m-%dT%H:%M:%fZ','now')";async function p(e,t,n=!1){try{await e.execute(t)}catch(s){let a=s.code;if(!n||a!=="SQL_PARSE_ERROR")throw s}}var M=[`CREATE TABLE IF NOT EXISTS oauth_store_metadata (
11
- id INTEGER PRIMARY KEY CHECK (id = 1),
12
- store_id TEXT NOT NULL UNIQUE,
13
- schema_version INTEGER NOT NULL CHECK (schema_version > 0),
14
- authority_epoch INTEGER NOT NULL CHECK (authority_epoch > 0),
15
- authority_state TEXT NOT NULL CHECK (authority_state IN ('ready','authoritative','retired')),
16
- updated_at TEXT NOT NULL DEFAULT (${u})
17
- ) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_clients (
18
- client_id TEXT PRIMARY KEY,
19
- client_name TEXT NOT NULL,
20
- client_type TEXT NOT NULL CHECK (client_type = 'public'),
21
- token_endpoint_auth_method TEXT NOT NULL CHECK (token_endpoint_auth_method = 'none'),
22
- status TEXT NOT NULL CHECK (status IN ('active','disabled','expired')),
23
- created_at TEXT NOT NULL DEFAULT (${u}),
24
- last_used_at TEXT,
25
- expires_at TEXT
26
- ) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_client_redirect_uris (
27
- client_id TEXT NOT NULL REFERENCES oauth_clients(client_id) ON DELETE CASCADE,
28
- redirect_uri TEXT NOT NULL,
29
- redirect_kind TEXT NOT NULL CHECK (redirect_kind IN ('https','loopback','private_scheme')),
30
- PRIMARY KEY (client_id, redirect_uri)
31
- ) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_codes (
32
- code_digest BLOB PRIMARY KEY,
33
- lookup_key_id TEXT NOT NULL,
34
- client_id TEXT NOT NULL REFERENCES oauth_clients(client_id) ON DELETE RESTRICT,
35
- redirect_uri TEXT NOT NULL,
36
- code_challenge TEXT NOT NULL,
37
- challenge_method TEXT NOT NULL CHECK (challenge_method = 'S256'),
38
- user_id TEXT NOT NULL,
39
- scope TEXT NOT NULL,
40
- resource TEXT,
41
- issued_at TEXT NOT NULL DEFAULT (${u}),
42
- expires_at TEXT NOT NULL
43
- ) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_code_exchanges (
44
- code_digest BLOB PRIMARY KEY,
45
- request_fingerprint BLOB NOT NULL UNIQUE,
46
- client_id TEXT NOT NULL,
47
- family_id TEXT NOT NULL UNIQUE,
48
- grant_scope TEXT NOT NULL,
49
- grant_resource TEXT,
50
- scope TEXT NOT NULL,
51
- resource TEXT,
52
- sealed_refresh BLOB NOT NULL,
53
- sealed_nonce BLOB NOT NULL,
54
- sealed_tag BLOB NOT NULL,
55
- replay_key_id TEXT NOT NULL,
56
- completed_at TEXT NOT NULL DEFAULT (${u}),
57
- replay_expires_at TEXT NOT NULL
58
- ) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_refresh_families (
59
- family_id TEXT PRIMARY KEY,
60
- user_id TEXT NOT NULL,
61
- client_id TEXT NOT NULL REFERENCES oauth_clients(client_id) ON DELETE RESTRICT,
62
- issuer TEXT NOT NULL,
63
- scope TEXT NOT NULL,
64
- resource TEXT,
65
- status TEXT NOT NULL CHECK (status IN ('active','revoked','compromised','expired')),
66
- current_generation INTEGER NOT NULL CHECK (current_generation > 0),
67
- created_at TEXT NOT NULL DEFAULT (${u}),
68
- expires_at TEXT NOT NULL,
69
- revoked_at TEXT,
70
- compromised_at TEXT,
71
- UNIQUE (family_id, client_id),
72
- FOREIGN KEY (family_id, current_generation)
73
- REFERENCES oauth_refresh_tokens(family_id, generation)
74
- DEFERRABLE INITIALLY DEFERRED
75
- ) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_refresh_tokens (
76
- family_id TEXT NOT NULL REFERENCES oauth_refresh_families(family_id) ON DELETE CASCADE,
77
- generation INTEGER NOT NULL CHECK (generation > 0),
78
- token_digest BLOB NOT NULL UNIQUE,
79
- lookup_key_id TEXT NOT NULL,
80
- token_prefix TEXT NOT NULL,
81
- predecessor_generation INTEGER,
82
- issued_at TEXT NOT NULL DEFAULT (${u}),
83
- expires_at TEXT NOT NULL,
84
- used_at TEXT,
85
- revoked_at TEXT,
86
- PRIMARY KEY (family_id, generation),
87
- CHECK (predecessor_generation IS NULL OR (predecessor_generation > 0 AND predecessor_generation < generation))
88
- ) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_refresh_rotations (
89
- family_id TEXT NOT NULL REFERENCES oauth_refresh_families(family_id) ON DELETE CASCADE,
90
- predecessor_generation INTEGER NOT NULL,
91
- request_fingerprint BLOB NOT NULL,
92
- successor_generation INTEGER NOT NULL,
93
- sealed_successor BLOB NOT NULL,
94
- sealed_nonce BLOB NOT NULL,
95
- sealed_tag BLOB NOT NULL,
96
- replay_key_id TEXT NOT NULL,
97
- rotated_at TEXT NOT NULL DEFAULT (${u}),
98
- replay_expires_at TEXT NOT NULL,
99
- PRIMARY KEY (family_id, predecessor_generation),
100
- UNIQUE (family_id, successor_generation),
101
- CHECK (successor_generation = predecessor_generation + 1)
102
- ) STRICT`,`CREATE TABLE IF NOT EXISTS oauth_security_events (
103
- event_id TEXT PRIMARY KEY,
104
- family_id TEXT NOT NULL,
105
- event_type TEXT NOT NULL CHECK (event_type IN ('reuse','binding_mismatch','manual_revoke','expiry')),
106
- reason_code TEXT NOT NULL,
107
- occurred_at TEXT NOT NULL DEFAULT (${u}),
108
- retain_until TEXT NOT NULL
109
- ) STRICT`,"CREATE INDEX IF NOT EXISTS oauth_clients_inactivity_idx ON oauth_clients(status, last_used_at, client_id)","CREATE INDEX IF NOT EXISTS oauth_codes_expiry_idx ON oauth_codes(expires_at, code_digest)","CREATE INDEX IF NOT EXISTS oauth_code_exchanges_replay_expiry_idx ON oauth_code_exchanges(replay_expires_at, code_digest)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_lifecycle_idx ON oauth_refresh_families(status, expires_at, family_id)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_user_status_idx ON oauth_refresh_families(user_id, status)","CREATE INDEX IF NOT EXISTS oauth_refresh_tokens_expiry_idx ON oauth_refresh_tokens(expires_at, family_id, generation)","CREATE INDEX IF NOT EXISTS oauth_refresh_rotations_replay_expiry_idx ON oauth_refresh_rotations(replay_expires_at, family_id, predecessor_generation)","CREATE INDEX IF NOT EXISTS oauth_security_events_retention_idx ON oauth_security_events(retain_until, event_id)"],U=["CREATE INDEX IF NOT EXISTS oauth_clients_cleanup_idx ON oauth_clients(COALESCE(last_used_at,created_at), client_id)","CREATE INDEX IF NOT EXISTS oauth_codes_client_idx ON oauth_codes(client_id, code_digest)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_client_idx ON oauth_refresh_families(client_id, family_id)",`CREATE INDEX IF NOT EXISTS oauth_refresh_families_cleanup_idx
110
- ON oauth_refresh_families(COALESCE(compromised_at,revoked_at,expires_at), family_id)
111
- WHERE status!='active'`],g=[`CREATE TABLE IF NOT EXISTS oauth_rate_limit_buckets (
112
- scope TEXT NOT NULL CHECK (length(scope) BETWEEN 1 AND 80),
113
- key_digest BLOB NOT NULL CHECK (typeof(key_digest) = 'blob' AND length(key_digest) = 32),
114
- window_start INTEGER NOT NULL CHECK (window_start >= 0),
115
- window_seconds INTEGER NOT NULL CHECK (window_seconds BETWEEN 1 AND 604800),
116
- count INTEGER NOT NULL CHECK (count >= 1),
117
- expires_at INTEGER NOT NULL CHECK (expires_at = window_start + window_seconds),
118
- updated_at TEXT NOT NULL DEFAULT (${u}),
119
- PRIMARY KEY (scope, key_digest, window_start, window_seconds)
120
- ) STRICT`,`CREATE INDEX IF NOT EXISTS oauth_rate_limit_buckets_expiry_idx
121
- ON oauth_rate_limit_buckets(expires_at, scope, key_digest, window_start, window_seconds)`],L=[...M,...U,...g];async function B(e){if(await p(e,"PRAGMA foreign_keys = ON"),await p(e,"PRAGMA busy_timeout = 5000",!0),(await e.execute("SELECT name FROM pragma_table_info('oauth_codes')")).rows.some(r=>String(r.name)==="code"))throw new Error("Legacy raw OAuth tables require the explicit maintenance-mode coexistence migration");let s=(await e.execute("SELECT 1 present FROM sqlite_master WHERE type='table' AND name='oauth_store_metadata'")).rows.length>0?await e.execute("SELECT schema_version FROM oauth_store_metadata WHERE id=1"):void 0,a=s?.rows[0]?.schema_version==null?void 0:Number(s.rows[0].schema_version);if(a!==void 0&&(!Number.isSafeInteger(a)||a<1||a>3))throw new Error("OAuth store schema version cannot be migrated by this runtime");let o=a===void 0?L:a===1?[...U,...g]:a===2?g:[];for(let r of o)await e.execute(r);if(a!==void 0&&a<3&&(await e.execute({sql:`UPDATE oauth_store_metadata SET schema_version=?,updated_at=${u} WHERE id=1 AND schema_version=?`,args:[3,a]})).rowsAffected!==1)throw new Error("OAuth store schema version changed during migration");await p(e,"PRAGMA optimize",!0)}async function Z(e){await p(e,"PRAGMA foreign_keys = ON"),await p(e,"PRAGMA busy_timeout = 5000",!0);let t=await e.execute("SELECT name FROM pragma_table_info('oauth_codes')");if(!t.rows.some(o=>String(o.name)==="code")){let o=t.rows.some(r=>String(r.name)==="code_digest");return await B(e),o?"current":"created"}if((await e.execute({sql:"SELECT name FROM sqlite_master WHERE type='table' AND name IN (?,?,?)",args:Object.values(C)})).rows.length>0)throw new Error("Legacy OAuth archive names already exist; refusing ambiguous migration");let a=await e.transaction("write");try{for(let[o,r]of Object.entries(C))(await a.execute({sql:"SELECT 1 present FROM sqlite_master WHERE type='table' AND name=?",args:[o]})).rows.length>0&&await a.execute({sql:`ALTER TABLE ${o} RENAME TO ${r}`,args:[]});for(let o of L)await a.execute({sql:o,args:[]});await a.commit()}finally{a.close()}return"archived_legacy"}var P={oauth_store_metadata:["id","store_id","schema_version","authority_epoch","authority_state","updated_at"],oauth_clients:["client_id","client_name","client_type","token_endpoint_auth_method","status","created_at","last_used_at","expires_at"],oauth_client_redirect_uris:["client_id","redirect_uri","redirect_kind"],oauth_codes:["code_digest","lookup_key_id","client_id","redirect_uri","code_challenge","challenge_method","user_id","scope","resource","issued_at","expires_at"],oauth_code_exchanges:["code_digest","request_fingerprint","client_id","family_id","grant_scope","grant_resource","scope","resource","sealed_refresh","sealed_nonce","sealed_tag","replay_key_id","completed_at","replay_expires_at"],oauth_refresh_families:["family_id","user_id","client_id","issuer","scope","resource","status","current_generation","created_at","expires_at","revoked_at","compromised_at"],oauth_refresh_tokens:["family_id","generation","token_digest","lookup_key_id","token_prefix","predecessor_generation","issued_at","expires_at","used_at","revoked_at"],oauth_refresh_rotations:["family_id","predecessor_generation","request_fingerprint","successor_generation","sealed_successor","sealed_nonce","sealed_tag","replay_key_id","rotated_at","replay_expires_at"],oauth_security_events:["event_id","family_id","event_type","reason_code","occurred_at","retain_until"],oauth_rate_limit_buckets:["scope","key_digest","window_start","window_seconds","count","expires_at","updated_at"]},K={oauth_clients_inactivity_idx:["status","last_used_at","client_id"],oauth_clients_cleanup_idx:[null,"client_id"],oauth_codes_expiry_idx:["expires_at","code_digest"],oauth_codes_client_idx:["client_id","code_digest"],oauth_code_exchanges_replay_expiry_idx:["replay_expires_at","code_digest"],oauth_refresh_families_lifecycle_idx:["status","expires_at","family_id"],oauth_refresh_families_user_status_idx:["user_id","status"],oauth_refresh_families_client_idx:["client_id","family_id"],oauth_refresh_families_cleanup_idx:[null,"family_id"],oauth_refresh_tokens_expiry_idx:["expires_at","family_id","generation"],oauth_refresh_rotations_replay_expiry_idx:["replay_expires_at","family_id","predecessor_generation"],oauth_security_events_retention_idx:["retain_until","event_id"],oauth_rate_limit_buckets_expiry_idx:["expires_at","scope","key_digest","window_start","window_seconds"]};async function ee(e){let t=await e.execute({sql:`SELECT name FROM sqlite_master WHERE type = 'table' AND name IN (${m.map(()=>"?").join(",")})`,args:[...m]}),n=await e.execute({sql:`SELECT name FROM sqlite_master WHERE type = 'index' AND name IN (${h.map(()=>"?").join(",")})`,args:[...h]}),s=new Set(t.rows.map(i=>String(i.name))),a=new Set(n.rows.map(i=>String(i.name))),o=await e.execute("PRAGMA foreign_keys"),r=[],d=i=>i.replace(/\bIF\s+NOT\s+EXISTS\b/gi,"").replace(/\s+/g," ").trim().toLowerCase();for(let i of m){if(!s.has(i))continue;let _=(await e.execute(`PRAGMA table_info('${i}')`)).rows.map(T=>String(T.name));JSON.stringify(_)!==JSON.stringify(P[i])&&r.push(`${i}:columns`);let c=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='table' AND name=?",args:[i]}),l=String(c.rows[0]?.sql??""),N=L.find(T=>d(T).startsWith(`create table ${i} `));(!N||d(l)!==d(N))&&r.push(`${i}:definition`)}for(let i of h){if(!a.has(i))continue;let _=(await e.execute(`PRAGMA index_info('${i}')`)).rows.map(T=>T.name==null?null:String(T.name));JSON.stringify(_)!==JSON.stringify(K[i])&&r.push(`${i}:columns`);let c=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='index' AND name=?",args:[i]}),l=String(c.rows[0]?.sql??""),N=L.find(T=>d(T).startsWith(`create index ${i} `));(!N||d(l)!==d(N))&&r.push(`${i}:definition`)}return{ok:m.every(i=>s.has(i))&&h.every(i=>a.has(i))&&Number(o.rows[0]?.foreign_keys??0)===1&&r.length===0,missingTables:m.filter(i=>!s.has(i)),missingIndexes:h.filter(i=>!a.has(i)),foreignKeysEnabled:Number(o.rows[0]?.foreign_keys??0)===1,problems:r}}export{j as a,z as b,Z as c,ee as d};
@@ -1 +0,0 @@
1
- var o="0.97.1";export{o as a};