@belticlabs/agent-risk-sdk 0.3.0 → 0.4.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/dist/{adapter-BEpzr2R3.d.ts → adapter-CLy44CD2.d.ts} +2 -2
- package/dist/ai/index.d.ts +2 -2
- package/dist/ai/index.js +3 -4
- package/dist/{chunk-46QN2KEZ.js → chunk-4BUUPU3O.js} +0 -9
- package/dist/chunk-WY5ZX4BD.js +177 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +17 -8
- package/dist/protocol/index.d.ts +2 -2
- package/dist/protocol/index.js +1 -5
- package/dist/{session-DsBWEP8d.d.ts → session-gK51QVAM.d.ts} +5 -6
- package/dist/{verdict-6vCyoAHE.d.ts → verdict-CDAsxktI.d.ts} +1 -17
- package/dist/x402/hono.d.ts +16 -5
- package/dist/x402/hono.js +14 -8
- package/dist/x402/index.d.ts +12 -22
- package/dist/x402/index.js +14 -57
- package/package.json +2 -30
- package/dist/chunk-7G5EHNVW.js +0 -17
- package/dist/chunk-FAQ442YH.js +0 -24
- package/dist/chunk-LM4NIYE5.js +0 -92
- package/dist/chunk-NJVO2WIV.js +0 -17
- package/dist/chunk-OKC6VMFH.js +0 -84
- package/dist/mcp/index.d.ts +0 -58
- package/dist/mcp/index.js +0 -135
- package/dist/middleware-9gI0ou2i.d.ts +0 -15
- package/dist/seller/anti-fraud-gateway.d.ts +0 -40
- package/dist/seller/anti-fraud-gateway.js +0 -38
- package/dist/x402/express.d.ts +0 -13
- package/dist/x402/express.js +0 -27
package/dist/x402/index.js
CHANGED
|
@@ -1,71 +1,55 @@
|
|
|
1
|
-
import {
|
|
2
|
-
attachX402
|
|
3
|
-
} from "../chunk-OKC6VMFH.js";
|
|
4
1
|
import {
|
|
5
2
|
Session,
|
|
6
3
|
Sessions
|
|
7
4
|
} from "../chunk-4MG6VNAU.js";
|
|
8
5
|
import {
|
|
9
6
|
DECISION_EXTENSION,
|
|
10
|
-
DECISION_HEADER,
|
|
11
7
|
SESSION_EXTENSION,
|
|
12
8
|
SESSION_HEADER,
|
|
9
|
+
attachX402,
|
|
13
10
|
decisionIdOf,
|
|
14
|
-
sessionIdOf
|
|
15
|
-
} from "../chunk-FAQ442YH.js";
|
|
16
|
-
import "../chunk-X3W2Z5GC.js";
|
|
17
|
-
import "../chunk-46QN2KEZ.js";
|
|
18
|
-
import {
|
|
19
11
|
payerOf,
|
|
12
|
+
sessionIdOf,
|
|
20
13
|
x402Currency,
|
|
21
14
|
x402Moments,
|
|
22
15
|
x402Summary
|
|
23
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-WY5ZX4BD.js";
|
|
24
17
|
import "../chunk-FQDHFTVR.js";
|
|
18
|
+
import "../chunk-X3W2Z5GC.js";
|
|
25
19
|
|
|
26
20
|
// src/x402/fetch.ts
|
|
27
21
|
var BASE64 = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
28
|
-
var CHALLENGE_MEMORY = 32;
|
|
29
22
|
function belticFetch(source, inner = globalThis.fetch) {
|
|
30
23
|
if (!source) return inner;
|
|
31
24
|
const run = source instanceof Session ? null : source;
|
|
32
|
-
const challenges = /* @__PURE__ */ new Map();
|
|
33
25
|
return async (input, init) => {
|
|
34
26
|
const session = await Sessions.resolve(source);
|
|
35
27
|
if (!session) return inner(input, init);
|
|
36
|
-
const url = urlOf(input);
|
|
37
28
|
const headers = new Headers(
|
|
38
29
|
init?.headers ?? (input instanceof Request ? input.headers : void 0)
|
|
39
30
|
);
|
|
40
31
|
headers.set(SESSION_HEADER, session.id);
|
|
41
32
|
const signature = headers.get("PAYMENT-SIGNATURE");
|
|
42
|
-
const
|
|
43
|
-
const payload = presented ? decodeHeader(presented) : null;
|
|
33
|
+
const payload = signature ? decodeHeader(signature) : null;
|
|
44
34
|
if (payload) {
|
|
45
|
-
const
|
|
46
|
-
const decision = run?.decisionFor(x402Moments.payload(payload, accepts));
|
|
35
|
+
const decision = run?.decisionFor(x402Moments.payload(payload));
|
|
47
36
|
const decisionId = decision && !decision.absent ? decision.decisionId : null;
|
|
48
|
-
const bound =
|
|
37
|
+
const bound = {
|
|
49
38
|
...payload,
|
|
50
39
|
extensions: {
|
|
51
40
|
...payload.extensions,
|
|
52
41
|
[SESSION_EXTENSION]: session.id,
|
|
53
42
|
...decisionId ? { [DECISION_EXTENSION]: decisionId } : {}
|
|
54
43
|
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
await session.emit("payment.presented", x402Moments.payload(bound, accepts));
|
|
44
|
+
};
|
|
45
|
+
headers.set("PAYMENT-SIGNATURE", encodeHeader(bound));
|
|
46
|
+
await session.emit("payment.presented", x402Moments.payload(bound));
|
|
59
47
|
await session.flush();
|
|
60
48
|
}
|
|
61
49
|
const res = await inner(input, { ...init, headers });
|
|
62
50
|
if (res.status !== 402) return res;
|
|
63
|
-
const required =
|
|
64
|
-
if (required)
|
|
65
|
-
challenges.set(url, required);
|
|
66
|
-
if (challenges.size > CHALLENGE_MEMORY) challenges.delete(challenges.keys().next().value);
|
|
67
|
-
await session.emit("payment.requested", x402Moments.required(required));
|
|
68
|
-
}
|
|
51
|
+
const required = challengeOf(res);
|
|
52
|
+
if (required) await session.emit("payment.requested", x402Moments.required(required));
|
|
69
53
|
return res;
|
|
70
54
|
};
|
|
71
55
|
}
|
|
@@ -81,35 +65,9 @@ function decodeHeader(value) {
|
|
|
81
65
|
function encodeHeader(value) {
|
|
82
66
|
return Buffer.from(JSON.stringify(value), "utf8").toString("base64");
|
|
83
67
|
}
|
|
84
|
-
function
|
|
85
|
-
return typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
86
|
-
}
|
|
87
|
-
async function challengeOf(res) {
|
|
68
|
+
function challengeOf(res) {
|
|
88
69
|
const header = res.headers.get("PAYMENT-REQUIRED");
|
|
89
|
-
|
|
90
|
-
if (!/json/i.test(res.headers.get("content-type") ?? "")) return null;
|
|
91
|
-
try {
|
|
92
|
-
const body = await res.clone().json();
|
|
93
|
-
return Array.isArray(body?.accepts) ? body : null;
|
|
94
|
-
} catch {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
function answeredAccepts(required, payload) {
|
|
99
|
-
const auth = payload.payload?.authorization;
|
|
100
|
-
const payTo = typeof auth?.to === "string" ? auth.to : void 0;
|
|
101
|
-
const amount = typeof auth?.value === "string" ? auth.value : void 0;
|
|
102
|
-
const options = required?.accepts ?? [];
|
|
103
|
-
const answered = options.find(
|
|
104
|
-
(a) => a.payTo?.toLowerCase() === payTo?.toLowerCase() && (a.amount ?? a.maxAmountRequired) === amount
|
|
105
|
-
) ?? options[0];
|
|
106
|
-
if (answered) return answered;
|
|
107
|
-
if (!payTo && !amount) return void 0;
|
|
108
|
-
return {
|
|
109
|
-
...payTo ? { payTo } : {},
|
|
110
|
-
...amount ? { amount } : {},
|
|
111
|
-
...payload.network ? { network: payload.network } : {}
|
|
112
|
-
};
|
|
70
|
+
return header ? decodeHeader(header) : null;
|
|
113
71
|
}
|
|
114
72
|
|
|
115
73
|
// src/x402/intent.ts
|
|
@@ -126,7 +84,6 @@ function x402Intent(input) {
|
|
|
126
84
|
}
|
|
127
85
|
export {
|
|
128
86
|
DECISION_EXTENSION,
|
|
129
|
-
DECISION_HEADER,
|
|
130
87
|
SESSION_EXTENSION,
|
|
131
88
|
SESSION_HEADER,
|
|
132
89
|
attachX402,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@belticlabs/agent-risk-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "The Beltic Agent Risk SDK — one client, two halves: instrument the buyer agent (AI SDK, x402 fetch
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "The Beltic Agent Risk SDK — one client, two halves: instrument the buyer agent (AI SDK, x402 fetch) and guard the seller boundary (x402 over hono, evaluate).",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -32,18 +32,6 @@
|
|
|
32
32
|
"types": "./dist/x402/hono.d.ts",
|
|
33
33
|
"default": "./dist/x402/hono.js"
|
|
34
34
|
},
|
|
35
|
-
"./express": {
|
|
36
|
-
"types": "./dist/x402/express.d.ts",
|
|
37
|
-
"default": "./dist/x402/express.js"
|
|
38
|
-
},
|
|
39
|
-
"./mcp": {
|
|
40
|
-
"types": "./dist/mcp/index.d.ts",
|
|
41
|
-
"default": "./dist/mcp/index.js"
|
|
42
|
-
},
|
|
43
|
-
"./platform-adapter": {
|
|
44
|
-
"types": "./dist/seller/anti-fraud-gateway.d.ts",
|
|
45
|
-
"default": "./dist/seller/anti-fraud-gateway.js"
|
|
46
|
-
},
|
|
47
35
|
"./package.json": "./package.json"
|
|
48
36
|
},
|
|
49
37
|
"files": [
|
|
@@ -57,45 +45,29 @@
|
|
|
57
45
|
"zod": "^4.6.5"
|
|
58
46
|
},
|
|
59
47
|
"peerDependencies": {
|
|
60
|
-
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
61
48
|
"@x402/core": "^2.25.0",
|
|
62
|
-
"@x402/express": "^2.25.0",
|
|
63
49
|
"@x402/hono": "^2.25.0",
|
|
64
50
|
"ai": "^7.0.0",
|
|
65
|
-
"express": "^5.0.0",
|
|
66
51
|
"hono": "^4.0.0"
|
|
67
52
|
},
|
|
68
53
|
"peerDependenciesMeta": {
|
|
69
|
-
"@modelcontextprotocol/sdk": {
|
|
70
|
-
"optional": true
|
|
71
|
-
},
|
|
72
54
|
"@x402/core": {
|
|
73
55
|
"optional": true
|
|
74
56
|
},
|
|
75
|
-
"@x402/express": {
|
|
76
|
-
"optional": true
|
|
77
|
-
},
|
|
78
57
|
"@x402/hono": {
|
|
79
58
|
"optional": true
|
|
80
59
|
},
|
|
81
60
|
"ai": {
|
|
82
61
|
"optional": true
|
|
83
62
|
},
|
|
84
|
-
"express": {
|
|
85
|
-
"optional": true
|
|
86
|
-
},
|
|
87
63
|
"hono": {
|
|
88
64
|
"optional": true
|
|
89
65
|
}
|
|
90
66
|
},
|
|
91
67
|
"devDependencies": {
|
|
92
|
-
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
93
|
-
"@types/express": "^5.0.6",
|
|
94
68
|
"@x402/core": "^2.25.0",
|
|
95
|
-
"@x402/express": "^2.25.0",
|
|
96
69
|
"@x402/hono": "^2.25.0",
|
|
97
70
|
"ai": "^7.0.100",
|
|
98
|
-
"express": "^5.2.1",
|
|
99
71
|
"hono": "^4.13.7",
|
|
100
72
|
"tsup": "8.5.1",
|
|
101
73
|
"typescript": "5.9.3",
|
package/dist/chunk-7G5EHNVW.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// src/core/payment-moment.ts
|
|
2
|
-
function summaryOf(m) {
|
|
3
|
-
return {
|
|
4
|
-
protocol: m.protocol,
|
|
5
|
-
payee: m.payee,
|
|
6
|
-
amount: { value: m.amount.value, currency: m.amount.currency },
|
|
7
|
-
...m.payer ? { payer: m.payer } : {}
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
function presentedFrom(summary, raw) {
|
|
11
|
-
return { ...summary, artifact: "payment-signature", raw };
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export {
|
|
15
|
-
summaryOf,
|
|
16
|
-
presentedFrom
|
|
17
|
-
};
|
package/dist/chunk-FAQ442YH.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// src/x402/binding.ts
|
|
2
|
-
var SESSION_EXTENSION = "beltic.sessionId";
|
|
3
|
-
var SESSION_HEADER = "Beltic-Session-Id";
|
|
4
|
-
var DECISION_EXTENSION = "beltic.decisionId";
|
|
5
|
-
var DECISION_HEADER = "Beltic-Decision-Id";
|
|
6
|
-
function sessionIdOf(extensions) {
|
|
7
|
-
return stringAt(extensions, SESSION_EXTENSION);
|
|
8
|
-
}
|
|
9
|
-
function decisionIdOf(extensions) {
|
|
10
|
-
return stringAt(extensions, DECISION_EXTENSION);
|
|
11
|
-
}
|
|
12
|
-
function stringAt(extensions, key) {
|
|
13
|
-
const v = extensions?.[key];
|
|
14
|
-
return typeof v === "string" && v.length > 0 ? v : null;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export {
|
|
18
|
-
SESSION_EXTENSION,
|
|
19
|
-
SESSION_HEADER,
|
|
20
|
-
DECISION_EXTENSION,
|
|
21
|
-
DECISION_HEADER,
|
|
22
|
-
sessionIdOf,
|
|
23
|
-
decisionIdOf
|
|
24
|
-
};
|
package/dist/chunk-LM4NIYE5.js
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
toJsonObject
|
|
3
|
-
} from "./chunk-FQDHFTVR.js";
|
|
4
|
-
|
|
5
|
-
// src/x402/moments.ts
|
|
6
|
-
function x402Currency(network, asset) {
|
|
7
|
-
return `${network}/${asset}`;
|
|
8
|
-
}
|
|
9
|
-
function x402Summary(accepts, opts = {}) {
|
|
10
|
-
const payer = opts.payer?.toLowerCase();
|
|
11
|
-
return {
|
|
12
|
-
protocol: "x402",
|
|
13
|
-
payee: accepts?.payTo ?? "unknown",
|
|
14
|
-
amount: {
|
|
15
|
-
value: accepts?.amount ?? accepts?.maxAmountRequired ?? "0",
|
|
16
|
-
currency: accepts ? x402Currency(accepts.network ?? "unknown", accepts.asset ?? "unknown") : "unknown"
|
|
17
|
-
},
|
|
18
|
-
...payer ? { payer } : {}
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
function fromAccepts(a, artifact, raw, payer) {
|
|
22
|
-
return { ...x402Summary(a, { payer }), artifact, raw };
|
|
23
|
-
}
|
|
24
|
-
function payerOf(payload) {
|
|
25
|
-
const p = payload.payload ?? {};
|
|
26
|
-
const auth = p.authorization;
|
|
27
|
-
const candidates = [
|
|
28
|
-
auth?.from,
|
|
29
|
-
p.from,
|
|
30
|
-
p.payer,
|
|
31
|
-
p.signer,
|
|
32
|
-
p.permit?.owner
|
|
33
|
-
];
|
|
34
|
-
const hit = candidates.find((c) => typeof c === "string" && c.length > 0);
|
|
35
|
-
return typeof hit === "string" ? hit.toLowerCase() : void 0;
|
|
36
|
-
}
|
|
37
|
-
var x402Moments = {
|
|
38
|
-
/** The 402 challenge as the buyer saw it, v2 header or v1 body. */
|
|
39
|
-
required(required) {
|
|
40
|
-
return fromAccepts(required.accepts?.[0], "http-402", toJsonObject(required));
|
|
41
|
-
},
|
|
42
|
-
/** The requirements the seller's resource server resolved for a request. */
|
|
43
|
-
requirements(req) {
|
|
44
|
-
return fromAccepts(req, "http-402", toJsonObject(req));
|
|
45
|
-
},
|
|
46
|
-
/** A route's static `accepts` config, before any payment header exists. */
|
|
47
|
-
route(route, raw) {
|
|
48
|
-
const accepts = route ?? {};
|
|
49
|
-
const extra = accepts.extra;
|
|
50
|
-
return fromAccepts(
|
|
51
|
-
{
|
|
52
|
-
payTo: typeof accepts.payTo === "string" ? accepts.payTo : "dynamic",
|
|
53
|
-
amount: priceValue(accepts.price),
|
|
54
|
-
network: accepts.network,
|
|
55
|
-
asset: extra?.asset ?? "route"
|
|
56
|
-
},
|
|
57
|
-
"http-402",
|
|
58
|
-
raw
|
|
59
|
-
);
|
|
60
|
-
},
|
|
61
|
-
/** An in-band ask (MRTR `input_required` or a `_meta` envelope) carrying an x402-style `accepts`. */
|
|
62
|
-
ask(first, raw) {
|
|
63
|
-
return fromAccepts(first, "mrtr-input-required", raw);
|
|
64
|
-
},
|
|
65
|
-
/**
|
|
66
|
-
* The signed payment the buyer presented. A v2 payload carries the
|
|
67
|
-
* requirement it accepted; a v1 payload does not, so the caller passes
|
|
68
|
-
* the `accepts` entry it answered.
|
|
69
|
-
*/
|
|
70
|
-
payload(payload, accepts) {
|
|
71
|
-
return fromAccepts(
|
|
72
|
-
accepts ?? payload.accepted,
|
|
73
|
-
"payment-signature",
|
|
74
|
-
toJsonObject(payload),
|
|
75
|
-
payerOf(payload)
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
function priceValue(price) {
|
|
80
|
-
if (typeof price === "string") return price.replace(/[^0-9.]/g, "") || "0";
|
|
81
|
-
if (typeof price === "number") return String(price);
|
|
82
|
-
if (price && typeof price === "object" && typeof price.amount === "string")
|
|
83
|
-
return price.amount;
|
|
84
|
-
return "0";
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export {
|
|
88
|
-
x402Currency,
|
|
89
|
-
x402Summary,
|
|
90
|
-
payerOf,
|
|
91
|
-
x402Moments
|
|
92
|
-
};
|
package/dist/chunk-NJVO2WIV.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
attachX402
|
|
3
|
-
} from "./chunk-OKC6VMFH.js";
|
|
4
|
-
|
|
5
|
-
// src/x402/middleware.ts
|
|
6
|
-
import {
|
|
7
|
-
x402HTTPResourceServer
|
|
8
|
-
} from "@x402/core/server";
|
|
9
|
-
function guardedPaymentMiddleware(fromHTTPServer, beltic, routes, server, opts = {}) {
|
|
10
|
-
const http = new x402HTTPResourceServer(server, routes);
|
|
11
|
-
attachX402(beltic, server, http, opts);
|
|
12
|
-
return fromHTTPServer(http, opts.paywall);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export {
|
|
16
|
-
guardedPaymentMiddleware
|
|
17
|
-
};
|
package/dist/chunk-OKC6VMFH.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
SESSION_HEADER,
|
|
3
|
-
decisionIdOf,
|
|
4
|
-
sessionIdOf
|
|
5
|
-
} from "./chunk-FAQ442YH.js";
|
|
6
|
-
import {
|
|
7
|
-
payloadDigest
|
|
8
|
-
} from "./chunk-X3W2Z5GC.js";
|
|
9
|
-
import {
|
|
10
|
-
x402Moments
|
|
11
|
-
} from "./chunk-LM4NIYE5.js";
|
|
12
|
-
|
|
13
|
-
// src/x402/adapter.ts
|
|
14
|
-
function attachX402(beltic, server, http, opts = {}) {
|
|
15
|
-
const inFlight = /* @__PURE__ */ new Map();
|
|
16
|
-
const resolveSession = async (bound, ctx) => {
|
|
17
|
-
const key = opts.correlate?.(ctx) ?? null;
|
|
18
|
-
return bound ?? (key ? await beltic.correlation.resolve(key) : null);
|
|
19
|
-
};
|
|
20
|
-
http?.onProtectedRequest(async (ctx, route) => {
|
|
21
|
-
if (ctx.paymentHeader) return;
|
|
22
|
-
const bound = ctx.adapter.getHeader(SESSION_HEADER) ?? ctx.adapter.getHeader(SESSION_HEADER.toLowerCase());
|
|
23
|
-
const sessionId = await resolveSession(bound ?? null, {
|
|
24
|
-
path: ctx.path,
|
|
25
|
-
method: ctx.method,
|
|
26
|
-
header: (n) => ctx.adapter.getHeader(n)
|
|
27
|
-
});
|
|
28
|
-
if (!sessionId) return;
|
|
29
|
-
const session = await beltic.sessions.ensure(sessionId);
|
|
30
|
-
const accepts = Array.isArray(route.accepts) ? route.accepts[0] : route.accepts;
|
|
31
|
-
await session.emit(
|
|
32
|
-
"payment.requested",
|
|
33
|
-
x402Moments.route(accepts, {
|
|
34
|
-
path: ctx.path,
|
|
35
|
-
method: ctx.method,
|
|
36
|
-
route: JSON.parse(JSON.stringify(route))
|
|
37
|
-
})
|
|
38
|
-
);
|
|
39
|
-
});
|
|
40
|
-
server.onBeforeVerify(async (ctx) => {
|
|
41
|
-
const payload = ctx.paymentPayload;
|
|
42
|
-
const requirements = ctx.requirements;
|
|
43
|
-
const sessionId = await resolveSession(sessionIdOf(payload.extensions), {
|
|
44
|
-
path: payload.resource?.url ?? "",
|
|
45
|
-
method: "PAY",
|
|
46
|
-
header: () => void 0
|
|
47
|
-
});
|
|
48
|
-
const session = await beltic.sessions.ensure(sessionId);
|
|
49
|
-
if (session.born === "seller")
|
|
50
|
-
await session.emit("payment.requested", x402Moments.requirements(requirements));
|
|
51
|
-
const presented = x402Moments.payload(payload);
|
|
52
|
-
await session.emit("payment.presented", presented);
|
|
53
|
-
inFlight.set(payloadDigest(payload), session);
|
|
54
|
-
const out = await beltic.evaluate(session.id, presented);
|
|
55
|
-
if (!out) return;
|
|
56
|
-
opts.onDecision?.({
|
|
57
|
-
sessionId: session.id,
|
|
58
|
-
decision: out.decision,
|
|
59
|
-
reasonCodes: out.reasonCodes,
|
|
60
|
-
born: session.born,
|
|
61
|
-
buyerDecisionId: decisionIdOf(payload.extensions)
|
|
62
|
-
});
|
|
63
|
-
if (out.verdict.blocks(beltic.onReview)) {
|
|
64
|
-
return {
|
|
65
|
-
abort: true,
|
|
66
|
-
reason: `BELTIC_${out.verdict.value}`,
|
|
67
|
-
message: out.reasonCodes.join(",")
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
return;
|
|
71
|
-
});
|
|
72
|
-
server.onAfterSettle(async (ctx) => {
|
|
73
|
-
const key = payloadDigest(ctx.paymentPayload);
|
|
74
|
-
const session = inFlight.get(key);
|
|
75
|
-
if (!session) return;
|
|
76
|
-
inFlight.delete(key);
|
|
77
|
-
if (ctx.result.success) await session.close("settled", { transaction: ctx.result.transaction });
|
|
78
|
-
});
|
|
79
|
-
return { inFlight };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export {
|
|
83
|
-
attachX402
|
|
84
|
-
};
|
package/dist/mcp/index.d.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { a as PaymentSummary, P as PaymentMomentPayload } from '../verdict-6vCyoAHE.js';
|
|
2
|
-
import { B as Beltic, S as SessionSource } from '../session-DsBWEP8d.js';
|
|
3
|
-
import 'zod';
|
|
4
|
-
|
|
5
|
-
interface CallToolParams {
|
|
6
|
-
name: string;
|
|
7
|
-
arguments?: Record<string, unknown> | undefined;
|
|
8
|
-
_meta?: Record<string, unknown> | undefined;
|
|
9
|
-
}
|
|
10
|
-
/** Structural: `Client` from `@modelcontextprotocol/sdk/client` satisfies it. */
|
|
11
|
-
interface McpClientLike {
|
|
12
|
-
callTool(params: CallToolParams, ...rest: unknown[]): Promise<unknown>;
|
|
13
|
-
}
|
|
14
|
-
declare function wrapClient<C extends McpClientLike>(source: SessionSource, client: C, opts?: {
|
|
15
|
-
server?: string;
|
|
16
|
-
}): C;
|
|
17
|
-
/**
|
|
18
|
-
* An in-band payment ask: any object in the result carrying an x402-style
|
|
19
|
-
* `accepts` array (MRTR `input_required`, or a `_meta` envelope). One
|
|
20
|
-
* moment, two artifacts — either becomes the same `payment.requested`.
|
|
21
|
-
*/
|
|
22
|
-
declare function findPaymentAsk(result: unknown): PaymentMomentPayload | null;
|
|
23
|
-
interface ServerCallExtra {
|
|
24
|
-
_meta?: Record<string, unknown> | undefined;
|
|
25
|
-
sessionId?: string | undefined;
|
|
26
|
-
}
|
|
27
|
-
interface WithBelticOptions<Args> {
|
|
28
|
-
toolName: string;
|
|
29
|
-
/** Return the payment this call moves, or null when the call is not value-moving. */
|
|
30
|
-
valueMoving?: (args: Args) => PaymentSummary | null;
|
|
31
|
-
gateway?: string;
|
|
32
|
-
}
|
|
33
|
-
type ToolHandler<Args, R> = (args: Args, extra: ServerCallExtra) => Promise<R> | R;
|
|
34
|
-
interface McpErrorResult {
|
|
35
|
-
isError: true;
|
|
36
|
-
content: Array<{
|
|
37
|
-
type: 'text';
|
|
38
|
-
text: string;
|
|
39
|
-
}>;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Wraps a tool handler on the seller side. Value-moving calls are evaluated
|
|
43
|
-
* synchronously (DENY ⇒ isError result); every decided call is recorded
|
|
44
|
-
* as `gateway.decision` in the buyer's session, or a seller-born one.
|
|
45
|
-
*/
|
|
46
|
-
declare function withBeltic<Args, R>(beltic: Beltic, handler: ToolHandler<Args, R>, opts: WithBelticOptions<Args>): ToolHandler<Args, R | McpErrorResult>;
|
|
47
|
-
/** Structural: `McpServer` from `@modelcontextprotocol/sdk/server/mcp` satisfies it. */
|
|
48
|
-
interface McpServerLike {
|
|
49
|
-
registerTool(name: string, config: unknown, cb: (...a: never[]) => unknown): unknown;
|
|
50
|
-
}
|
|
51
|
-
interface WrapServerOptions {
|
|
52
|
-
valueMoving?: (toolName: string, args: unknown) => PaymentSummary | null;
|
|
53
|
-
gateway?: string;
|
|
54
|
-
}
|
|
55
|
-
/** Patches `registerTool` so every tool goes through `withBeltic`; `valueMoving` decides per tool. */
|
|
56
|
-
declare function wrapServer<S extends McpServerLike>(beltic: Beltic, server: S, opts?: WrapServerOptions): S;
|
|
57
|
-
|
|
58
|
-
export { type CallToolParams, type McpClientLike, type McpErrorResult, type McpServerLike, type ServerCallExtra, type ToolHandler, type WithBelticOptions, type WrapServerOptions, findPaymentAsk, withBeltic, wrapClient, wrapServer };
|
package/dist/mcp/index.js
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Sessions,
|
|
3
|
-
recordCall
|
|
4
|
-
} from "../chunk-4MG6VNAU.js";
|
|
5
|
-
import {
|
|
6
|
-
SESSION_EXTENSION
|
|
7
|
-
} from "../chunk-FAQ442YH.js";
|
|
8
|
-
import {
|
|
9
|
-
uuidv7
|
|
10
|
-
} from "../chunk-X3W2Z5GC.js";
|
|
11
|
-
import {
|
|
12
|
-
Verdict
|
|
13
|
-
} from "../chunk-46QN2KEZ.js";
|
|
14
|
-
import {
|
|
15
|
-
presentedFrom
|
|
16
|
-
} from "../chunk-7G5EHNVW.js";
|
|
17
|
-
import {
|
|
18
|
-
x402Moments
|
|
19
|
-
} from "../chunk-LM4NIYE5.js";
|
|
20
|
-
import {
|
|
21
|
-
toJson,
|
|
22
|
-
toJsonObject
|
|
23
|
-
} from "../chunk-FQDHFTVR.js";
|
|
24
|
-
|
|
25
|
-
// src/mcp/index.ts
|
|
26
|
-
function wrapClient(source, client, opts = {}) {
|
|
27
|
-
if (!source) return client;
|
|
28
|
-
const original = client.callTool.bind(client);
|
|
29
|
-
const callTool = async (params, ...rest) => {
|
|
30
|
-
const session = await Sessions.resolve(source);
|
|
31
|
-
if (!session) return original(params, ...rest);
|
|
32
|
-
return recordCall(
|
|
33
|
-
session,
|
|
34
|
-
"tool_call",
|
|
35
|
-
uuidv7(),
|
|
36
|
-
{
|
|
37
|
-
toolName: params.name,
|
|
38
|
-
input: toJson(params.arguments ?? {}),
|
|
39
|
-
transport: "mcp",
|
|
40
|
-
...opts.server ? { server: opts.server } : {}
|
|
41
|
-
},
|
|
42
|
-
async () => {
|
|
43
|
-
await session.flush();
|
|
44
|
-
return original(
|
|
45
|
-
{ ...params, _meta: { ...params._meta ?? {}, [SESSION_EXTENSION]: session.id } },
|
|
46
|
-
...rest
|
|
47
|
-
);
|
|
48
|
-
},
|
|
49
|
-
async (result) => {
|
|
50
|
-
const ask = findPaymentAsk(result);
|
|
51
|
-
if (ask) await session.emit("payment.requested", ask);
|
|
52
|
-
return { output: toJson(result) };
|
|
53
|
-
}
|
|
54
|
-
);
|
|
55
|
-
};
|
|
56
|
-
return new Proxy(client, {
|
|
57
|
-
get(target, prop, receiver) {
|
|
58
|
-
return prop === "callTool" ? callTool : Reflect.get(target, prop, receiver);
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
function findPaymentAsk(result) {
|
|
63
|
-
const seen = /* @__PURE__ */ new Set();
|
|
64
|
-
const walk = (v, depth) => {
|
|
65
|
-
if (!v || typeof v !== "object" || seen.has(v) || depth > 6) return null;
|
|
66
|
-
seen.add(v);
|
|
67
|
-
const o = v;
|
|
68
|
-
const first = Array.isArray(o.accepts) ? o.accepts[0] : void 0;
|
|
69
|
-
if (typeof first?.payTo === "string") {
|
|
70
|
-
return x402Moments.ask(first, toJsonObject(o));
|
|
71
|
-
}
|
|
72
|
-
for (const child of Array.isArray(o) ? o : Object.values(o)) {
|
|
73
|
-
const hit = walk(child, depth + 1);
|
|
74
|
-
if (hit) return hit;
|
|
75
|
-
}
|
|
76
|
-
return null;
|
|
77
|
-
};
|
|
78
|
-
return walk(result, 0);
|
|
79
|
-
}
|
|
80
|
-
function withBeltic(beltic, handler, opts) {
|
|
81
|
-
const gateway = opts.gateway ?? "sdk-mcp";
|
|
82
|
-
return async (args, extra) => {
|
|
83
|
-
const bound = extra?._meta?.[SESSION_EXTENSION];
|
|
84
|
-
const session = await beltic.sessions.ensure(typeof bound === "string" ? bound : null);
|
|
85
|
-
const payment = opts.valueMoving?.(args) ?? null;
|
|
86
|
-
let verdict = Verdict.ALLOW;
|
|
87
|
-
let reasonCodes = [];
|
|
88
|
-
if (payment) {
|
|
89
|
-
await session.emit(
|
|
90
|
-
"payment.presented",
|
|
91
|
-
presentedFrom(payment, { tool: opts.toolName, args: toJson(args) })
|
|
92
|
-
);
|
|
93
|
-
const out = await beltic.evaluate(session.id, payment);
|
|
94
|
-
if (out) {
|
|
95
|
-
verdict = out.verdict;
|
|
96
|
-
reasonCodes = out.reasonCodes;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
await session.emit("gateway.decision", {
|
|
100
|
-
gateway,
|
|
101
|
-
call: { tool: opts.toolName, args: toJson(args) },
|
|
102
|
-
decision: verdict.effective(beltic.onReview),
|
|
103
|
-
reasonCodes,
|
|
104
|
-
record: { valueMoving: payment !== null, bound: typeof bound === "string" }
|
|
105
|
-
});
|
|
106
|
-
if (verdict.blocks(beltic.onReview)) {
|
|
107
|
-
return {
|
|
108
|
-
isError: true,
|
|
109
|
-
content: [
|
|
110
|
-
{ type: "text", text: `Beltic ${verdict.value}: ${reasonCodes.join(",") || "denied"}` }
|
|
111
|
-
]
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
return handler(args, extra);
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
function wrapServer(beltic, server, opts = {}) {
|
|
118
|
-
const original = server.registerTool.bind(server);
|
|
119
|
-
server.registerTool = ((name, config, cb) => original(
|
|
120
|
-
name,
|
|
121
|
-
config,
|
|
122
|
-
withBeltic(beltic, cb, {
|
|
123
|
-
toolName: name,
|
|
124
|
-
...opts.gateway ? { gateway: opts.gateway } : {},
|
|
125
|
-
valueMoving: (args) => opts.valueMoving?.(name, args) ?? null
|
|
126
|
-
})
|
|
127
|
-
));
|
|
128
|
-
return server;
|
|
129
|
-
}
|
|
130
|
-
export {
|
|
131
|
-
findPaymentAsk,
|
|
132
|
-
withBeltic,
|
|
133
|
-
wrapClient,
|
|
134
|
-
wrapServer
|
|
135
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { PaywallConfig } from '@x402/core/server';
|
|
2
|
-
import { A as AttachOptions } from './adapter-BEpzr2R3.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The seller half as one middleware: the framework's `@x402/*` payment
|
|
6
|
-
* middleware over an `x402HTTPResourceServer` with the Beltic hooks
|
|
7
|
-
* attached. `@belticlabs/agent-risk-sdk/hono` and `@belticlabs/agent-risk-sdk/express` differ only in
|
|
8
|
-
* which `paymentMiddlewareFromHTTPServer` they hand in.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
type GuardedMiddlewareOptions = AttachOptions & {
|
|
12
|
-
paywall?: PaywallConfig | undefined;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export type { GuardedMiddlewareOptions as G };
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { B as Beltic } from '../session-DsBWEP8d.js';
|
|
2
|
-
import '../verdict-6vCyoAHE.js';
|
|
3
|
-
import 'zod';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Adapter for the anti-fraud port already in Beltic's `platform` monorepo
|
|
7
|
-
* (`x402-core/gateways/anti-fraud.gateway.interface.ts`), GAP-37. That
|
|
8
|
-
* port is binary and session-less; the mapping is lossy by construction:
|
|
9
|
-
* `REVIEW` becomes a deny unless `onReview` says otherwise, and reason
|
|
10
|
-
* codes travel joined in `reason`. The structural type is copied so this
|
|
11
|
-
* module needs no dependency on `platform`.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
interface PaymentRiskContext {
|
|
15
|
-
wallet: string;
|
|
16
|
-
resource: string;
|
|
17
|
-
amountAtomic: string;
|
|
18
|
-
asset: string;
|
|
19
|
-
network: string;
|
|
20
|
-
paymentIdentifier?: string;
|
|
21
|
-
/** Not in the platform port yet — pass it when you have it. */
|
|
22
|
-
sessionId?: string;
|
|
23
|
-
payTo?: string;
|
|
24
|
-
}
|
|
25
|
-
type RiskDecision = {
|
|
26
|
-
allow: true;
|
|
27
|
-
} | {
|
|
28
|
-
allow: false;
|
|
29
|
-
reason: string;
|
|
30
|
-
};
|
|
31
|
-
interface AntiFraudGateway {
|
|
32
|
-
assess(context: PaymentRiskContext): Promise<RiskDecision>;
|
|
33
|
-
}
|
|
34
|
-
declare class BelticAntiFraudGateway implements AntiFraudGateway {
|
|
35
|
-
private readonly beltic;
|
|
36
|
-
constructor(beltic: Beltic);
|
|
37
|
-
assess(ctx: PaymentRiskContext): Promise<RiskDecision>;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export { type AntiFraudGateway, BelticAntiFraudGateway, type PaymentRiskContext, type RiskDecision };
|