@agentcash/discovery 1.2.0 → 1.4.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/index.cjs CHANGED
@@ -44,6 +44,7 @@ __export(index_exports, {
44
44
  getL3: () => getL3,
45
45
  getL3ForOpenAPI: () => getL3ForOpenAPI,
46
46
  getL3ForProbe: () => getL3ForProbe,
47
+ getMppWellKnown: () => getMppWellKnown,
47
48
  getOpenAPI: () => getOpenAPI,
48
49
  getProbe: () => getProbe,
49
50
  getWarningsFor402Body: () => getWarningsFor402Body,
@@ -54,6 +55,8 @@ __export(index_exports, {
54
55
  getWarningsForOpenAPI: () => getWarningsForOpenAPI,
55
56
  getWarningsForWellKnown: () => getWarningsForWellKnown,
56
57
  getWellKnown: () => getWellKnown,
58
+ getX402WellKnown: () => getX402WellKnown,
59
+ isOpenApiParseFailure: () => isOpenApiParseFailure,
57
60
  validatePaymentRequiredDetailed: () => validatePaymentRequiredDetailed
58
61
  });
59
62
  module.exports = __toCommonJS(index_exports);
@@ -13896,7 +13899,8 @@ var WellKnownParsedSchema = external_exports.object({
13896
13899
  routes: external_exports.array(
13897
13900
  external_exports.object({
13898
13901
  path: external_exports.string(),
13899
- method: external_exports.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "TRACE"])
13902
+ method: external_exports.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "TRACE"]),
13903
+ price: external_exports.string().optional()
13900
13904
  })
13901
13905
  ),
13902
13906
  instructions: external_exports.string().optional()
@@ -13989,9 +13993,9 @@ function toAbsoluteUrl(origin, value) {
13989
13993
 
13990
13994
  // src/core/source/fetch.ts
13991
13995
  var import_neverthrow = require("neverthrow");
13992
- function toFetchError(err) {
13993
- const cause = err instanceof DOMException && (err.name === "TimeoutError" || err.name === "AbortError") ? "timeout" : "network";
13994
- return { cause, message: String(err) };
13996
+ function toFetchError(err2) {
13997
+ const cause = err2 instanceof DOMException && (err2.name === "TimeoutError" || err2.name === "AbortError") ? "timeout" : "network";
13998
+ return { cause, message: String(err2) };
13995
13999
  }
13996
14000
  function fetchSafe(url2, init) {
13997
14001
  return import_neverthrow.ResultAsync.fromPromise(fetch(url2, init), toFetchError);
@@ -14038,7 +14042,13 @@ async function parseBody(response, url2) {
14038
14042
  try {
14039
14043
  const payload = await response.json();
14040
14044
  const parsed = OpenApiParsedSchema.safeParse(payload);
14041
- if (!parsed.success) return null;
14045
+ if (!parsed.success) {
14046
+ return {
14047
+ parseFailure: true,
14048
+ fetchedUrl: url2,
14049
+ issues: parsed.error.issues.map((i) => ({ path: i.path, message: i.message }))
14050
+ };
14051
+ }
14042
14052
  return { raw: payload, ...parsed.data, fetchedUrl: url2 };
14043
14053
  } catch {
14044
14054
  return null;
@@ -14057,6 +14067,9 @@ function getOpenAPI(origin, headers, signal, specificationOverrideUrl) {
14057
14067
  }
14058
14068
 
14059
14069
  // src/core/source/wellknown/index.ts
14070
+ var import_neverthrow5 = require("neverthrow");
14071
+
14072
+ // src/core/source/wellknown/x402.ts
14060
14073
  var import_neverthrow3 = require("neverthrow");
14061
14074
  function toWellKnownParsed(origin, doc) {
14062
14075
  const routes = doc.resources.flatMap((entry) => {
@@ -14083,12 +14096,17 @@ async function parseBody2(response, origin, url2) {
14083
14096
  if (!doc.success) return null;
14084
14097
  const parsed = WellKnownParsedSchema.safeParse(toWellKnownParsed(origin, doc.data));
14085
14098
  if (!parsed.success) return null;
14086
- return { raw: payload, ...parsed.data, fetchedUrl: url2 };
14099
+ return {
14100
+ raw: payload,
14101
+ ...parsed.data,
14102
+ protocol: "x402",
14103
+ fetchedUrl: url2
14104
+ };
14087
14105
  } catch {
14088
14106
  return null;
14089
14107
  }
14090
14108
  }
14091
- function getWellKnown(origin, headers, signal) {
14109
+ function getX402WellKnown(origin, headers, signal) {
14092
14110
  const url2 = `${origin}/.well-known/x402`;
14093
14111
  return fetchSafe(url2, {
14094
14112
  method: "GET",
@@ -14100,6 +14118,127 @@ function getWellKnown(origin, headers, signal) {
14100
14118
  });
14101
14119
  }
14102
14120
 
14121
+ // src/core/source/wellknown/mpp.ts
14122
+ var import_neverthrow4 = require("neverthrow");
14123
+ var MppEndpointSchema = external_exports.object({
14124
+ method: external_exports.string(),
14125
+ path: external_exports.string(),
14126
+ description: external_exports.string().optional(),
14127
+ payment: external_exports.object({
14128
+ intent: external_exports.string().optional(),
14129
+ method: external_exports.string().optional(),
14130
+ amount: external_exports.string().optional(),
14131
+ currency: external_exports.string().optional()
14132
+ }).optional()
14133
+ });
14134
+ var MppWellKnownDocSchema = external_exports.object({
14135
+ version: external_exports.number().optional(),
14136
+ name: external_exports.string().optional(),
14137
+ description: external_exports.string().optional(),
14138
+ categories: external_exports.array(external_exports.string()).optional(),
14139
+ methods: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
14140
+ endpoints: external_exports.array(MppEndpointSchema).default([]),
14141
+ docs: external_exports.object({
14142
+ homepage: external_exports.string().optional(),
14143
+ apiReference: external_exports.string().optional()
14144
+ }).optional()
14145
+ });
14146
+ var MPP_DECIMALS = 6;
14147
+ function formatMppAmount(raw) {
14148
+ if (!raw) return void 0;
14149
+ const n = Number(raw);
14150
+ if (!Number.isFinite(n)) return void 0;
14151
+ return `$${(n / 10 ** MPP_DECIMALS).toFixed(MPP_DECIMALS)}`;
14152
+ }
14153
+ function toWellKnownParsed2(doc) {
14154
+ const routes = doc.endpoints.flatMap((entry) => {
14155
+ const method = parseMethod(entry.method);
14156
+ if (!method) return [];
14157
+ const path = normalizePath(entry.path);
14158
+ if (!path) return [];
14159
+ const price = formatMppAmount(entry.payment?.amount);
14160
+ return [{ path, method, ...price ? { price } : {} }];
14161
+ });
14162
+ return {
14163
+ routes,
14164
+ ...doc.description ? { instructions: doc.description } : {}
14165
+ };
14166
+ }
14167
+ async function parseBody3(response, url2) {
14168
+ try {
14169
+ const payload = await response.json();
14170
+ const doc = MppWellKnownDocSchema.safeParse(payload);
14171
+ if (!doc.success) return null;
14172
+ const parsed = WellKnownParsedSchema.safeParse(toWellKnownParsed2(doc.data));
14173
+ if (!parsed.success) return null;
14174
+ return {
14175
+ raw: payload,
14176
+ ...parsed.data,
14177
+ ...doc.data.name ? { title: doc.data.name } : {},
14178
+ ...doc.data.description ? { description: doc.data.description } : {},
14179
+ protocol: "mpp",
14180
+ fetchedUrl: url2
14181
+ };
14182
+ } catch {
14183
+ return null;
14184
+ }
14185
+ }
14186
+ function getMppWellKnown(origin, headers, signal) {
14187
+ const url2 = `${origin}/.well-known/mpp`;
14188
+ return fetchSafe(url2, {
14189
+ method: "GET",
14190
+ headers: { Accept: "application/json", ...headers },
14191
+ signal
14192
+ }).andThen((response) => {
14193
+ if (!response.ok) return (0, import_neverthrow4.okAsync)(null);
14194
+ return import_neverthrow4.ResultAsync.fromSafePromise(parseBody3(response, url2));
14195
+ });
14196
+ }
14197
+
14198
+ // src/core/source/wellknown/index.ts
14199
+ function mergeError(a, b) {
14200
+ return {
14201
+ cause: a.cause === "network" || b.cause === "network" ? "network" : "timeout",
14202
+ message: `x402: ${a.message} | mpp: ${b.message}`
14203
+ };
14204
+ }
14205
+ function merge2(x402, mpp) {
14206
+ const seen = /* @__PURE__ */ new Set();
14207
+ const routes = [...x402.routes, ...mpp.routes].filter((r) => {
14208
+ const key = `${r.method} ${r.path}`;
14209
+ if (seen.has(key)) return false;
14210
+ seen.add(key);
14211
+ return true;
14212
+ });
14213
+ return {
14214
+ raw: { ...mpp.raw, ...x402.raw },
14215
+ routes,
14216
+ protocol: "x402+mpp",
14217
+ // Prefer x402 instructions; fall back to mpp
14218
+ ...x402.instructions || mpp.instructions ? { instructions: x402.instructions ?? mpp.instructions } : {},
14219
+ fetchedUrl: x402.fetchedUrl
14220
+ };
14221
+ }
14222
+ function getWellKnown(origin, headers, signal) {
14223
+ return new import_neverthrow5.ResultAsync(
14224
+ Promise.all([
14225
+ getX402WellKnown(origin, headers, signal),
14226
+ getMppWellKnown(origin, headers, signal)
14227
+ ]).then(([x402Result, mppResult]) => {
14228
+ const x402 = x402Result.isOk() ? x402Result.value : null;
14229
+ const mpp = mppResult.isOk() ? mppResult.value : null;
14230
+ if (x402 && mpp) return (0, import_neverthrow5.ok)(merge2(x402, mpp));
14231
+ if (x402) return (0, import_neverthrow5.ok)(x402);
14232
+ if (mpp) return (0, import_neverthrow5.ok)(mpp);
14233
+ if (x402Result.isErr() && mppResult.isErr())
14234
+ return (0, import_neverthrow5.err)(mergeError(x402Result.error, mppResult.error));
14235
+ if (x402Result.isErr()) return (0, import_neverthrow5.err)(x402Result.error);
14236
+ if (mppResult.isErr()) return (0, import_neverthrow5.err)(mppResult.error);
14237
+ return (0, import_neverthrow5.ok)(null);
14238
+ })
14239
+ );
14240
+ }
14241
+
14103
14242
  // src/core/layers/l2.ts
14104
14243
  function formatPrice(pricing) {
14105
14244
  if (pricing.pricingMode === "fixed") return `$${pricing.price}`;
@@ -14125,15 +14264,27 @@ function checkL2ForOpenAPI(openApi) {
14125
14264
  source: "openapi"
14126
14265
  };
14127
14266
  }
14267
+ var WELL_KNOWN_PROTOCOLS = {
14268
+ x402: ["x402"],
14269
+ mpp: ["mpp"],
14270
+ "x402+mpp": ["x402", "mpp"]
14271
+ };
14128
14272
  function checkL2ForWellknown(wellKnown) {
14273
+ const protocols = WELL_KNOWN_PROTOCOLS[wellKnown.protocol];
14129
14274
  const routes = wellKnown.routes.map((route) => ({
14130
14275
  path: route.path,
14131
14276
  method: route.method,
14132
14277
  summary: `${route.method} ${route.path}`,
14133
14278
  authMode: "paid",
14134
- protocols: ["x402"]
14279
+ protocols,
14280
+ ...route.price ? { price: route.price } : {}
14135
14281
  }));
14136
- return { routes, source: "well-known/x402" };
14282
+ return {
14283
+ ...wellKnown.title ? { title: wellKnown.title } : {},
14284
+ ...wellKnown.description ? { description: wellKnown.description } : {},
14285
+ routes,
14286
+ source: `well-known/${wellKnown.protocol}`
14287
+ };
14137
14288
  }
14138
14289
 
14139
14290
  // src/core/layers/l4.ts
@@ -14145,7 +14296,7 @@ function checkL4ForOpenAPI(openApi) {
14145
14296
  }
14146
14297
  function checkL4ForWellknown(wellKnown) {
14147
14298
  if (wellKnown.instructions) {
14148
- return { guidance: wellKnown.instructions, source: "well-known/x402" };
14299
+ return { guidance: wellKnown.instructions, source: `well-known/${wellKnown.protocol}` };
14149
14300
  }
14150
14301
  return null;
14151
14302
  }
@@ -14163,8 +14314,41 @@ var GuidanceMode = /* @__PURE__ */ ((GuidanceMode2) => {
14163
14314
  return GuidanceMode2;
14164
14315
  })(GuidanceMode || {});
14165
14316
 
14317
+ // src/core/types/sources.ts
14318
+ function isOpenApiSource(raw) {
14319
+ return raw !== null && !("parseFailure" in raw);
14320
+ }
14321
+
14166
14322
  // src/runtime/discover.ts
14167
14323
  var GUIDANCE_AUTO_INCLUDE_MAX_TOKENS_LENGTH = 1e3;
14324
+ function extractFromWellknown(raw) {
14325
+ if (Array.isArray(raw["ownershipProofs"])) {
14326
+ const proofs = raw["ownershipProofs"].filter(
14327
+ (p) => typeof p === "string"
14328
+ );
14329
+ if (proofs.length > 0) return proofs;
14330
+ }
14331
+ return void 0;
14332
+ }
14333
+ function extractFromOpenapi(raw) {
14334
+ const xDiscovery = raw["x-discovery"];
14335
+ if (xDiscovery && typeof xDiscovery === "object" && !Array.isArray(xDiscovery)) {
14336
+ const proofs = xDiscovery["ownershipProofs"];
14337
+ if (Array.isArray(proofs)) {
14338
+ const filtered = proofs.filter((p) => typeof p === "string");
14339
+ if (filtered.length > 0) return filtered;
14340
+ }
14341
+ }
14342
+ const legacy = raw["x-agentcash-provenance"];
14343
+ if (legacy && typeof legacy === "object" && !Array.isArray(legacy)) {
14344
+ const proofs = legacy["ownershipProofs"];
14345
+ if (Array.isArray(proofs)) {
14346
+ const filtered = proofs.filter((p) => typeof p === "string");
14347
+ if (filtered.length > 0) return filtered;
14348
+ }
14349
+ }
14350
+ return void 0;
14351
+ }
14168
14352
  function withGuidance(base, l4, guidanceMode) {
14169
14353
  if (guidanceMode === "never" /* Never */) return { ...base, guidanceAvailable: !!l4 };
14170
14354
  if (!l4) return { ...base, guidanceAvailable: false };
@@ -14183,10 +14367,12 @@ async function discoverOriginSchema(options) {
14183
14367
  options.signal,
14184
14368
  options.specificationOverrideUrl
14185
14369
  );
14186
- const openApi = openApiResult.isOk() ? openApiResult.value : null;
14370
+ const openApiRaw = openApiResult.isOk() ? openApiResult.value : null;
14371
+ const openApi = isOpenApiSource(openApiRaw) ? openApiRaw : null;
14187
14372
  if (openApi) {
14188
14373
  const l22 = checkL2ForOpenAPI(openApi);
14189
14374
  const l42 = checkL4ForOpenAPI(openApi);
14375
+ const ownershipProofs2 = extractFromOpenapi(openApi.raw);
14190
14376
  const base2 = {
14191
14377
  found: true,
14192
14378
  origin,
@@ -14198,7 +14384,8 @@ async function discoverOriginSchema(options) {
14198
14384
  ...l22.version ? { version: l22.version } : {}
14199
14385
  }
14200
14386
  } : {},
14201
- endpoints: l22.routes
14387
+ endpoints: l22.routes,
14388
+ ...ownershipProofs2 ? { ownershipProofs: ownershipProofs2 } : {}
14202
14389
  };
14203
14390
  return withGuidance(base2, l42, guidanceMode);
14204
14391
  }
@@ -14215,17 +14402,25 @@ async function discoverOriginSchema(options) {
14215
14402
  if (!wellKnown) return { found: false, origin, cause: "not_found" };
14216
14403
  const l2 = checkL2ForWellknown(wellKnown);
14217
14404
  const l4 = checkL4ForWellknown(wellKnown);
14405
+ const ownershipProofs = extractFromWellknown(wellKnown.raw);
14218
14406
  const base = {
14219
14407
  found: true,
14220
14408
  origin,
14221
- source: "well-known/x402",
14222
- endpoints: l2.routes
14409
+ source: l2.source,
14410
+ ...l2.title ? {
14411
+ info: {
14412
+ title: l2.title,
14413
+ ...l2.description ? { description: l2.description } : {}
14414
+ }
14415
+ } : {},
14416
+ endpoints: l2.routes,
14417
+ ...ownershipProofs ? { ownershipProofs } : {}
14223
14418
  };
14224
14419
  return withGuidance(base, l4, guidanceMode);
14225
14420
  }
14226
14421
 
14227
14422
  // src/core/source/probe/index.ts
14228
- var import_neverthrow4 = require("neverthrow");
14423
+ var import_neverthrow6 = require("neverthrow");
14229
14424
 
14230
14425
  // src/core/protocols/x402/v1/schema.ts
14231
14426
  function extractSchemas(accepts) {
@@ -14675,8 +14870,8 @@ function probeMethod(url2, method, path, headers, signal, inputBody) {
14675
14870
  ...hasBody ? { body: JSON.stringify(inputBody) } : {},
14676
14871
  signal
14677
14872
  }).andThen((response) => {
14678
- if (!isUsableStatus(response.status)) return import_neverthrow4.ResultAsync.fromSafePromise(Promise.resolve(null));
14679
- return import_neverthrow4.ResultAsync.fromSafePromise(
14873
+ if (!isUsableStatus(response.status)) return import_neverthrow6.ResultAsync.fromSafePromise(Promise.resolve(null));
14874
+ return import_neverthrow6.ResultAsync.fromSafePromise(
14680
14875
  (async () => {
14681
14876
  let authHint = response.status === 402 ? "paid" : "unprotected";
14682
14877
  let paymentRequiredBody;
@@ -14707,7 +14902,7 @@ function probeMethod(url2, method, path, headers, signal, inputBody) {
14707
14902
  }
14708
14903
  function getProbe(url2, headers, signal, inputBody) {
14709
14904
  const path = normalizePath(new URL(url2).pathname || "/");
14710
- return import_neverthrow4.ResultAsync.fromSafePromise(
14905
+ return import_neverthrow6.ResultAsync.fromSafePromise(
14711
14906
  Promise.all(
14712
14907
  [...HTTP_METHODS].map(
14713
14908
  (method) => probeMethod(url2, method, path, headers, signal, inputBody).match(
@@ -14720,6 +14915,20 @@ function getProbe(url2, headers, signal, inputBody) {
14720
14915
  }
14721
14916
 
14722
14917
  // src/core/protocols/mpp/index.ts
14918
+ var import_neverthrow7 = require("neverthrow");
14919
+ function parseBase64Json(encoded) {
14920
+ return import_neverthrow7.Result.fromThrowable(
14921
+ () => {
14922
+ const decoded = typeof Buffer !== "undefined" ? Buffer.from(encoded, "base64").toString("utf8") : atob(encoded);
14923
+ const parsed = JSON.parse(decoded);
14924
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
14925
+ throw new Error("not an object");
14926
+ }
14927
+ return parsed;
14928
+ },
14929
+ (e) => e
14930
+ )();
14931
+ }
14723
14932
  var TEMPO_DEFAULT_CHAIN_ID = 4217;
14724
14933
  function parseAuthParams(segment) {
14725
14934
  const params = {};
@@ -14742,14 +14951,9 @@ function extractPaymentOptions4(wwwAuthenticate) {
14742
14951
  const description = params["description"];
14743
14952
  const requestStr = params["request"];
14744
14953
  if (!paymentMethod || !intent || !realm || !requestStr) continue;
14745
- let request;
14746
- try {
14747
- const parsed = JSON.parse(requestStr);
14748
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) continue;
14749
- request = parsed;
14750
- } catch {
14751
- continue;
14752
- }
14954
+ const requestResult = parseBase64Json(requestStr);
14955
+ if (requestResult.isErr()) continue;
14956
+ const request = requestResult.value;
14753
14957
  const asset = typeof request["currency"] === "string" ? request["currency"] : void 0;
14754
14958
  const amountRaw = request["amount"];
14755
14959
  const amount = typeof amountRaw === "string" ? amountRaw : typeof amountRaw === "number" ? String(amountRaw) : void 0;
@@ -14988,7 +15192,8 @@ async function checkEndpointSchema(options) {
14988
15192
  return { found: false, origin, path, cause: "not_found" };
14989
15193
  }
14990
15194
  const openApiResult = await getOpenAPI(origin, options.headers, options.signal);
14991
- const openApi = openApiResult.isOk() ? openApiResult.value : null;
15195
+ const openApiRaw = openApiResult.isOk() ? openApiResult.value : null;
15196
+ const openApi = isOpenApiSource(openApiRaw) ? openApiRaw : null;
14992
15197
  if (openApi) {
14993
15198
  const advisories2 = getAdvisoriesForOpenAPI(openApi, path);
14994
15199
  if (advisories2.length > 0) return { found: true, origin, path, advisories: advisories2 };
@@ -15099,6 +15304,7 @@ var AUDIT_CODES = {
15099
15304
  OPENAPI_NOT_FOUND: "OPENAPI_NOT_FOUND",
15100
15305
  WELLKNOWN_NOT_FOUND: "WELLKNOWN_NOT_FOUND",
15101
15306
  // ─── OpenAPI quality ─────────────────────────────────────────────────────────
15307
+ OPENAPI_PARSE_ERROR: "OPENAPI_PARSE_ERROR",
15102
15308
  OPENAPI_NO_ROUTES: "OPENAPI_NO_ROUTES",
15103
15309
  // ─── L2 route-list checks ────────────────────────────────────────────────────
15104
15310
  L2_NO_ROUTES: "L2_NO_ROUTES",
@@ -15586,6 +15792,9 @@ function validatePaymentRequiredDetailed(payload, options = {}) {
15586
15792
  }
15587
15793
 
15588
15794
  // src/audit/warnings/sources.ts
15795
+ function isOpenApiParseFailure(value) {
15796
+ return value !== null && "parseFailure" in value;
15797
+ }
15589
15798
  function getWarningsForOpenAPI(openApi) {
15590
15799
  if (openApi === null) {
15591
15800
  return [
@@ -15597,6 +15806,18 @@ function getWarningsForOpenAPI(openApi) {
15597
15806
  }
15598
15807
  ];
15599
15808
  }
15809
+ if (isOpenApiParseFailure(openApi)) {
15810
+ const details = openApi.issues.map((i) => ` ${i.path.map(String).join(".")}: ${i.message}`).join("\n");
15811
+ return [
15812
+ {
15813
+ code: AUDIT_CODES.OPENAPI_PARSE_ERROR,
15814
+ severity: "warn",
15815
+ message: `OpenAPI spec found at ${openApi.fetchedUrl} but failed schema validation:
15816
+ ${details}`,
15817
+ hint: "Fix the schema issues above so discovery can read the spec."
15818
+ }
15819
+ ];
15820
+ }
15600
15821
  const warnings = [];
15601
15822
  if (openApi.routes.length === 0) {
15602
15823
  warnings.push({
@@ -15738,6 +15959,7 @@ function getWarningsForL4(l4) {
15738
15959
  getL3,
15739
15960
  getL3ForOpenAPI,
15740
15961
  getL3ForProbe,
15962
+ getMppWellKnown,
15741
15963
  getOpenAPI,
15742
15964
  getProbe,
15743
15965
  getWarningsFor402Body,
@@ -15748,5 +15970,7 @@ function getWarningsForL4(l4) {
15748
15970
  getWarningsForOpenAPI,
15749
15971
  getWarningsForWellKnown,
15750
15972
  getWellKnown,
15973
+ getX402WellKnown,
15974
+ isOpenApiParseFailure,
15751
15975
  validatePaymentRequiredDetailed
15752
15976
  });
package/dist/index.d.cts CHANGED
@@ -78,6 +78,15 @@ interface OpenApiSource {
78
78
  guidance?: string;
79
79
  fetchedUrl: string;
80
80
  }
81
+ /** Returned when the spec was fetched successfully but failed schema validation. */
82
+ interface OpenApiParseFailure {
83
+ parseFailure: true;
84
+ fetchedUrl: string;
85
+ issues: Array<{
86
+ path: (string | number | symbol)[];
87
+ message: string;
88
+ }>;
89
+ }
81
90
  interface OpenApiRoute {
82
91
  path: string;
83
92
  method: HttpMethod;
@@ -89,12 +98,18 @@ interface OpenApiRoute {
89
98
  interface WellKnownSource {
90
99
  raw: Record<string, unknown>;
91
100
  routes: WellKnownRoute[];
101
+ title?: string;
102
+ description?: string;
92
103
  instructions?: string;
93
104
  fetchedUrl: string;
105
+ /** Which well-known document(s) this source was built from. */
106
+ protocol: 'x402' | 'mpp' | 'x402+mpp';
94
107
  }
95
108
  interface WellKnownRoute {
96
109
  path: string;
97
110
  method: HttpMethod;
111
+ /** Raw price hint from the well-known document (e.g. MPP `payment.amount`). */
112
+ price?: string;
98
113
  }
99
114
  interface ProbeResult {
100
115
  path: string;
@@ -111,7 +126,7 @@ interface L2Result {
111
126
  description?: string;
112
127
  version?: string;
113
128
  routes: L2Route[];
114
- source: 'openapi' | 'well-known/x402' | null;
129
+ source: 'openapi' | 'well-known/x402' | 'well-known/mpp' | 'well-known/x402+mpp' | null;
115
130
  }
116
131
  interface L2Route {
117
132
  path: string;
@@ -145,7 +160,7 @@ interface L3Result {
145
160
  }
146
161
  interface L4Result {
147
162
  guidance: string;
148
- source: 'openapi' | 'well-known/x402';
163
+ source: 'openapi' | 'well-known/x402' | 'well-known/mpp' | 'well-known/x402+mpp';
149
164
  }
150
165
 
151
166
  declare enum GuidanceMode {
@@ -182,6 +197,8 @@ interface DiscoverOriginSchemaSuccess {
182
197
  guidanceTokens?: number;
183
198
  /** Guidance text. Included when short enough (auto mode) or guidance='always'. */
184
199
  guidance?: string;
200
+ /** Ownership proof strings collected from the discovery document, if any. */
201
+ ownershipProofs?: string[];
185
202
  }
186
203
  interface DiscoverOriginSchemaNotFound {
187
204
  found: false;
@@ -239,10 +256,23 @@ interface FetchError {
239
256
  message: string;
240
257
  }
241
258
 
242
- declare function getOpenAPI(origin: string, headers?: Record<string, string>, signal?: AbortSignal, specificationOverrideUrl?: string): ResultAsync<OpenApiSource | null, FetchError>;
259
+ declare function getOpenAPI(origin: string, headers?: Record<string, string>, signal?: AbortSignal, specificationOverrideUrl?: string): ResultAsync<OpenApiSource | OpenApiParseFailure | null, FetchError>;
243
260
 
261
+ /**
262
+ * Fetches both `/.well-known/x402` and `/.well-known/mpp` in parallel and merges results.
263
+ *
264
+ * In practice these are mutually exclusive, but if both exist their routes are combined
265
+ * (deduplicated by method+path). x402 wins on instruction/fetchedUrl conflicts.
266
+ *
267
+ * Individual leg failures are treated as "not found" for that leg so valid data from
268
+ * the other is never suppressed. Returns Err(FetchError) only when both legs hard-fail.
269
+ */
244
270
  declare function getWellKnown(origin: string, headers?: Record<string, string>, signal?: AbortSignal): ResultAsync<WellKnownSource | null, FetchError>;
245
271
 
272
+ declare function getX402WellKnown(origin: string, headers?: Record<string, string>, signal?: AbortSignal): ResultAsync<WellKnownSource | null, FetchError>;
273
+
274
+ declare function getMppWellKnown(origin: string, headers?: Record<string, string>, signal?: AbortSignal): ResultAsync<WellKnownSource | null, FetchError>;
275
+
246
276
  declare function getProbe(url: string, headers?: Record<string, string>, signal?: AbortSignal, inputBody?: Record<string, unknown>): ResultAsync<ProbeResult[], FetchError>;
247
277
 
248
278
  declare function checkL2ForOpenAPI(openApi: OpenApiSource): L2Result;
@@ -354,6 +384,7 @@ declare function validatePaymentRequiredDetailed(payload: unknown, options?: Val
354
384
  declare const AUDIT_CODES: {
355
385
  readonly OPENAPI_NOT_FOUND: "OPENAPI_NOT_FOUND";
356
386
  readonly WELLKNOWN_NOT_FOUND: "WELLKNOWN_NOT_FOUND";
387
+ readonly OPENAPI_PARSE_ERROR: "OPENAPI_PARSE_ERROR";
357
388
  readonly OPENAPI_NO_ROUTES: "OPENAPI_NO_ROUTES";
358
389
  readonly L2_NO_ROUTES: "L2_NO_ROUTES";
359
390
  readonly L2_ROUTE_COUNT_HIGH: "L2_ROUTE_COUNT_HIGH";
@@ -394,7 +425,9 @@ interface AuditWarning {
394
425
  path?: string;
395
426
  }
396
427
 
397
- declare function getWarningsForOpenAPI(openApi: OpenApiSource | null): AuditWarning[];
428
+ /** Type guard: true when the value is a parse-failure sentinel (spec fetched but invalid). */
429
+ declare function isOpenApiParseFailure(value: OpenApiSource | OpenApiParseFailure | null): value is OpenApiParseFailure;
430
+ declare function getWarningsForOpenAPI(openApi: OpenApiSource | OpenApiParseFailure | null): AuditWarning[];
398
431
  declare function getWarningsForWellKnown(wellKnown: WellKnownSource | null): AuditWarning[];
399
432
 
400
433
  declare function getWarningsForL2(l2: L2Result): AuditWarning[];
@@ -424,4 +457,4 @@ declare function getWarningsForL4(l4: L4Result | null): AuditWarning[];
424
457
  */
425
458
  declare function getWarningsForMppHeader(wwwAuthenticate: string | null | undefined): AuditWarning[];
426
459
 
427
- export { AUDIT_CODES, type AuditCode, type AuditSeverity, type AuditWarning, type AuthMode, type CheckEndpointNotFound, type CheckEndpointOptions, type CheckEndpointResult, type CheckEndpointSuccess, type DiscoverOriginSchemaNotFound, type DiscoverOriginSchemaOptions, type DiscoverOriginSchemaResult, type DiscoverOriginSchemaSuccess, type EndpointMethodAdvisory, GuidanceMode, type HttpMethod, type L2Result, type L2Route, type L3Result, type L4Result, type MetadataPreview, type MppPaymentOption, type NormalizedAccept, type NormalizedPaymentRequired, type OpenApiRoute, type OpenApiSource, type PaymentOption, type PricingMode, type ProbeResult, type TrustTier, VALIDATION_CODES, type ValidatePaymentRequiredDetailedResult, type ValidatePaymentRequiredOptions, type ValidationIssue, type ValidationSeverity, type ValidationStage, type ValidationSummary, type WellKnownRoute, type WellKnownSource, type X402PaymentOption, type X402V1PaymentOption, type X402V2PaymentOption, attachProbePayload, checkEndpointSchema, checkL2ForOpenAPI, checkL2ForWellknown, checkL4ForOpenAPI, checkL4ForWellknown, discoverOriginSchema, evaluateMetadataCompleteness, getL3, getL3ForOpenAPI, getL3ForProbe, getOpenAPI, getProbe, getWarningsFor402Body, getWarningsForL2, getWarningsForL3, getWarningsForL4, getWarningsForMppHeader, getWarningsForOpenAPI, getWarningsForWellKnown, getWellKnown, validatePaymentRequiredDetailed };
460
+ export { AUDIT_CODES, type AuditCode, type AuditSeverity, type AuditWarning, type AuthMode, type CheckEndpointNotFound, type CheckEndpointOptions, type CheckEndpointResult, type CheckEndpointSuccess, type DiscoverOriginSchemaNotFound, type DiscoverOriginSchemaOptions, type DiscoverOriginSchemaResult, type DiscoverOriginSchemaSuccess, type EndpointMethodAdvisory, GuidanceMode, type HttpMethod, type L2Result, type L2Route, type L3Result, type L4Result, type MetadataPreview, type MppPaymentOption, type NormalizedAccept, type NormalizedPaymentRequired, type OpenApiParseFailure, type OpenApiRoute, type OpenApiSource, type PaymentOption, type PricingMode, type ProbeResult, type TrustTier, VALIDATION_CODES, type ValidatePaymentRequiredDetailedResult, type ValidatePaymentRequiredOptions, type ValidationIssue, type ValidationSeverity, type ValidationStage, type ValidationSummary, type WellKnownRoute, type WellKnownSource, type X402PaymentOption, type X402V1PaymentOption, type X402V2PaymentOption, attachProbePayload, checkEndpointSchema, checkL2ForOpenAPI, checkL2ForWellknown, checkL4ForOpenAPI, checkL4ForWellknown, discoverOriginSchema, evaluateMetadataCompleteness, getL3, getL3ForOpenAPI, getL3ForProbe, getMppWellKnown, getOpenAPI, getProbe, getWarningsFor402Body, getWarningsForL2, getWarningsForL3, getWarningsForL4, getWarningsForMppHeader, getWarningsForOpenAPI, getWarningsForWellKnown, getWellKnown, getX402WellKnown, isOpenApiParseFailure, validatePaymentRequiredDetailed };