@agentcash/discovery 0.1.2 → 0.1.3

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
@@ -24,6 +24,7 @@ __export(index_exports, {
24
24
  LEGACY_SUNSET_DATE: () => LEGACY_SUNSET_DATE,
25
25
  STRICT_ESCALATION_CODES: () => STRICT_ESCALATION_CODES,
26
26
  UPGRADE_WARNING_CODES: () => UPGRADE_WARNING_CODES,
27
+ VALIDATION_CODES: () => VALIDATION_CODES,
27
28
  auditContextHarness: () => auditContextHarness,
28
29
  buildContextHarnessReport: () => buildContextHarnessReport,
29
30
  computeUpgradeSignal: () => computeUpgradeSignal,
@@ -31,9 +32,11 @@ __export(index_exports, {
31
32
  discover: () => discover,
32
33
  discoverDetailed: () => discoverDetailed,
33
34
  discoverForMcp: () => discoverForMcp,
35
+ evaluateMetadataCompleteness: () => evaluateMetadataCompleteness,
34
36
  getHarnessClientProfile: () => getHarnessClientProfile,
35
37
  inspectEndpointForMcp: () => inspectEndpointForMcp,
36
- listHarnessClientProfiles: () => listHarnessClientProfiles
38
+ listHarnessClientProfiles: () => listHarnessClientProfiles,
39
+ validatePaymentRequiredDetailed: () => validatePaymentRequiredDetailed
37
40
  });
38
41
  module.exports = __toCommonJS(index_exports);
39
42
 
@@ -51,7 +54,7 @@ var STRICT_ESCALATION_CODES = [
51
54
  ];
52
55
 
53
56
  // src/mmm-enabled.ts
54
- var isMmmEnabled = () => "0.1.2".includes("-mmm");
57
+ var isMmmEnabled = () => "0.1.3".includes("-mmm");
55
58
 
56
59
  // src/core/constants.ts
57
60
  var OPENAPI_PATH_CANDIDATES = ["/openapi.json", "/.well-known/openapi.json"];
@@ -1439,6 +1442,471 @@ async function runDiscovery({
1439
1442
  };
1440
1443
  }
1441
1444
 
1445
+ // src/validation/codes.ts
1446
+ var VALIDATION_CODES = {
1447
+ COINBASE_SCHEMA_INVALID: "COINBASE_SCHEMA_INVALID",
1448
+ X402_NOT_OBJECT: "X402_NOT_OBJECT",
1449
+ X402_VERSION_MISSING: "X402_VERSION_MISSING",
1450
+ X402_VERSION_UNSUPPORTED: "X402_VERSION_UNSUPPORTED",
1451
+ X402_ACCEPTS_MISSING: "X402_ACCEPTS_MISSING",
1452
+ X402_ACCEPTS_INVALID: "X402_ACCEPTS_INVALID",
1453
+ X402_ACCEPTS_EMPTY: "X402_ACCEPTS_EMPTY",
1454
+ X402_ACCEPT_ENTRY_INVALID: "X402_ACCEPT_ENTRY_INVALID",
1455
+ NETWORK_CAIP2_INVALID: "NETWORK_CAIP2_INVALID",
1456
+ NETWORK_EIP155_REFERENCE_INVALID: "NETWORK_EIP155_REFERENCE_INVALID",
1457
+ NETWORK_SOLANA_ALIAS_INVALID: "NETWORK_SOLANA_ALIAS_INVALID",
1458
+ NETWORK_SOLANA_ALIAS_COMPAT: "NETWORK_SOLANA_ALIAS_COMPAT",
1459
+ NETWORK_REFERENCE_UNKNOWN: "NETWORK_REFERENCE_UNKNOWN",
1460
+ SCHEMA_INPUT_MISSING: "SCHEMA_INPUT_MISSING",
1461
+ SCHEMA_OUTPUT_MISSING: "SCHEMA_OUTPUT_MISSING",
1462
+ METADATA_TITLE_MISSING: "METADATA_TITLE_MISSING",
1463
+ METADATA_DESCRIPTION_MISSING: "METADATA_DESCRIPTION_MISSING",
1464
+ METADATA_FAVICON_MISSING: "METADATA_FAVICON_MISSING",
1465
+ METADATA_OG_IMAGE_MISSING: "METADATA_OG_IMAGE_MISSING"
1466
+ };
1467
+
1468
+ // src/validation/metadata.ts
1469
+ function hasText(value) {
1470
+ return typeof value === "string" && value.trim().length > 0;
1471
+ }
1472
+ function hasOgImage(metadata) {
1473
+ const images = metadata.ogImages;
1474
+ if (!Array.isArray(images) || images.length === 0) return false;
1475
+ return images.some((entry) => {
1476
+ if (typeof entry === "string") {
1477
+ return entry.trim().length > 0;
1478
+ }
1479
+ if (!entry || typeof entry !== "object") return false;
1480
+ return hasText(entry.url);
1481
+ });
1482
+ }
1483
+ function evaluateMetadataCompleteness(metadata) {
1484
+ const issues = [];
1485
+ if (!hasText(metadata.title)) {
1486
+ issues.push({
1487
+ code: VALIDATION_CODES.METADATA_TITLE_MISSING,
1488
+ severity: "warn",
1489
+ message: "Metadata title is missing",
1490
+ hint: "Provide a page title to improve discovery quality and UX.",
1491
+ path: "metadata.title",
1492
+ stage: "metadata"
1493
+ });
1494
+ }
1495
+ if (!hasText(metadata.description)) {
1496
+ issues.push({
1497
+ code: VALIDATION_CODES.METADATA_DESCRIPTION_MISSING,
1498
+ severity: "warn",
1499
+ message: "Metadata description is missing",
1500
+ hint: "Provide a concise description for integrators and search previews.",
1501
+ path: "metadata.description",
1502
+ stage: "metadata"
1503
+ });
1504
+ }
1505
+ if (!hasText(metadata.favicon)) {
1506
+ issues.push({
1507
+ code: VALIDATION_CODES.METADATA_FAVICON_MISSING,
1508
+ severity: "warn",
1509
+ message: "Metadata favicon is missing",
1510
+ hint: "Expose a favicon URL for stronger brand attribution.",
1511
+ path: "metadata.favicon",
1512
+ stage: "metadata"
1513
+ });
1514
+ }
1515
+ if (!hasOgImage(metadata)) {
1516
+ issues.push({
1517
+ code: VALIDATION_CODES.METADATA_OG_IMAGE_MISSING,
1518
+ severity: "warn",
1519
+ message: "Metadata OG image is missing",
1520
+ hint: "Provide an Open Graph image to improve sharing previews.",
1521
+ path: "metadata.ogImages",
1522
+ stage: "metadata"
1523
+ });
1524
+ }
1525
+ return issues;
1526
+ }
1527
+
1528
+ // src/validation/payment-required.ts
1529
+ var import_schemas = require("@x402/core/schemas");
1530
+ var SOLANA_CANONICAL_BY_REF = {
1531
+ "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp": "solana",
1532
+ EtWTRABZaYq6iMfeYKouRu166VU2xqa1: "solana-devnet",
1533
+ "4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z": "solana-testnet"
1534
+ };
1535
+ var SOLANA_ALIAS_BY_REF = {
1536
+ mainnet: "solana",
1537
+ devnet: "solana-devnet",
1538
+ testnet: "solana-testnet"
1539
+ };
1540
+ function isRecord4(value) {
1541
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1542
+ }
1543
+ function asNonEmptyString(value) {
1544
+ if (typeof value !== "string") return void 0;
1545
+ const trimmed = value.trim();
1546
+ return trimmed.length > 0 ? trimmed : void 0;
1547
+ }
1548
+ function asPositiveNumber(value) {
1549
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
1550
+ }
1551
+ function pushIssue(issues, issue) {
1552
+ issues.push({
1553
+ stage: issue.stage ?? "payment_required",
1554
+ ...issue
1555
+ });
1556
+ }
1557
+ function summarizeIssues(issues) {
1558
+ const summary = {
1559
+ errorCount: 0,
1560
+ warnCount: 0,
1561
+ infoCount: 0,
1562
+ byCode: {}
1563
+ };
1564
+ for (const issue of issues) {
1565
+ if (issue.severity === "error") summary.errorCount += 1;
1566
+ else if (issue.severity === "warn") summary.warnCount += 1;
1567
+ else summary.infoCount += 1;
1568
+ summary.byCode[issue.code] = (summary.byCode[issue.code] ?? 0) + 1;
1569
+ }
1570
+ return summary;
1571
+ }
1572
+ function outputSchemaMissingSeverity(compatMode) {
1573
+ return compatMode === "strict" ? "error" : "warn";
1574
+ }
1575
+ function zodPathToString(path) {
1576
+ if (path.length === 0) return "$";
1577
+ let out = "";
1578
+ for (const segment of path) {
1579
+ if (typeof segment === "number") out += `[${segment}]`;
1580
+ else out += out.length === 0 ? segment : `.${segment}`;
1581
+ }
1582
+ return out;
1583
+ }
1584
+ function parseWithCoinbaseStructuralGate(payload, issues) {
1585
+ const baseParsed = (0, import_schemas.parsePaymentRequired)(payload);
1586
+ if (baseParsed.success) {
1587
+ return baseParsed.data;
1588
+ }
1589
+ for (const issue of baseParsed.error.issues) {
1590
+ pushIssue(issues, {
1591
+ code: VALIDATION_CODES.COINBASE_SCHEMA_INVALID,
1592
+ severity: "error",
1593
+ message: `Coinbase schema validation failed: ${issue.message}`,
1594
+ path: zodPathToString(issue.path),
1595
+ actual: issue.code
1596
+ });
1597
+ }
1598
+ return void 0;
1599
+ }
1600
+ function validateV2Network(networkRaw, index, issues) {
1601
+ if (!/^[^:\s]+:[^:\s]+$/.test(networkRaw)) {
1602
+ pushIssue(issues, {
1603
+ code: VALIDATION_CODES.NETWORK_CAIP2_INVALID,
1604
+ severity: "error",
1605
+ message: `Accept at index ${index} has invalid CAIP-2 network format`,
1606
+ hint: "Expected '<namespace>:<reference>', e.g. 'eip155:8453' or 'solana:5eykt4...'.",
1607
+ path: `accepts[${index}].network`,
1608
+ expected: "<namespace>:<reference>",
1609
+ actual: networkRaw
1610
+ });
1611
+ return void 0;
1612
+ }
1613
+ const [namespace, reference] = networkRaw.split(":");
1614
+ if (namespace === "eip155") {
1615
+ if (!/^\d+$/.test(reference)) {
1616
+ pushIssue(issues, {
1617
+ code: VALIDATION_CODES.NETWORK_EIP155_REFERENCE_INVALID,
1618
+ severity: "error",
1619
+ message: `Accept at index ${index} has invalid eip155 reference`,
1620
+ hint: "Use a numeric chain id, e.g. 'eip155:8453'.",
1621
+ path: `accepts[${index}].network`,
1622
+ expected: "eip155:<numeric-chain-id>",
1623
+ actual: networkRaw
1624
+ });
1625
+ return void 0;
1626
+ }
1627
+ return networkRaw;
1628
+ }
1629
+ if (namespace === "solana") {
1630
+ const canonical = SOLANA_CANONICAL_BY_REF[reference];
1631
+ if (canonical) return canonical;
1632
+ const alias = SOLANA_ALIAS_BY_REF[reference];
1633
+ if (alias) {
1634
+ pushIssue(issues, {
1635
+ code: VALIDATION_CODES.NETWORK_SOLANA_ALIAS_COMPAT,
1636
+ severity: "warn",
1637
+ message: `Accept at index ${index} uses compatibility Solana reference '${reference}'`,
1638
+ hint: "Use canonical Solana CAIP references for deterministic behavior.",
1639
+ path: `accepts[${index}].network`,
1640
+ actual: networkRaw
1641
+ });
1642
+ return alias;
1643
+ }
1644
+ pushIssue(issues, {
1645
+ code: VALIDATION_CODES.NETWORK_REFERENCE_UNKNOWN,
1646
+ severity: "error",
1647
+ message: `Accept at index ${index} uses unknown Solana reference '${reference}'`,
1648
+ hint: "Use canonical references for mainnet/devnet/testnet.",
1649
+ path: `accepts[${index}].network`,
1650
+ actual: networkRaw
1651
+ });
1652
+ return void 0;
1653
+ }
1654
+ return networkRaw;
1655
+ }
1656
+ function validateV1Network(networkRaw, index, issues) {
1657
+ if (networkRaw === "solana-mainnet-beta") {
1658
+ pushIssue(issues, {
1659
+ code: VALIDATION_CODES.NETWORK_SOLANA_ALIAS_INVALID,
1660
+ severity: "error",
1661
+ message: `Accept at index ${index} uses invalid Solana network alias`,
1662
+ hint: "Use 'solana' (v1) or canonical Solana CAIP reference (v2).",
1663
+ path: `accepts[${index}].network`,
1664
+ expected: "solana",
1665
+ actual: networkRaw
1666
+ });
1667
+ return void 0;
1668
+ }
1669
+ if (networkRaw.startsWith("solana-") && networkRaw !== "solana-devnet") {
1670
+ pushIssue(issues, {
1671
+ code: VALIDATION_CODES.NETWORK_SOLANA_ALIAS_INVALID,
1672
+ severity: "error",
1673
+ message: `Accept at index ${index} uses unsupported Solana network alias`,
1674
+ hint: "Use 'solana' or 'solana-devnet' for v1 payloads.",
1675
+ path: `accepts[${index}].network`,
1676
+ actual: networkRaw
1677
+ });
1678
+ return void 0;
1679
+ }
1680
+ if (networkRaw.includes(":")) {
1681
+ return validateV2Network(networkRaw, index, issues);
1682
+ }
1683
+ return networkRaw;
1684
+ }
1685
+ function validateAccept(acceptRaw, index, version, issues) {
1686
+ if (!isRecord4(acceptRaw)) {
1687
+ pushIssue(issues, {
1688
+ code: VALIDATION_CODES.X402_ACCEPT_ENTRY_INVALID,
1689
+ severity: "error",
1690
+ message: `Accept at index ${index} must be an object`,
1691
+ path: `accepts[${index}]`
1692
+ });
1693
+ return null;
1694
+ }
1695
+ const scheme = asNonEmptyString(acceptRaw.scheme);
1696
+ const networkRaw = asNonEmptyString(acceptRaw.network);
1697
+ const payTo = asNonEmptyString(acceptRaw.payTo);
1698
+ const asset = asNonEmptyString(acceptRaw.asset);
1699
+ const maxTimeoutSeconds = asPositiveNumber(acceptRaw.maxTimeoutSeconds);
1700
+ const amount = version === 2 ? asNonEmptyString(acceptRaw.amount) : asNonEmptyString(acceptRaw.maxAmountRequired);
1701
+ if (!scheme) {
1702
+ pushIssue(issues, {
1703
+ code: VALIDATION_CODES.X402_ACCEPT_ENTRY_INVALID,
1704
+ severity: "error",
1705
+ message: `Accept at index ${index} is missing scheme`,
1706
+ path: `accepts[${index}].scheme`
1707
+ });
1708
+ }
1709
+ if (!networkRaw) {
1710
+ pushIssue(issues, {
1711
+ code: VALIDATION_CODES.X402_ACCEPT_ENTRY_INVALID,
1712
+ severity: "error",
1713
+ message: `Accept at index ${index} is missing network`,
1714
+ path: `accepts[${index}].network`
1715
+ });
1716
+ }
1717
+ if (!amount) {
1718
+ pushIssue(issues, {
1719
+ code: VALIDATION_CODES.X402_ACCEPT_ENTRY_INVALID,
1720
+ severity: "error",
1721
+ message: `Accept at index ${index} is missing ${version === 2 ? "amount" : "maxAmountRequired"}`,
1722
+ path: `accepts[${index}].${version === 2 ? "amount" : "maxAmountRequired"}`
1723
+ });
1724
+ }
1725
+ if (!payTo) {
1726
+ pushIssue(issues, {
1727
+ code: VALIDATION_CODES.X402_ACCEPT_ENTRY_INVALID,
1728
+ severity: "error",
1729
+ message: `Accept at index ${index} is missing payTo`,
1730
+ path: `accepts[${index}].payTo`
1731
+ });
1732
+ }
1733
+ if (!asset) {
1734
+ pushIssue(issues, {
1735
+ code: VALIDATION_CODES.X402_ACCEPT_ENTRY_INVALID,
1736
+ severity: "error",
1737
+ message: `Accept at index ${index} is missing asset`,
1738
+ path: `accepts[${index}].asset`
1739
+ });
1740
+ }
1741
+ if (!maxTimeoutSeconds) {
1742
+ pushIssue(issues, {
1743
+ code: VALIDATION_CODES.X402_ACCEPT_ENTRY_INVALID,
1744
+ severity: "error",
1745
+ message: `Accept at index ${index} is missing or has invalid maxTimeoutSeconds`,
1746
+ path: `accepts[${index}].maxTimeoutSeconds`
1747
+ });
1748
+ }
1749
+ let normalizedNetwork;
1750
+ if (networkRaw) {
1751
+ normalizedNetwork = version === 2 ? validateV2Network(networkRaw, index, issues) : validateV1Network(networkRaw, index, issues);
1752
+ }
1753
+ return {
1754
+ index,
1755
+ network: normalizedNetwork ?? networkRaw ?? "unknown",
1756
+ networkRaw: networkRaw ?? "unknown",
1757
+ scheme,
1758
+ asset,
1759
+ payTo,
1760
+ amount,
1761
+ maxTimeoutSeconds
1762
+ };
1763
+ }
1764
+ function getSchemaPresence(payload, accepts, version) {
1765
+ if (version === 1) {
1766
+ const first = accepts[0];
1767
+ if (!isRecord4(first)) {
1768
+ return { hasInputSchema: false, hasOutputSchema: false };
1769
+ }
1770
+ const outputSchema = isRecord4(first.outputSchema) ? first.outputSchema : void 0;
1771
+ return {
1772
+ hasInputSchema: outputSchema?.input !== void 0 && outputSchema.input !== null,
1773
+ hasOutputSchema: outputSchema?.output !== void 0 && outputSchema.output !== null
1774
+ };
1775
+ }
1776
+ const extensions = isRecord4(payload.extensions) ? payload.extensions : void 0;
1777
+ const bazaar = extensions && isRecord4(extensions.bazaar) ? extensions.bazaar : void 0;
1778
+ const info = bazaar && isRecord4(bazaar.info) ? bazaar.info : void 0;
1779
+ return {
1780
+ hasInputSchema: info?.input !== void 0 && info.input !== null,
1781
+ hasOutputSchema: info?.output !== void 0 && info.output !== null
1782
+ };
1783
+ }
1784
+ function validatePaymentRequiredDetailed(payload, options = {}) {
1785
+ const issues = [];
1786
+ const compatMode = options.compatMode ?? DEFAULT_COMPAT_MODE;
1787
+ const requireInputSchema = options.requireInputSchema ?? true;
1788
+ const requireOutputSchema = options.requireOutputSchema ?? true;
1789
+ if (!isRecord4(payload)) {
1790
+ pushIssue(issues, {
1791
+ code: VALIDATION_CODES.X402_NOT_OBJECT,
1792
+ severity: "error",
1793
+ message: "Payment required payload must be a JSON object",
1794
+ path: "$"
1795
+ });
1796
+ if (options.metadata) {
1797
+ issues.push(...evaluateMetadataCompleteness(options.metadata));
1798
+ }
1799
+ return {
1800
+ valid: false,
1801
+ issues,
1802
+ summary: summarizeIssues(issues)
1803
+ };
1804
+ }
1805
+ const coinbaseParsed = parseWithCoinbaseStructuralGate(payload, issues);
1806
+ const versionRaw = payload.x402Version;
1807
+ let version;
1808
+ if (versionRaw === 1 || versionRaw === 2) {
1809
+ version = versionRaw;
1810
+ } else if (versionRaw === void 0) {
1811
+ pushIssue(issues, {
1812
+ code: VALIDATION_CODES.X402_VERSION_MISSING,
1813
+ severity: "error",
1814
+ message: "x402Version is required",
1815
+ path: "x402Version"
1816
+ });
1817
+ } else {
1818
+ pushIssue(issues, {
1819
+ code: VALIDATION_CODES.X402_VERSION_UNSUPPORTED,
1820
+ severity: "error",
1821
+ message: `Unsupported x402Version '${String(versionRaw)}'`,
1822
+ path: "x402Version",
1823
+ expected: "1 | 2",
1824
+ actual: String(versionRaw)
1825
+ });
1826
+ }
1827
+ const acceptsRaw = payload.accepts;
1828
+ let accepts = [];
1829
+ if (acceptsRaw === void 0) {
1830
+ pushIssue(issues, {
1831
+ code: VALIDATION_CODES.X402_ACCEPTS_MISSING,
1832
+ severity: "error",
1833
+ message: "accepts is required",
1834
+ path: "accepts"
1835
+ });
1836
+ } else if (!Array.isArray(acceptsRaw)) {
1837
+ pushIssue(issues, {
1838
+ code: VALIDATION_CODES.X402_ACCEPTS_INVALID,
1839
+ severity: "error",
1840
+ message: "accepts must be an array",
1841
+ path: "accepts"
1842
+ });
1843
+ } else {
1844
+ accepts = acceptsRaw;
1845
+ if (accepts.length === 0) {
1846
+ pushIssue(issues, {
1847
+ code: VALIDATION_CODES.X402_ACCEPTS_EMPTY,
1848
+ severity: "error",
1849
+ message: "accepts must contain at least one payment requirement",
1850
+ path: "accepts"
1851
+ });
1852
+ }
1853
+ }
1854
+ const normalizedAccepts = [];
1855
+ if (version && Array.isArray(accepts)) {
1856
+ accepts.forEach((accept, index) => {
1857
+ const normalized = validateAccept(accept, index, version, issues);
1858
+ if (normalized) normalizedAccepts.push(normalized);
1859
+ });
1860
+ const schemaPresence = getSchemaPresence(payload, accepts, version);
1861
+ if (requireInputSchema && !schemaPresence.hasInputSchema) {
1862
+ pushIssue(issues, {
1863
+ code: VALIDATION_CODES.SCHEMA_INPUT_MISSING,
1864
+ severity: "error",
1865
+ message: "Input schema is missing",
1866
+ hint: "Include input schema details so clients can invoke the endpoint correctly.",
1867
+ path: version === 1 ? "accepts[0].outputSchema.input" : "extensions.bazaar.info.input"
1868
+ });
1869
+ }
1870
+ if (requireOutputSchema && !schemaPresence.hasOutputSchema) {
1871
+ pushIssue(issues, {
1872
+ code: VALIDATION_CODES.SCHEMA_OUTPUT_MISSING,
1873
+ severity: outputSchemaMissingSeverity(compatMode),
1874
+ message: "Output schema is missing",
1875
+ hint: "Include output schema details so clients can validate responses.",
1876
+ path: version === 1 ? "accepts[0].outputSchema.output" : "extensions.bazaar.info.output"
1877
+ });
1878
+ }
1879
+ if (options.metadata) {
1880
+ issues.push(...evaluateMetadataCompleteness(options.metadata));
1881
+ }
1882
+ const summary2 = summarizeIssues(issues);
1883
+ return {
1884
+ valid: summary2.errorCount === 0,
1885
+ version,
1886
+ parsed: coinbaseParsed ?? payload,
1887
+ normalized: {
1888
+ version,
1889
+ accepts: normalizedAccepts,
1890
+ hasInputSchema: schemaPresence.hasInputSchema,
1891
+ hasOutputSchema: schemaPresence.hasOutputSchema
1892
+ },
1893
+ issues,
1894
+ summary: summary2
1895
+ };
1896
+ }
1897
+ if (options.metadata) {
1898
+ issues.push(...evaluateMetadataCompleteness(options.metadata));
1899
+ }
1900
+ const summary = summarizeIssues(issues);
1901
+ return {
1902
+ valid: summary.errorCount === 0,
1903
+ version,
1904
+ parsed: coinbaseParsed ?? payload,
1905
+ issues,
1906
+ summary
1907
+ };
1908
+ }
1909
+
1442
1910
  // src/adapters/mcp.ts
1443
1911
  var DEFAULT_GUIDANCE_AUTO_INCLUDE_MAX_TOKENS = 1e3;
1444
1912
  var OPENAPI_METHODS = [
@@ -1451,7 +1919,7 @@ var OPENAPI_METHODS = [
1451
1919
  "OPTIONS",
1452
1920
  "TRACE"
1453
1921
  ];
1454
- function isRecord4(value) {
1922
+ function isRecord5(value) {
1455
1923
  return value != null && typeof value === "object" && !Array.isArray(value);
1456
1924
  }
1457
1925
  function toFiniteNumber(value) {
@@ -1511,7 +1979,7 @@ function inferFailureCause(warnings) {
1511
1979
  return { cause: "not_found" };
1512
1980
  }
1513
1981
  function getOpenApiInfo(document) {
1514
- if (!isRecord4(document) || !isRecord4(document.info)) return void 0;
1982
+ if (!isRecord5(document) || !isRecord5(document.info)) return void 0;
1515
1983
  if (typeof document.info.title !== "string") return void 0;
1516
1984
  return {
1517
1985
  title: document.info.title,
@@ -1554,15 +2022,15 @@ async function resolveGuidance(options) {
1554
2022
  };
1555
2023
  }
1556
2024
  function extractPathsDocument(document) {
1557
- if (!isRecord4(document)) return void 0;
1558
- if (!isRecord4(document.paths)) return void 0;
2025
+ if (!isRecord5(document)) return void 0;
2026
+ if (!isRecord5(document.paths)) return void 0;
1559
2027
  return document.paths;
1560
2028
  }
1561
2029
  function findMatchingOpenApiPath(paths, targetPath) {
1562
2030
  const exact = paths[targetPath];
1563
- if (isRecord4(exact)) return { matchedPath: targetPath, pathItem: exact };
2031
+ if (isRecord5(exact)) return { matchedPath: targetPath, pathItem: exact };
1564
2032
  for (const [specPath, entry] of Object.entries(paths)) {
1565
- if (!isRecord4(entry)) continue;
2033
+ if (!isRecord5(entry)) continue;
1566
2034
  const pattern = specPath.replace(/\{[^}]+\}/g, "[^/]+");
1567
2035
  const regex = new RegExp(`^${pattern}$`);
1568
2036
  if (regex.test(targetPath)) {
@@ -1578,11 +2046,11 @@ function resolveRef(document, ref, seen) {
1578
2046
  const parts = ref.slice(2).split("/");
1579
2047
  let current = document;
1580
2048
  for (const part of parts) {
1581
- if (!isRecord4(current)) return void 0;
2049
+ if (!isRecord5(current)) return void 0;
1582
2050
  current = current[part];
1583
2051
  if (current === void 0) return void 0;
1584
2052
  }
1585
- if (isRecord4(current)) return resolveRefs(document, current, seen);
2053
+ if (isRecord5(current)) return resolveRefs(document, current, seen);
1586
2054
  return current;
1587
2055
  }
1588
2056
  function resolveRefs(document, obj, seen, depth = 0) {
@@ -1591,20 +2059,20 @@ function resolveRefs(document, obj, seen, depth = 0) {
1591
2059
  for (const [key, value] of Object.entries(obj)) {
1592
2060
  if (key === "$ref" && typeof value === "string") {
1593
2061
  const deref = resolveRef(document, value, seen);
1594
- if (isRecord4(deref)) {
2062
+ if (isRecord5(deref)) {
1595
2063
  Object.assign(resolved, deref);
1596
2064
  } else {
1597
2065
  resolved[key] = value;
1598
2066
  }
1599
2067
  continue;
1600
2068
  }
1601
- if (isRecord4(value)) {
2069
+ if (isRecord5(value)) {
1602
2070
  resolved[key] = resolveRefs(document, value, seen, depth + 1);
1603
2071
  continue;
1604
2072
  }
1605
2073
  if (Array.isArray(value)) {
1606
2074
  resolved[key] = value.map(
1607
- (item) => isRecord4(item) ? resolveRefs(document, item, seen, depth + 1) : item
2075
+ (item) => isRecord5(item) ? resolveRefs(document, item, seen, depth + 1) : item
1608
2076
  );
1609
2077
  continue;
1610
2078
  }
@@ -1614,15 +2082,15 @@ function resolveRefs(document, obj, seen, depth = 0) {
1614
2082
  }
1615
2083
  function extractRequestBodySchema(operationSchema) {
1616
2084
  const requestBody = operationSchema.requestBody;
1617
- if (!isRecord4(requestBody)) return void 0;
2085
+ if (!isRecord5(requestBody)) return void 0;
1618
2086
  const content = requestBody.content;
1619
- if (!isRecord4(content)) return void 0;
2087
+ if (!isRecord5(content)) return void 0;
1620
2088
  const jsonMediaType = content["application/json"];
1621
- if (isRecord4(jsonMediaType) && isRecord4(jsonMediaType.schema)) {
2089
+ if (isRecord5(jsonMediaType) && isRecord5(jsonMediaType.schema)) {
1622
2090
  return jsonMediaType.schema;
1623
2091
  }
1624
2092
  for (const mediaType of Object.values(content)) {
1625
- if (isRecord4(mediaType) && isRecord4(mediaType.schema)) {
2093
+ if (isRecord5(mediaType) && isRecord5(mediaType.schema)) {
1626
2094
  return mediaType.schema;
1627
2095
  }
1628
2096
  }
@@ -1631,7 +2099,7 @@ function extractRequestBodySchema(operationSchema) {
1631
2099
  function extractParameters(operationSchema) {
1632
2100
  const params = operationSchema.parameters;
1633
2101
  if (!Array.isArray(params)) return [];
1634
- return params.filter((value) => isRecord4(value));
2102
+ return params.filter((value) => isRecord5(value));
1635
2103
  }
1636
2104
  function extractInputSchema(operationSchema) {
1637
2105
  const requestBody = extractRequestBodySchema(operationSchema);
@@ -1645,7 +2113,7 @@ function extractInputSchema(operationSchema) {
1645
2113
  }
1646
2114
  function parseOperationPrice(operation) {
1647
2115
  const paymentInfo = operation["x-payment-info"];
1648
- if (!isRecord4(paymentInfo)) return void 0;
2116
+ if (!isRecord5(paymentInfo)) return void 0;
1649
2117
  const fixed = toFiniteNumber(paymentInfo.price);
1650
2118
  if (fixed != null) return `$${String(fixed)}`;
1651
2119
  const min = toFiniteNumber(paymentInfo.minPrice);
@@ -1655,7 +2123,7 @@ function parseOperationPrice(operation) {
1655
2123
  }
1656
2124
  function parseOperationProtocols(operation) {
1657
2125
  const paymentInfo = operation["x-payment-info"];
1658
- if (!isRecord4(paymentInfo) || !Array.isArray(paymentInfo.protocols)) return void 0;
2126
+ if (!isRecord5(paymentInfo) || !Array.isArray(paymentInfo.protocols)) return void 0;
1659
2127
  const protocols = paymentInfo.protocols.filter(
1660
2128
  (protocol) => typeof protocol === "string" && protocol.length > 0
1661
2129
  );
@@ -1663,13 +2131,13 @@ function parseOperationProtocols(operation) {
1663
2131
  }
1664
2132
  function parseOperationAuthMode(operation) {
1665
2133
  const authExtension = operation["x-agentcash-auth"];
1666
- if (isRecord4(authExtension)) {
2134
+ if (isRecord5(authExtension)) {
1667
2135
  const mode = authExtension.mode;
1668
2136
  if (mode === "paid" || mode === "siwx" || mode === "apiKey" || mode === "unprotected") {
1669
2137
  return mode;
1670
2138
  }
1671
2139
  }
1672
- if (isRecord4(operation["x-payment-info"])) return "paid";
2140
+ if (isRecord5(operation["x-payment-info"])) return "paid";
1673
2141
  return void 0;
1674
2142
  }
1675
2143
  function createResourceMap(result) {
@@ -1763,7 +2231,7 @@ async function inspectEndpointForMcp(options) {
1763
2231
  if (matched) {
1764
2232
  for (const candidate of OPENAPI_METHODS) {
1765
2233
  const operation = matched.pathItem[candidate.toLowerCase()];
1766
- if (!isRecord4(operation) || !isRecord4(document)) continue;
2234
+ if (!isRecord5(operation) || !isRecord5(document)) continue;
1767
2235
  specMethods.push(candidate);
1768
2236
  const resolvedOperation = resolveRefs(document, operation, /* @__PURE__ */ new Set());
1769
2237
  const resource = resourceMap.get(toResourceKey(origin, candidate, matched.matchedPath));
@@ -2082,6 +2550,7 @@ async function discoverDetailed(options) {
2082
2550
  LEGACY_SUNSET_DATE,
2083
2551
  STRICT_ESCALATION_CODES,
2084
2552
  UPGRADE_WARNING_CODES,
2553
+ VALIDATION_CODES,
2085
2554
  auditContextHarness,
2086
2555
  buildContextHarnessReport,
2087
2556
  computeUpgradeSignal,
@@ -2089,7 +2558,9 @@ async function discoverDetailed(options) {
2089
2558
  discover,
2090
2559
  discoverDetailed,
2091
2560
  discoverForMcp,
2561
+ evaluateMetadataCompleteness,
2092
2562
  getHarnessClientProfile,
2093
2563
  inspectEndpointForMcp,
2094
- listHarnessClientProfiles
2564
+ listHarnessClientProfiles,
2565
+ validatePaymentRequiredDetailed
2095
2566
  });