mcp-scraper 0.97.0 → 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 (97) hide show
  1. package/CHANGELOG.md +5 -2425
  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-NCZNPYEY.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-XR6XKYJM.js +0 -1
  22. package/dist/chunk-24YDQ3EO.js +0 -5
  23. package/dist/chunk-3F7AFM53.js +0 -1
  24. package/dist/chunk-4HZXATHB.js +0 -27
  25. package/dist/chunk-4P3LZNVA.js +0 -954
  26. package/dist/chunk-4ZVO6GX4.js +0 -1
  27. package/dist/chunk-55ZANTHL.js +0 -3
  28. package/dist/chunk-63VWBMYR.js +0 -3
  29. package/dist/chunk-6FAMBNHY.js +0 -1
  30. package/dist/chunk-6N5EC7ZO.js +0 -1
  31. package/dist/chunk-7POHNTVW.js +0 -1
  32. package/dist/chunk-7SR7MEU5.js +0 -62
  33. package/dist/chunk-A4UASMEQ.js +0 -1
  34. package/dist/chunk-AMYPXA2F.js +0 -930
  35. package/dist/chunk-ANQ4JJVI.js +0 -71
  36. package/dist/chunk-B3JRL45T.js +0 -1
  37. package/dist/chunk-B4ZKPLSP.js +0 -1
  38. package/dist/chunk-B5Y26E3A.js +0 -1
  39. package/dist/chunk-C7MGJUTU.js +0 -1
  40. package/dist/chunk-CNSVZTTT.js +0 -13
  41. package/dist/chunk-EYGA6LOU.js +0 -1
  42. package/dist/chunk-GLCR4KJI.js +0 -21722
  43. package/dist/chunk-HCK6PLM3.js +0 -3
  44. package/dist/chunk-HNNYXMSI.js +0 -1
  45. package/dist/chunk-IFPION5D.js +0 -121
  46. package/dist/chunk-JMZIDHYQ.js +0 -2
  47. package/dist/chunk-JNPM3U3L.js +0 -189
  48. package/dist/chunk-K3VDGJNK.js +0 -1
  49. package/dist/chunk-KJQXUZ4Y.js +0 -4
  50. package/dist/chunk-KXJCGV3H.js +0 -1
  51. package/dist/chunk-M5QHXNFZ.js +0 -10
  52. package/dist/chunk-MVMWPKRC.js +0 -2
  53. package/dist/chunk-NALXKTUU.js +0 -1
  54. package/dist/chunk-ND4WIBXT.js +0 -16
  55. package/dist/chunk-NNOX3FYG.js +0 -198
  56. package/dist/chunk-NULRGHJ4.js +0 -41
  57. package/dist/chunk-OILOHQNL.js +0 -2
  58. package/dist/chunk-OLYPLX5C.js +0 -1
  59. package/dist/chunk-OOB3RKWD.js +0 -4
  60. package/dist/chunk-OSKCHEVM.js +0 -218
  61. package/dist/chunk-PD7BI7TR.js +0 -12
  62. package/dist/chunk-PKQHHCO4.js +0 -20
  63. package/dist/chunk-PQRT4T2G.js +0 -159
  64. package/dist/chunk-QER2ELZP.js +0 -1
  65. package/dist/chunk-RDHGQ2WZ.js +0 -1
  66. package/dist/chunk-SDQW7IJN.js +0 -1
  67. package/dist/chunk-SEZETSB3.js +0 -1
  68. package/dist/chunk-U3NV72AL.js +0 -8
  69. package/dist/chunk-U4WIJZCX.js +0 -1
  70. package/dist/chunk-UIOSADPB.js +0 -1718
  71. package/dist/chunk-UNEJYZ4T.js +0 -102
  72. package/dist/chunk-VVSHZV5S.js +0 -73
  73. package/dist/chunk-WHVK6FUB.js +0 -11
  74. package/dist/chunk-WNUXMPVX.js +0 -1
  75. package/dist/chunk-XYUJTIPE.js +0 -203
  76. package/dist/chunk-YJPFEL2E.js +0 -1
  77. package/dist/chunk-Z4EHBBL4.js +0 -41
  78. package/dist/contracts-GUXGFCVV.js +0 -1
  79. package/dist/core-schema-Y47YFKH2.js +0 -899
  80. package/dist/dispatch-ILBBKOSW.js +0 -1
  81. package/dist/editorial-reading-room/assets/app.js +0 -433
  82. package/dist/editorial-reading-room/assets/index.html +0 -139
  83. package/dist/editorial-reading-room/assets/styles.css +0 -1091
  84. package/dist/index.d.cts +0 -607
  85. package/dist/media-artifacts-67CJWI7O.js +0 -1
  86. package/dist/metering-YHZ46GV4.js +0 -1
  87. package/dist/migrations-3AKEC5QE.js +0 -1
  88. package/dist/queue-VOGXQDPR.js +0 -1
  89. package/dist/reconciliation-OXBG7JA2.js +0 -1
  90. package/dist/report-artifact-offload-6OOY2PTM.js +0 -1
  91. package/dist/repository-CYXVMYAI.js +0 -1
  92. package/dist/repository-UKDA4IWP.js +0 -1
  93. package/dist/server-6HUBN3OR.js +0 -5547
  94. package/dist/settlement-3PS32LQO.js +0 -1
  95. package/dist/worker-NXRU3TT3.js +0 -1
  96. package/public/.well-known/xray-install.json +0 -183
  97. package/public/agent-install.md +0 -200
@@ -1 +0,0 @@
1
- import{load as w}from"cheerio";var T="script,style,noscript,svg,iframe,canvas,nav,header,footer,aside",_=4096;function l(r){return(r??"").replace(/\s+/g," ").trim()}function C(r){let e=r.replace(/[\x00-\x09\x0b\x0c\x0e-\x1f]/g," ").trim();if(!e)return null;try{return JSON.parse(e)}catch(a){let o=/at position (\d+)/.exec(a instanceof Error?a.message:"")?.[1];if(!o)return null;try{return JSON.parse(e.slice(0,Number(o)))}catch{return null}}}function f(r,e,a={value:2e3}){if(a.value--<=0||r==null)return;if(Array.isArray(r)){for(let d of r)f(d,e,a);return}if(typeof r!="object")return;let o=r,c=o["@type"];if(typeof c=="string"&&c&&e.add(c),Array.isArray(c))for(let d of c)typeof d=="string"&&d&&e.add(d);Array.isArray(o["@graph"])&&f(o["@graph"],e,a)}function N(r){let e=r("main").first();if(e.length)return e;let a=r("article").first();if(a.length)return a;let o=r("body").first();return o.length?o:r.root()}function x(r,e){let a=Number(r.attr(e)??0);return Number.isFinite(a)&&a>0?a:null}function P(r){let e=w(r),a={};e("meta").each((m,s)=>{let t=e(s),n=l(t.attr("name")??t.attr("property")).toLowerCase(),i=l(t.attr("content"));n&&i&&(a[n]=i)});let o=[];e("h1,h2,h3,h4,h5,h6").each((m,s)=>{let t=e(s),n=l(t.text());n&&o.push({level:Number(s.tagName.slice(1)),text:n})});let c=[],d=new Set;e('script[type="application/ld+json"]').each((m,s)=>{let t=C(e(s).text());t!=null&&(Array.isArray(t)?c.push(...t):c.push(t),f(t,d))});let g=new Set;e("[itemtype]").each((m,s)=>{let t=e(s).attr("itemtype")??"";for(let n of t.split(/\s+/))try{let i=new URL(n);if(i.hostname==="schema.org"||i.hostname==="www.schema.org"){let h=i.pathname.replace(/^\/+/,"");h&&g.add(h)}}catch{}});let u=N(e).clone();u.find(T).remove(),u.find("[href],[src],[srcset],[data-src],[data-srcset]").each((m,s)=>{let t=e(s);for(let n of["href","src","srcset","data-src","data-srcset"]){let i=t.attr(n);i&&i.length>_&&t.removeAttr(n)}}),u.find("img").each((m,s)=>{let t=e(s),n=t.attr("src");if(!n||n.startsWith("data:")){let i=t.attr("data-src")??t.attr("data-lazy-src")??t.attr("data-original");i&&t.attr("src",i)}});let b=u.html()??"",A=l(u.text()),p=[];e("a[href]").each((m,s)=>{let t=e(s),n=l(t.attr("href"));n&&p.push({href:n,text:l(t.text()),rel:l(t.attr("rel")).toLowerCase()||null})});let y=[];return e("img").each((m,s)=>{let t=e(s),n=Object.fromEntries(Object.entries(s.attribs??{}).map(([i,h])=>[i.toLowerCase(),h]));y.push({src:t.attr("src")??t.attr("data-src")??t.attr("data-lazy-src")??t.attr("data-original")??null,srcset:t.attr("srcset")??t.attr("data-srcset")??null,alt:t.attr("alt")??null,width:x(t,"width"),height:x(t,"height"),attributes:n})}),{$:e,sourceHtml:r,title:l(e("title").first().text())||null,meta:a,headings:o,schema:c,schemaTypes:[...d],microdataTypes:[...g],canonicalUrl:l(e('link[rel~="canonical"]').first().attr("href"))||null,mainHtml:b,mainText:A,bodyClass:e("body").first().attr("class")??"",links:p,images:y}}export{P as a};
@@ -1,4 +0,0 @@
1
- import{$ as E,B as R,D as v,Fa as C,Ga as P,Y as S,_ as T,ha as w,ja as h,ka as _,la as y,x as f,y as u,z as g}from"./chunk-4P3LZNVA.js";import{a as x}from"./chunk-ND4WIBXT.js";import{a as c}from"./chunk-6FAMBNHY.js";import{readFileSync as L}from"fs";import{homedir as B}from"os";import{join as U}from"path";import{serveStdio as Y}from"@modelcontextprotocol/server/stdio";import{McpServer as J}from"@modelcontextprotocol/server";var I=new Map(_.map(r=>[r.upstreamName,r.id]));function N(r){let s=r.split(`
2
- `).filter(t=>t.startsWith("data:")).map(t=>t.slice(5).trim()).filter(Boolean);if(!s.length)return JSON.parse(r);for(let t of s){let e=JSON.parse(t);if(e.result||e.error)return e}throw new Error("hosted MCP returned no JSON-RPC result")}function l(r){return{content:[{type:"text",text:JSON.stringify({ok:!1,error:r})}],isError:!0}}var p=class{baseUrl;apiKey;constructor(s,t){this.baseUrl=s.replace(/\/$/,""),this.apiKey=t}async callMemoryTool(s,t){let e=I.get(s);if(!e)return l(`unknown memory tool: ${s}`);try{let n=await fetch(`${this.baseUrl}/mcp`,{method:"POST",headers:{"content-type":"application/json",accept:"application/json, text/event-stream","x-api-key":this.apiKey},body:JSON.stringify({jsonrpc:"2.0",id:`memory:${e}`,method:"tools/call",params:{name:e,arguments:t}})}),i=await n.text();if(!n.ok)return l(`hosted memory ${e} failed (HTTP ${n.status})`);let o=N(i);return o.error?l(o.error.message??`hosted memory ${e} failed`):o.result??l(`hosted memory ${e} returned no result`)}catch(n){return l(n instanceof Error?n.message:`hosted memory ${e} call failed`)}}};function M(r,s){if(s.length===0)throw new Error("Restricted MCP tool allowlist must contain at least one tool name");let t=new Set;for(let o of s){if(typeof o!="string"||o.trim()!==o||o.length===0)throw new Error("Restricted MCP tool allowlist contains a malformed tool name");if(t.has(o))throw new Error(`Restricted MCP tool allowlist contains duplicate tool name: ${o}`);t.add(o)}let e=new Set,n=r,i=n.registerTool.bind(r);return n.registerTool=(o,a,m)=>{if(t.has(o))return e.add(o),i(o,a,m)},{assertComplete(){let o=[...t].filter(a=>!e.has(a));if(o.length>0)throw new Error(`Restricted MCP tool allowlist contains unknown or unavailable tool names: ${o.join(", ")}`)},registeredToolNames(){return[...e]}}}import{Client as b,StreamableHTTPClientTransport as k}from"@modelcontextprotocol/client";var $=new Set(["artifact_read","artifact_describe","artifact_download","report_artifact_read"]),A=()=>({content:[{type:"text",text:"Retained file storage is unavailable. Preserve the artifactId and retry retrieval; do not repeat acquisition."}],isError:!0});function O(r,s,t={}){return async(e,n)=>{if(!$.has(e))return A();let i=new b({name:"mcp-scraper-artifact-client",version:c},{versionNegotiation:{mode:"auto"}}),o=AbortSignal.timeout(3e4);try{let a=new k(new URL(`${r.replace(/\/$/,"")}/mcp`),{requestInit:{signal:o,headers:{Authorization:`Bearer ${s}`,"x-api-key":s,...t.localNetworkAccess?{"x-mcp-scraper-local-network":"1"}:{}}}});return await i.connect(a,{signal:o,timeout:3e4}),await i.callTool({name:e,arguments:n},{signal:o,timeout:3e4})}catch{return A()}finally{await i.close().catch(()=>{})}}}var G=new Set(["paa","serp","browser-agent","artifact-templates","memory"]);function K(){let s=[process.env.MCP_SCRAPER_KEY_PATH?.trim(),U(B(),".mcp-scraper-key")].filter(Boolean);for(let t of s)try{let e=L(t,"utf8").trim();if(e)return e}catch{}}function j(r,s={}){let t=s.toolsets??G,e=process.env.MCP_SCRAPER_BASE_URL?.trim()||process.env.MCP_BASE_URL?.trim()||"https://mcpscraper.dev",n=R(),i=v({deploymentProfile:n,transportProfile:"stdio",baseUrl:e,explicitlyEnabled:process.env.MCP_SCRAPER_ALLOW_PRIVATE_NETWORK==="1"}),o=process.env.BROWSER_AGENT_CONSOLE_URL?.trim()||e,a=new J({name:"mcp-scraper",version:c},{instructions:u,cacheHints:{"server/discover":{ttlMs:3e5,cacheScope:"private"},"tools/list":{ttlMs:3e5,cacheScope:"private"},"prompts/list":{ttlMs:3e5,cacheScope:"private"},"resources/list":{ttlMs:3e5,cacheScope:"private"},"resources/templates/list":{ttlMs:3e5,cacheScope:"private"},"resources/read":{ttlMs:6e4,cacheScope:"private"}}});g(a);let m=s.allowedToolNames?M(a,s.allowedToolNames):void 0,d=s.httpExecutor??new w(e,r,{localNetworkAccess:i,analyticsIdentity:()=>E(a.server.getClientVersion()?.name)});return t.has("paa")&&T(a,d,{ownerId:S(r),deploymentProfile:n,transportProfile:"stdio",baseUrl:e,localNetworkAccess:i,taskHandleSecret:r,remoteArtifactAccess:O(e,r,{localNetworkAccess:i})}),t.has("serp")&&f(a,d,{exposeDevelopmentDiagnostics:n==="development"||n==="test"}),t.has("browser-agent")&&h(a,{baseUrl:e,apiKey:r,consoleBaseUrl:o}),t.has("artifact-templates")&&P(a,new C(e,r)),t.has("memory")&&y(a,new p(e,r)),m?.assertComplete(),a}function Re(r={}){let s=process.argv.includes("--stdio")||process.env.MCP_SCRAPER_FORCE_STDIO==="1",t=!!(process.stdin.isTTY&&process.stdout.isTTY),e=process.argv.includes("--help")||process.argv.includes("-h");if(!s&&(t||e)){let i=process.argv.includes("--no-color")||process.env.NO_COLOR!==void 0||process.env.FORCE_COLOR==="0"||!process.stdout.isTTY;process.stdout.write(x({version:c,color:!i,apiKeyConfigured:!!process.env.MCP_SCRAPER_API_KEY?.trim()}),()=>process.exit(0));return}let n=(process.env.MCP_SCRAPER_API_KEY??process.env.MCP_SCRAPER_KEY??process.env.MCP_API_KEY??K())?.trim();n||(process.stderr.write(`MCP_SCRAPER_API_KEY env var or ~/.mcp-scraper-key is required
3
- `),process.exit(1)),Y(()=>j(n,r),{legacy:"serve",onerror(i){process.stderr.write(`${i.message}
4
- `)}})}export{Re as a};
@@ -1,218 +0,0 @@
1
- import{a as _,b as N,c as I}from"./chunk-U3NV72AL.js";import{a as u}from"./chunk-WNUXMPVX.js";var y="2026-06-26 21:58:03";var k="+3 months";function D(t){return{sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, expires_at)
2
- SELECT ?, legacy.balance_mc, legacy.balance_mc, 'migration', datetime('now', ?)
3
- FROM (
4
- SELECT COALESCE(SUM(amount_mc), 0) AS balance_mc
5
- FROM ledger
6
- WHERE user_id = ?
7
- ) AS legacy
8
- WHERE legacy.balance_mc > 0
9
- AND EXISTS (
10
- SELECT 1 FROM ledger
11
- WHERE user_id = ? AND created_at < ?
12
- )
13
- AND NOT EXISTS (
14
- SELECT 1 FROM credit_lots WHERE user_id = ?
15
- )`,args:[t,k,t,t,y,t]}}async function O(t){return(await u().execute(D(t))).rowsAffected}import{createHash as T,randomUUID as A}from"crypto";var R="(CAST(strftime('%s', 'now') AS INTEGER) * 1000)",f="operation-debit:",w=t=>t==="execute"?"e.phase = 'effects_started' AND r.status = 'running'":"e.phase = 'unknown' AND r.status = 'unknown'";function C(t,e,r){if(!r){if(e.startsWith(f))throw new _;return}if(r.userId!==t||!r.runId||!r.token||!["execute","compensate"].includes(r.mode))throw new _}var W=t=>String(t).includes("operation_wallet_claim_current");function h(t,e,r,i){if(C(t,e,r),!r){let a=A(),d="NOT EXISTS (SELECT 1 FROM operation_debit_plans WHERE debit_key = ?)";return{before:[{sql:`INSERT INTO operation_wallet_fences (id, allowed)
16
- SELECT ?, CASE WHEN ${d} THEN 1 ELSE 0 END`,args:[a,e]}],after:[{sql:"DELETE FROM operation_wallet_fences WHERE id = ?",args:[a]}],current:async p=>!!(await p.execute({sql:`SELECT ${d} AS allowed`,args:[e]})).rows[0]?.allowed}}if(i.kind==="debit"&&r.mode!=="execute"||r.mode==="compensate"&&i.amountMc!==0&&!r.settlementPlanId)throw new _;let n=r.settlementPlanId?" AND EXISTS (SELECT 1 FROM operation_final_settlements s WHERE s.id=? AND s.run_id=p.run_id AND s.user_id=r.user_id AND s.debit_key=p.debit_key AND s.final_amount_mc=? AND s.refund_operation=? AND s.source_surface=?)":"",l=`SELECT 1 FROM operation_debit_plans p
17
- JOIN operation_runs r ON r.id = p.run_id JOIN operation_executions e ON e.run_id = r.id
18
- WHERE p.debit_key = ? AND r.id = ? AND r.user_id = ? AND e.claim_token = ?
19
- AND e.expires_at_ms > ${R} AND ${w(r.mode)}
20
- AND ${i.kind==="debit"?"p.amount_mc = ? AND p.operation = ? AND p.description = ?":"p.refund_operation = ? AND p.source_surface = ?"}${n}`,c=[e,r.runId,t,r.token,...i.kind==="debit"?[i.amountMc,i.operation,i.description]:[i.operation,i.sourceSurface],...r.settlementPlanId?[r.settlementPlanId,i.amountMc,i.operation,i.sourceSurface]:[]],o=A(),s=i.kind==="debit"?{sql:`INSERT OR IGNORE INTO operation_billing_links (run_id, billing_table, billing_key, relation, amount_mc)
21
- SELECT p.run_id, 'billing_debits', d.idempotency_key, 'debit', d.amount_mc FROM operation_debit_plans p
22
- JOIN billing_debits d ON d.idempotency_key = p.debit_key
23
- WHERE p.debit_key = ? AND d.user_id = ? AND d.status = 'applied'`,args:[e,t]}:{sql:`INSERT OR IGNORE INTO operation_billing_links (run_id, billing_table, billing_key, relation, amount_mc)
24
- SELECT p.run_id, 'billing_events', b.id, 'settlement', b.amount_mc FROM operation_debit_plans p
25
- JOIN billing_events b ON b.idempotency_key = ?
26
- WHERE p.debit_key = ? AND b.user_id = ? AND b.status = 'settled'`,args:[`debit-settlement:${T("sha256").update(e).digest("hex")}`,e,t]};return{before:[{sql:`INSERT INTO operation_wallet_fences (id, allowed)
27
- SELECT ?, CASE WHEN EXISTS (${l}) THEN 1 ELSE 0 END`,args:[o,...c]},D(t)],after:[s,{sql:"DELETE FROM operation_wallet_fences WHERE id = ?",args:[o]}],current:async a=>(await a.execute({sql:l,args:c})).rows.length===1}}function M(t){return{label:String(t.label),key:String(t.debit_key),amountMc:Number(t.amount_mc),operation:String(t.operation),description:String(t.description),refundOperation:String(t.refund_operation),sourceSurface:String(t.source_surface)}}async function X(t,e){if(t.mode!=="execute"||!Number.isSafeInteger(e.amountMc)||e.amountMc<=0||!e.label||e.label.length>200||!e.operation||!e.refundOperation||!e.sourceSurface)throw new N;let r=u(),i=f+A();C(t.userId,i,t);let n=`EXISTS (SELECT 1 FROM operation_runs r JOIN operation_executions e ON e.run_id = r.id
28
- WHERE r.id = ? AND r.user_id = ? AND e.claim_token = ? AND e.expires_at_ms > ${R}
29
- AND ${w("execute")})`,l=[t.runId,t.userId,t.token],c;try{await r.batch([{sql:`INSERT OR IGNORE INTO operation_debit_plans
30
- (run_id, label, debit_key, amount_mc, operation, description, refund_operation, source_surface)
31
- SELECT ?, ?, ?, ?, ?, ?, ?, ? WHERE ${n}`,args:[t.runId,e.label,i,e.amountMc,e.operation,e.description,e.refundOperation,e.sourceSurface,...l]},{sql:`UPDATE operation_debit_plans SET amount_mc = ? WHERE run_id = ? AND label = ?
32
- AND operation = ? AND description = ? AND refund_operation = ? AND source_surface = ? AND ${n}
33
- AND EXISTS (SELECT 1 FROM billing_debits d WHERE d.idempotency_key = operation_debit_plans.debit_key
34
- AND d.user_id = ? AND d.status = 'claimed' AND d.amount_mc = operation_debit_plans.amount_mc
35
- AND d.operation = operation_debit_plans.operation AND d.description = operation_debit_plans.description)`,args:[e.amountMc,t.runId,e.label,e.operation,e.description,e.refundOperation,e.sourceSurface,...l,t.userId]}],"write")}catch(a){c=a}let o;try{o=(await r.execute({sql:`SELECT p.* FROM operation_debit_plans p WHERE p.run_id = ? AND p.label = ? AND ${n}`,args:[t.runId,e.label,...l]})).rows[0]}catch(a){throw c??a}if(!o)throw c||new _;let s=M(o);if(s.amountMc!==e.amountMc||s.operation!==e.operation||s.description!==e.description||s.refundOperation!==e.refundOperation||s.sourceSurface!==e.sourceSurface)throw new N;return s}async function B(t){C(t.userId,f,t);let e=u();if(!(await e.execute({sql:`SELECT 1 FROM operation_executions e JOIN operation_runs r ON r.id = e.run_id
36
- WHERE r.id = ? AND r.user_id = ? AND e.claim_token = ? AND e.expires_at_ms > ${R}
37
- AND ${w(t.mode)}`,args:[t.runId,t.userId,t.token]})).rows.length)throw new _;return(await e.execute({sql:"SELECT * FROM operation_debit_plans WHERE run_id = ? ORDER BY label",args:[t.runId]})).rows.map(M)}async function j(t,e){let i=(await u().execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? AND user_id = ? LIMIT 1",args:[e,t]})).rows[0];return i?{amountMc:Number(i.amount_mc),operation:String(i.operation),description:String(i.description),status:String(i.status)}:null}async function J(t,e,r,i,n,l){if(!Number.isSafeInteger(e)||e<=0)throw new Error("idempotent debit amount must be a positive integer");if(!n||n.length>500)throw new Error("idempotent debit key is required and must be bounded");let c=u(),o=h(t,n,l,{kind:"debit",amountMc:e,operation:r,description:i});l||await O(t);let s;try{s=await c.batch([...o.before,{sql:"UPDATE billing_debits SET amount_mc = ? WHERE idempotency_key = ? AND user_id = ? AND operation = ? AND description = ? AND status = 'claimed'",args:[e,n,t,r,i]},{sql:"INSERT OR IGNORE INTO billing_debits (idempotency_key, user_id, amount_mc, operation, description, status) VALUES (?, ?, ?, ?, ?, 'claimed')",args:[n,t,e,r,i]},{sql:`UPDATE users
38
- SET balance_mc = balance_mc - ?
39
- WHERE id = ?
40
- AND balance_mc >= ?
41
- AND (SELECT COALESCE(SUM(remaining_mc), 0)
42
- FROM credit_lots
43
- WHERE user_id = ?
44
- AND remaining_mc > 0
45
- AND (never_expires = 1 OR expires_at > datetime('now'))) >= ?
46
- AND EXISTS (SELECT 1 FROM billing_debits WHERE idempotency_key = ? AND user_id = ? AND amount_mc = ? AND operation = ? AND description = ? AND status = 'claimed')`,args:[e,t,e,t,e,n,t,e,r,i]},{sql:"UPDATE billing_debits SET status = 'applying' WHERE idempotency_key = ? AND user_id = ? AND amount_mc = ? AND operation = ? AND description = ? AND status = 'claimed' AND changes() = 1",args:[n,t,e,r,i]},{sql:`INSERT OR IGNORE INTO billing_debit_allocations
47
- (debit_idempotency_key, lot_id, user_id, amount_mc, expires_at)
48
- WITH ordered AS MATERIALIZED (
49
- SELECT id,
50
- remaining_mc,
51
- expires_at,
52
- COALESCE(SUM(remaining_mc) OVER (
53
- ORDER BY never_expires ASC, expires_at ASC, granted_at ASC, id ASC
54
- ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
55
- ), 0) AS prior_mc
56
- FROM credit_lots
57
- WHERE user_id = ? AND remaining_mc > 0 AND (never_expires = 1 OR expires_at > datetime('now'))
58
- ), allocation AS (
59
- SELECT id, expires_at, MIN(remaining_mc, MAX(0, ? - prior_mc)) AS take_mc
60
- FROM ordered
61
- )
62
- SELECT ?, id, ?, take_mc, expires_at
63
- FROM allocation
64
- WHERE take_mc > 0
65
- AND EXISTS (SELECT 1 FROM billing_debits WHERE idempotency_key = ? AND status = 'applying')`,args:[t,e,n,t,n]},{sql:`UPDATE credit_lots
66
- SET remaining_mc = remaining_mc - COALESCE((
67
- SELECT amount_mc FROM billing_debit_allocations
68
- WHERE debit_idempotency_key = ? AND lot_id = credit_lots.id
69
- ), 0)
70
- WHERE id IN (
71
- SELECT lot_id FROM billing_debit_allocations WHERE debit_idempotency_key = ?
72
- )
73
- AND EXISTS (SELECT 1 FROM billing_debits WHERE idempotency_key = ? AND status = 'applying')`,args:[n,n,n]},{sql:"INSERT INTO ledger (user_id, amount_mc, operation, description) SELECT user_id, -amount_mc, operation, description FROM billing_debits WHERE idempotency_key = ? AND status = 'applying'",args:[n]},{sql:"UPDATE billing_debits SET status = 'applied', applied_at = datetime('now') WHERE idempotency_key = ? AND status = 'applying'",args:[n]},...o.after],"write")}catch(b){if(W(b))throw new _;try{if(!await o.current(c))throw new _;let E=(await c.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? AND status = 'applied' LIMIT 1",args:[n]})).rows[0];if(E&&Number(E.user_id)===t&&Number(E.amount_mc)===e&&String(E.operation)===r&&String(E.description)===i){let S=await c.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[t]});return{ok:!0,balance_mc:Number(S.rows[0]?.balance_mc??0),duplicate:!0}}}catch(m){if(m instanceof _)throw m}throw b}let d=(await c.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? LIMIT 1",args:[n]})).rows[0];if(!d||Number(d.user_id)!==t||Number(d.amount_mc)!==e||String(d.operation)!==r||String(d.description)!==i)throw new Error("idempotent debit key conflicts with another debit");let p=await c.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[t]});return{ok:String(d.status)==="applied",balance_mc:Number(p.rows[0]?.balance_mc??0),duplicate:s[2+o.before.length]?.rowsAffected===0&&String(d.status)==="applied"}}async function V(t,e,r,i,n,l,c){if(!Number.isSafeInteger(r)||r<0)throw new Error("idempotent debit settlement amount must be a non-negative integer");if(!e||e.length>500)throw new Error("idempotent debit settlement key is required and must be bounded");if(!i||!l)throw new Error("idempotent debit settlement operation and source are required");let o=u(),s=h(t,e,c,{kind:"settlement",amountMc:r,operation:i,description:n,sourceSurface:l});c||await O(t);let a=`debit-settlement:${T("sha256").update(e).digest("hex")}`,d="wallet_hold_settlement",p=A(),b=JSON.stringify({debitIdempotencyKey:e,refundOperation:i,description:n}),m=()=>x(t,e,l),E;try{E=await o.batch([...s.before,{sql:`INSERT OR IGNORE INTO billing_events
74
- (id, user_id, idempotency_key, billing_class, source_surface, status, amount_mc, metadata)
75
- VALUES (?, ?, ?, ?, ?, 'settling', ?, ?)`,args:[p,t,a,d,l,r,b]},{sql:`WITH ordered AS (
76
- SELECT a.lot_id,
77
- a.amount_mc,
78
- a.expires_at,
79
- COALESCE(SUM(a.amount_mc) OVER (
80
- ORDER BY a.expires_at ASC, a.lot_id ASC
81
- ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
82
- ), 0) AS prior_mc
83
- FROM billing_debit_allocations a
84
- WHERE a.debit_idempotency_key = ?
85
- ), refunds AS (
86
- SELECT lot_id,
87
- expires_at,
88
- amount_mc - MIN(amount_mc, MAX(0, ? - prior_mc)) AS refund_mc
89
- FROM ordered
90
- )
91
- UPDATE users
92
- SET balance_mc = balance_mc + CASE
93
- WHEN EXISTS (SELECT 1 FROM ordered) THEN COALESCE(
94
- (SELECT SUM(refund_mc) FROM refunds WHERE expires_at > datetime('now')),
95
- 0
96
- )
97
- -- Holds created before allocation provenance cannot be safely
98
- -- tied back to a source lot. Treat their unused portion as
99
- -- expired instead of minting spendable credits with a guessed
100
- -- expiry.
101
- ELSE 0
102
- END
103
- WHERE id = ?
104
- AND EXISTS (
105
- SELECT 1
106
- FROM billing_events e
107
- JOIN billing_debits d ON d.idempotency_key = ?
108
- WHERE e.idempotency_key = ?
109
- AND e.user_id = ?
110
- AND e.billing_class = ?
111
- AND e.source_surface = ?
112
- AND e.status = 'settling'
113
- AND d.user_id = e.user_id
114
- AND d.status = 'applied'
115
- AND e.amount_mc BETWEEN 0 AND d.amount_mc
116
- )`,args:[e,r,t,e,a,t,d,l]},{sql:`UPDATE billing_events
117
- SET status = 'applying'
118
- WHERE idempotency_key = ?
119
- AND user_id = ?
120
- AND billing_class = ?
121
- AND source_surface = ?
122
- AND status = 'settling'
123
- AND changes() = 1`,args:[a,t,d,l]},{sql:`WITH ordered AS (
124
- SELECT a.lot_id,
125
- a.amount_mc,
126
- a.expires_at,
127
- COALESCE(SUM(a.amount_mc) OVER (
128
- ORDER BY a.expires_at ASC, a.lot_id ASC
129
- ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
130
- ), 0) AS prior_mc
131
- FROM billing_debit_allocations a
132
- WHERE a.debit_idempotency_key = ?
133
- ), refunds AS (
134
- SELECT lot_id,
135
- expires_at,
136
- amount_mc - MIN(amount_mc, MAX(0, ? - prior_mc)) AS refund_mc
137
- FROM ordered
138
- )
139
- UPDATE credit_lots
140
- SET remaining_mc = remaining_mc + COALESCE((SELECT refund_mc FROM refunds WHERE refunds.lot_id = credit_lots.id), 0)
141
- WHERE id IN (
142
- SELECT lot_id FROM refunds
143
- WHERE refund_mc > 0 AND expires_at > datetime('now')
144
- )
145
- AND EXISTS (SELECT 1 FROM billing_events WHERE idempotency_key = ? AND status = 'applying')`,args:[e,r,a]},{sql:`WITH ordered AS (
146
- SELECT a.amount_mc,
147
- a.expires_at,
148
- COALESCE(SUM(a.amount_mc) OVER (
149
- ORDER BY a.expires_at ASC, a.lot_id ASC
150
- ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
151
- ), 0) AS prior_mc
152
- FROM billing_debit_allocations a
153
- WHERE a.debit_idempotency_key = ?
154
- ), refunds AS (
155
- SELECT expires_at,
156
- amount_mc - MIN(amount_mc, MAX(0, ? - prior_mc)) AS refund_mc
157
- FROM ordered
158
- ), credited AS (
159
- SELECT e.user_id,
160
- CASE
161
- WHEN EXISTS (SELECT 1 FROM ordered) THEN COALESCE(
162
- (SELECT SUM(refund_mc) FROM refunds WHERE expires_at > datetime('now')),
163
- 0
164
- )
165
- ELSE 0
166
- END AS refund_mc
167
- FROM billing_events e
168
- JOIN billing_debits d ON d.idempotency_key = ?
169
- WHERE e.idempotency_key = ?
170
- AND e.status = 'applying'
171
- )
172
- INSERT INTO ledger (user_id, amount_mc, operation, description)
173
- SELECT user_id,
174
- refund_mc,
175
- ?,
176
- ?
177
- FROM credited
178
- WHERE refund_mc > 0`,args:[e,r,e,a,i,n]},{sql:`UPDATE billing_events
179
- SET status = 'settled', settled_at = datetime('now')
180
- WHERE idempotency_key = ?
181
- AND status = 'applying'`,args:[a]},...s.after],"write")}catch(L){if(W(L))throw new _;try{if(!await s.current(o))throw new _;let g=await m();if(g)return g}catch(g){if(g instanceof _)throw g}throw L}let S=await m();if(!S)throw new Error("idempotent debit settlement did not reach a durable settled state");return{...S,duplicate:E[s.before.length]?.rowsAffected===0}}async function Y(t,e){let{hold:r}=e,i=I(r);if(r.userId!==t.userId||!t.runId||!t.token||!e.label||e.label.length>200||!e.refundOperation||!e.sourceSurface||!e.tool||!e.jobId)throw new N;let n=`EXISTS (SELECT 1 FROM operation_runs r JOIN operation_executions e ON e.run_id=r.id
182
- WHERE r.id=? AND r.user_id=? AND r.tool=? AND r.job_id=? AND r.status='running'
183
- AND json_extract(r.normalized_flags_json,'$._storeGateRequired') IS 1
184
- AND e.claim_token=? AND e.phase='claimed' AND e.expires_at_ms > ${R})`,l=[t.runId,t.userId,e.tool,e.jobId,t.token],c=u(),o;try{await c.batch([{sql:`INSERT OR IGNORE INTO operation_debit_plans
185
- (run_id,label,debit_key,amount_mc,operation,description,refund_operation,source_surface)
186
- SELECT ?,?,?,?,?,?,?,? WHERE ${n} AND (${i.sql})`,args:[t.runId,e.label,r.key,r.amountMc,r.operation,r.description,e.refundOperation,e.sourceSurface,...l,...i.args]},{sql:`INSERT OR IGNORE INTO operation_billing_links (run_id,billing_table,billing_key,relation,amount_mc)
187
- SELECT p.run_id,'billing_debits',p.debit_key,'hold',p.amount_mc FROM operation_debit_plans p
188
- WHERE p.run_id=? AND p.label=? AND p.debit_key=? AND p.amount_mc=? AND p.operation=? AND p.description=?
189
- AND p.refund_operation=? AND p.source_surface=? AND ${n} AND (${i.sql})`,args:[t.runId,e.label,r.key,r.amountMc,r.operation,r.description,e.refundOperation,e.sourceSurface,...l,...i.args]}],"write")}catch(d){o=d}let s;try{s=(await c.execute({sql:`SELECT p.* FROM operation_debit_plans p
190
- WHERE p.run_id=? AND p.label=? AND ${n} AND (${i.sql})`,args:[t.runId,e.label,...l,...i.args]})).rows[0]}catch(d){throw o??d}if(!s)throw o||new _;let a=M(s);if(a.key!==r.key||a.amountMc!==r.amountMc||a.operation!==r.operation||a.description!==r.description||a.refundOperation!==e.refundOperation||a.sourceSurface!==e.sourceSurface)throw new N;return a}async function x(t,e,r){if(!Number.isSafeInteger(t)||t<=0||!e||!r)throw new _;let i=u(),n=`debit-settlement:${T("sha256").update(e).digest("hex")}`,l="wallet_hold_settlement",o=(await i.execute({sql:`SELECT e.user_id,
191
- e.status,
192
- e.amount_mc AS final_amount_mc,
193
- e.billing_class,
194
- e.source_surface,
195
- e.settled_at,
196
- d.amount_mc AS held_amount_mc
197
- FROM billing_events e
198
- JOIN billing_debits d ON d.idempotency_key = ?
199
- WHERE e.idempotency_key = ?
200
- AND d.user_id = e.user_id
201
- AND d.status = 'applied'
202
- LIMIT 1`,args:[e,n]})).rows[0];if(!o)return null;if(Number(o.user_id)!==t||String(o.billing_class)!==l||String(o.source_surface)!==r)throw new Error("idempotent debit settlement key conflicts with another settlement");if(String(o.status)!=="settled")return null;let s=Number(o.held_amount_mc),a=Number(o.final_amount_mc);if(!Number.isSafeInteger(s)||!Number.isSafeInteger(a)||a<0||a>s)throw new Error("idempotent debit settlement receipt is invalid");let d=s-a,p=await i.execute({sql:`WITH ordered AS (
203
- SELECT a.amount_mc,
204
- a.expires_at,
205
- COALESCE(SUM(a.amount_mc) OVER (
206
- ORDER BY a.expires_at ASC, a.lot_id ASC
207
- ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
208
- ), 0) AS prior_mc
209
- FROM billing_debit_allocations a
210
- WHERE a.debit_idempotency_key = ?
211
- ), refunds AS (
212
- SELECT expires_at,
213
- amount_mc - MIN(amount_mc, MAX(0, ? - prior_mc)) AS refund_mc
214
- FROM ordered
215
- )
216
- SELECT (SELECT COUNT(*) FROM ordered) AS allocation_count,
217
- COALESCE(SUM(CASE WHEN expires_at > ? THEN refund_mc ELSE 0 END), 0) AS credited_refund_mc
218
- FROM refunds`,args:[e,a,String(o.settled_at)]}),m=Number(p.rows[0]?.allocation_count??0)>0?Number(p.rows[0]?.credited_refund_mc??0):0,E=await i.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[t]});return{balance_mc:Number(E.rows[0]?.balance_mc??0),final_amount_mc:a,refund_mc:m,expired_refund_mc:d-m,duplicate:!0}}export{k as a,O as b,X as c,B as d,j as e,J as f,V as g,Y as h,x as i};
@@ -1,12 +0,0 @@
1
- import{a as D,c as A,d as T,e as C,f as w,g as p}from"./chunk-OSKCHEVM.js";import{C as k,D as x,E as v,b as E,g,y as I}from"./chunk-JNPM3U3L.js";import{e as P,f as S}from"./chunk-U3NV72AL.js";import{a as _}from"./chunk-WNUXMPVX.js";import{randomUUID as O}from"crypto";var L=class{constructor(t,r,i){this.userId=t;this.sourceSurface=r;this.fence=i;if(i&&i.userId!==t)throw Error("Billing scope principal differs from execution claim")}userId;sourceSurface;fence;identity=`debit:${O()}`;charges=new Map;pending=new Map;compensating=new Set;closing=!1;async debit(t,r,i,c,a){if(this.closing||this.compensating.has(t))throw Error("Billing scope is compensating; new charges are forbidden");let s=this.charges.get(t);if(s?.outcome==="pending")throw Error("Named debit outcome is pending; reconcile before retrying");if(s?.outcome==="funded"&&s.amountMc!==r)throw Error("An applied debit amount cannot change");let o={key:s?.key??`${this.identity}:${t}`,amountMc:r,operation:i,description:c,refundOperation:a,outcome:"pending"};if(s&&(s.operation!==i||s.description!==c||s.refundOperation!==a))throw Error("Named charge identity cannot change");this.charges.set(t,o);let u=(async()=>{if(this.fence){let f=await A(this.fence,{label:t,amountMc:r,operation:i,description:c,refundOperation:a,sourceSurface:this.sourceSurface});if(o.key=f.key,this.closing||this.compensating.has(t))throw Error("Billing scope began compensating while planning")}return this.fence?w(this.userId,r,i,c,o.key,this.fence):w(this.userId,r,i,c,o.key)})();this.pending.set(t,u);try{let f=await u;return o.outcome=f.ok?"funded":"unfunded",{...f,billingKey:o.key}}finally{this.pending.delete(t)}}async compensate(t){this.compensating.add(t),await this.pending.get(t)?.catch(()=>{});try{this.fence&&await this.loadDurablePlans();let r=this.charges.get(t);if(!r)return"not_charged";let i=await C(this.userId,r.key);return i?i.amountMc!==r.amountMc||i.operation!==r.operation||i.description!==r.description?"refund_pending":i.status==="claimed"?this.fence?.mode==="compensate"||r.outcome==="unfunded"?"not_charged":"refund_pending":i.status!=="applied"?"refund_pending":(this.fence?await p(this.userId,r.key,0,r.refundOperation,`${this.sourceSurface} failed`,this.sourceSurface,this.fence):await p(this.userId,r.key,0,r.refundOperation,`${this.sourceSurface} failed`,this.sourceSurface)).final_amount_mc===0?"refunded":"refund_pending":this.fence?.mode==="compensate"||r.outcome==="unfunded"?"not_charged":"refund_pending"}catch{return"refund_pending"}}async compensateAll(){if(this.closing=!0,await Promise.allSettled([...this.pending.values()]),this.fence)try{await this.loadDurablePlans()}catch{return"refund_pending"}let t=await Promise.all([...this.charges.keys()].map(r=>this.compensate(r)));return t.includes("refund_pending")?"refund_pending":t.includes("refunded")?"refunded":"not_charged"}async loadDurablePlans(){if(this.fence)for(let t of await T(this.fence)){let r=this.charges.get(t.label);if(t.sourceSurface!==this.sourceSurface)throw Error("Persisted billing source differs from scope");this.charges.set(t.label,{key:t.key,amountMc:t.amountMc,operation:t.operation,description:t.description,refundOperation:t.refundOperation,outcome:r?.key===t.key?r.outcome:"pending"})}}};async function H(e){if(!Number.isSafeInteger(e.userId)||e.userId<=0||!Number.isSafeInteger(e.refundMc)||e.refundMc<0)throw Error("invalid_legacy_refund");await _().batch([e.admission,{sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, expires_at)
2
- SELECT ?, ?, ?, ?, ? WHERE changes() = 1 AND ? > 0 AND datetime(?) > datetime('now')`,args:[e.userId,e.refundMc,e.refundMc,e.operation,e.expiresAt,e.refundMc,e.expiresAt]},{sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ? AND ? > 0 AND changes() = 1",args:[e.refundMc,e.userId,e.refundMc]},{sql:`INSERT INTO ledger (user_id, amount_mc, operation, description)
3
- SELECT ?, ?, ?, ? WHERE ? > 0 AND changes() = 1`,args:[e.userId,e.refundMc,e.operation,e.description,e.refundMc]},e.acknowledgment],"write")}function J(e){return e.status==="complete"||e.status==="partial"||e.status==="failed"}function y(e,t,r){return e.userId===t&&(e.executionGeneration??0)===r&&J(e)}function W(e){let t=e.options.xraySetupReceipt;return e.options.heldMc===0&&e.options.debitKey==null&&t?.billingClass===E&&t.consumesMcpScraperCredits===!1&&t.heldMc===0&&t.billedMc===0}function b(e,t){if(!e||!y(e,t.userId,t.generation)||JSON.stringify(e.settlementPlan)!==JSON.stringify(t))return null;let r=e.settlementReceipt;return!r||r.jobId!==t.jobId||r.userId!==t.userId||r.generation!==t.generation||e.billedMc!==r.netChargeMc?null:r}async function Q(e,t,r,i,c,a=0){let s=await g(e);if(!s||!y(s,t,a))throw Error("extract_settlement_identity_or_terminal_conflict");if(s.billedMc!=null)return s.settlementReceipt??null;let o=Number(s.options.heldMc??0);if(![o,r,i].every(d=>Number.isSafeInteger(d)&&d>=0)||r+i!==o)throw Error("extract_settlement_amount_conflict");let u=String(s.options.billingClass??"credits");if(u===E&&!W(s))throw Error("xray_extract_zero_charge_finalization_rejected");let f={version:1,jobId:e,userId:t,generation:a,status:s.status,heldMc:o,debitKey:typeof s.options.debitKey=="string"?s.options.debitKey:null,billingClass:u,netChargeMc:i,refundMc:r,reference:c},l;try{l=await k(f)}catch(d){if(l=await g(e).catch(()=>null),!l?.settlementPlan||!y(l,t,a))throw d}if(!l||!y(l,t,a)||!l.settlementPlan)throw Error("extract_settlement_admission_conflict");let n=l.settlementPlan;if(n.jobId!==e||n.userId!==t||n.generation!==a||n.status!==l.status||n.heldMc!==o||n.debitKey!==f.debitKey||n.billingClass!==u)throw Error("extract_settlement_plan_conflict");let N=b(l,n);if(N)return N;let m={version:1,jobId:e,userId:t,generation:a,netChargeMc:n.netChargeMc,refundMc:0,expiredRefundMc:0};try{if(u===E)await x(n,m);else if(n.debitKey){let d=await p(t,n.debitKey,n.netChargeMc,S.EXTRACT_SITE_REFUND,n.reference,"extract_site");m.netChargeMc=d.final_amount_mc,m.refundMc=d.refund_mc,m.expiredRefundMc=d.expired_refund_mc??0,await x(n,m)}else{let h=await _().execute({sql:"SELECT datetime(created_at, ?) AS expires_at FROM site_extract_jobs WHERE id = ?",args:[D,e]}),R=[e,t,a,n.status,JSON.stringify(n)];await H({userId:t,refundMc:n.refundMc,expiresAt:String(h.rows[0]?.expires_at),operation:S.EXTRACT_SITE_REFUND,description:n.reference,admission:{sql:`UPDATE site_extract_jobs SET billed_mc = -1
4
- WHERE id = ? AND user_id = ? AND execution_generation = ? AND status = ?
5
- AND settlement_plan_json = ? AND billed_mc IS NULL`,args:R},acknowledgment:{sql:`UPDATE site_extract_jobs SET billed_mc = ?,
6
- settlement_receipt_json = json_set(?, '$.refundMc', CASE WHEN changes() = 1 THEN ? ELSE 0 END,
7
- '$.expiredRefundMc', CASE WHEN changes() = 1 THEN 0 ELSE ? END),
8
- public_error_json = CASE WHEN json_valid(public_error_json) THEN json_set(public_error_json, '$.charge_status',
9
- CASE WHEN ? > 0 THEN 'charged' WHEN changes() = 1 AND ? > 0 THEN 'refunded' ELSE 'not_charged' END) ELSE public_error_json END,
10
- updated_at = datetime('now')
11
- WHERE id = ? AND user_id = ? AND execution_generation = ? AND status = ?
12
- AND settlement_plan_json = ? AND billed_mc = -1`,args:[n.netChargeMc,JSON.stringify(m),n.refundMc,n.refundMc,n.netChargeMc,n.refundMc,...R]}})}}catch(d){let h=b(await g(e).catch(()=>null),n);if(h)return h;throw d}let M=b(await g(e),n);if(!M)throw Error("extract_settlement_acknowledgment_unknown");return M}async function V(e){if(e.userId==null||e.billedMc!=null)return e.settlementReceipt??null;if(!J(e))throw Error("extract_settlement_requires_terminal_job");let t=Number(e.options.heldMc??0),r=await I(e.id),i=Math.min(r*P.page_scrape,t),c="site";try{c=new URL(e.startUrl).hostname}catch{}return await v(e.id,e.userId,t-i,i,c,e.executionGeneration??0)}export{L as a,Q as b,V as c};
@@ -1,20 +0,0 @@
1
- var a="2026-10-10-operation-physical-attempts.1",s="operation_physical_attempts";async function r(t){let[i,_,p,E,c]=await Promise.all([t.execute(`PRAGMA table_info(${s})`),t.execute("PRAGMA index_info(operation_physical_identity)"),t.execute(`PRAGMA foreign_key_list(${s})`),t.execute("SELECT name,sql FROM sqlite_master WHERE name IN ('operation_physical_attempts','operation_physical_unresolved','operation_physical_identity')"),t.execute({sql:"SELECT 1 FROM schema_migrations WHERE version=?",args:[a]})]),n=e=>String(E.rows.find(o=>o.name===e)?.sql??"").replace(/\s+/g," ");return["id","parent_run_id","user_id","controller_token","claim_token","scope","attempt_number","provider","profile","intent_json","state","effects_json","resources_json","created_at","updated_at"].every(e=>i.rows.some(o=>o.name===e&&Number(o.notnull)===1))&&i.rows.some(e=>e.name==="id"&&Number(e.pk)===1)&&i.rows.some(e=>e.name==="receipt_json")&&_.rows.map(e=>e.name).join(",")==="parent_run_id,scope,attempt_number"&&p.rows.some(e=>e.table==="operation_runs"&&e.from==="parent_run_id"&&e.to==="id"&&e.on_delete==="CASCADE")&&n(s).includes("state IN ('prepared','effects_started','terminated','not_started','unknown')")&&n(s).includes("CHECK (json_valid(intent_json))")&&n(s).includes("CHECK (json_valid(effects_json))")&&n(s).includes("CHECK (json_valid(resources_json))")&&n(s).includes("CHECK (receipt_json IS NULL OR json_valid(receipt_json))")&&n(s).includes("CHECK ((state IN ('terminated','not_started','unknown') AND receipt_json IS NOT NULL)")&&n("operation_physical_identity").includes("CREATE UNIQUE INDEX")&&n("operation_physical_unresolved").includes("CREATE UNIQUE INDEX")&&n("operation_physical_unresolved").includes("WHERE state IN ('prepared','effects_started','unknown')")&&c.rows.length===1}async function l(t){if(!await r(t)){try{await t.batch([`CREATE TABLE IF NOT EXISTS operation_physical_attempts (
2
- id TEXT NOT NULL PRIMARY KEY,
3
- parent_run_id TEXT NOT NULL REFERENCES operation_runs(id) ON DELETE CASCADE,
4
- user_id INTEGER NOT NULL CHECK (user_id > 0),
5
- controller_token TEXT NOT NULL,
6
- claim_token TEXT NOT NULL,
7
- scope TEXT NOT NULL,
8
- attempt_number INTEGER NOT NULL CHECK (attempt_number > 0),
9
- provider TEXT NOT NULL CHECK (length(provider) BETWEEN 1 AND 100),
10
- profile TEXT NOT NULL CHECK (profile IN ('customer-funded','funded-parent')),
11
- intent_json TEXT NOT NULL CHECK (json_valid(intent_json)),
12
- state TEXT NOT NULL CHECK (state IN ('prepared','effects_started','terminated','not_started','unknown')),
13
- effects_json TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(effects_json)),
14
- resources_json TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(resources_json)),
15
- receipt_json TEXT CHECK (receipt_json IS NULL OR json_valid(receipt_json)),
16
- created_at TEXT NOT NULL DEFAULT (datetime('now')),
17
- updated_at TEXT NOT NULL DEFAULT (datetime('now')),
18
- CHECK ((state IN ('terminated','not_started','unknown') AND receipt_json IS NOT NULL)
19
- OR (state IN ('prepared','effects_started') AND receipt_json IS NULL))
20
- )`,"CREATE UNIQUE INDEX IF NOT EXISTS operation_physical_identity ON operation_physical_attempts(parent_run_id,scope,attempt_number)","CREATE UNIQUE INDEX IF NOT EXISTS operation_physical_unresolved ON operation_physical_attempts(parent_run_id) WHERE state IN ('prepared','effects_started','unknown')",{sql:"INSERT OR IGNORE INTO schema_migrations(version) VALUES (?)",args:[a]}],"write")}catch(i){if(!await r(t).catch(()=>!1))throw i}if(!await r(t))throw Error("Physical attempt schema is incomplete")}}export{l as a};
@@ -1,159 +0,0 @@
1
- import{a as M,b as q,f as L}from"./chunk-OSKCHEVM.js";import{A as ge,f as I,h as F,s as b,v as J,w as pe,x as _e,y as H}from"./chunk-U3NV72AL.js";import{g as j}from"./chunk-VVSHZV5S.js";import{b as $}from"./chunk-4ZVO6GX4.js";import{a as l}from"./chunk-WNUXMPVX.js";import{createHash as O,randomUUID as Oe}from"crypto";import{Client as tt,StreamableHTTPClientTransport as nt}from"@modelcontextprotocol/client";import{randomUUID as Q}from"crypto";import{createHash as Y,randomBytes as W,scryptSync as fe,timingSafeEqual as We}from"crypto";function Ee(){return"sk_"+W(24).toString("hex")}function ye(e){let t=W(16).toString("hex"),n=fe(e,t,64);return`${t}:${n.toString("hex")}`}function Ct(e,t){let[n,i]=t.split(":"),r=Buffer.from(i,"hex"),o=fe(e,n,64);return We(r,o)}function K(e){return{id:Number(e.id),email:String(e.email),name:e.name!=null?String(e.name):null,api_key:String(e.api_key),key_active:Number(e.key_active??1),password_hash:e.password_hash!=null?String(e.password_hash):null,created_at:String(e.created_at),active:Number(e.active),stripe_customer_id:e.stripe_customer_id!=null?String(e.stripe_customer_id):null,balance_mc:Number(e.balance_mc??0),extra_concurrency_slots:Number(e.extra_concurrency_slots??0),concurrency_stripe_sub_id:e.concurrency_stripe_sub_id!=null?String(e.concurrency_stripe_sub_id):null,concurrency_pack_quantity:Number(e.concurrency_pack_quantity??0),subscription_concurrency:Number(e.subscription_concurrency??0),subscription_tier:e.subscription_tier!=null?String(e.subscription_tier):null,subscription_id:e.subscription_id!=null?String(e.subscription_id):null,memory_plan:e.memory_plan!=null?String(e.memory_plan):"free",memory_subscription_id:e.memory_subscription_id!=null?String(e.memory_subscription_id):null,memory_provisioned:Number(e.memory_provisioned??0)}}async function X(e){let t=await l().execute({sql:"SELECT * FROM users WHERE email = ? AND active = 1",args:[e]});return t.rows[0]?K(t.rows[0]):void 0}async function St(e){let t=await l().execute({sql:"SELECT * FROM users WHERE api_key = ? AND active = 1 AND key_active = 1",args:[e]});return t.rows[0]?K(t.rows[0]):void 0}async function Nt(e){let t=await l().execute({sql:"SELECT * FROM users WHERE id = ? AND active = 1",args:[e]});return t.rows[0]?K(t.rows[0]):void 0}async function ht(e,t){await l().execute({sql:"UPDATE users SET password_hash = ? WHERE id = ?",args:[ye(t),e]})}async function Rt(e){let t=l(),[n,i,r,o,s]=await Promise.all([t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ?",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'failed'",args:[e]}),t.execute({sql:"SELECT COALESCE(SUM(json_extract(result, '$.totalQuestions')), 0) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT MAX(created_at) as t FROM jobs WHERE user_id = ?",args:[e]})]);return{total:Number(n.rows[0]?.n??0),done:Number(i.rows[0]?.n??0),failed:Number(r.rows[0]?.n??0),totalQuestions:Number(o.rows[0]?.n??0),lastUsed:s.rows[0]?.t!=null?String(s.rows[0].t):null}}async function At(e,t,n,i){let r=l(),o=Ee(),s=n??W(6).toString("hex"),a=ye(s);return{id:(await r.execute({sql:"INSERT INTO users (email, name, api_key, password_hash, stripe_customer_id) VALUES (?, ?, ?, ?, ?)",args:[e,t??null,o,a,i??null]})).lastInsertRowid,email:e,name:t,api_key:o,password:s}}async function xt(e,t,n,i){let r=Math.floor(Date.now()/1e3),o=Math.floor(r/i)*i,s=Y("sha256").update(t).digest("hex"),d=await l().execute({sql:`
2
- 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 +0,0 @@
1
- function u(e){if(Date.now()>=e)throw new Error("Reddit request deadline exhausted")}var t=class extends Error{constructor(n){super(`${n} deadline exceeded`),this.name="DeadlineExceededError"}};async function w(e,n,r,s=Number.POSITIVE_INFINITY){let o=Math.min(e-Date.now(),s);if(o<=0)throw new t(r);let T=Date.now()+o,i,a=Promise.resolve().then(()=>{if(Date.now()>=e)throw new t(r);return n()});try{let E=await Promise.race([a,new Promise((_,D)=>{i=setTimeout(()=>D(new t(r)),o)})]);if(Date.now()>=Math.min(e,T))throw new t(r);return E}finally{i&&clearTimeout(i)}}export{u as a,t as b,w as c};
@@ -1 +0,0 @@
1
- import{c as f,d,e as p,h as u,i as A,j as m}from"./chunk-SEZETSB3.js";import{c as s,i as l}from"./chunk-SDQW7IJN.js";import{randomUUID as D}from"crypto";var x="connected-data-exports/",_=10080*60*1e3,b=900*1e3;function C(){return process.env.CONNECTED_DATA_READ_WRITE_TOKEN?.trim()||process.env.CONNECTED_DATA_BLOB_READ_WRITE_TOKEN?.trim()||null}function r(){return{prefix:x,artifactTtlMs:_,downloadTtlMs:b,token:C()}}function i(t){return(t.toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"connected-data-export").slice(0,120)}function N(t){return l(t,x)}function w(t){return f(t,r())}function O(t,e=Date.now()){let n=w(t);return!n||n.getTime()<=e}async function P(t){return g({...t,contentType:"application/x-ndjson"})}async function g(t){let e=t.stableCreatedAt?Date.parse(t.stableCreatedAt):NaN,n=Number.isFinite(e)?e:Date.now(),c=i(t.filename),y=t.stableKey?i(t.stableKey):D(),a;try{a=await p({policy:r(),ownerId:t.ownerId,artifactKey:`${i(t.exportId)}-${y}--${c}`,createdAt:n,filename:c,contentType:t.contentType,content:typeof t.content=="string"?t.content:Buffer.from(t.content)})}catch(o){throw o instanceof Error&&o.message==="private_artifact_blob_not_configured"?new Error("connected_data_private_blob_not_configured"):o}return{...a,...a.capabilities.includes("text")?{readback:{tool:"report_artifact_read",arguments:{artifactId:a.artifactId,offset:0,maxBytes:2e4},continuation:"Repeat with offset set to the previous result nextOffset until nextOffset is null."}}:{}}}async function B(t){return u({...t,policy:r()})}async function R(t,e,n){return A({policy:r(),artifactId:t,offset:e,maxBytes:n})}async function U(t){try{return await m({...t,policy:r(),maxBytes:t.maxBytes??25*1024*1024})}catch(e){if(e instanceof s&&e.code==="read_limit")return null;throw e}}async function h(t={}){let e=t.now??new Date,n=r();return n.token?!t.force&&!(e.getUTCHours()===3&&e.getUTCMinutes()===17)?{deleted:0,store:"private-vercel-blob",skipped:!0}:d({policy:n,now:e,includeLegacy:!0,maxObjects:2e4}):{deleted:0,store:process.env.VERCEL==="1"||process.env.NODE_ENV==="production"?"none":"local"}}export{x as a,_ as b,b as c,r as d,N as e,w as f,O as g,P as h,g as i,B as j,R as k,U as l,h as m};