@devlab.group/agent-commerce 1.6.0 → 2.0.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/LICENSE +187 -2
- package/README.md +6 -6
- package/dist/ap2.d.ts +2 -2
- package/dist/ap2.js +94 -28
- package/dist/ap2.js.map +1 -1
- package/dist/{chunk-V2V2E7HX.js → chunk-3LUJHVKX.js} +4 -4
- package/dist/{chunk-V2V2E7HX.js.map → chunk-3LUJHVKX.js.map} +1 -1
- package/dist/{chunk-IVJC5YLE.js → chunk-53WXXIPR.js} +3 -3
- package/dist/{chunk-IVJC5YLE.js.map → chunk-53WXXIPR.js.map} +1 -1
- package/dist/chunk-CKJRITWY.js +113 -0
- package/dist/chunk-CKJRITWY.js.map +1 -0
- package/dist/chunk-HOZA3IWP.js +115 -0
- package/dist/chunk-HOZA3IWP.js.map +1 -0
- package/dist/{chunk-ATTWSFQP.js → chunk-RKBGCPCK.js} +78 -25
- package/dist/chunk-RKBGCPCK.js.map +1 -0
- package/dist/{chunk-RAJGPGJG.js → chunk-SYEGCNJZ.js} +3 -3
- package/dist/{chunk-RAJGPGJG.js.map → chunk-SYEGCNJZ.js.map} +1 -1
- package/dist/{chunk-74BSEXB5.js → chunk-TWRUNWDR.js} +11 -4
- package/dist/chunk-TWRUNWDR.js.map +1 -0
- package/dist/cli/index.js +143 -34
- package/dist/cli/index.js.map +1 -1
- package/dist/{constants-Bkq04FRZ.d.ts → constants-BSBRlKRR.d.ts} +2 -2
- package/dist/index.d.ts +42 -22
- package/dist/index.js +1254 -377
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +247 -94
- package/dist/mcp.js.map +1 -1
- package/dist/mpp.d.ts +6 -2
- package/dist/mpp.js +65 -28
- package/dist/mpp.js.map +1 -1
- package/dist/{guardrails-71XwtXlT.d.ts → payment-flow-DCS882tR.d.ts} +9 -1
- package/dist/{protocol-adapter-DTkrXTev.d.ts → protocol-adapter-DonxfAwa.d.ts} +2 -0
- package/dist/{types-O6lg3Q5V.d.ts → types-CVw6Sf46.d.ts} +11 -0
- package/dist/x402.d.ts +11 -3
- package/dist/x402.js +4 -4
- package/package.json +22 -17
- package/dist/chunk-74BSEXB5.js.map +0 -1
- package/dist/chunk-AFI2CEZS.js +0 -10
- package/dist/chunk-AFI2CEZS.js.map +0 -1
- package/dist/chunk-ATTWSFQP.js.map +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import picocolors from 'picocolors';
|
|
|
10
10
|
import { randomUUID } from 'crypto';
|
|
11
11
|
import 'module';
|
|
12
12
|
import Database from 'better-sqlite3';
|
|
13
|
-
import { writeFile, stat, rename, rm, open } from 'fs/promises';
|
|
13
|
+
import { writeFile, stat, mkdir, rename, rm, open } from 'fs/promises';
|
|
14
14
|
import { validate } from '@scalar/openapi-parser';
|
|
15
15
|
import * as clack from '@clack/prompts';
|
|
16
16
|
|
|
@@ -279,6 +279,12 @@ var init_backend_http = __esm({
|
|
|
279
279
|
PATH_PARAM_PATTERN = /\{([a-zA-Z0-9_.-]+)\}/g;
|
|
280
280
|
}
|
|
281
281
|
});
|
|
282
|
+
|
|
283
|
+
// src/core/execution/settlement-order.ts
|
|
284
|
+
var init_settlement_order = __esm({
|
|
285
|
+
"src/core/execution/settlement-order.ts"() {
|
|
286
|
+
}
|
|
287
|
+
});
|
|
282
288
|
function typeList(raw) {
|
|
283
289
|
if (typeof raw === "string") return [raw];
|
|
284
290
|
if (Array.isArray(raw) && raw.every((entry) => typeof entry === "string")) {
|
|
@@ -302,6 +308,7 @@ var init_pipeline = __esm({
|
|
|
302
308
|
init_errors();
|
|
303
309
|
init_is_record();
|
|
304
310
|
init_backend_http();
|
|
311
|
+
init_settlement_order();
|
|
305
312
|
init_validation();
|
|
306
313
|
[...RESERVED_INPUT_FIELDS, "__proto__"];
|
|
307
314
|
}
|
|
@@ -341,12 +348,12 @@ var init_constants2 = __esm({
|
|
|
341
348
|
"src/payments/mpp/constants.ts"() {
|
|
342
349
|
MPP_SPEC_COMMIT = "806fdb8b8c92cda5c84b8660558921b6bbeef7e0";
|
|
343
350
|
MPP_SPEC_DRAFTS = {
|
|
344
|
-
core: "draft-httpauth-payment-
|
|
351
|
+
core: "draft-httpauth-payment-01",
|
|
345
352
|
intent: "draft-payment-intent-charge-00",
|
|
346
353
|
method: "draft-evm-charge-00"
|
|
347
354
|
};
|
|
348
355
|
MPP_MIN_CHALLENGE_SECRET_LENGTH = 32;
|
|
349
|
-
MPPX_VERSION = "0.
|
|
356
|
+
MPPX_VERSION = "0.13.1";
|
|
350
357
|
MPP_PROFILE = {
|
|
351
358
|
intent: "charge",
|
|
352
359
|
method: "evm",
|
|
@@ -419,7 +426,7 @@ var init_networks = __esm({
|
|
|
419
426
|
});
|
|
420
427
|
|
|
421
428
|
// src/protocols/acp/constants.ts
|
|
422
|
-
var ACP_SPEC_VERSION, ACP_API_VERSION, ACP_WELL_KNOWN_PATH, ACP_CHECKOUT_OPERATIONS, ACP_OPERATION_INPUT_KEYS, ACP_OPERATION_OPTIONAL_INPUT_KEYS;
|
|
429
|
+
var ACP_SPEC_VERSION, ACP_API_VERSION, ACP_WELL_KNOWN_PATH, ACP_CHECKOUT_OPERATIONS, ACP_OPERATION_INPUT_KEYS, ACP_OPERATION_OPTIONAL_INPUT_KEYS, ACP_SESSION_ID_INPUT_KEY;
|
|
423
430
|
var init_constants3 = __esm({
|
|
424
431
|
"src/protocols/acp/constants.ts"() {
|
|
425
432
|
ACP_SPEC_VERSION = "2026-04-17";
|
|
@@ -442,6 +449,7 @@ var init_constants3 = __esm({
|
|
|
442
449
|
ACP_OPERATION_OPTIONAL_INPUT_KEYS = {
|
|
443
450
|
cancelCheckoutSession: ["body"]
|
|
444
451
|
};
|
|
452
|
+
ACP_SESSION_ID_INPUT_KEY = "checkout_session_id";
|
|
445
453
|
}
|
|
446
454
|
});
|
|
447
455
|
|
|
@@ -694,6 +702,15 @@ var init_guardrails = __esm({
|
|
|
694
702
|
}
|
|
695
703
|
});
|
|
696
704
|
|
|
705
|
+
// src/payments/x402/payment-flow.ts
|
|
706
|
+
var X402_PAYMENT_FLOWS, X402_DEFAULT_PAYMENT_FLOW;
|
|
707
|
+
var init_payment_flow = __esm({
|
|
708
|
+
"src/payments/x402/payment-flow.ts"() {
|
|
709
|
+
X402_PAYMENT_FLOWS = ["authorization", "upfront"];
|
|
710
|
+
X402_DEFAULT_PAYMENT_FLOW = "authorization";
|
|
711
|
+
}
|
|
712
|
+
});
|
|
713
|
+
|
|
697
714
|
// src/protocols/mcp/constants.ts
|
|
698
715
|
var MCP_TOOL_NAME_CHARS, MCP_TOOL_NAME_MAX_LENGTH, MCP_TOOL_NAME_PATTERN;
|
|
699
716
|
var init_constants4 = __esm({
|
|
@@ -836,6 +853,7 @@ function normalize(raw) {
|
|
|
836
853
|
min: 1
|
|
837
854
|
}
|
|
838
855
|
),
|
|
856
|
+
paymentFlow: x402Raw.paymentFlow ?? X402_DEFAULT_PAYMENT_FLOW,
|
|
839
857
|
facilitator: normalizeFacilitator(x402Raw.facilitator),
|
|
840
858
|
...x402Raw.allowMainnet !== void 0 ? { allowMainnet: toBoolean(x402Raw.allowMainnet, "payments.x402.allowMainnet") } : {},
|
|
841
859
|
...x402Raw.allowUnauthenticatedFacilitator !== void 0 ? {
|
|
@@ -867,7 +885,22 @@ function normalize(raw) {
|
|
|
867
885
|
const resources = Object.entries(raw.resources).map(
|
|
868
886
|
([id, entry]) => normalizeResource(id, entry, protocols, x402, mpp, ap2)
|
|
869
887
|
);
|
|
888
|
+
const resourcePaymentFlows = Object.fromEntries(
|
|
889
|
+
Object.entries(raw.resources).flatMap(
|
|
890
|
+
([id, entry]) => entry.paymentFlow !== void 0 ? [[id, entry.paymentFlow]] : []
|
|
891
|
+
)
|
|
892
|
+
);
|
|
893
|
+
const hasFlowOverrides = Object.keys(resourcePaymentFlows).length > 0;
|
|
894
|
+
const x402WithFlows = x402 !== void 0 && hasFlowOverrides ? { ...x402, resourcePaymentFlows } : x402;
|
|
895
|
+
const mppWithFlows = mpp !== void 0 && hasFlowOverrides ? { ...mpp, resourcePaymentFlows } : mpp;
|
|
870
896
|
if (protocols.acp.enabled) validateAcpCheckoutMapping(protocols.acp, resources);
|
|
897
|
+
if (protocols.a2a.enabled && !resources.some((r) => r.exposedVia.includes("a2a"))) {
|
|
898
|
+
throw new CommerceError(
|
|
899
|
+
"CONFIG_INVALID",
|
|
900
|
+
'protocols.a2a.enabled is true but no resource lists "a2a" in its expose',
|
|
901
|
+
{ details: { path: "protocols.a2a.enabled" } }
|
|
902
|
+
);
|
|
903
|
+
}
|
|
871
904
|
return {
|
|
872
905
|
version: SUPPORTED_CONFIG_VERSION,
|
|
873
906
|
merchant: {
|
|
@@ -886,8 +919,8 @@ function normalize(raw) {
|
|
|
886
919
|
protocols,
|
|
887
920
|
resources,
|
|
888
921
|
payments: {
|
|
889
|
-
...
|
|
890
|
-
...
|
|
922
|
+
...x402WithFlows !== void 0 ? { x402: x402WithFlows } : {},
|
|
923
|
+
...mppWithFlows !== void 0 ? { mpp: mppWithFlows } : {}
|
|
891
924
|
},
|
|
892
925
|
...ap2 !== void 0 ? { authorization: { ap2 } } : {}
|
|
893
926
|
};
|
|
@@ -956,6 +989,14 @@ function normalizeAp2(raw) {
|
|
|
956
989
|
"authorization.ap2.clockSkewSeconds",
|
|
957
990
|
{ min: 0, max: AP2_MAX_CLOCK_SKEW_SECONDS }
|
|
958
991
|
),
|
|
992
|
+
requireMandateAudience: toBoolean(
|
|
993
|
+
raw.requireMandateAudience ?? false,
|
|
994
|
+
"authorization.ap2.requireMandateAudience"
|
|
995
|
+
),
|
|
996
|
+
requireMandateExpiry: toBoolean(
|
|
997
|
+
raw.requireMandateExpiry ?? false,
|
|
998
|
+
"authorization.ap2.requireMandateExpiry"
|
|
999
|
+
),
|
|
959
1000
|
replay: { path: raw.replay.path }
|
|
960
1001
|
};
|
|
961
1002
|
}
|
|
@@ -1131,7 +1172,8 @@ function normalizeAcp(raw) {
|
|
|
1131
1172
|
raw.idempotency.retentionHours ?? ACP_RETENTION_HOURS,
|
|
1132
1173
|
"protocols.acp.idempotency.retentionHours",
|
|
1133
1174
|
{ min: ACP_RETENTION_HOURS }
|
|
1134
|
-
)
|
|
1175
|
+
),
|
|
1176
|
+
merchantIdempotent: raw.idempotency.merchantIdempotent ?? false
|
|
1135
1177
|
},
|
|
1136
1178
|
checkout: { operations: normalizeAcpOperations(raw.checkout) },
|
|
1137
1179
|
// Built key by key so absent metadata stays absent rather than `undefined`
|
|
@@ -1214,10 +1256,11 @@ function validateAcpOperationInput(path2, operation, resource) {
|
|
|
1214
1256
|
if (schema === void 0) return;
|
|
1215
1257
|
const keys = ACP_OPERATION_INPUT_KEYS[operation];
|
|
1216
1258
|
const optionalKeys = ACP_OPERATION_OPTIONAL_INPUT_KEYS[operation] ?? [];
|
|
1217
|
-
const
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1259
|
+
const sent = [...keys, ...optionalKeys];
|
|
1260
|
+
const topLevel = closedObjectProperties(schema);
|
|
1261
|
+
if (topLevel !== void 0) {
|
|
1262
|
+
for (const key of sent) {
|
|
1263
|
+
if (!Object.hasOwn(topLevel, key)) {
|
|
1221
1264
|
const when = keys.includes(key) ? "always sends" : "sends when the caller supplies it";
|
|
1222
1265
|
throw acpInvalid(
|
|
1223
1266
|
path2,
|
|
@@ -1227,6 +1270,23 @@ function validateAcpOperationInput(path2, operation, resource) {
|
|
|
1227
1270
|
}
|
|
1228
1271
|
}
|
|
1229
1272
|
}
|
|
1273
|
+
const declared = isRecord(schema["properties"]) ? schema["properties"] : {};
|
|
1274
|
+
const pathKeys = closedObjectProperties(declared["path"]);
|
|
1275
|
+
if (sent.includes("path") && pathKeys !== void 0 && !Object.hasOwn(pathKeys, ACP_SESSION_ID_INPUT_KEY)) {
|
|
1276
|
+
throw acpInvalid(
|
|
1277
|
+
path2,
|
|
1278
|
+
`Resource "${resource.id}" implements ACP operation "${operation}" but its "path" schema sets additionalProperties: false without declaring "${ACP_SESSION_ID_INPUT_KEY}", which the adapter always sends inside "path"`,
|
|
1279
|
+
{ resourceId: resource.id }
|
|
1280
|
+
);
|
|
1281
|
+
}
|
|
1282
|
+
const bodyKeys = closedObjectProperties(declared["body"]);
|
|
1283
|
+
if (sent.includes("body") && bodyKeys !== void 0 && Object.keys(bodyKeys).length === 0) {
|
|
1284
|
+
throw acpInvalid(
|
|
1285
|
+
path2,
|
|
1286
|
+
`Resource "${resource.id}" implements ACP operation "${operation}" but its "body" schema accepts no keys, so it refuses every ACP document. Config load closes an object schema that omits additionalProperties: declare body as { type: object, additionalProperties: true }`,
|
|
1287
|
+
{ resourceId: resource.id }
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1230
1290
|
const required = schema["required"];
|
|
1231
1291
|
if (Array.isArray(required)) {
|
|
1232
1292
|
for (const entry of required) {
|
|
@@ -1240,6 +1300,10 @@ function validateAcpOperationInput(path2, operation, resource) {
|
|
|
1240
1300
|
}
|
|
1241
1301
|
}
|
|
1242
1302
|
}
|
|
1303
|
+
function closedObjectProperties(schema) {
|
|
1304
|
+
if (!isRecord(schema) || schema["additionalProperties"] !== false) return void 0;
|
|
1305
|
+
return isRecord(schema["properties"]) ? schema["properties"] : {};
|
|
1306
|
+
}
|
|
1243
1307
|
function normalizeFacilitator(raw) {
|
|
1244
1308
|
return raw.mode === "local" ? { mode: "local", signerPrivateKey: raw.signerPrivateKey } : { mode: "remote", url: raw.url, auth: raw.auth ?? { type: "none" } };
|
|
1245
1309
|
}
|
|
@@ -1270,6 +1334,7 @@ function normalizeMpp(raw) {
|
|
|
1270
1334
|
{ min: 1 }
|
|
1271
1335
|
)
|
|
1272
1336
|
} : {},
|
|
1337
|
+
paymentFlow: raw.paymentFlow ?? X402_DEFAULT_PAYMENT_FLOW,
|
|
1273
1338
|
facilitator: normalizeFacilitator(raw.facilitator),
|
|
1274
1339
|
...raw.allowMainnet !== void 0 ? { allowMainnet: toBoolean(raw.allowMainnet, "payments.mpp.allowMainnet") } : {},
|
|
1275
1340
|
...raw.allowUnauthenticatedFacilitator !== void 0 ? {
|
|
@@ -1423,6 +1488,13 @@ function normalizeResource(id, entry, protocols, x402, mpp, ap2) {
|
|
|
1423
1488
|
validatePricingAmount(id, entry.pricing.amount, MPP_PROFILE.assetDecimals);
|
|
1424
1489
|
}
|
|
1425
1490
|
}
|
|
1491
|
+
if (entry.paymentFlow !== void 0 && (entry.pricing.type !== "fixed" || !paymentMethods.some((method) => method === "x402" || method === "mpp"))) {
|
|
1492
|
+
throw new CommerceError(
|
|
1493
|
+
"CONFIG_INVALID",
|
|
1494
|
+
`Resource "${id}" sets paymentFlow, which requires fixed pricing and "x402" or "mpp" in payments`,
|
|
1495
|
+
{ details: { path: `resources.${id}.paymentFlow`, resourceId: id } }
|
|
1496
|
+
);
|
|
1497
|
+
}
|
|
1426
1498
|
const pricing = entry.pricing.type === "free" ? { type: "free" } : { type: "fixed", amount: entry.pricing.amount, currency: entry.pricing.currency };
|
|
1427
1499
|
const authorization = normalizeResourceAuthorization(id, entry, pricing, ap2);
|
|
1428
1500
|
return {
|
|
@@ -1745,6 +1817,7 @@ var init_schema = __esm({
|
|
|
1745
1817
|
init_is_record();
|
|
1746
1818
|
init_constants2();
|
|
1747
1819
|
init_guardrails();
|
|
1820
|
+
init_payment_flow();
|
|
1748
1821
|
init_constants3();
|
|
1749
1822
|
init_constants4();
|
|
1750
1823
|
init_env();
|
|
@@ -1812,7 +1885,11 @@ var init_schema = __esm({
|
|
|
1812
1885
|
}
|
|
1813
1886
|
);
|
|
1814
1887
|
AcpAuthSchema = z.object({ type: z.literal("bearer"), token: z.string().min(1) }).strict();
|
|
1815
|
-
AcpIdempotencySchema = z.object({
|
|
1888
|
+
AcpIdempotencySchema = z.object({
|
|
1889
|
+
path: z.string().min(1),
|
|
1890
|
+
retentionHours: NumberOrString.optional(),
|
|
1891
|
+
merchantIdempotent: z.boolean().optional()
|
|
1892
|
+
}).strict();
|
|
1816
1893
|
AcpCheckoutSchema = z.object({ operations: z.record(z.string().min(1)) }).strict();
|
|
1817
1894
|
AcpDiscoverySchema = z.object({
|
|
1818
1895
|
documentationUrl: z.string().min(1).optional(),
|
|
@@ -1882,6 +1959,7 @@ var init_schema = __esm({
|
|
|
1882
1959
|
pricing: PricingSchema,
|
|
1883
1960
|
expose: z.array(z.string().min(1)).min(1),
|
|
1884
1961
|
payments: z.array(z.string().min(1)).optional(),
|
|
1962
|
+
paymentFlow: z.enum(X402_PAYMENT_FLOWS).optional(),
|
|
1885
1963
|
authorization: z.object({ required: z.array(z.string().min(1)).min(1) }).strict().optional()
|
|
1886
1964
|
}).strict();
|
|
1887
1965
|
ResourcesMapSchema = z.record(z.string().min(1), ResourceEntrySchema);
|
|
@@ -1919,6 +1997,8 @@ var init_schema = __esm({
|
|
|
1919
1997
|
assetDecimals: NumberOrString,
|
|
1920
1998
|
payTo: z.string().min(1),
|
|
1921
1999
|
maxTimeoutSeconds: NumberOrString,
|
|
2000
|
+
// `authorization` (the x402 default) settles after the backend call
|
|
2001
|
+
paymentFlow: z.enum(X402_PAYMENT_FLOWS).optional(),
|
|
1922
2002
|
facilitator: FacilitatorSchema,
|
|
1923
2003
|
// Real funds. Never defaulted; see src/payments/x402/guardrails.ts
|
|
1924
2004
|
allowMainnet: BooleanOrString.optional(),
|
|
@@ -1936,6 +2016,8 @@ var init_schema = __esm({
|
|
|
1936
2016
|
realm: z.string().min(1),
|
|
1937
2017
|
challengeSecret: z.string().min(1),
|
|
1938
2018
|
challengeTtlSeconds: NumberOrString.optional(),
|
|
2019
|
+
// Same values and default as `payments.x402.paymentFlow`
|
|
2020
|
+
paymentFlow: z.enum(X402_PAYMENT_FLOWS).optional(),
|
|
1939
2021
|
facilitator: FacilitatorSchema,
|
|
1940
2022
|
// Real funds. Never defaulted; see src/payments/x402/guardrails.ts
|
|
1941
2023
|
allowMainnet: BooleanOrString.optional(),
|
|
@@ -1966,6 +2048,8 @@ var init_schema = __esm({
|
|
|
1966
2048
|
checkoutIssuers: z.array(Ap2IssuerSchema).optional()
|
|
1967
2049
|
}).strict().optional(),
|
|
1968
2050
|
clockSkewSeconds: NumberOrString.optional(),
|
|
2051
|
+
requireMandateAudience: BooleanOrString.optional(),
|
|
2052
|
+
requireMandateExpiry: BooleanOrString.optional(),
|
|
1969
2053
|
replay: z.object({ path: z.string().min(1) }).strict().optional()
|
|
1970
2054
|
}).strict();
|
|
1971
2055
|
AuthorizationSchema = z.object({ ap2: Ap2Schema.optional() }).strict();
|
|
@@ -2166,10 +2250,12 @@ var AP2_UNSUPPORTED = [
|
|
|
2166
2250
|
// Mandate kinds. Open mandates are refused: see AP2_CHECKOUT_MANDATE_VCT
|
|
2167
2251
|
"autonomous mode",
|
|
2168
2252
|
"open checkout mandates (mandate.checkout.open.1)",
|
|
2169
|
-
"
|
|
2170
|
-
"cart mandates",
|
|
2253
|
+
"payment mandates (mandate.payment.1)",
|
|
2171
2254
|
"spending constraint evaluation",
|
|
2172
2255
|
"cnf-bound agent keys",
|
|
2256
|
+
// Delegation models other than a trusted agent provider
|
|
2257
|
+
"user credential delegation (OpenID4VP)",
|
|
2258
|
+
"delegation chains and key-binding JWTs",
|
|
2173
2259
|
// Key handling. Every key is written into config by an operator
|
|
2174
2260
|
"JWKS and any key discovery by URL (jku, x5u)",
|
|
2175
2261
|
"issuer metadata fetching",
|
|
@@ -2179,6 +2265,7 @@ var AP2_UNSUPPORTED = [
|
|
|
2179
2265
|
"digest algorithms other than sha-256",
|
|
2180
2266
|
// Roles this gateway does not play
|
|
2181
2267
|
"mandate issuance",
|
|
2268
|
+
"checkout receipts",
|
|
2182
2269
|
"AP2 over the ACP checkout adapter"
|
|
2183
2270
|
];
|
|
2184
2271
|
|
|
@@ -2189,20 +2276,23 @@ init_constants2();
|
|
|
2189
2276
|
init_networks();
|
|
2190
2277
|
|
|
2191
2278
|
// src/protocols/a2a/constants.ts
|
|
2192
|
-
var A2A_SPEC_VERSION = "1.0.
|
|
2279
|
+
var A2A_SPEC_VERSION = "1.0.1";
|
|
2193
2280
|
var A2A_PROTOCOL_VERSION = "1.0";
|
|
2194
2281
|
var A2A_PROTOCOL_BINDING = "JSONRPC";
|
|
2195
2282
|
var A2A_AGENT_CARD_PATH = "/.well-known/agent-card.json";
|
|
2283
|
+
var A2A_PUSH_CONFIG_METHODS = [
|
|
2284
|
+
"CreateTaskPushNotificationConfig",
|
|
2285
|
+
"GetTaskPushNotificationConfig",
|
|
2286
|
+
"ListTaskPushNotificationConfigs",
|
|
2287
|
+
"DeleteTaskPushNotificationConfig"
|
|
2288
|
+
];
|
|
2196
2289
|
var A2A_UNSUPPORTED_METHODS = [
|
|
2197
2290
|
"SendStreamingMessage",
|
|
2198
2291
|
"GetTask",
|
|
2199
2292
|
"ListTasks",
|
|
2200
2293
|
"CancelTask",
|
|
2201
2294
|
"SubscribeToTask",
|
|
2202
|
-
|
|
2203
|
-
"GetTaskPushNotificationConfig",
|
|
2204
|
-
"ListTaskPushNotificationConfigs",
|
|
2205
|
-
"DeleteTaskPushNotificationConfig",
|
|
2295
|
+
...A2A_PUSH_CONFIG_METHODS,
|
|
2206
2296
|
"GetExtendedAgentCard"
|
|
2207
2297
|
];
|
|
2208
2298
|
|
|
@@ -2216,12 +2306,14 @@ var A2A_UNSUPPORTED = [
|
|
|
2216
2306
|
// Behaviors
|
|
2217
2307
|
"SSE",
|
|
2218
2308
|
"long-running task persistence",
|
|
2219
|
-
"task resumption",
|
|
2309
|
+
"task resumption other than an x402 extension payment",
|
|
2220
2310
|
"push notifications",
|
|
2221
2311
|
"multi-turn conversational continuation",
|
|
2222
2312
|
"authenticated extended agent cards",
|
|
2223
2313
|
"A2A authentication schemes",
|
|
2224
|
-
"artifact types beyond Agent Commerce outcome data"
|
|
2314
|
+
"artifact types beyond Agent Commerce outcome data",
|
|
2315
|
+
// Pending x402 payments live in process memory
|
|
2316
|
+
"x402 extension payments across gateway restarts or instances"
|
|
2225
2317
|
];
|
|
2226
2318
|
|
|
2227
2319
|
// src/cli/commands/doctor.ts
|
|
@@ -2233,7 +2325,9 @@ init_constants3();
|
|
|
2233
2325
|
"rest transport",
|
|
2234
2326
|
"well-known discovery",
|
|
2235
2327
|
"bearer authentication",
|
|
2236
|
-
"API-Version
|
|
2328
|
+
"API-Version enforcement",
|
|
2329
|
+
// Forwarded as received: the gateway verifies neither signature header
|
|
2330
|
+
"request header forwarding to the merchant",
|
|
2237
2331
|
"checkout service",
|
|
2238
2332
|
...ACP_CHECKOUT_OPERATIONS
|
|
2239
2333
|
];
|
|
@@ -2262,7 +2356,7 @@ var ACP_UNSUPPORTED = [
|
|
|
2262
2356
|
|
|
2263
2357
|
// src/storage/receipts/store.ts
|
|
2264
2358
|
init_core();
|
|
2265
|
-
var PACKAGE_VERSION = "
|
|
2359
|
+
var PACKAGE_VERSION = "2.0.0" ;
|
|
2266
2360
|
|
|
2267
2361
|
// src/storage/sqlite.ts
|
|
2268
2362
|
init_core();
|
|
@@ -2558,6 +2652,9 @@ function createSqliteReceiptStore(options) {
|
|
|
2558
2652
|
const listPaymentAttemptsByRequestStmt = db.prepare(
|
|
2559
2653
|
"SELECT * FROM payment_attempts WHERE request_id = ? ORDER BY created_at DESC, seq DESC LIMIT ?"
|
|
2560
2654
|
);
|
|
2655
|
+
const paymentAttemptStatusStmt = db.prepare(
|
|
2656
|
+
"SELECT status FROM payment_attempts WHERE replay_key = ?"
|
|
2657
|
+
);
|
|
2561
2658
|
let closed = false;
|
|
2562
2659
|
const descriptor = {
|
|
2563
2660
|
name: "sqlite-receipt-store",
|
|
@@ -2614,10 +2711,15 @@ function createSqliteReceiptStore(options) {
|
|
|
2614
2711
|
});
|
|
2615
2712
|
} catch (err) {
|
|
2616
2713
|
if (isUniqueConstraintOn(err, "payment_attempts.replay_key")) {
|
|
2714
|
+
const existing = paymentAttemptStatusStmt.get(reservation.replayKey);
|
|
2617
2715
|
throw new CommerceError(
|
|
2618
2716
|
"PAYMENT_REPLAYED",
|
|
2619
2717
|
`Payment authorization has already been used (replayKey=${reservation.replayKey})`,
|
|
2620
|
-
{
|
|
2718
|
+
{
|
|
2719
|
+
requestId: reservation.requestId,
|
|
2720
|
+
resourceId: reservation.resourceId,
|
|
2721
|
+
...existing !== void 0 ? { details: { attemptStatus: existing.status } } : {}
|
|
2722
|
+
}
|
|
2621
2723
|
);
|
|
2622
2724
|
}
|
|
2623
2725
|
throw toCommerceError(err, "STORAGE_ERROR", "Failed to reserve payment attempt");
|
|
@@ -3003,7 +3105,7 @@ var package_default = {
|
|
|
3003
3105
|
"ajv-formats": "3.0.1",
|
|
3004
3106
|
"better-sqlite3": "13.0.3",
|
|
3005
3107
|
commander: "15.0.0",
|
|
3006
|
-
fastify: "5.12.
|
|
3108
|
+
fastify: "5.12.5",
|
|
3007
3109
|
picocolors: "1.1.1",
|
|
3008
3110
|
pino: "10.3.1",
|
|
3009
3111
|
yaml: "2.9.0",
|
|
@@ -3011,19 +3113,19 @@ var package_default = {
|
|
|
3011
3113
|
},
|
|
3012
3114
|
peerDependencies: {
|
|
3013
3115
|
"@coinbase/x402": "2.1.0",
|
|
3014
|
-
"@modelcontextprotocol/
|
|
3116
|
+
"@modelcontextprotocol/server": "2.3.0",
|
|
3015
3117
|
"@sd-jwt/core": "0.20.1",
|
|
3016
|
-
"@x402/core": "2.
|
|
3017
|
-
"@x402/evm": "2.
|
|
3118
|
+
"@x402/core": "2.25.0",
|
|
3119
|
+
"@x402/evm": "2.25.0",
|
|
3018
3120
|
canonicalize: "5.0.0",
|
|
3019
3121
|
jose: "6.2.12",
|
|
3020
|
-
mppx: "0.
|
|
3021
|
-
viem: "2.
|
|
3122
|
+
mppx: "0.13.1",
|
|
3123
|
+
viem: "2.57.1"
|
|
3022
3124
|
}};
|
|
3023
3125
|
|
|
3024
3126
|
// src/cli/lib/versions.ts
|
|
3025
3127
|
var PINS = [
|
|
3026
|
-
["@modelcontextprotocol/
|
|
3128
|
+
["@modelcontextprotocol/server", "protocols/mcp"],
|
|
3027
3129
|
["ajv", "protocols/acp"],
|
|
3028
3130
|
["ajv-formats", "protocols/acp"],
|
|
3029
3131
|
["@x402/core", "payments/x402"],
|
|
@@ -3071,6 +3173,11 @@ function substitutePathParams(url) {
|
|
|
3071
3173
|
}
|
|
3072
3174
|
return filled;
|
|
3073
3175
|
}
|
|
3176
|
+
function describePaymentFlow(rail) {
|
|
3177
|
+
const overrides = Object.keys(rail.resourcePaymentFlows ?? {}).length;
|
|
3178
|
+
const overrideCount = overrides > 0 ? ` (${overrides} resource ${overrides === 1 ? "override" : "overrides"})` : "";
|
|
3179
|
+
return `paymentFlow=${rail.paymentFlow ?? "authorization"}${overrideCount}`;
|
|
3180
|
+
}
|
|
3074
3181
|
function extractWellKnownX402(body, rail = "x402") {
|
|
3075
3182
|
const payments = body?.["payments"];
|
|
3076
3183
|
if (typeof payments !== "object" || payments === null) return void 0;
|
|
@@ -3327,7 +3434,7 @@ async function runDoctor(options, deps = {}) {
|
|
|
3327
3434
|
checks.push({
|
|
3328
3435
|
name: "AP2",
|
|
3329
3436
|
status: "PASS",
|
|
3330
|
-
detail: `experimental \xB7 spec ${AP2_SPEC_VERSION} \xB7 mode ${ap2.mode} \xB7 ${AP2_CHECKOUT_MANDATE_VCT} \xB7 profile ${AP2_CHECKOUT_PROFILE} \xB7 clock skew ${ap2.clockSkewSeconds}s`
|
|
3437
|
+
detail: `experimental \xB7 spec ${AP2_SPEC_VERSION} \xB7 mode ${ap2.mode} \xB7 ${AP2_CHECKOUT_MANDATE_VCT} \xB7 profile ${AP2_CHECKOUT_PROFILE} \xB7 clock skew ${ap2.clockSkewSeconds}s \xB7 mandate aud ${ap2.requireMandateAudience === true ? "required" : "optional"} \xB7 mandate exp ${ap2.requireMandateExpiry === true ? "required" : "optional"}`
|
|
3331
3438
|
});
|
|
3332
3439
|
checks.push({
|
|
3333
3440
|
name: "AP2 trust",
|
|
@@ -3359,7 +3466,8 @@ async function runDoctor(options, deps = {}) {
|
|
|
3359
3466
|
checks.push({ name: "Payments", status: "INFO", detail: "x402 not configured" });
|
|
3360
3467
|
} else {
|
|
3361
3468
|
const { mode, where, via } = describeSettlement(x402.network, x402.facilitator);
|
|
3362
|
-
const
|
|
3469
|
+
const flow = describePaymentFlow(x402);
|
|
3470
|
+
const summary = `x402 v2 (scheme=exact) enabled - ${where}, destination=${maskMiddle(x402.payTo)}, facilitator=${via}, ${flow}`;
|
|
3363
3471
|
const live = wellKnown?.ok ? extractWellKnownX402(wellKnown.body) : void 0;
|
|
3364
3472
|
if (sameAddress2(x402.asset, PLACEHOLDER_ASSET_ADDRESS)) {
|
|
3365
3473
|
checks.push({
|
|
@@ -3394,7 +3502,7 @@ async function runDoctor(options, deps = {}) {
|
|
|
3394
3502
|
checks.push({ name: "Payments (MPP)", status: "INFO", detail: "MPP not configured" });
|
|
3395
3503
|
} else {
|
|
3396
3504
|
const { mode, where, via } = describeSettlement(mpp.network, mpp.facilitator);
|
|
3397
|
-
const summary = `MPP ${MPP_PROFILE.intent}/${MPP_PROFILE.method}/${MPP_PROFILE.credentialType} enabled - ${where}, asset=${MPP_PROFILE.assetSymbol} ${maskMiddle(mpp.asset)}, recipient=${maskMiddle(mpp.recipient)}, facilitator=${via}, spec ${MPP_SPEC_DRAFTS.core}@${MPP_SPEC_COMMIT.slice(0, 7)}, mppx ${MPPX_VERSION}`;
|
|
3505
|
+
const summary = `MPP ${MPP_PROFILE.intent}/${MPP_PROFILE.method}/${MPP_PROFILE.credentialType} enabled - ${where}, asset=${MPP_PROFILE.assetSymbol} ${maskMiddle(mpp.asset)}, recipient=${maskMiddle(mpp.recipient)}, facilitator=${via}, ${describePaymentFlow(mpp)}, spec ${MPP_SPEC_DRAFTS.core}@${MPP_SPEC_COMMIT.slice(0, 7)}, mppx ${MPPX_VERSION}`;
|
|
3398
3506
|
const configured = { asset: mpp.asset, network: mpp.network, payTo: mpp.recipient };
|
|
3399
3507
|
const live = wellKnown?.ok ? extractWellKnownX402(wellKnown.body, "mpp") : void 0;
|
|
3400
3508
|
if (live === "disabled") {
|
|
@@ -4662,6 +4770,7 @@ async function writeAtomically(outputPath, content, deps) {
|
|
|
4662
4770
|
const target = resolve(outputPath);
|
|
4663
4771
|
const temporary = `${target}.${process.pid}.tmp`;
|
|
4664
4772
|
try {
|
|
4773
|
+
await mkdir(dirname(target), { recursive: true });
|
|
4665
4774
|
await writeFile(temporary, content, "utf8");
|
|
4666
4775
|
await rename(temporary, target);
|
|
4667
4776
|
} catch (error) {
|