mcp-scraper 0.95.2 → 0.96.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -1
- package/README.md +19 -3
- package/dist/actions-YCMJY3PF.js +1 -0
- package/dist/artifacts-4ZDNP2JW.js +1 -0
- package/dist/artifacts-N62OPIT5.js +1 -0
- package/dist/artifacts-PSADD5OC.js +1 -0
- package/dist/artifacts-RUR3OHAK.js +1 -0
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.js +22 -22
- package/dist/bin/mcp-scraper-core.js +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.js +1 -1
- package/dist/bin/paa-harvest.js +1 -1
- package/dist/blob-store-GIH26EDO.js +1 -0
- package/dist/bundle-TTJP6DHU.js +1 -0
- package/dist/chunk-24YDQ3EO.js +5 -0
- package/dist/chunk-2PRH4Z3N.js +181 -0
- package/dist/chunk-3F7AFM53.js +1 -0
- package/dist/chunk-4HZXATHB.js +27 -0
- package/dist/chunk-55ZANTHL.js +3 -0
- package/dist/chunk-5BKSKLHX.js +1 -0
- package/dist/chunk-63VWBMYR.js +3 -0
- package/dist/chunk-6N5EC7ZO.js +1 -0
- package/dist/chunk-6SNOUSSZ.js +182 -0
- package/dist/chunk-7POHNTVW.js +1 -0
- package/dist/chunk-7SR7MEU5.js +62 -0
- package/dist/chunk-7UHDOIUE.js +1 -0
- package/dist/chunk-ARSQZCTJ.js +945 -0
- package/dist/chunk-B3JRL45T.js +1 -0
- package/dist/chunk-B4ZKPLSP.js +1 -0
- package/dist/chunk-C7MGJUTU.js +1 -0
- package/dist/{chunk-W2BVJ7S2.js → chunk-CNSVZTTT.js} +4 -4
- package/dist/chunk-DGAW7FD7.js +12 -0
- package/dist/chunk-FRXKMOXI.js +41 -0
- package/dist/chunk-GVYGAZV7.js +1 -0
- package/dist/chunk-HCK6PLM3.js +3 -0
- package/dist/{chunk-Y3Q4FIKK.js → chunk-HJIOH7HF.js} +199 -84
- package/dist/chunk-HNNYXMSI.js +1 -0
- package/dist/chunk-HUNSEGUN.js +57 -0
- package/dist/chunk-IFPION5D.js +121 -0
- package/dist/{chunk-MC4W6TZT.js → chunk-JAV5V3JT.js} +41 -8
- package/dist/chunk-JMZIDHYQ.js +2 -0
- package/dist/{chunk-ENZUJEIM.js → chunk-JW4GDY7S.js} +1 -1
- package/dist/chunk-KXJCGV3H.js +1 -0
- package/dist/chunk-LFRAA3MY.js +4 -0
- package/dist/chunk-MVMWPKRC.js +2 -0
- package/dist/chunk-NALXKTUU.js +1 -0
- package/dist/chunk-NNOX3FYG.js +198 -0
- package/dist/chunk-OB6E6UTD.js +1 -0
- package/dist/chunk-OILOHQNL.js +2 -0
- package/dist/chunk-OLYPLX5C.js +1 -0
- package/dist/chunk-QER2ELZP.js +1 -0
- package/dist/chunk-QWE7VKIX.js +1 -0
- package/dist/chunk-R5LJL6IR.js +225 -0
- package/dist/chunk-RDHGQ2WZ.js +1 -0
- package/dist/chunk-SDQW7IJN.js +1 -0
- package/dist/chunk-SEZETSB3.js +1 -0
- package/dist/chunk-SNJR5N36.js +1 -0
- package/dist/chunk-TPN25AFZ.js +159 -0
- package/dist/chunk-UIOSADPB.js +1718 -0
- package/dist/{chunk-ZH75KWBI.js → chunk-UNEJYZ4T.js} +1 -1
- package/dist/chunk-VAC3SQ5T.js +16 -0
- package/dist/{chunk-VREXSMC6.js → chunk-VVSHZV5S.js} +5 -5
- package/dist/chunk-WNUXMPVX.js +1 -0
- package/dist/chunk-WP3QS4CJ.js +1 -0
- package/dist/chunk-ZPQNY5TI.js +1 -0
- package/dist/contracts-GUXGFCVV.js +1 -0
- package/dist/core-schema-423BSTE6.js +936 -0
- package/dist/dispatch-3HY4735M.js +1 -0
- package/dist/index.cjs +104 -214
- package/dist/index.d.cts +181 -169
- package/dist/index.d.ts +181 -169
- package/dist/index.js +1 -1
- package/dist/media-artifacts-67CJWI7O.js +1 -0
- package/dist/metering-ZH2P62IC.js +1 -0
- package/dist/migrations-3AKEC5QE.js +1 -0
- package/dist/queue-HUP2GNXF.js +1 -0
- package/dist/reconciliation-ANXNJWME.js +1 -0
- package/dist/report-artifact-offload-6OOY2PTM.js +1 -0
- package/dist/repository-4EC5EXVN.js +1 -0
- package/dist/{location-data-repository-A2QZVP7O.js → repository-CYXVMYAI.js} +1 -1
- package/dist/server-VQU6S24A.js +5825 -0
- package/dist/settlement-6CCE2PDH.js +1 -0
- package/dist/worker-5G5BK23B.js +1 -0
- package/package.json +2 -2
- package/dist/analytics-repository-DZZKDZL6.js +0 -1
- package/dist/chunk-6DRKDSXY.js +0 -182
- package/dist/chunk-6ND5AFV5.js +0 -27
- package/dist/chunk-7XDBGQDY.js +0 -6
- package/dist/chunk-7YOXSMHG.js +0 -1565
- package/dist/chunk-BLVBUMH5.js +0 -21
- package/dist/chunk-EDQ57S4P.js +0 -1
- package/dist/chunk-GLTECY3U.js +0 -1282
- package/dist/chunk-GPSPSJBJ.js +0 -1
- package/dist/chunk-HE45FFBU.js +0 -1
- package/dist/chunk-HUV2WTRW.js +0 -1
- package/dist/chunk-IXJQHXDC.js +0 -2595
- package/dist/chunk-K3D2S36Q.js +0 -16
- package/dist/chunk-KFOFU3LA.js +0 -1
- package/dist/chunk-LMWU7VPZ.js +0 -63
- package/dist/chunk-O4LUUIYG.js +0 -4
- package/dist/chunk-OLSW4AN4.js +0 -19
- package/dist/chunk-RLFCJGHA.js +0 -100
- package/dist/chunk-T4VTJNDZ.js +0 -84
- package/dist/chunk-TMB56NCA.js +0 -1
- package/dist/chunk-VXOXB3IB.js +0 -1
- package/dist/chunk-WO3N5FH2.js +0 -5
- package/dist/chunk-WO46LTBW.js +0 -1
- package/dist/chunk-XPEJB4BZ.js +0 -1
- package/dist/db-CDEZHBRN.js +0 -1
- package/dist/extract-bundle-SXC6EWJR.js +0 -26
- package/dist/gmail-service-EWR76XE7.js +0 -1
- package/dist/lead-list-enrichment-repository-SIWGXWQV.js +0 -1
- package/dist/operation-metering-UJ53YX7S.js +0 -1
- package/dist/server-QVEKDIDQ.js +0 -5014
- package/dist/site-extract-repository-23ND4N77.js +0 -1
- package/dist/stripe-event-worker-LPXTITVC.js +0 -1
- package/dist/worker-EDN2TJH3.js +0 -1
- /package/dist/{chunk-YGBTTW5D.js → chunk-2IATUJO6.js} +0 -0
- /package/dist/{chunk-6DTXIZY2.js → chunk-4ZVO6GX4.js} +0 -0
- /package/dist/{chunk-XG6GCEUE.js → chunk-U4WIJZCX.js} +0 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import{a as M,b as q,h as L}from"./chunk-R5LJL6IR.js";import{o as b,r as J,s as pe,t as _e,u as H,w as ge}from"./chunk-QWE7VKIX.js";import{b as I,d as F}from"./chunk-ZPQNY5TI.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="mastra_scheduler",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","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{an as a,cn as b,un as c,dn as d,ln as e,mn as f,pn as g,D as h,Ct as i,K as j,X as k,St as l,Nt as m,ht as n,Rt as o,At as p,xt as q,It as r,Ot as s,Lt as t,Ut as u,Dt as v,Pt as w,kt as x,Mt as y,Qt as z,$e as A,je as B,T as C,ae as D,ce as E,Cn as F,Kt as G,C as H,Ke as I,S as J,Xt as K,Bt as L,Gt as M,Vt as N,$t as O,g as P,G as Q,Le as R,Ln as S,Un as T,Dn as U,Pn as V,kn as W,Mn as X,qn as Y,He as Z,Fn as _,Hn as $};
|