@fidacy/mcp 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assess.js +110 -129
- package/dist/core.js +406 -147
- package/dist/index.js +719 -103
- package/dist/lib.js +527 -5
- package/package.json +19 -11
- package/dist/assess.d.ts +0 -78
- package/dist/assess.js.map +0 -1
- package/dist/audit-store.d.ts +0 -11
- package/dist/audit-store.js +0 -51
- package/dist/audit-store.js.map +0 -1
- package/dist/core.d.ts +0 -34
- package/dist/core.js.map +0 -1
- package/dist/executor.d.ts +0 -30
- package/dist/executor.js +0 -64
- package/dist/executor.js.map +0 -1
- package/dist/grant.d.ts +0 -20
- package/dist/grant.js +0 -41
- package/dist/grant.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js.map +0 -1
- package/dist/lib.d.ts +0 -4
- package/dist/lib.js.map +0 -1
- package/dist/signing.d.ts +0 -10
- package/dist/signing.js +0 -32
- package/dist/signing.js.map +0 -1
- package/dist/types.d.ts +0 -52
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/util.d.ts +0 -1
- package/dist/util.js +0 -9
- package/dist/util.js.map +0 -1
package/dist/assess.js
CHANGED
|
@@ -1,139 +1,120 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
status;
|
|
20
|
-
details;
|
|
21
|
-
rejection_reasons;
|
|
22
|
-
constructor(opts) {
|
|
23
|
-
super(`Fidacy assess error (${opts.type}, HTTP ${opts.status})`);
|
|
24
|
-
this.name = "AssessError";
|
|
25
|
-
this.type = opts.type;
|
|
26
|
-
this.status = opts.status;
|
|
27
|
-
this.details = opts.details;
|
|
28
|
-
this.rejection_reasons = opts.rejection_reasons;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
const DEFAULT_TIMEOUT = 10_000;
|
|
32
|
-
const DEFAULT_RETRIES = 2;
|
|
33
|
-
const defaultBackoff = (n) => Math.min(200 * 2 ** n, 2_000);
|
|
1
|
+
// src/assess.ts
|
|
2
|
+
var AssessError = class extends Error {
|
|
3
|
+
type;
|
|
4
|
+
status;
|
|
5
|
+
details;
|
|
6
|
+
rejection_reasons;
|
|
7
|
+
constructor(opts) {
|
|
8
|
+
super(`Fidacy assess error (${opts.type}, HTTP ${opts.status})`);
|
|
9
|
+
this.name = "AssessError";
|
|
10
|
+
this.type = opts.type;
|
|
11
|
+
this.status = opts.status;
|
|
12
|
+
this.details = opts.details;
|
|
13
|
+
this.rejection_reasons = opts.rejection_reasons;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var DEFAULT_TIMEOUT = 1e4;
|
|
17
|
+
var DEFAULT_RETRIES = 2;
|
|
18
|
+
var defaultBackoff = (n) => Math.min(200 * 2 ** n, 2e3);
|
|
34
19
|
function isRecord(v) {
|
|
35
|
-
|
|
20
|
+
return typeof v === "object" && v !== null;
|
|
36
21
|
}
|
|
37
22
|
function sleep(ms) {
|
|
38
|
-
|
|
23
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
39
24
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
25
|
+
function requireSafeBaseUrl(raw) {
|
|
26
|
+
const trimmed = String(raw ?? "").replace(/\/+$/, "");
|
|
27
|
+
let u;
|
|
28
|
+
try {
|
|
29
|
+
u = new URL(trimmed);
|
|
30
|
+
} catch {
|
|
31
|
+
throw new AssessError({ type: "config_error", status: 0 });
|
|
32
|
+
}
|
|
33
|
+
const isLocalHttp = u.protocol === "http:" && (u.hostname === "localhost" || u.hostname === "127.0.0.1" || u.hostname === "[::1]");
|
|
34
|
+
if (u.protocol !== "https:" && !isLocalHttp) {
|
|
35
|
+
throw new AssessError({ type: "config_error", status: 0 });
|
|
36
|
+
}
|
|
37
|
+
return trimmed;
|
|
38
|
+
}
|
|
39
|
+
async function assessAction(params, cfg) {
|
|
40
|
+
const fetchImpl = cfg.fetchImpl ?? globalThis.fetch;
|
|
41
|
+
if (typeof fetchImpl !== "function") {
|
|
42
|
+
throw new AssessError({ type: "config_error", status: 0 });
|
|
43
|
+
}
|
|
44
|
+
const baseUrl = requireSafeBaseUrl(cfg.engineUrl);
|
|
45
|
+
const url = `${baseUrl}/v1/assess`;
|
|
46
|
+
const timeoutMs = cfg.timeoutMs ?? DEFAULT_TIMEOUT;
|
|
47
|
+
const maxRetries = cfg.maxRetries ?? DEFAULT_RETRIES;
|
|
48
|
+
const backoffMs = cfg.backoffMs ?? defaultBackoff;
|
|
49
|
+
const body = {
|
|
50
|
+
kind: params.kind ?? "ap2_payment",
|
|
51
|
+
mandate: params.mandate
|
|
52
|
+
};
|
|
53
|
+
if (params.mandateType !== void 0) body.mandateType = params.mandateType;
|
|
54
|
+
if (params.a2a !== void 0) body.a2a = params.a2a;
|
|
55
|
+
if (params.spendingMandate !== void 0) body.spending_mandate = params.spendingMandate;
|
|
56
|
+
if (params.idempotencyKey !== void 0) body.idempotency_key = params.idempotencyKey;
|
|
57
|
+
const payload = JSON.stringify(body);
|
|
58
|
+
if (payload.length > 256 * 1024) {
|
|
59
|
+
throw new AssessError({ type: "config_error", status: 0 });
|
|
60
|
+
}
|
|
61
|
+
const headers = {
|
|
62
|
+
"content-type": "application/json",
|
|
63
|
+
authorization: `Bearer ${cfg.apiKey}`
|
|
64
|
+
};
|
|
65
|
+
if (params.a2a !== void 0) headers["A2A-Version"] = "0.1.0";
|
|
66
|
+
const canRetryTransient = params.idempotencyKey !== void 0;
|
|
67
|
+
let attempt = 0;
|
|
68
|
+
for (; ; ) {
|
|
69
|
+
try {
|
|
70
|
+
return await postOnce(fetchImpl, url, headers, payload, timeoutMs);
|
|
71
|
+
} catch (err) {
|
|
72
|
+
const isTransient = err instanceof AssessError && (err.status === 0 || err.status === 429 || err.status >= 500);
|
|
73
|
+
const canRetry = isTransient && canRetryTransient && attempt < maxRetries;
|
|
74
|
+
if (!canRetry) throw err;
|
|
75
|
+
await sleep(backoffMs(attempt));
|
|
76
|
+
attempt += 1;
|
|
93
77
|
}
|
|
78
|
+
}
|
|
94
79
|
}
|
|
95
80
|
async function postOnce(fetchImpl, url, headers, payload, timeoutMs) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
81
|
+
const controller = new AbortController();
|
|
82
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
83
|
+
let res;
|
|
84
|
+
try {
|
|
85
|
+
res = await fetchImpl(url, {
|
|
86
|
+
method: "POST",
|
|
87
|
+
headers,
|
|
88
|
+
body: payload,
|
|
89
|
+
signal: controller.signal
|
|
90
|
+
});
|
|
91
|
+
} catch (err) {
|
|
92
|
+
const aborted = controller.signal.aborted;
|
|
93
|
+
throw new AssessError({ type: aborted ? "timeout" : "network_error", status: 0 });
|
|
94
|
+
} finally {
|
|
95
|
+
clearTimeout(timer);
|
|
96
|
+
}
|
|
97
|
+
const text = await res.text();
|
|
98
|
+
let parsed = void 0;
|
|
99
|
+
if (text) {
|
|
99
100
|
try {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
headers,
|
|
103
|
-
body: payload,
|
|
104
|
-
signal: controller.signal,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
catch (err) {
|
|
108
|
-
const aborted = controller.signal.aborted;
|
|
109
|
-
// Never attach the key/body/err message that could leak a secret.
|
|
110
|
-
throw new AssessError({ type: aborted ? "timeout" : "network_error", status: 0 });
|
|
111
|
-
}
|
|
112
|
-
finally {
|
|
113
|
-
clearTimeout(timer);
|
|
114
|
-
}
|
|
115
|
-
const text = await res.text();
|
|
116
|
-
let parsed = undefined;
|
|
117
|
-
if (text) {
|
|
118
|
-
try {
|
|
119
|
-
parsed = JSON.parse(text);
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
// non-JSON response: handled below by status
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
if (!res.ok) {
|
|
126
|
-
const type = (isRecord(parsed) && typeof parsed.error === "string" && parsed.error) ||
|
|
127
|
-
`http_${res.status}`;
|
|
128
|
-
const details = isRecord(parsed) ? parsed.details : undefined;
|
|
129
|
-
const rejection_reasons = isRecord(parsed) && Array.isArray(parsed.rejection_reasons)
|
|
130
|
-
? parsed.rejection_reasons
|
|
131
|
-
: undefined;
|
|
132
|
-
throw new AssessError({ type, status: res.status, details, rejection_reasons });
|
|
133
|
-
}
|
|
134
|
-
if (!isRecord(parsed)) {
|
|
135
|
-
throw new AssessError({ type: "invalid_response", status: res.status });
|
|
101
|
+
parsed = JSON.parse(text);
|
|
102
|
+
} catch {
|
|
136
103
|
}
|
|
137
|
-
|
|
104
|
+
}
|
|
105
|
+
if (!res.ok) {
|
|
106
|
+
const type = isRecord(parsed) && typeof parsed.error === "string" && parsed.error || `http_${res.status}`;
|
|
107
|
+
const details = isRecord(parsed) ? parsed.details : void 0;
|
|
108
|
+
const rejection_reasons = isRecord(parsed) && Array.isArray(parsed.rejection_reasons) ? parsed.rejection_reasons : void 0;
|
|
109
|
+
throw new AssessError({ type, status: res.status, details, rejection_reasons });
|
|
110
|
+
}
|
|
111
|
+
if (!isRecord(parsed)) {
|
|
112
|
+
throw new AssessError({ type: "invalid_response", status: res.status });
|
|
113
|
+
}
|
|
114
|
+
return parsed;
|
|
138
115
|
}
|
|
139
|
-
|
|
116
|
+
export {
|
|
117
|
+
AssessError,
|
|
118
|
+
assessAction,
|
|
119
|
+
requireSafeBaseUrl
|
|
120
|
+
};
|