@agentcash/discovery 1.0.2 → 1.1.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/cli.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/cli.ts
@@ -194,7 +204,7 @@ function fetchSafe(url, init) {
194
204
  }
195
205
 
196
206
  // src/mmm-enabled.ts
197
- var isMmmEnabled = () => "1.0.2".includes("-mmm");
207
+ var isMmmEnabled = () => "1.1.0".includes("-mmm");
198
208
 
199
209
  // src/core/source/openapi/index.ts
200
210
  var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
@@ -360,6 +370,7 @@ var AUDIT_CODES = {
360
370
  L2_NO_ROUTES: "L2_NO_ROUTES",
361
371
  L2_ROUTE_COUNT_HIGH: "L2_ROUTE_COUNT_HIGH",
362
372
  L2_AUTH_MODE_MISSING: "L2_AUTH_MODE_MISSING",
373
+ L2_NO_PAID_ROUTES: "L2_NO_PAID_ROUTES",
363
374
  L2_PRICE_MISSING_ON_PAID: "L2_PRICE_MISSING_ON_PAID",
364
375
  L2_PROTOCOLS_MISSING_ON_PAID: "L2_PROTOCOLS_MISSING_ON_PAID",
365
376
  // ─── L3 endpoint advisory checks ─────────────────────────────────────────────
@@ -421,6 +432,15 @@ function getWarningsForL2(l2) {
421
432
  });
422
433
  return warnings;
423
434
  }
435
+ const hasPaidRoute = l2.routes.some((r) => r.authMode === "paid" || r.authMode === "apiKey+paid");
436
+ if (!hasPaidRoute) {
437
+ warnings.push({
438
+ code: AUDIT_CODES.L2_NO_PAID_ROUTES,
439
+ severity: "info",
440
+ message: "No endpoints are marked as paid or apiKey+paid.",
441
+ hint: "Add x-payment-info to operations that require payment so agents know which endpoints are monetized."
442
+ });
443
+ }
424
444
  if (l2.routes.length > ROUTE_COUNT_HIGH) {
425
445
  warnings.push({
426
446
  code: AUDIT_CODES.L2_ROUTE_COUNT_HIGH,
@@ -507,8 +527,8 @@ function getWarningsForL4(l4) {
507
527
  {
508
528
  code: AUDIT_CODES.L4_GUIDANCE_MISSING,
509
529
  severity: "info",
510
- message: "No guidance text found (llms.txt or OpenAPI info.guidance).",
511
- hint: "Add an info.guidance field to your OpenAPI spec or expose /llms.txt for agent-readable instructions."
530
+ message: "No guidance text found (OpenAPI info.guidance).",
531
+ hint: "Add an info.guidance field to your OpenAPI spec for agent-readable instructions."
512
532
  }
513
533
  ];
514
534
  }
@@ -817,54 +837,31 @@ function extractPaymentOptions4(wwwAuthenticate) {
817
837
  return options;
818
838
  }
819
839
 
820
- // src/core/layers/l3.ts
821
- function findMatchingOpenApiPath(paths, targetPath) {
822
- const exact = paths[targetPath];
823
- if (isRecord(exact)) return { matchedPath: targetPath, pathItem: exact };
824
- for (const [specPath, entry] of Object.entries(paths)) {
825
- if (!isRecord(entry)) continue;
826
- const pattern = specPath.replace(/\{[^}]+\}/g, "[^/]+");
827
- const regex = new RegExp(`^${pattern}$`);
828
- if (regex.test(targetPath)) {
829
- return { matchedPath: specPath, pathItem: entry };
830
- }
831
- }
832
- return null;
833
- }
834
- function resolveRef(document, ref, seen) {
835
- if (!ref.startsWith("#/")) return void 0;
836
- if (seen.has(ref)) return { $circular: ref };
837
- seen.add(ref);
838
- const parts = ref.slice(2).split("/");
839
- let current = document;
840
- for (const part of parts) {
841
- if (!isRecord(current)) return void 0;
842
- current = current[part];
843
- if (current === void 0) return void 0;
844
- }
845
- if (isRecord(current)) return resolveRefs(document, current, seen);
846
- return current;
840
+ // src/core/lib/resolve-ref.ts
841
+ var import_dereference_json_schema = __toESM(require("dereference-json-schema"), 1);
842
+ var { resolveRefSync } = import_dereference_json_schema.default;
843
+ function isRecord2(value) {
844
+ return value !== null && typeof value === "object" && !Array.isArray(value);
847
845
  }
848
- function resolveRefs(document, obj, seen, depth = 0) {
849
- if (depth > 4) return obj;
846
+ function deepResolveRefs(document, obj) {
850
847
  const resolved = {};
851
848
  for (const [key, value] of Object.entries(obj)) {
852
849
  if (key === "$ref" && typeof value === "string") {
853
- const deref = resolveRef(document, value, seen);
854
- if (isRecord(deref)) {
855
- Object.assign(resolved, deref);
850
+ const deref = resolveRefSync(document, value);
851
+ if (isRecord2(deref)) {
852
+ Object.assign(resolved, deepResolveRefs(document, deref));
856
853
  } else {
857
854
  resolved[key] = value;
858
855
  }
859
856
  continue;
860
857
  }
861
- if (isRecord(value)) {
862
- resolved[key] = resolveRefs(document, value, seen, depth + 1);
858
+ if (isRecord2(value)) {
859
+ resolved[key] = deepResolveRefs(document, value);
863
860
  continue;
864
861
  }
865
862
  if (Array.isArray(value)) {
866
863
  resolved[key] = value.map(
867
- (item) => isRecord(item) ? resolveRefs(document, item, seen, depth + 1) : item
864
+ (item) => isRecord2(item) ? deepResolveRefs(document, item) : item
868
865
  );
869
866
  continue;
870
867
  }
@@ -872,6 +869,24 @@ function resolveRefs(document, obj, seen, depth = 0) {
872
869
  }
873
870
  return resolved;
874
871
  }
872
+ function resolveRefs(obj, document) {
873
+ return deepResolveRefs(document, obj);
874
+ }
875
+
876
+ // src/core/layers/l3.ts
877
+ function findMatchingOpenApiPath(paths, targetPath) {
878
+ const exact = paths[targetPath];
879
+ if (isRecord(exact)) return { matchedPath: targetPath, pathItem: exact };
880
+ for (const [specPath, entry] of Object.entries(paths)) {
881
+ if (!isRecord(entry)) continue;
882
+ const pattern = specPath.replace(/\{[^}]+\}/g, "[^/]+");
883
+ const regex = new RegExp(`^${pattern}$`);
884
+ if (regex.test(targetPath)) {
885
+ return { matchedPath: specPath, pathItem: entry };
886
+ }
887
+ }
888
+ return null;
889
+ }
875
890
  function extractRequestBodySchema(operationSchema) {
876
891
  const requestBody = operationSchema.requestBody;
877
892
  if (!isRecord(requestBody)) return void 0;
@@ -951,7 +966,7 @@ function getL3ForOpenAPI(openApi, path, method) {
951
966
  if (!matched) return null;
952
967
  const operation = matched.pathItem[method.toLowerCase()];
953
968
  if (!isRecord(operation)) return null;
954
- const resolvedOperation = resolveRefs(document, operation, /* @__PURE__ */ new Set());
969
+ const resolvedOperation = resolveRefs(operation, document);
955
970
  const summary = typeof resolvedOperation.summary === "string" ? resolvedOperation.summary : typeof resolvedOperation.description === "string" ? resolvedOperation.description : void 0;
956
971
  return {
957
972
  source: "openapi",
package/dist/cli.js CHANGED
@@ -168,7 +168,7 @@ function fetchSafe(url, init) {
168
168
  }
169
169
 
170
170
  // src/mmm-enabled.ts
171
- var isMmmEnabled = () => "1.0.2".includes("-mmm");
171
+ var isMmmEnabled = () => "1.1.0".includes("-mmm");
172
172
 
173
173
  // src/core/source/openapi/index.ts
174
174
  var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
@@ -334,6 +334,7 @@ var AUDIT_CODES = {
334
334
  L2_NO_ROUTES: "L2_NO_ROUTES",
335
335
  L2_ROUTE_COUNT_HIGH: "L2_ROUTE_COUNT_HIGH",
336
336
  L2_AUTH_MODE_MISSING: "L2_AUTH_MODE_MISSING",
337
+ L2_NO_PAID_ROUTES: "L2_NO_PAID_ROUTES",
337
338
  L2_PRICE_MISSING_ON_PAID: "L2_PRICE_MISSING_ON_PAID",
338
339
  L2_PROTOCOLS_MISSING_ON_PAID: "L2_PROTOCOLS_MISSING_ON_PAID",
339
340
  // ─── L3 endpoint advisory checks ─────────────────────────────────────────────
@@ -395,6 +396,15 @@ function getWarningsForL2(l2) {
395
396
  });
396
397
  return warnings;
397
398
  }
399
+ const hasPaidRoute = l2.routes.some((r) => r.authMode === "paid" || r.authMode === "apiKey+paid");
400
+ if (!hasPaidRoute) {
401
+ warnings.push({
402
+ code: AUDIT_CODES.L2_NO_PAID_ROUTES,
403
+ severity: "info",
404
+ message: "No endpoints are marked as paid or apiKey+paid.",
405
+ hint: "Add x-payment-info to operations that require payment so agents know which endpoints are monetized."
406
+ });
407
+ }
398
408
  if (l2.routes.length > ROUTE_COUNT_HIGH) {
399
409
  warnings.push({
400
410
  code: AUDIT_CODES.L2_ROUTE_COUNT_HIGH,
@@ -481,8 +491,8 @@ function getWarningsForL4(l4) {
481
491
  {
482
492
  code: AUDIT_CODES.L4_GUIDANCE_MISSING,
483
493
  severity: "info",
484
- message: "No guidance text found (llms.txt or OpenAPI info.guidance).",
485
- hint: "Add an info.guidance field to your OpenAPI spec or expose /llms.txt for agent-readable instructions."
494
+ message: "No guidance text found (OpenAPI info.guidance).",
495
+ hint: "Add an info.guidance field to your OpenAPI spec for agent-readable instructions."
486
496
  }
487
497
  ];
488
498
  }
@@ -791,54 +801,31 @@ function extractPaymentOptions4(wwwAuthenticate) {
791
801
  return options;
792
802
  }
793
803
 
794
- // src/core/layers/l3.ts
795
- function findMatchingOpenApiPath(paths, targetPath) {
796
- const exact = paths[targetPath];
797
- if (isRecord(exact)) return { matchedPath: targetPath, pathItem: exact };
798
- for (const [specPath, entry] of Object.entries(paths)) {
799
- if (!isRecord(entry)) continue;
800
- const pattern = specPath.replace(/\{[^}]+\}/g, "[^/]+");
801
- const regex = new RegExp(`^${pattern}$`);
802
- if (regex.test(targetPath)) {
803
- return { matchedPath: specPath, pathItem: entry };
804
- }
805
- }
806
- return null;
807
- }
808
- function resolveRef(document, ref, seen) {
809
- if (!ref.startsWith("#/")) return void 0;
810
- if (seen.has(ref)) return { $circular: ref };
811
- seen.add(ref);
812
- const parts = ref.slice(2).split("/");
813
- let current = document;
814
- for (const part of parts) {
815
- if (!isRecord(current)) return void 0;
816
- current = current[part];
817
- if (current === void 0) return void 0;
818
- }
819
- if (isRecord(current)) return resolveRefs(document, current, seen);
820
- return current;
804
+ // src/core/lib/resolve-ref.ts
805
+ import pkg from "dereference-json-schema";
806
+ var { resolveRefSync } = pkg;
807
+ function isRecord2(value) {
808
+ return value !== null && typeof value === "object" && !Array.isArray(value);
821
809
  }
822
- function resolveRefs(document, obj, seen, depth = 0) {
823
- if (depth > 4) return obj;
810
+ function deepResolveRefs(document, obj) {
824
811
  const resolved = {};
825
812
  for (const [key, value] of Object.entries(obj)) {
826
813
  if (key === "$ref" && typeof value === "string") {
827
- const deref = resolveRef(document, value, seen);
828
- if (isRecord(deref)) {
829
- Object.assign(resolved, deref);
814
+ const deref = resolveRefSync(document, value);
815
+ if (isRecord2(deref)) {
816
+ Object.assign(resolved, deepResolveRefs(document, deref));
830
817
  } else {
831
818
  resolved[key] = value;
832
819
  }
833
820
  continue;
834
821
  }
835
- if (isRecord(value)) {
836
- resolved[key] = resolveRefs(document, value, seen, depth + 1);
822
+ if (isRecord2(value)) {
823
+ resolved[key] = deepResolveRefs(document, value);
837
824
  continue;
838
825
  }
839
826
  if (Array.isArray(value)) {
840
827
  resolved[key] = value.map(
841
- (item) => isRecord(item) ? resolveRefs(document, item, seen, depth + 1) : item
828
+ (item) => isRecord2(item) ? deepResolveRefs(document, item) : item
842
829
  );
843
830
  continue;
844
831
  }
@@ -846,6 +833,24 @@ function resolveRefs(document, obj, seen, depth = 0) {
846
833
  }
847
834
  return resolved;
848
835
  }
836
+ function resolveRefs(obj, document) {
837
+ return deepResolveRefs(document, obj);
838
+ }
839
+
840
+ // src/core/layers/l3.ts
841
+ function findMatchingOpenApiPath(paths, targetPath) {
842
+ const exact = paths[targetPath];
843
+ if (isRecord(exact)) return { matchedPath: targetPath, pathItem: exact };
844
+ for (const [specPath, entry] of Object.entries(paths)) {
845
+ if (!isRecord(entry)) continue;
846
+ const pattern = specPath.replace(/\{[^}]+\}/g, "[^/]+");
847
+ const regex = new RegExp(`^${pattern}$`);
848
+ if (regex.test(targetPath)) {
849
+ return { matchedPath: specPath, pathItem: entry };
850
+ }
851
+ }
852
+ return null;
853
+ }
849
854
  function extractRequestBodySchema(operationSchema) {
850
855
  const requestBody = operationSchema.requestBody;
851
856
  if (!isRecord(requestBody)) return void 0;
@@ -925,7 +930,7 @@ function getL3ForOpenAPI(openApi, path, method) {
925
930
  if (!matched) return null;
926
931
  const operation = matched.pathItem[method.toLowerCase()];
927
932
  if (!isRecord(operation)) return null;
928
- const resolvedOperation = resolveRefs(document, operation, /* @__PURE__ */ new Set());
933
+ const resolvedOperation = resolveRefs(operation, document);
929
934
  const summary = typeof resolvedOperation.summary === "string" ? resolvedOperation.summary : typeof resolvedOperation.description === "string" ? resolvedOperation.description : void 0;
930
935
  return {
931
936
  source: "openapi",
package/dist/index.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -215,7 +225,7 @@ function fetchSafe(url, init) {
215
225
  }
216
226
 
217
227
  // src/mmm-enabled.ts
218
- var isMmmEnabled = () => "1.0.2".includes("-mmm");
228
+ var isMmmEnabled = () => "1.1.0".includes("-mmm");
219
229
 
220
230
  // src/core/source/openapi/index.ts
221
231
  var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
@@ -990,54 +1000,31 @@ function extractPaymentOptions4(wwwAuthenticate) {
990
1000
  return options;
991
1001
  }
992
1002
 
993
- // src/core/layers/l3.ts
994
- function findMatchingOpenApiPath(paths, targetPath) {
995
- const exact = paths[targetPath];
996
- if (isRecord(exact)) return { matchedPath: targetPath, pathItem: exact };
997
- for (const [specPath, entry] of Object.entries(paths)) {
998
- if (!isRecord(entry)) continue;
999
- const pattern = specPath.replace(/\{[^}]+\}/g, "[^/]+");
1000
- const regex = new RegExp(`^${pattern}$`);
1001
- if (regex.test(targetPath)) {
1002
- return { matchedPath: specPath, pathItem: entry };
1003
- }
1004
- }
1005
- return null;
1006
- }
1007
- function resolveRef(document, ref, seen) {
1008
- if (!ref.startsWith("#/")) return void 0;
1009
- if (seen.has(ref)) return { $circular: ref };
1010
- seen.add(ref);
1011
- const parts = ref.slice(2).split("/");
1012
- let current = document;
1013
- for (const part of parts) {
1014
- if (!isRecord(current)) return void 0;
1015
- current = current[part];
1016
- if (current === void 0) return void 0;
1017
- }
1018
- if (isRecord(current)) return resolveRefs(document, current, seen);
1019
- return current;
1003
+ // src/core/lib/resolve-ref.ts
1004
+ var import_dereference_json_schema = __toESM(require("dereference-json-schema"), 1);
1005
+ var { resolveRefSync } = import_dereference_json_schema.default;
1006
+ function isRecord2(value) {
1007
+ return value !== null && typeof value === "object" && !Array.isArray(value);
1020
1008
  }
1021
- function resolveRefs(document, obj, seen, depth = 0) {
1022
- if (depth > 4) return obj;
1009
+ function deepResolveRefs(document, obj) {
1023
1010
  const resolved = {};
1024
1011
  for (const [key, value] of Object.entries(obj)) {
1025
1012
  if (key === "$ref" && typeof value === "string") {
1026
- const deref = resolveRef(document, value, seen);
1027
- if (isRecord(deref)) {
1028
- Object.assign(resolved, deref);
1013
+ const deref = resolveRefSync(document, value);
1014
+ if (isRecord2(deref)) {
1015
+ Object.assign(resolved, deepResolveRefs(document, deref));
1029
1016
  } else {
1030
1017
  resolved[key] = value;
1031
1018
  }
1032
1019
  continue;
1033
1020
  }
1034
- if (isRecord(value)) {
1035
- resolved[key] = resolveRefs(document, value, seen, depth + 1);
1021
+ if (isRecord2(value)) {
1022
+ resolved[key] = deepResolveRefs(document, value);
1036
1023
  continue;
1037
1024
  }
1038
1025
  if (Array.isArray(value)) {
1039
1026
  resolved[key] = value.map(
1040
- (item) => isRecord(item) ? resolveRefs(document, item, seen, depth + 1) : item
1027
+ (item) => isRecord2(item) ? deepResolveRefs(document, item) : item
1041
1028
  );
1042
1029
  continue;
1043
1030
  }
@@ -1045,6 +1032,24 @@ function resolveRefs(document, obj, seen, depth = 0) {
1045
1032
  }
1046
1033
  return resolved;
1047
1034
  }
1035
+ function resolveRefs(obj, document) {
1036
+ return deepResolveRefs(document, obj);
1037
+ }
1038
+
1039
+ // src/core/layers/l3.ts
1040
+ function findMatchingOpenApiPath(paths, targetPath) {
1041
+ const exact = paths[targetPath];
1042
+ if (isRecord(exact)) return { matchedPath: targetPath, pathItem: exact };
1043
+ for (const [specPath, entry] of Object.entries(paths)) {
1044
+ if (!isRecord(entry)) continue;
1045
+ const pattern = specPath.replace(/\{[^}]+\}/g, "[^/]+");
1046
+ const regex = new RegExp(`^${pattern}$`);
1047
+ if (regex.test(targetPath)) {
1048
+ return { matchedPath: specPath, pathItem: entry };
1049
+ }
1050
+ }
1051
+ return null;
1052
+ }
1048
1053
  function extractRequestBodySchema(operationSchema) {
1049
1054
  const requestBody = operationSchema.requestBody;
1050
1055
  if (!isRecord(requestBody)) return void 0;
@@ -1124,7 +1129,7 @@ function getL3ForOpenAPI(openApi, path, method) {
1124
1129
  if (!matched) return null;
1125
1130
  const operation = matched.pathItem[method.toLowerCase()];
1126
1131
  if (!isRecord(operation)) return null;
1127
- const resolvedOperation = resolveRefs(document, operation, /* @__PURE__ */ new Set());
1132
+ const resolvedOperation = resolveRefs(operation, document);
1128
1133
  const summary = typeof resolvedOperation.summary === "string" ? resolvedOperation.summary : typeof resolvedOperation.description === "string" ? resolvedOperation.description : void 0;
1129
1134
  return {
1130
1135
  source: "openapi",
@@ -1309,7 +1314,7 @@ var import_schemas3 = require("@x402/core/schemas");
1309
1314
  var DEFAULT_COMPAT_MODE = "on";
1310
1315
 
1311
1316
  // src/x402scan-validation/payment-required.ts
1312
- function isRecord2(value) {
1317
+ function isRecord3(value) {
1313
1318
  return typeof value === "object" && value !== null && !Array.isArray(value);
1314
1319
  }
1315
1320
  function pushIssue2(issues, issue) {
@@ -1363,7 +1368,7 @@ function validatePaymentRequiredDetailed(payload, options = {}) {
1363
1368
  const compatMode = options.compatMode ?? DEFAULT_COMPAT_MODE;
1364
1369
  const requireInputSchema = options.requireInputSchema ?? true;
1365
1370
  const requireOutputSchema = options.requireOutputSchema ?? true;
1366
- if (!isRecord2(payload)) {
1371
+ if (!isRecord3(payload)) {
1367
1372
  pushIssue2(issues, {
1368
1373
  code: VALIDATION_CODES.X402_NOT_OBJECT,
1369
1374
  severity: "error",
@@ -1482,6 +1487,7 @@ var AUDIT_CODES = {
1482
1487
  L2_NO_ROUTES: "L2_NO_ROUTES",
1483
1488
  L2_ROUTE_COUNT_HIGH: "L2_ROUTE_COUNT_HIGH",
1484
1489
  L2_AUTH_MODE_MISSING: "L2_AUTH_MODE_MISSING",
1490
+ L2_NO_PAID_ROUTES: "L2_NO_PAID_ROUTES",
1485
1491
  L2_PRICE_MISSING_ON_PAID: "L2_PRICE_MISSING_ON_PAID",
1486
1492
  L2_PROTOCOLS_MISSING_ON_PAID: "L2_PROTOCOLS_MISSING_ON_PAID",
1487
1493
  // ─── L3 endpoint advisory checks ─────────────────────────────────────────────
@@ -1543,6 +1549,15 @@ function getWarningsForL2(l2) {
1543
1549
  });
1544
1550
  return warnings;
1545
1551
  }
1552
+ const hasPaidRoute = l2.routes.some((r) => r.authMode === "paid" || r.authMode === "apiKey+paid");
1553
+ if (!hasPaidRoute) {
1554
+ warnings.push({
1555
+ code: AUDIT_CODES.L2_NO_PAID_ROUTES,
1556
+ severity: "info",
1557
+ message: "No endpoints are marked as paid or apiKey+paid.",
1558
+ hint: "Add x-payment-info to operations that require payment so agents know which endpoints are monetized."
1559
+ });
1560
+ }
1546
1561
  if (l2.routes.length > ROUTE_COUNT_HIGH) {
1547
1562
  warnings.push({
1548
1563
  code: AUDIT_CODES.L2_ROUTE_COUNT_HIGH,
@@ -1629,8 +1644,8 @@ function getWarningsForL4(l4) {
1629
1644
  {
1630
1645
  code: AUDIT_CODES.L4_GUIDANCE_MISSING,
1631
1646
  severity: "info",
1632
- message: "No guidance text found (llms.txt or OpenAPI info.guidance).",
1633
- hint: "Add an info.guidance field to your OpenAPI spec or expose /llms.txt for agent-readable instructions."
1647
+ message: "No guidance text found (OpenAPI info.guidance).",
1648
+ hint: "Add an info.guidance field to your OpenAPI spec for agent-readable instructions."
1634
1649
  }
1635
1650
  ];
1636
1651
  }
package/dist/index.d.cts CHANGED
@@ -325,6 +325,7 @@ declare const AUDIT_CODES: {
325
325
  readonly L2_NO_ROUTES: "L2_NO_ROUTES";
326
326
  readonly L2_ROUTE_COUNT_HIGH: "L2_ROUTE_COUNT_HIGH";
327
327
  readonly L2_AUTH_MODE_MISSING: "L2_AUTH_MODE_MISSING";
328
+ readonly L2_NO_PAID_ROUTES: "L2_NO_PAID_ROUTES";
328
329
  readonly L2_PRICE_MISSING_ON_PAID: "L2_PRICE_MISSING_ON_PAID";
329
330
  readonly L2_PROTOCOLS_MISSING_ON_PAID: "L2_PROTOCOLS_MISSING_ON_PAID";
330
331
  readonly L3_NOT_FOUND: "L3_NOT_FOUND";
package/dist/index.d.ts CHANGED
@@ -325,6 +325,7 @@ declare const AUDIT_CODES: {
325
325
  readonly L2_NO_ROUTES: "L2_NO_ROUTES";
326
326
  readonly L2_ROUTE_COUNT_HIGH: "L2_ROUTE_COUNT_HIGH";
327
327
  readonly L2_AUTH_MODE_MISSING: "L2_AUTH_MODE_MISSING";
328
+ readonly L2_NO_PAID_ROUTES: "L2_NO_PAID_ROUTES";
328
329
  readonly L2_PRICE_MISSING_ON_PAID: "L2_PRICE_MISSING_ON_PAID";
329
330
  readonly L2_PROTOCOLS_MISSING_ON_PAID: "L2_PROTOCOLS_MISSING_ON_PAID";
330
331
  readonly L3_NOT_FOUND: "L3_NOT_FOUND";
package/dist/index.js CHANGED
@@ -168,7 +168,7 @@ function fetchSafe(url, init) {
168
168
  }
169
169
 
170
170
  // src/mmm-enabled.ts
171
- var isMmmEnabled = () => "1.0.2".includes("-mmm");
171
+ var isMmmEnabled = () => "1.1.0".includes("-mmm");
172
172
 
173
173
  // src/core/source/openapi/index.ts
174
174
  var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
@@ -943,54 +943,31 @@ function extractPaymentOptions4(wwwAuthenticate) {
943
943
  return options;
944
944
  }
945
945
 
946
- // src/core/layers/l3.ts
947
- function findMatchingOpenApiPath(paths, targetPath) {
948
- const exact = paths[targetPath];
949
- if (isRecord(exact)) return { matchedPath: targetPath, pathItem: exact };
950
- for (const [specPath, entry] of Object.entries(paths)) {
951
- if (!isRecord(entry)) continue;
952
- const pattern = specPath.replace(/\{[^}]+\}/g, "[^/]+");
953
- const regex = new RegExp(`^${pattern}$`);
954
- if (regex.test(targetPath)) {
955
- return { matchedPath: specPath, pathItem: entry };
956
- }
957
- }
958
- return null;
959
- }
960
- function resolveRef(document, ref, seen) {
961
- if (!ref.startsWith("#/")) return void 0;
962
- if (seen.has(ref)) return { $circular: ref };
963
- seen.add(ref);
964
- const parts = ref.slice(2).split("/");
965
- let current = document;
966
- for (const part of parts) {
967
- if (!isRecord(current)) return void 0;
968
- current = current[part];
969
- if (current === void 0) return void 0;
970
- }
971
- if (isRecord(current)) return resolveRefs(document, current, seen);
972
- return current;
946
+ // src/core/lib/resolve-ref.ts
947
+ import pkg from "dereference-json-schema";
948
+ var { resolveRefSync } = pkg;
949
+ function isRecord2(value) {
950
+ return value !== null && typeof value === "object" && !Array.isArray(value);
973
951
  }
974
- function resolveRefs(document, obj, seen, depth = 0) {
975
- if (depth > 4) return obj;
952
+ function deepResolveRefs(document, obj) {
976
953
  const resolved = {};
977
954
  for (const [key, value] of Object.entries(obj)) {
978
955
  if (key === "$ref" && typeof value === "string") {
979
- const deref = resolveRef(document, value, seen);
980
- if (isRecord(deref)) {
981
- Object.assign(resolved, deref);
956
+ const deref = resolveRefSync(document, value);
957
+ if (isRecord2(deref)) {
958
+ Object.assign(resolved, deepResolveRefs(document, deref));
982
959
  } else {
983
960
  resolved[key] = value;
984
961
  }
985
962
  continue;
986
963
  }
987
- if (isRecord(value)) {
988
- resolved[key] = resolveRefs(document, value, seen, depth + 1);
964
+ if (isRecord2(value)) {
965
+ resolved[key] = deepResolveRefs(document, value);
989
966
  continue;
990
967
  }
991
968
  if (Array.isArray(value)) {
992
969
  resolved[key] = value.map(
993
- (item) => isRecord(item) ? resolveRefs(document, item, seen, depth + 1) : item
970
+ (item) => isRecord2(item) ? deepResolveRefs(document, item) : item
994
971
  );
995
972
  continue;
996
973
  }
@@ -998,6 +975,24 @@ function resolveRefs(document, obj, seen, depth = 0) {
998
975
  }
999
976
  return resolved;
1000
977
  }
978
+ function resolveRefs(obj, document) {
979
+ return deepResolveRefs(document, obj);
980
+ }
981
+
982
+ // src/core/layers/l3.ts
983
+ function findMatchingOpenApiPath(paths, targetPath) {
984
+ const exact = paths[targetPath];
985
+ if (isRecord(exact)) return { matchedPath: targetPath, pathItem: exact };
986
+ for (const [specPath, entry] of Object.entries(paths)) {
987
+ if (!isRecord(entry)) continue;
988
+ const pattern = specPath.replace(/\{[^}]+\}/g, "[^/]+");
989
+ const regex = new RegExp(`^${pattern}$`);
990
+ if (regex.test(targetPath)) {
991
+ return { matchedPath: specPath, pathItem: entry };
992
+ }
993
+ }
994
+ return null;
995
+ }
1001
996
  function extractRequestBodySchema(operationSchema) {
1002
997
  const requestBody = operationSchema.requestBody;
1003
998
  if (!isRecord(requestBody)) return void 0;
@@ -1077,7 +1072,7 @@ function getL3ForOpenAPI(openApi, path, method) {
1077
1072
  if (!matched) return null;
1078
1073
  const operation = matched.pathItem[method.toLowerCase()];
1079
1074
  if (!isRecord(operation)) return null;
1080
- const resolvedOperation = resolveRefs(document, operation, /* @__PURE__ */ new Set());
1075
+ const resolvedOperation = resolveRefs(operation, document);
1081
1076
  const summary = typeof resolvedOperation.summary === "string" ? resolvedOperation.summary : typeof resolvedOperation.description === "string" ? resolvedOperation.description : void 0;
1082
1077
  return {
1083
1078
  source: "openapi",
@@ -1262,7 +1257,7 @@ import { parsePaymentRequired } from "@x402/core/schemas";
1262
1257
  var DEFAULT_COMPAT_MODE = "on";
1263
1258
 
1264
1259
  // src/x402scan-validation/payment-required.ts
1265
- function isRecord2(value) {
1260
+ function isRecord3(value) {
1266
1261
  return typeof value === "object" && value !== null && !Array.isArray(value);
1267
1262
  }
1268
1263
  function pushIssue2(issues, issue) {
@@ -1316,7 +1311,7 @@ function validatePaymentRequiredDetailed(payload, options = {}) {
1316
1311
  const compatMode = options.compatMode ?? DEFAULT_COMPAT_MODE;
1317
1312
  const requireInputSchema = options.requireInputSchema ?? true;
1318
1313
  const requireOutputSchema = options.requireOutputSchema ?? true;
1319
- if (!isRecord2(payload)) {
1314
+ if (!isRecord3(payload)) {
1320
1315
  pushIssue2(issues, {
1321
1316
  code: VALIDATION_CODES.X402_NOT_OBJECT,
1322
1317
  severity: "error",
@@ -1435,6 +1430,7 @@ var AUDIT_CODES = {
1435
1430
  L2_NO_ROUTES: "L2_NO_ROUTES",
1436
1431
  L2_ROUTE_COUNT_HIGH: "L2_ROUTE_COUNT_HIGH",
1437
1432
  L2_AUTH_MODE_MISSING: "L2_AUTH_MODE_MISSING",
1433
+ L2_NO_PAID_ROUTES: "L2_NO_PAID_ROUTES",
1438
1434
  L2_PRICE_MISSING_ON_PAID: "L2_PRICE_MISSING_ON_PAID",
1439
1435
  L2_PROTOCOLS_MISSING_ON_PAID: "L2_PROTOCOLS_MISSING_ON_PAID",
1440
1436
  // ─── L3 endpoint advisory checks ─────────────────────────────────────────────
@@ -1496,6 +1492,15 @@ function getWarningsForL2(l2) {
1496
1492
  });
1497
1493
  return warnings;
1498
1494
  }
1495
+ const hasPaidRoute = l2.routes.some((r) => r.authMode === "paid" || r.authMode === "apiKey+paid");
1496
+ if (!hasPaidRoute) {
1497
+ warnings.push({
1498
+ code: AUDIT_CODES.L2_NO_PAID_ROUTES,
1499
+ severity: "info",
1500
+ message: "No endpoints are marked as paid or apiKey+paid.",
1501
+ hint: "Add x-payment-info to operations that require payment so agents know which endpoints are monetized."
1502
+ });
1503
+ }
1499
1504
  if (l2.routes.length > ROUTE_COUNT_HIGH) {
1500
1505
  warnings.push({
1501
1506
  code: AUDIT_CODES.L2_ROUTE_COUNT_HIGH,
@@ -1582,8 +1587,8 @@ function getWarningsForL4(l4) {
1582
1587
  {
1583
1588
  code: AUDIT_CODES.L4_GUIDANCE_MISSING,
1584
1589
  severity: "info",
1585
- message: "No guidance text found (llms.txt or OpenAPI info.guidance).",
1586
- hint: "Add an info.guidance field to your OpenAPI spec or expose /llms.txt for agent-readable instructions."
1590
+ message: "No guidance text found (OpenAPI info.guidance).",
1591
+ hint: "Add an info.guidance field to your OpenAPI spec for agent-readable instructions."
1587
1592
  }
1588
1593
  ];
1589
1594
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentcash/discovery",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "Canonical OpenAPI-first discovery runtime for the agentcash ecosystem",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -65,6 +65,7 @@
65
65
  },
66
66
  "dependencies": {
67
67
  "@x402/core": "^2.5.0",
68
+ "dereference-json-schema": "^0.2.2",
68
69
  "neverthrow": "^8.2.0",
69
70
  "zod": "^4.0.0"
70
71
  },