@agentcash/router 0.5.0 → 0.5.2

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/index.cjs CHANGED
@@ -43,25 +43,26 @@ async function createX402Server(config) {
43
43
  const { facilitator: defaultFacilitator } = await import("@coinbase/x402");
44
44
  const raw = config.facilitatorUrl ?? defaultFacilitator;
45
45
  const facilitatorConfig = typeof raw === "string" ? { url: raw } : raw;
46
- const client = new HTTPFacilitatorClient(facilitatorConfig);
46
+ const httpClient = new HTTPFacilitatorClient(facilitatorConfig);
47
+ const network = config.network ?? "eip155:8453";
48
+ const client = cachedClient(httpClient, network);
47
49
  const server = new x402ResourceServer(client);
48
50
  registerExactEvmScheme(server);
49
51
  server.registerExtension(bazaarResourceServerExtension);
50
52
  server.registerExtension(siwxResourceServerExtension);
51
- const initPromise = retryInit(server);
53
+ const initPromise = server.initialize();
52
54
  return { server, initPromise };
53
55
  }
54
- async function retryInit(server, maxAttempts = 3, backoff = [1e3, 2e3, 4e3]) {
55
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
56
- try {
57
- await server.initialize();
58
- return;
59
- } catch (err) {
60
- const is429 = err instanceof Error && (err.message.includes("429") || err.message.includes("rate limit"));
61
- if (!is429 || attempt === maxAttempts - 1) throw err;
62
- await new Promise((r) => setTimeout(r, backoff[attempt] ?? 4e3));
63
- }
64
- }
56
+ function cachedClient(inner, network) {
57
+ return {
58
+ verify: inner.verify.bind(inner),
59
+ settle: inner.settle.bind(inner),
60
+ getSupported: async () => ({
61
+ kinds: [{ x402Version: 2, scheme: "exact", network }],
62
+ extensions: [],
63
+ signers: {}
64
+ })
65
+ };
65
66
  }
66
67
  var init_server = __esm({
67
68
  "src/server.ts"() {
@@ -1019,11 +1020,15 @@ async function build402(request, routeEntry, deps, meta, pluginCtx, bodyData) {
1019
1020
  );
1020
1021
  response.headers.set("PAYMENT-REQUIRED", encoded);
1021
1022
  } catch (err) {
1023
+ const message = `x402 challenge build failed: ${err instanceof Error ? err.message : String(err)}`;
1022
1024
  firePluginHook(deps.plugin, "onAlert", pluginCtx, {
1023
1025
  level: "critical",
1024
- message: `x402 challenge build failed: ${err instanceof Error ? err.message : String(err)}`,
1026
+ message,
1025
1027
  route: routeEntry.key
1026
1028
  });
1029
+ const errorResponse = import_server2.NextResponse.json({ success: false, error: message }, { status: 500 });
1030
+ firePluginResponse(deps, pluginCtx, meta, errorResponse);
1031
+ return errorResponse;
1027
1032
  }
1028
1033
  }
1029
1034
  if (routeEntry.protocols.includes("mpp") && deps.mppx) {
@@ -1301,6 +1306,7 @@ var RouteBuilder = class {
1301
1306
  // src/discovery/well-known.ts
1302
1307
  var import_server3 = require("next/server");
1303
1308
  function createWellKnownHandler(registry, baseUrl, pricesKeys, options = {}) {
1309
+ const normalizedBase = baseUrl.replace(/\/+$/, "");
1304
1310
  let validated = false;
1305
1311
  return async (_request) => {
1306
1312
  if (!validated && pricesKeys) {
@@ -1310,7 +1316,7 @@ function createWellKnownHandler(registry, baseUrl, pricesKeys, options = {}) {
1310
1316
  const x402Set = /* @__PURE__ */ new Set();
1311
1317
  const mppSet = /* @__PURE__ */ new Set();
1312
1318
  for (const [key, entry] of registry.entries()) {
1313
- const url = `${baseUrl}/api/${entry.path ?? key}`;
1319
+ const url = `${normalizedBase}/api/${entry.path ?? key}`;
1314
1320
  if (entry.authMode !== "unprotected") x402Set.add(url);
1315
1321
  if (entry.protocols.includes("mpp")) mppSet.add(url);
1316
1322
  }
@@ -1350,6 +1356,7 @@ function createWellKnownHandler(registry, baseUrl, pricesKeys, options = {}) {
1350
1356
  // src/discovery/openapi.ts
1351
1357
  var import_server4 = require("next/server");
1352
1358
  function createOpenAPIHandler(registry, baseUrl, pricesKeys, options) {
1359
+ const normalizedBase = baseUrl.replace(/\/+$/, "");
1353
1360
  let cached = null;
1354
1361
  let validated = false;
1355
1362
  return async (_request) => {
@@ -1376,7 +1383,7 @@ function createOpenAPIHandler(registry, baseUrl, pricesKeys, options) {
1376
1383
  version: options.version,
1377
1384
  ...options.contact && { contact: options.contact }
1378
1385
  },
1379
- servers: [{ url: options.baseUrl ?? baseUrl }],
1386
+ servers: [{ url: (options.baseUrl ?? normalizedBase).replace(/\/+$/, "") }],
1380
1387
  tags: Array.from(tagSet).sort().map((name) => ({ name })),
1381
1388
  paths
1382
1389
  });
@@ -1461,7 +1468,7 @@ function createRouter(config) {
1461
1468
  }
1462
1469
  console.warn(`[router] ${msg}`);
1463
1470
  }
1464
- const resolvedBaseUrl = baseUrl ?? "http://localhost:3000";
1471
+ const resolvedBaseUrl = (baseUrl ?? "http://localhost:3000").replace(/\/+$/, "");
1465
1472
  let x402ConfigError;
1466
1473
  let mppConfigError;
1467
1474
  if ((!config.protocols || config.protocols.includes("x402")) && !config.payeeAddress) {
package/dist/index.js CHANGED
@@ -21,25 +21,26 @@ async function createX402Server(config) {
21
21
  const { facilitator: defaultFacilitator } = await import("@coinbase/x402");
22
22
  const raw = config.facilitatorUrl ?? defaultFacilitator;
23
23
  const facilitatorConfig = typeof raw === "string" ? { url: raw } : raw;
24
- const client = new HTTPFacilitatorClient(facilitatorConfig);
24
+ const httpClient = new HTTPFacilitatorClient(facilitatorConfig);
25
+ const network = config.network ?? "eip155:8453";
26
+ const client = cachedClient(httpClient, network);
25
27
  const server = new x402ResourceServer(client);
26
28
  registerExactEvmScheme(server);
27
29
  server.registerExtension(bazaarResourceServerExtension);
28
30
  server.registerExtension(siwxResourceServerExtension);
29
- const initPromise = retryInit(server);
31
+ const initPromise = server.initialize();
30
32
  return { server, initPromise };
31
33
  }
32
- async function retryInit(server, maxAttempts = 3, backoff = [1e3, 2e3, 4e3]) {
33
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
34
- try {
35
- await server.initialize();
36
- return;
37
- } catch (err) {
38
- const is429 = err instanceof Error && (err.message.includes("429") || err.message.includes("rate limit"));
39
- if (!is429 || attempt === maxAttempts - 1) throw err;
40
- await new Promise((r) => setTimeout(r, backoff[attempt] ?? 4e3));
41
- }
42
- }
34
+ function cachedClient(inner, network) {
35
+ return {
36
+ verify: inner.verify.bind(inner),
37
+ settle: inner.settle.bind(inner),
38
+ getSupported: async () => ({
39
+ kinds: [{ x402Version: 2, scheme: "exact", network }],
40
+ extensions: [],
41
+ signers: {}
42
+ })
43
+ };
43
44
  }
44
45
  var init_server = __esm({
45
46
  "src/server.ts"() {
@@ -982,11 +983,15 @@ async function build402(request, routeEntry, deps, meta, pluginCtx, bodyData) {
982
983
  );
983
984
  response.headers.set("PAYMENT-REQUIRED", encoded);
984
985
  } catch (err) {
986
+ const message = `x402 challenge build failed: ${err instanceof Error ? err.message : String(err)}`;
985
987
  firePluginHook(deps.plugin, "onAlert", pluginCtx, {
986
988
  level: "critical",
987
- message: `x402 challenge build failed: ${err instanceof Error ? err.message : String(err)}`,
989
+ message,
988
990
  route: routeEntry.key
989
991
  });
992
+ const errorResponse = NextResponse2.json({ success: false, error: message }, { status: 500 });
993
+ firePluginResponse(deps, pluginCtx, meta, errorResponse);
994
+ return errorResponse;
990
995
  }
991
996
  }
992
997
  if (routeEntry.protocols.includes("mpp") && deps.mppx) {
@@ -1264,6 +1269,7 @@ var RouteBuilder = class {
1264
1269
  // src/discovery/well-known.ts
1265
1270
  import { NextResponse as NextResponse3 } from "next/server";
1266
1271
  function createWellKnownHandler(registry, baseUrl, pricesKeys, options = {}) {
1272
+ const normalizedBase = baseUrl.replace(/\/+$/, "");
1267
1273
  let validated = false;
1268
1274
  return async (_request) => {
1269
1275
  if (!validated && pricesKeys) {
@@ -1273,7 +1279,7 @@ function createWellKnownHandler(registry, baseUrl, pricesKeys, options = {}) {
1273
1279
  const x402Set = /* @__PURE__ */ new Set();
1274
1280
  const mppSet = /* @__PURE__ */ new Set();
1275
1281
  for (const [key, entry] of registry.entries()) {
1276
- const url = `${baseUrl}/api/${entry.path ?? key}`;
1282
+ const url = `${normalizedBase}/api/${entry.path ?? key}`;
1277
1283
  if (entry.authMode !== "unprotected") x402Set.add(url);
1278
1284
  if (entry.protocols.includes("mpp")) mppSet.add(url);
1279
1285
  }
@@ -1313,6 +1319,7 @@ function createWellKnownHandler(registry, baseUrl, pricesKeys, options = {}) {
1313
1319
  // src/discovery/openapi.ts
1314
1320
  import { NextResponse as NextResponse4 } from "next/server";
1315
1321
  function createOpenAPIHandler(registry, baseUrl, pricesKeys, options) {
1322
+ const normalizedBase = baseUrl.replace(/\/+$/, "");
1316
1323
  let cached = null;
1317
1324
  let validated = false;
1318
1325
  return async (_request) => {
@@ -1339,7 +1346,7 @@ function createOpenAPIHandler(registry, baseUrl, pricesKeys, options) {
1339
1346
  version: options.version,
1340
1347
  ...options.contact && { contact: options.contact }
1341
1348
  },
1342
- servers: [{ url: options.baseUrl ?? baseUrl }],
1349
+ servers: [{ url: (options.baseUrl ?? normalizedBase).replace(/\/+$/, "") }],
1343
1350
  tags: Array.from(tagSet).sort().map((name) => ({ name })),
1344
1351
  paths
1345
1352
  });
@@ -1424,7 +1431,7 @@ function createRouter(config) {
1424
1431
  }
1425
1432
  console.warn(`[router] ${msg}`);
1426
1433
  }
1427
- const resolvedBaseUrl = baseUrl ?? "http://localhost:3000";
1434
+ const resolvedBaseUrl = (baseUrl ?? "http://localhost:3000").replace(/\/+$/, "");
1428
1435
  let x402ConfigError;
1429
1436
  let mppConfigError;
1430
1437
  if ((!config.protocols || config.protocols.includes("x402")) && !config.payeeAddress) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentcash/router",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Unified route builder for Next.js App Router APIs with x402, MPP, SIWX, and API key auth",
5
5
  "type": "module",
6
6
  "exports": {
@@ -28,7 +28,7 @@
28
28
  "@x402/core": "^2.3.0",
29
29
  "@x402/evm": "^2.3.0",
30
30
  "@x402/extensions": "^2.3.0",
31
- "mppx": "^0.2.6",
31
+ "mppx": "^0.3.2",
32
32
  "next": ">=15.0.0",
33
33
  "zod": "^4.0.0",
34
34
  "zod-openapi": "^5.0.0"
@@ -48,7 +48,7 @@
48
48
  "@x402/evm": "^2.3.0",
49
49
  "@x402/extensions": "^2.3.0",
50
50
  "eslint": "^10.0.0",
51
- "mppx": "^0.2.6",
51
+ "mppx": "^0.3.2",
52
52
  "next": "^15.0.0",
53
53
  "prettier": "^3.8.1",
54
54
  "react": "^19.0.0",