@agentcash/discovery 1.1.3 → 1.3.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
@@ -13872,7 +13872,8 @@ var WellKnownParsedSchema = external_exports.object({
13872
13872
  routes: external_exports.array(
13873
13873
  external_exports.object({
13874
13874
  path: external_exports.string(),
13875
- method: external_exports.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "TRACE"])
13875
+ method: external_exports.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "TRACE"]),
13876
+ price: external_exports.string().optional()
13876
13877
  })
13877
13878
  ),
13878
13879
  instructions: external_exports.string().optional()
@@ -13965,9 +13966,9 @@ function toAbsoluteUrl(origin, value) {
13965
13966
 
13966
13967
  // src/core/source/fetch.ts
13967
13968
  var import_neverthrow = require("neverthrow");
13968
- function toFetchError(err) {
13969
- const cause = err instanceof DOMException && (err.name === "TimeoutError" || err.name === "AbortError") ? "timeout" : "network";
13970
- return { cause, message: String(err) };
13969
+ function toFetchError(err2) {
13970
+ const cause = err2 instanceof DOMException && (err2.name === "TimeoutError" || err2.name === "AbortError") ? "timeout" : "network";
13971
+ return { cause, message: String(err2) };
13971
13972
  }
13972
13973
  function fetchSafe(url2, init) {
13973
13974
  return import_neverthrow.ResultAsync.fromPromise(fetch(url2, init), toFetchError);
@@ -14033,6 +14034,9 @@ function getOpenAPI(origin, headers, signal, specificationOverrideUrl) {
14033
14034
  }
14034
14035
 
14035
14036
  // src/core/source/wellknown/index.ts
14037
+ var import_neverthrow5 = require("neverthrow");
14038
+
14039
+ // src/core/source/wellknown/x402.ts
14036
14040
  var import_neverthrow3 = require("neverthrow");
14037
14041
  function toWellKnownParsed(origin, doc) {
14038
14042
  const routes = doc.resources.flatMap((entry) => {
@@ -14059,12 +14063,17 @@ async function parseBody2(response, origin, url2) {
14059
14063
  if (!doc.success) return null;
14060
14064
  const parsed = WellKnownParsedSchema.safeParse(toWellKnownParsed(origin, doc.data));
14061
14065
  if (!parsed.success) return null;
14062
- return { raw: payload, ...parsed.data, fetchedUrl: url2 };
14066
+ return {
14067
+ raw: payload,
14068
+ ...parsed.data,
14069
+ protocol: "x402",
14070
+ fetchedUrl: url2
14071
+ };
14063
14072
  } catch {
14064
14073
  return null;
14065
14074
  }
14066
14075
  }
14067
- function getWellKnown(origin, headers, signal) {
14076
+ function getX402WellKnown(origin, headers, signal) {
14068
14077
  const url2 = `${origin}/.well-known/x402`;
14069
14078
  return fetchSafe(url2, {
14070
14079
  method: "GET",
@@ -14076,6 +14085,127 @@ function getWellKnown(origin, headers, signal) {
14076
14085
  });
14077
14086
  }
14078
14087
 
14088
+ // src/core/source/wellknown/mpp.ts
14089
+ var import_neverthrow4 = require("neverthrow");
14090
+ var MppEndpointSchema = external_exports.object({
14091
+ method: external_exports.string(),
14092
+ path: external_exports.string(),
14093
+ description: external_exports.string().optional(),
14094
+ payment: external_exports.object({
14095
+ intent: external_exports.string().optional(),
14096
+ method: external_exports.string().optional(),
14097
+ amount: external_exports.string().optional(),
14098
+ currency: external_exports.string().optional()
14099
+ }).optional()
14100
+ });
14101
+ var MppWellKnownDocSchema = external_exports.object({
14102
+ version: external_exports.number().optional(),
14103
+ name: external_exports.string().optional(),
14104
+ description: external_exports.string().optional(),
14105
+ categories: external_exports.array(external_exports.string()).optional(),
14106
+ methods: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
14107
+ endpoints: external_exports.array(MppEndpointSchema).default([]),
14108
+ docs: external_exports.object({
14109
+ homepage: external_exports.string().optional(),
14110
+ apiReference: external_exports.string().optional()
14111
+ }).optional()
14112
+ });
14113
+ var MPP_DECIMALS = 6;
14114
+ function formatMppAmount(raw) {
14115
+ if (!raw) return void 0;
14116
+ const n = Number(raw);
14117
+ if (!Number.isFinite(n)) return void 0;
14118
+ return `$${(n / 10 ** MPP_DECIMALS).toFixed(MPP_DECIMALS)}`;
14119
+ }
14120
+ function toWellKnownParsed2(doc) {
14121
+ const routes = doc.endpoints.flatMap((entry) => {
14122
+ const method = parseMethod(entry.method);
14123
+ if (!method) return [];
14124
+ const path = normalizePath(entry.path);
14125
+ if (!path) return [];
14126
+ const price = formatMppAmount(entry.payment?.amount);
14127
+ return [{ path, method, ...price ? { price } : {} }];
14128
+ });
14129
+ return {
14130
+ routes,
14131
+ ...doc.description ? { instructions: doc.description } : {}
14132
+ };
14133
+ }
14134
+ async function parseBody3(response, url2) {
14135
+ try {
14136
+ const payload = await response.json();
14137
+ const doc = MppWellKnownDocSchema.safeParse(payload);
14138
+ if (!doc.success) return null;
14139
+ const parsed = WellKnownParsedSchema.safeParse(toWellKnownParsed2(doc.data));
14140
+ if (!parsed.success) return null;
14141
+ return {
14142
+ raw: payload,
14143
+ ...parsed.data,
14144
+ ...doc.data.name ? { title: doc.data.name } : {},
14145
+ ...doc.data.description ? { description: doc.data.description } : {},
14146
+ protocol: "mpp",
14147
+ fetchedUrl: url2
14148
+ };
14149
+ } catch {
14150
+ return null;
14151
+ }
14152
+ }
14153
+ function getMppWellKnown(origin, headers, signal) {
14154
+ const url2 = `${origin}/.well-known/mpp`;
14155
+ return fetchSafe(url2, {
14156
+ method: "GET",
14157
+ headers: { Accept: "application/json", ...headers },
14158
+ signal
14159
+ }).andThen((response) => {
14160
+ if (!response.ok) return (0, import_neverthrow4.okAsync)(null);
14161
+ return import_neverthrow4.ResultAsync.fromSafePromise(parseBody3(response, url2));
14162
+ });
14163
+ }
14164
+
14165
+ // src/core/source/wellknown/index.ts
14166
+ function mergeError(a, b) {
14167
+ return {
14168
+ cause: a.cause === "network" || b.cause === "network" ? "network" : "timeout",
14169
+ message: `x402: ${a.message} | mpp: ${b.message}`
14170
+ };
14171
+ }
14172
+ function merge2(x402, mpp) {
14173
+ const seen = /* @__PURE__ */ new Set();
14174
+ const routes = [...x402.routes, ...mpp.routes].filter((r) => {
14175
+ const key = `${r.method} ${r.path}`;
14176
+ if (seen.has(key)) return false;
14177
+ seen.add(key);
14178
+ return true;
14179
+ });
14180
+ return {
14181
+ raw: { ...mpp.raw, ...x402.raw },
14182
+ routes,
14183
+ protocol: "x402+mpp",
14184
+ // Prefer x402 instructions; fall back to mpp
14185
+ ...x402.instructions || mpp.instructions ? { instructions: x402.instructions ?? mpp.instructions } : {},
14186
+ fetchedUrl: x402.fetchedUrl
14187
+ };
14188
+ }
14189
+ function getWellKnown(origin, headers, signal) {
14190
+ return new import_neverthrow5.ResultAsync(
14191
+ Promise.all([
14192
+ getX402WellKnown(origin, headers, signal),
14193
+ getMppWellKnown(origin, headers, signal)
14194
+ ]).then(([x402Result, mppResult]) => {
14195
+ const x402 = x402Result.isOk() ? x402Result.value : null;
14196
+ const mpp = mppResult.isOk() ? mppResult.value : null;
14197
+ if (x402 && mpp) return (0, import_neverthrow5.ok)(merge2(x402, mpp));
14198
+ if (x402) return (0, import_neverthrow5.ok)(x402);
14199
+ if (mpp) return (0, import_neverthrow5.ok)(mpp);
14200
+ if (x402Result.isErr() && mppResult.isErr())
14201
+ return (0, import_neverthrow5.err)(mergeError(x402Result.error, mppResult.error));
14202
+ if (x402Result.isErr()) return (0, import_neverthrow5.err)(x402Result.error);
14203
+ if (mppResult.isErr()) return (0, import_neverthrow5.err)(mppResult.error);
14204
+ return (0, import_neverthrow5.ok)(null);
14205
+ })
14206
+ );
14207
+ }
14208
+
14079
14209
  // src/core/layers/l2.ts
14080
14210
  function formatPrice(pricing) {
14081
14211
  if (pricing.pricingMode === "fixed") return `$${pricing.price}`;
@@ -14101,15 +14231,27 @@ function checkL2ForOpenAPI(openApi) {
14101
14231
  source: "openapi"
14102
14232
  };
14103
14233
  }
14234
+ var WELL_KNOWN_PROTOCOLS = {
14235
+ x402: ["x402"],
14236
+ mpp: ["mpp"],
14237
+ "x402+mpp": ["x402", "mpp"]
14238
+ };
14104
14239
  function checkL2ForWellknown(wellKnown) {
14240
+ const protocols = WELL_KNOWN_PROTOCOLS[wellKnown.protocol];
14105
14241
  const routes = wellKnown.routes.map((route) => ({
14106
14242
  path: route.path,
14107
14243
  method: route.method,
14108
14244
  summary: `${route.method} ${route.path}`,
14109
14245
  authMode: "paid",
14110
- protocols: ["x402"]
14246
+ protocols,
14247
+ ...route.price ? { price: route.price } : {}
14111
14248
  }));
14112
- return { routes, source: "well-known/x402" };
14249
+ return {
14250
+ ...wellKnown.title ? { title: wellKnown.title } : {},
14251
+ ...wellKnown.description ? { description: wellKnown.description } : {},
14252
+ routes,
14253
+ source: `well-known/${wellKnown.protocol}`
14254
+ };
14113
14255
  }
14114
14256
 
14115
14257
  // src/core/layers/l4.ts
@@ -14121,7 +14263,7 @@ function checkL4ForOpenAPI(openApi) {
14121
14263
  }
14122
14264
  function checkL4ForWellknown(wellKnown) {
14123
14265
  if (wellKnown.instructions) {
14124
- return { guidance: wellKnown.instructions, source: "well-known/x402" };
14266
+ return { guidance: wellKnown.instructions, source: `well-known/${wellKnown.protocol}` };
14125
14267
  }
14126
14268
  return null;
14127
14269
  }
@@ -14146,9 +14288,23 @@ var AUDIT_CODES = {
14146
14288
  L3_INPUT_SCHEMA_MISSING: "L3_INPUT_SCHEMA_MISSING",
14147
14289
  L3_AUTH_MODE_MISSING: "L3_AUTH_MODE_MISSING",
14148
14290
  L3_PROTOCOLS_MISSING_ON_PAID: "L3_PROTOCOLS_MISSING_ON_PAID",
14291
+ L3_PAYMENT_OPTIONS_MISSING_ON_PAID: "L3_PAYMENT_OPTIONS_MISSING_ON_PAID",
14149
14292
  // ─── L4 guidance checks ──────────────────────────────────────────────────────
14150
14293
  L4_GUIDANCE_MISSING: "L4_GUIDANCE_MISSING",
14151
- L4_GUIDANCE_TOO_LONG: "L4_GUIDANCE_TOO_LONG"
14294
+ L4_GUIDANCE_TOO_LONG: "L4_GUIDANCE_TOO_LONG",
14295
+ // ─── MPP WWW-Authenticate header checks ──────────────────────────────────────
14296
+ MPP_HEADER_MISSING: "MPP_HEADER_MISSING",
14297
+ MPP_NO_PAYMENT_CHALLENGES: "MPP_NO_PAYMENT_CHALLENGES",
14298
+ MPP_CHALLENGE_ID_MISSING: "MPP_CHALLENGE_ID_MISSING",
14299
+ MPP_CHALLENGE_METHOD_MISSING: "MPP_CHALLENGE_METHOD_MISSING",
14300
+ MPP_CHALLENGE_INTENT_MISSING: "MPP_CHALLENGE_INTENT_MISSING",
14301
+ MPP_CHALLENGE_REALM_MISSING: "MPP_CHALLENGE_REALM_MISSING",
14302
+ MPP_CHALLENGE_EXPIRES_MISSING: "MPP_CHALLENGE_EXPIRES_MISSING",
14303
+ MPP_CHALLENGE_REQUEST_MISSING: "MPP_CHALLENGE_REQUEST_MISSING",
14304
+ MPP_CHALLENGE_REQUEST_INVALID: "MPP_CHALLENGE_REQUEST_INVALID",
14305
+ MPP_CHALLENGE_ASSET_MISSING: "MPP_CHALLENGE_ASSET_MISSING",
14306
+ MPP_CHALLENGE_AMOUNT_MISSING: "MPP_CHALLENGE_AMOUNT_MISSING",
14307
+ MPP_CHALLENGE_RECIPIENT_MISSING: "MPP_CHALLENGE_RECIPIENT_MISSING"
14152
14308
  };
14153
14309
 
14154
14310
  // src/audit/warnings/sources.ts
@@ -14727,6 +14883,157 @@ function validateWithCoinbaseSchema2(body) {
14727
14883
  });
14728
14884
  }
14729
14885
 
14886
+ // src/audit/warnings/mpp.ts
14887
+ function parseAuthParams(segment) {
14888
+ const params = {};
14889
+ const re = /(\w+)=(?:"([^"]*)"|'([^']*)')/g;
14890
+ let match;
14891
+ while ((match = re.exec(segment)) !== null) {
14892
+ params[match[1]] = match[2] ?? match[3] ?? "";
14893
+ }
14894
+ return params;
14895
+ }
14896
+ function getWarningsForMppHeader(wwwAuthenticate) {
14897
+ if (!wwwAuthenticate?.trim()) {
14898
+ return [
14899
+ {
14900
+ code: AUDIT_CODES.MPP_HEADER_MISSING,
14901
+ severity: "error",
14902
+ message: "WWW-Authenticate header is absent.",
14903
+ hint: "MPP endpoints must respond to unauthenticated requests with a 402 and a WWW-Authenticate: Payment ... header."
14904
+ }
14905
+ ];
14906
+ }
14907
+ const segments = wwwAuthenticate.split(/,\s*(?=Payment\s)/i).filter((s) => /^Payment\s/i.test(s.trim()));
14908
+ if (segments.length === 0) {
14909
+ return [
14910
+ {
14911
+ code: AUDIT_CODES.MPP_NO_PAYMENT_CHALLENGES,
14912
+ severity: "error",
14913
+ message: "WWW-Authenticate header contains no Payment challenges.",
14914
+ hint: `Add at least one Payment challenge: WWW-Authenticate: Payment method="tempo" intent="charge" realm="..." request='...'`
14915
+ }
14916
+ ];
14917
+ }
14918
+ const warnings = [];
14919
+ for (let i = 0; i < segments.length; i++) {
14920
+ const stripped = segments[i].replace(/^Payment\s+/i, "").trim();
14921
+ const params = parseAuthParams(stripped);
14922
+ const idx = `WWW-Authenticate[${i}]`;
14923
+ if (!params["id"]) {
14924
+ warnings.push({
14925
+ code: AUDIT_CODES.MPP_CHALLENGE_ID_MISSING,
14926
+ severity: "error",
14927
+ message: `Payment challenge ${i} is missing the id parameter.`,
14928
+ hint: "Set id to a unique challenge identifier so clients can correlate credentials to challenges.",
14929
+ path: `${idx}.id`
14930
+ });
14931
+ }
14932
+ if (!params["method"]) {
14933
+ warnings.push({
14934
+ code: AUDIT_CODES.MPP_CHALLENGE_METHOD_MISSING,
14935
+ severity: "error",
14936
+ message: `Payment challenge ${i} is missing the method parameter.`,
14937
+ hint: 'Set method="tempo" (or your payment method identifier) on the Payment challenge.',
14938
+ path: `${idx}.method`
14939
+ });
14940
+ }
14941
+ if (!params["intent"]) {
14942
+ warnings.push({
14943
+ code: AUDIT_CODES.MPP_CHALLENGE_INTENT_MISSING,
14944
+ severity: "error",
14945
+ message: `Payment challenge ${i} is missing the intent parameter.`,
14946
+ hint: 'Set intent="charge" on the Payment challenge.',
14947
+ path: `${idx}.intent`
14948
+ });
14949
+ }
14950
+ if (!params["realm"]) {
14951
+ warnings.push({
14952
+ code: AUDIT_CODES.MPP_CHALLENGE_REALM_MISSING,
14953
+ severity: "error",
14954
+ message: `Payment challenge ${i} is missing the realm parameter.`,
14955
+ hint: "Set realm to a stable server identifier so clients can associate payment credentials.",
14956
+ path: `${idx}.realm`
14957
+ });
14958
+ }
14959
+ if (!params["expires"]) {
14960
+ warnings.push({
14961
+ code: AUDIT_CODES.MPP_CHALLENGE_EXPIRES_MISSING,
14962
+ severity: "error",
14963
+ message: `Payment challenge ${i} is missing the expires parameter.`,
14964
+ hint: "Set expires to an RFC 3339 timestamp so clients know when the challenge lapses.",
14965
+ path: `${idx}.expires`
14966
+ });
14967
+ }
14968
+ const requestStr = params["request"];
14969
+ if (!requestStr) {
14970
+ warnings.push({
14971
+ code: AUDIT_CODES.MPP_CHALLENGE_REQUEST_MISSING,
14972
+ severity: "error",
14973
+ message: `Payment challenge ${i} is missing the request field.`,
14974
+ hint: `Include a base64url-encoded JSON request field: request=base64url('{"currency":"...","amount":"...","recipient":"..."}')`,
14975
+ path: `${idx}.request`
14976
+ });
14977
+ continue;
14978
+ }
14979
+ let request;
14980
+ try {
14981
+ const decoded = Buffer.from(requestStr, "base64url").toString("utf-8");
14982
+ const parsed = JSON.parse(decoded);
14983
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
14984
+ throw new Error("not an object");
14985
+ }
14986
+ request = parsed;
14987
+ } catch {
14988
+ warnings.push({
14989
+ code: AUDIT_CODES.MPP_CHALLENGE_REQUEST_INVALID,
14990
+ severity: "error",
14991
+ message: `Payment challenge ${i} request field is not valid base64url-encoded JSON.`,
14992
+ hint: "The request value must be a base64url-encoded JCS JSON object.",
14993
+ path: `${idx}.request`
14994
+ });
14995
+ continue;
14996
+ }
14997
+ if (!request["currency"]) {
14998
+ warnings.push({
14999
+ code: AUDIT_CODES.MPP_CHALLENGE_ASSET_MISSING,
15000
+ severity: "error",
15001
+ message: `Payment challenge ${i} is missing currency in the request object.`,
15002
+ hint: "Set currency to a TIP-20 token address (e.g. a USDC contract).",
15003
+ path: `${idx}.request.currency`
15004
+ });
15005
+ }
15006
+ const amount = request["amount"];
15007
+ if (amount === void 0 || amount === null) {
15008
+ warnings.push({
15009
+ code: AUDIT_CODES.MPP_CHALLENGE_AMOUNT_MISSING,
15010
+ severity: "error",
15011
+ message: `Payment challenge ${i} is missing amount in the request object.`,
15012
+ hint: 'Set amount to a raw token-unit string (e.g. "1000000" for 1 USDC with 6 decimals).',
15013
+ path: `${idx}.request.amount`
15014
+ });
15015
+ } else if (typeof amount !== "string" && typeof amount !== "number") {
15016
+ warnings.push({
15017
+ code: AUDIT_CODES.MPP_CHALLENGE_AMOUNT_MISSING,
15018
+ severity: "error",
15019
+ message: `Payment challenge ${i} has an invalid amount type (got ${typeof amount}, expected string or number).`,
15020
+ hint: "Set amount to a raw token-unit string.",
15021
+ path: `${idx}.request.amount`
15022
+ });
15023
+ }
15024
+ if (!request["recipient"]) {
15025
+ warnings.push({
15026
+ code: AUDIT_CODES.MPP_CHALLENGE_RECIPIENT_MISSING,
15027
+ severity: "error",
15028
+ message: `Payment challenge ${i} is missing recipient in the request object.`,
15029
+ hint: "Set recipient to the wallet address that should receive payment.",
15030
+ path: `${idx}.request.recipient`
15031
+ });
15032
+ }
15033
+ }
15034
+ return warnings;
15035
+ }
15036
+
14730
15037
  // src/audit/warnings/l3.ts
14731
15038
  function getWarningsFor402Body(body) {
14732
15039
  if (!isRecord(body)) {
@@ -14856,17 +15163,28 @@ function getWarningsForL3(l3) {
14856
15163
  hint: "Add a requestBody or parameters schema so agents can construct valid payloads."
14857
15164
  });
14858
15165
  }
14859
- if (l3.authMode === "paid" && !l3.protocols?.length) {
15166
+ if (l3.authMode === "paid" && l3.source === "openapi" && !l3.protocols?.length) {
14860
15167
  warnings.push({
14861
15168
  code: AUDIT_CODES.L3_PROTOCOLS_MISSING_ON_PAID,
14862
15169
  severity: "info",
14863
15170
  message: "Paid endpoint does not declare supported payment protocols.",
14864
- hint: "Add x-payment-info.protocols (e.g. ['x402']) to the operation."
15171
+ hint: "Add x-payment-info.protocols (e.g. ['x402', 'mpp']) to the operation."
15172
+ });
15173
+ }
15174
+ if (l3.authMode === "paid" && l3.source === "probe" && !l3.paymentOptions?.length) {
15175
+ warnings.push({
15176
+ code: AUDIT_CODES.L3_PAYMENT_OPTIONS_MISSING_ON_PAID,
15177
+ severity: "warn",
15178
+ message: "Paid endpoint did not return payment options in the 402 response.",
15179
+ hint: "Ensure the 402 response returns a valid payment challenge so clients know how to pay."
14865
15180
  });
14866
15181
  }
14867
15182
  if (l3.paymentRequiredBody !== void 0) {
14868
15183
  warnings.push(...getWarningsFor402Body(l3.paymentRequiredBody));
14869
15184
  }
15185
+ if (l3.wwwAuthenticate !== void 0) {
15186
+ warnings.push(...getWarningsForMppHeader(l3.wwwAuthenticate));
15187
+ }
14870
15188
  return warnings;
14871
15189
  }
14872
15190
 
@@ -14897,7 +15215,7 @@ function getWarningsForL4(l4) {
14897
15215
  }
14898
15216
 
14899
15217
  // src/core/source/probe/index.ts
14900
- var import_neverthrow4 = require("neverthrow");
15218
+ var import_neverthrow6 = require("neverthrow");
14901
15219
 
14902
15220
  // src/core/protocols/x402/index.ts
14903
15221
  function parseVersion(payload) {
@@ -14993,8 +15311,8 @@ function probeMethod(url2, method, path, headers, signal, inputBody) {
14993
15311
  ...hasBody ? { body: JSON.stringify(inputBody) } : {},
14994
15312
  signal
14995
15313
  }).andThen((response) => {
14996
- if (!isUsableStatus(response.status)) return import_neverthrow4.ResultAsync.fromSafePromise(Promise.resolve(null));
14997
- return import_neverthrow4.ResultAsync.fromSafePromise(
15314
+ if (!isUsableStatus(response.status)) return import_neverthrow6.ResultAsync.fromSafePromise(Promise.resolve(null));
15315
+ return import_neverthrow6.ResultAsync.fromSafePromise(
14998
15316
  (async () => {
14999
15317
  let authHint = response.status === 402 ? "paid" : "unprotected";
15000
15318
  let paymentRequiredBody;
@@ -15025,7 +15343,7 @@ function probeMethod(url2, method, path, headers, signal, inputBody) {
15025
15343
  }
15026
15344
  function getProbe(url2, headers, signal, inputBody) {
15027
15345
  const path = normalizePath(new URL(url2).pathname || "/");
15028
- return import_neverthrow4.ResultAsync.fromSafePromise(
15346
+ return import_neverthrow6.ResultAsync.fromSafePromise(
15029
15347
  Promise.all(
15030
15348
  [...HTTP_METHODS].map(
15031
15349
  (method) => probeMethod(url2, method, path, headers, signal, inputBody).match(
@@ -15038,8 +15356,22 @@ function getProbe(url2, headers, signal, inputBody) {
15038
15356
  }
15039
15357
 
15040
15358
  // src/core/protocols/mpp/index.ts
15359
+ var import_neverthrow7 = require("neverthrow");
15360
+ function parseBase64Json(encoded) {
15361
+ return import_neverthrow7.Result.fromThrowable(
15362
+ () => {
15363
+ const decoded = typeof Buffer !== "undefined" ? Buffer.from(encoded, "base64").toString("utf8") : atob(encoded);
15364
+ const parsed = JSON.parse(decoded);
15365
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
15366
+ throw new Error("not an object");
15367
+ }
15368
+ return parsed;
15369
+ },
15370
+ (e) => e
15371
+ )();
15372
+ }
15041
15373
  var TEMPO_DEFAULT_CHAIN_ID = 4217;
15042
- function parseAuthParams(segment) {
15374
+ function parseAuthParams2(segment) {
15043
15375
  const params = {};
15044
15376
  const re = /(\w+)=(?:"([^"]*)"|'([^']*)')/g;
15045
15377
  let match;
@@ -15053,21 +15385,16 @@ function extractPaymentOptions4(wwwAuthenticate) {
15053
15385
  const options = [];
15054
15386
  for (const segment of wwwAuthenticate.split(/,\s*(?=Payment\s)/i)) {
15055
15387
  const stripped = segment.replace(/^Payment\s+/i, "").trim();
15056
- const params = parseAuthParams(stripped);
15388
+ const params = parseAuthParams2(stripped);
15057
15389
  const paymentMethod = params["method"];
15058
15390
  const intent = params["intent"];
15059
15391
  const realm = params["realm"];
15060
15392
  const description = params["description"];
15061
15393
  const requestStr = params["request"];
15062
15394
  if (!paymentMethod || !intent || !realm || !requestStr) continue;
15063
- let request;
15064
- try {
15065
- const parsed = JSON.parse(requestStr);
15066
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) continue;
15067
- request = parsed;
15068
- } catch {
15069
- continue;
15070
- }
15395
+ const requestResult = parseBase64Json(requestStr);
15396
+ if (requestResult.isErr()) continue;
15397
+ const request = requestResult.value;
15071
15398
  const asset = typeof request["currency"] === "string" ? request["currency"] : void 0;
15072
15399
  const amountRaw = request["amount"];
15073
15400
  const amount = typeof amountRaw === "string" ? amountRaw : typeof amountRaw === "number" ? String(amountRaw) : void 0;
@@ -15249,7 +15576,8 @@ function getL3ForProbe(probe, path, method) {
15249
15576
  ...inputSchema ? { inputSchema } : {},
15250
15577
  ...outputSchema ? { outputSchema } : {},
15251
15578
  ...paymentOptions.length ? { paymentOptions } : {},
15252
- ...probeResult.paymentRequiredBody !== void 0 ? { paymentRequiredBody: probeResult.paymentRequiredBody } : {}
15579
+ ...probeResult.paymentRequiredBody !== void 0 ? { paymentRequiredBody: probeResult.paymentRequiredBody } : {},
15580
+ ...probeResult.wwwAuthenticate ? { wwwAuthenticate: probeResult.wwwAuthenticate } : {}
15253
15581
  };
15254
15582
  }
15255
15583
  async function attachProbePayload(url2, advisories) {
@@ -15440,12 +15768,14 @@ ${l4.guidance}`);
15440
15768
  warnings.push(...l3WarningArrays.flat());
15441
15769
  if (flags.json) {
15442
15770
  const meta3 = { origin, specUrl: wellKnown.fetchedUrl };
15771
+ if (l2.title) meta3.title = l2.title;
15772
+ if (l2.description) meta3.description = l2.description;
15443
15773
  if (l4 && flags.verbose) meta3.guidance = l4.guidance;
15444
15774
  console.log(
15445
15775
  JSON.stringify(
15446
15776
  {
15447
15777
  ok: true,
15448
- selectedStage: "well-known/x402",
15778
+ selectedStage: l2.source,
15449
15779
  resources: l2.routes.map(routeToResource),
15450
15780
  warnings,
15451
15781
  trace: [],
@@ -15457,12 +15787,15 @@ ${l4.guidance}`);
15457
15787
  );
15458
15788
  return 0;
15459
15789
  }
15460
- console.log(`Source: well-known/x402`);
15790
+ console.log(`Source: ${l2.source}`);
15461
15791
  console.log(`Spec: ${wellKnown.fetchedUrl}`);
15792
+ if (l2.title) console.log(`API: ${l2.title}`);
15462
15793
  console.log(`Routes: ${l2.routes.length}
15463
15794
  `);
15464
15795
  for (const route of l2.routes) {
15465
- console.log(` ${route.method.padEnd(7)} ${route.path} paid [x402]`);
15796
+ const price = route.price ? ` ${route.price}` : "";
15797
+ const protocols = route.protocols?.length ? ` [${route.protocols.join(", ")}]` : "";
15798
+ console.log(` ${route.method.padEnd(7)} ${route.path} paid${price}${protocols}`);
15466
15799
  }
15467
15800
  } else {
15468
15801
  if (flags.json) {