@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.js CHANGED
@@ -13842,7 +13842,8 @@ var WellKnownParsedSchema = external_exports.object({
13842
13842
  routes: external_exports.array(
13843
13843
  external_exports.object({
13844
13844
  path: external_exports.string(),
13845
- method: external_exports.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "TRACE"])
13845
+ method: external_exports.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "TRACE"]),
13846
+ price: external_exports.string().optional()
13846
13847
  })
13847
13848
  ),
13848
13849
  instructions: external_exports.string().optional()
@@ -13935,9 +13936,9 @@ function toAbsoluteUrl(origin, value) {
13935
13936
 
13936
13937
  // src/core/source/fetch.ts
13937
13938
  import { ResultAsync } from "neverthrow";
13938
- function toFetchError(err) {
13939
- const cause = err instanceof DOMException && (err.name === "TimeoutError" || err.name === "AbortError") ? "timeout" : "network";
13940
- return { cause, message: String(err) };
13939
+ function toFetchError(err2) {
13940
+ const cause = err2 instanceof DOMException && (err2.name === "TimeoutError" || err2.name === "AbortError") ? "timeout" : "network";
13941
+ return { cause, message: String(err2) };
13941
13942
  }
13942
13943
  function fetchSafe(url2, init) {
13943
13944
  return ResultAsync.fromPromise(fetch(url2, init), toFetchError);
@@ -14003,6 +14004,9 @@ function getOpenAPI(origin, headers, signal, specificationOverrideUrl) {
14003
14004
  }
14004
14005
 
14005
14006
  // src/core/source/wellknown/index.ts
14007
+ import { ok, err, ResultAsync as ResultAsync5 } from "neverthrow";
14008
+
14009
+ // src/core/source/wellknown/x402.ts
14006
14010
  import { okAsync as okAsync2, ResultAsync as ResultAsync3 } from "neverthrow";
14007
14011
  function toWellKnownParsed(origin, doc) {
14008
14012
  const routes = doc.resources.flatMap((entry) => {
@@ -14029,12 +14033,17 @@ async function parseBody2(response, origin, url2) {
14029
14033
  if (!doc.success) return null;
14030
14034
  const parsed = WellKnownParsedSchema.safeParse(toWellKnownParsed(origin, doc.data));
14031
14035
  if (!parsed.success) return null;
14032
- return { raw: payload, ...parsed.data, fetchedUrl: url2 };
14036
+ return {
14037
+ raw: payload,
14038
+ ...parsed.data,
14039
+ protocol: "x402",
14040
+ fetchedUrl: url2
14041
+ };
14033
14042
  } catch {
14034
14043
  return null;
14035
14044
  }
14036
14045
  }
14037
- function getWellKnown(origin, headers, signal) {
14046
+ function getX402WellKnown(origin, headers, signal) {
14038
14047
  const url2 = `${origin}/.well-known/x402`;
14039
14048
  return fetchSafe(url2, {
14040
14049
  method: "GET",
@@ -14046,6 +14055,127 @@ function getWellKnown(origin, headers, signal) {
14046
14055
  });
14047
14056
  }
14048
14057
 
14058
+ // src/core/source/wellknown/mpp.ts
14059
+ import { okAsync as okAsync3, ResultAsync as ResultAsync4 } from "neverthrow";
14060
+ var MppEndpointSchema = external_exports.object({
14061
+ method: external_exports.string(),
14062
+ path: external_exports.string(),
14063
+ description: external_exports.string().optional(),
14064
+ payment: external_exports.object({
14065
+ intent: external_exports.string().optional(),
14066
+ method: external_exports.string().optional(),
14067
+ amount: external_exports.string().optional(),
14068
+ currency: external_exports.string().optional()
14069
+ }).optional()
14070
+ });
14071
+ var MppWellKnownDocSchema = external_exports.object({
14072
+ version: external_exports.number().optional(),
14073
+ name: external_exports.string().optional(),
14074
+ description: external_exports.string().optional(),
14075
+ categories: external_exports.array(external_exports.string()).optional(),
14076
+ methods: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
14077
+ endpoints: external_exports.array(MppEndpointSchema).default([]),
14078
+ docs: external_exports.object({
14079
+ homepage: external_exports.string().optional(),
14080
+ apiReference: external_exports.string().optional()
14081
+ }).optional()
14082
+ });
14083
+ var MPP_DECIMALS = 6;
14084
+ function formatMppAmount(raw) {
14085
+ if (!raw) return void 0;
14086
+ const n = Number(raw);
14087
+ if (!Number.isFinite(n)) return void 0;
14088
+ return `$${(n / 10 ** MPP_DECIMALS).toFixed(MPP_DECIMALS)}`;
14089
+ }
14090
+ function toWellKnownParsed2(doc) {
14091
+ const routes = doc.endpoints.flatMap((entry) => {
14092
+ const method = parseMethod(entry.method);
14093
+ if (!method) return [];
14094
+ const path = normalizePath(entry.path);
14095
+ if (!path) return [];
14096
+ const price = formatMppAmount(entry.payment?.amount);
14097
+ return [{ path, method, ...price ? { price } : {} }];
14098
+ });
14099
+ return {
14100
+ routes,
14101
+ ...doc.description ? { instructions: doc.description } : {}
14102
+ };
14103
+ }
14104
+ async function parseBody3(response, url2) {
14105
+ try {
14106
+ const payload = await response.json();
14107
+ const doc = MppWellKnownDocSchema.safeParse(payload);
14108
+ if (!doc.success) return null;
14109
+ const parsed = WellKnownParsedSchema.safeParse(toWellKnownParsed2(doc.data));
14110
+ if (!parsed.success) return null;
14111
+ return {
14112
+ raw: payload,
14113
+ ...parsed.data,
14114
+ ...doc.data.name ? { title: doc.data.name } : {},
14115
+ ...doc.data.description ? { description: doc.data.description } : {},
14116
+ protocol: "mpp",
14117
+ fetchedUrl: url2
14118
+ };
14119
+ } catch {
14120
+ return null;
14121
+ }
14122
+ }
14123
+ function getMppWellKnown(origin, headers, signal) {
14124
+ const url2 = `${origin}/.well-known/mpp`;
14125
+ return fetchSafe(url2, {
14126
+ method: "GET",
14127
+ headers: { Accept: "application/json", ...headers },
14128
+ signal
14129
+ }).andThen((response) => {
14130
+ if (!response.ok) return okAsync3(null);
14131
+ return ResultAsync4.fromSafePromise(parseBody3(response, url2));
14132
+ });
14133
+ }
14134
+
14135
+ // src/core/source/wellknown/index.ts
14136
+ function mergeError(a, b) {
14137
+ return {
14138
+ cause: a.cause === "network" || b.cause === "network" ? "network" : "timeout",
14139
+ message: `x402: ${a.message} | mpp: ${b.message}`
14140
+ };
14141
+ }
14142
+ function merge2(x402, mpp) {
14143
+ const seen = /* @__PURE__ */ new Set();
14144
+ const routes = [...x402.routes, ...mpp.routes].filter((r) => {
14145
+ const key = `${r.method} ${r.path}`;
14146
+ if (seen.has(key)) return false;
14147
+ seen.add(key);
14148
+ return true;
14149
+ });
14150
+ return {
14151
+ raw: { ...mpp.raw, ...x402.raw },
14152
+ routes,
14153
+ protocol: "x402+mpp",
14154
+ // Prefer x402 instructions; fall back to mpp
14155
+ ...x402.instructions || mpp.instructions ? { instructions: x402.instructions ?? mpp.instructions } : {},
14156
+ fetchedUrl: x402.fetchedUrl
14157
+ };
14158
+ }
14159
+ function getWellKnown(origin, headers, signal) {
14160
+ return new ResultAsync5(
14161
+ Promise.all([
14162
+ getX402WellKnown(origin, headers, signal),
14163
+ getMppWellKnown(origin, headers, signal)
14164
+ ]).then(([x402Result, mppResult]) => {
14165
+ const x402 = x402Result.isOk() ? x402Result.value : null;
14166
+ const mpp = mppResult.isOk() ? mppResult.value : null;
14167
+ if (x402 && mpp) return ok(merge2(x402, mpp));
14168
+ if (x402) return ok(x402);
14169
+ if (mpp) return ok(mpp);
14170
+ if (x402Result.isErr() && mppResult.isErr())
14171
+ return err(mergeError(x402Result.error, mppResult.error));
14172
+ if (x402Result.isErr()) return err(x402Result.error);
14173
+ if (mppResult.isErr()) return err(mppResult.error);
14174
+ return ok(null);
14175
+ })
14176
+ );
14177
+ }
14178
+
14049
14179
  // src/core/layers/l2.ts
14050
14180
  function formatPrice(pricing) {
14051
14181
  if (pricing.pricingMode === "fixed") return `$${pricing.price}`;
@@ -14071,15 +14201,27 @@ function checkL2ForOpenAPI(openApi) {
14071
14201
  source: "openapi"
14072
14202
  };
14073
14203
  }
14204
+ var WELL_KNOWN_PROTOCOLS = {
14205
+ x402: ["x402"],
14206
+ mpp: ["mpp"],
14207
+ "x402+mpp": ["x402", "mpp"]
14208
+ };
14074
14209
  function checkL2ForWellknown(wellKnown) {
14210
+ const protocols = WELL_KNOWN_PROTOCOLS[wellKnown.protocol];
14075
14211
  const routes = wellKnown.routes.map((route) => ({
14076
14212
  path: route.path,
14077
14213
  method: route.method,
14078
14214
  summary: `${route.method} ${route.path}`,
14079
14215
  authMode: "paid",
14080
- protocols: ["x402"]
14216
+ protocols,
14217
+ ...route.price ? { price: route.price } : {}
14081
14218
  }));
14082
- return { routes, source: "well-known/x402" };
14219
+ return {
14220
+ ...wellKnown.title ? { title: wellKnown.title } : {},
14221
+ ...wellKnown.description ? { description: wellKnown.description } : {},
14222
+ routes,
14223
+ source: `well-known/${wellKnown.protocol}`
14224
+ };
14083
14225
  }
14084
14226
 
14085
14227
  // src/core/layers/l4.ts
@@ -14091,7 +14233,7 @@ function checkL4ForOpenAPI(openApi) {
14091
14233
  }
14092
14234
  function checkL4ForWellknown(wellKnown) {
14093
14235
  if (wellKnown.instructions) {
14094
- return { guidance: wellKnown.instructions, source: "well-known/x402" };
14236
+ return { guidance: wellKnown.instructions, source: `well-known/${wellKnown.protocol}` };
14095
14237
  }
14096
14238
  return null;
14097
14239
  }
@@ -14116,9 +14258,23 @@ var AUDIT_CODES = {
14116
14258
  L3_INPUT_SCHEMA_MISSING: "L3_INPUT_SCHEMA_MISSING",
14117
14259
  L3_AUTH_MODE_MISSING: "L3_AUTH_MODE_MISSING",
14118
14260
  L3_PROTOCOLS_MISSING_ON_PAID: "L3_PROTOCOLS_MISSING_ON_PAID",
14261
+ L3_PAYMENT_OPTIONS_MISSING_ON_PAID: "L3_PAYMENT_OPTIONS_MISSING_ON_PAID",
14119
14262
  // ─── L4 guidance checks ──────────────────────────────────────────────────────
14120
14263
  L4_GUIDANCE_MISSING: "L4_GUIDANCE_MISSING",
14121
- L4_GUIDANCE_TOO_LONG: "L4_GUIDANCE_TOO_LONG"
14264
+ L4_GUIDANCE_TOO_LONG: "L4_GUIDANCE_TOO_LONG",
14265
+ // ─── MPP WWW-Authenticate header checks ──────────────────────────────────────
14266
+ MPP_HEADER_MISSING: "MPP_HEADER_MISSING",
14267
+ MPP_NO_PAYMENT_CHALLENGES: "MPP_NO_PAYMENT_CHALLENGES",
14268
+ MPP_CHALLENGE_ID_MISSING: "MPP_CHALLENGE_ID_MISSING",
14269
+ MPP_CHALLENGE_METHOD_MISSING: "MPP_CHALLENGE_METHOD_MISSING",
14270
+ MPP_CHALLENGE_INTENT_MISSING: "MPP_CHALLENGE_INTENT_MISSING",
14271
+ MPP_CHALLENGE_REALM_MISSING: "MPP_CHALLENGE_REALM_MISSING",
14272
+ MPP_CHALLENGE_EXPIRES_MISSING: "MPP_CHALLENGE_EXPIRES_MISSING",
14273
+ MPP_CHALLENGE_REQUEST_MISSING: "MPP_CHALLENGE_REQUEST_MISSING",
14274
+ MPP_CHALLENGE_REQUEST_INVALID: "MPP_CHALLENGE_REQUEST_INVALID",
14275
+ MPP_CHALLENGE_ASSET_MISSING: "MPP_CHALLENGE_ASSET_MISSING",
14276
+ MPP_CHALLENGE_AMOUNT_MISSING: "MPP_CHALLENGE_AMOUNT_MISSING",
14277
+ MPP_CHALLENGE_RECIPIENT_MISSING: "MPP_CHALLENGE_RECIPIENT_MISSING"
14122
14278
  };
14123
14279
 
14124
14280
  // src/audit/warnings/sources.ts
@@ -14697,6 +14853,157 @@ function validateWithCoinbaseSchema2(body) {
14697
14853
  });
14698
14854
  }
14699
14855
 
14856
+ // src/audit/warnings/mpp.ts
14857
+ function parseAuthParams(segment) {
14858
+ const params = {};
14859
+ const re = /(\w+)=(?:"([^"]*)"|'([^']*)')/g;
14860
+ let match;
14861
+ while ((match = re.exec(segment)) !== null) {
14862
+ params[match[1]] = match[2] ?? match[3] ?? "";
14863
+ }
14864
+ return params;
14865
+ }
14866
+ function getWarningsForMppHeader(wwwAuthenticate) {
14867
+ if (!wwwAuthenticate?.trim()) {
14868
+ return [
14869
+ {
14870
+ code: AUDIT_CODES.MPP_HEADER_MISSING,
14871
+ severity: "error",
14872
+ message: "WWW-Authenticate header is absent.",
14873
+ hint: "MPP endpoints must respond to unauthenticated requests with a 402 and a WWW-Authenticate: Payment ... header."
14874
+ }
14875
+ ];
14876
+ }
14877
+ const segments = wwwAuthenticate.split(/,\s*(?=Payment\s)/i).filter((s) => /^Payment\s/i.test(s.trim()));
14878
+ if (segments.length === 0) {
14879
+ return [
14880
+ {
14881
+ code: AUDIT_CODES.MPP_NO_PAYMENT_CHALLENGES,
14882
+ severity: "error",
14883
+ message: "WWW-Authenticate header contains no Payment challenges.",
14884
+ hint: `Add at least one Payment challenge: WWW-Authenticate: Payment method="tempo" intent="charge" realm="..." request='...'`
14885
+ }
14886
+ ];
14887
+ }
14888
+ const warnings = [];
14889
+ for (let i = 0; i < segments.length; i++) {
14890
+ const stripped = segments[i].replace(/^Payment\s+/i, "").trim();
14891
+ const params = parseAuthParams(stripped);
14892
+ const idx = `WWW-Authenticate[${i}]`;
14893
+ if (!params["id"]) {
14894
+ warnings.push({
14895
+ code: AUDIT_CODES.MPP_CHALLENGE_ID_MISSING,
14896
+ severity: "error",
14897
+ message: `Payment challenge ${i} is missing the id parameter.`,
14898
+ hint: "Set id to a unique challenge identifier so clients can correlate credentials to challenges.",
14899
+ path: `${idx}.id`
14900
+ });
14901
+ }
14902
+ if (!params["method"]) {
14903
+ warnings.push({
14904
+ code: AUDIT_CODES.MPP_CHALLENGE_METHOD_MISSING,
14905
+ severity: "error",
14906
+ message: `Payment challenge ${i} is missing the method parameter.`,
14907
+ hint: 'Set method="tempo" (or your payment method identifier) on the Payment challenge.',
14908
+ path: `${idx}.method`
14909
+ });
14910
+ }
14911
+ if (!params["intent"]) {
14912
+ warnings.push({
14913
+ code: AUDIT_CODES.MPP_CHALLENGE_INTENT_MISSING,
14914
+ severity: "error",
14915
+ message: `Payment challenge ${i} is missing the intent parameter.`,
14916
+ hint: 'Set intent="charge" on the Payment challenge.',
14917
+ path: `${idx}.intent`
14918
+ });
14919
+ }
14920
+ if (!params["realm"]) {
14921
+ warnings.push({
14922
+ code: AUDIT_CODES.MPP_CHALLENGE_REALM_MISSING,
14923
+ severity: "error",
14924
+ message: `Payment challenge ${i} is missing the realm parameter.`,
14925
+ hint: "Set realm to a stable server identifier so clients can associate payment credentials.",
14926
+ path: `${idx}.realm`
14927
+ });
14928
+ }
14929
+ if (!params["expires"]) {
14930
+ warnings.push({
14931
+ code: AUDIT_CODES.MPP_CHALLENGE_EXPIRES_MISSING,
14932
+ severity: "error",
14933
+ message: `Payment challenge ${i} is missing the expires parameter.`,
14934
+ hint: "Set expires to an RFC 3339 timestamp so clients know when the challenge lapses.",
14935
+ path: `${idx}.expires`
14936
+ });
14937
+ }
14938
+ const requestStr = params["request"];
14939
+ if (!requestStr) {
14940
+ warnings.push({
14941
+ code: AUDIT_CODES.MPP_CHALLENGE_REQUEST_MISSING,
14942
+ severity: "error",
14943
+ message: `Payment challenge ${i} is missing the request field.`,
14944
+ hint: `Include a base64url-encoded JSON request field: request=base64url('{"currency":"...","amount":"...","recipient":"..."}')`,
14945
+ path: `${idx}.request`
14946
+ });
14947
+ continue;
14948
+ }
14949
+ let request;
14950
+ try {
14951
+ const decoded = Buffer.from(requestStr, "base64url").toString("utf-8");
14952
+ const parsed = JSON.parse(decoded);
14953
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
14954
+ throw new Error("not an object");
14955
+ }
14956
+ request = parsed;
14957
+ } catch {
14958
+ warnings.push({
14959
+ code: AUDIT_CODES.MPP_CHALLENGE_REQUEST_INVALID,
14960
+ severity: "error",
14961
+ message: `Payment challenge ${i} request field is not valid base64url-encoded JSON.`,
14962
+ hint: "The request value must be a base64url-encoded JCS JSON object.",
14963
+ path: `${idx}.request`
14964
+ });
14965
+ continue;
14966
+ }
14967
+ if (!request["currency"]) {
14968
+ warnings.push({
14969
+ code: AUDIT_CODES.MPP_CHALLENGE_ASSET_MISSING,
14970
+ severity: "error",
14971
+ message: `Payment challenge ${i} is missing currency in the request object.`,
14972
+ hint: "Set currency to a TIP-20 token address (e.g. a USDC contract).",
14973
+ path: `${idx}.request.currency`
14974
+ });
14975
+ }
14976
+ const amount = request["amount"];
14977
+ if (amount === void 0 || amount === null) {
14978
+ warnings.push({
14979
+ code: AUDIT_CODES.MPP_CHALLENGE_AMOUNT_MISSING,
14980
+ severity: "error",
14981
+ message: `Payment challenge ${i} is missing amount in the request object.`,
14982
+ hint: 'Set amount to a raw token-unit string (e.g. "1000000" for 1 USDC with 6 decimals).',
14983
+ path: `${idx}.request.amount`
14984
+ });
14985
+ } else if (typeof amount !== "string" && typeof amount !== "number") {
14986
+ warnings.push({
14987
+ code: AUDIT_CODES.MPP_CHALLENGE_AMOUNT_MISSING,
14988
+ severity: "error",
14989
+ message: `Payment challenge ${i} has an invalid amount type (got ${typeof amount}, expected string or number).`,
14990
+ hint: "Set amount to a raw token-unit string.",
14991
+ path: `${idx}.request.amount`
14992
+ });
14993
+ }
14994
+ if (!request["recipient"]) {
14995
+ warnings.push({
14996
+ code: AUDIT_CODES.MPP_CHALLENGE_RECIPIENT_MISSING,
14997
+ severity: "error",
14998
+ message: `Payment challenge ${i} is missing recipient in the request object.`,
14999
+ hint: "Set recipient to the wallet address that should receive payment.",
15000
+ path: `${idx}.request.recipient`
15001
+ });
15002
+ }
15003
+ }
15004
+ return warnings;
15005
+ }
15006
+
14700
15007
  // src/audit/warnings/l3.ts
14701
15008
  function getWarningsFor402Body(body) {
14702
15009
  if (!isRecord(body)) {
@@ -14826,17 +15133,28 @@ function getWarningsForL3(l3) {
14826
15133
  hint: "Add a requestBody or parameters schema so agents can construct valid payloads."
14827
15134
  });
14828
15135
  }
14829
- if (l3.authMode === "paid" && !l3.protocols?.length) {
15136
+ if (l3.authMode === "paid" && l3.source === "openapi" && !l3.protocols?.length) {
14830
15137
  warnings.push({
14831
15138
  code: AUDIT_CODES.L3_PROTOCOLS_MISSING_ON_PAID,
14832
15139
  severity: "info",
14833
15140
  message: "Paid endpoint does not declare supported payment protocols.",
14834
- hint: "Add x-payment-info.protocols (e.g. ['x402']) to the operation."
15141
+ hint: "Add x-payment-info.protocols (e.g. ['x402', 'mpp']) to the operation."
15142
+ });
15143
+ }
15144
+ if (l3.authMode === "paid" && l3.source === "probe" && !l3.paymentOptions?.length) {
15145
+ warnings.push({
15146
+ code: AUDIT_CODES.L3_PAYMENT_OPTIONS_MISSING_ON_PAID,
15147
+ severity: "warn",
15148
+ message: "Paid endpoint did not return payment options in the 402 response.",
15149
+ hint: "Ensure the 402 response returns a valid payment challenge so clients know how to pay."
14835
15150
  });
14836
15151
  }
14837
15152
  if (l3.paymentRequiredBody !== void 0) {
14838
15153
  warnings.push(...getWarningsFor402Body(l3.paymentRequiredBody));
14839
15154
  }
15155
+ if (l3.wwwAuthenticate !== void 0) {
15156
+ warnings.push(...getWarningsForMppHeader(l3.wwwAuthenticate));
15157
+ }
14840
15158
  return warnings;
14841
15159
  }
14842
15160
 
@@ -14867,7 +15185,7 @@ function getWarningsForL4(l4) {
14867
15185
  }
14868
15186
 
14869
15187
  // src/core/source/probe/index.ts
14870
- import { ResultAsync as ResultAsync4 } from "neverthrow";
15188
+ import { ResultAsync as ResultAsync6 } from "neverthrow";
14871
15189
 
14872
15190
  // src/core/protocols/x402/index.ts
14873
15191
  function parseVersion(payload) {
@@ -14963,8 +15281,8 @@ function probeMethod(url2, method, path, headers, signal, inputBody) {
14963
15281
  ...hasBody ? { body: JSON.stringify(inputBody) } : {},
14964
15282
  signal
14965
15283
  }).andThen((response) => {
14966
- if (!isUsableStatus(response.status)) return ResultAsync4.fromSafePromise(Promise.resolve(null));
14967
- return ResultAsync4.fromSafePromise(
15284
+ if (!isUsableStatus(response.status)) return ResultAsync6.fromSafePromise(Promise.resolve(null));
15285
+ return ResultAsync6.fromSafePromise(
14968
15286
  (async () => {
14969
15287
  let authHint = response.status === 402 ? "paid" : "unprotected";
14970
15288
  let paymentRequiredBody;
@@ -14995,7 +15313,7 @@ function probeMethod(url2, method, path, headers, signal, inputBody) {
14995
15313
  }
14996
15314
  function getProbe(url2, headers, signal, inputBody) {
14997
15315
  const path = normalizePath(new URL(url2).pathname || "/");
14998
- return ResultAsync4.fromSafePromise(
15316
+ return ResultAsync6.fromSafePromise(
14999
15317
  Promise.all(
15000
15318
  [...HTTP_METHODS].map(
15001
15319
  (method) => probeMethod(url2, method, path, headers, signal, inputBody).match(
@@ -15008,8 +15326,22 @@ function getProbe(url2, headers, signal, inputBody) {
15008
15326
  }
15009
15327
 
15010
15328
  // src/core/protocols/mpp/index.ts
15329
+ import { Result } from "neverthrow";
15330
+ function parseBase64Json(encoded) {
15331
+ return Result.fromThrowable(
15332
+ () => {
15333
+ const decoded = typeof Buffer !== "undefined" ? Buffer.from(encoded, "base64").toString("utf8") : atob(encoded);
15334
+ const parsed = JSON.parse(decoded);
15335
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
15336
+ throw new Error("not an object");
15337
+ }
15338
+ return parsed;
15339
+ },
15340
+ (e) => e
15341
+ )();
15342
+ }
15011
15343
  var TEMPO_DEFAULT_CHAIN_ID = 4217;
15012
- function parseAuthParams(segment) {
15344
+ function parseAuthParams2(segment) {
15013
15345
  const params = {};
15014
15346
  const re = /(\w+)=(?:"([^"]*)"|'([^']*)')/g;
15015
15347
  let match;
@@ -15023,21 +15355,16 @@ function extractPaymentOptions4(wwwAuthenticate) {
15023
15355
  const options = [];
15024
15356
  for (const segment of wwwAuthenticate.split(/,\s*(?=Payment\s)/i)) {
15025
15357
  const stripped = segment.replace(/^Payment\s+/i, "").trim();
15026
- const params = parseAuthParams(stripped);
15358
+ const params = parseAuthParams2(stripped);
15027
15359
  const paymentMethod = params["method"];
15028
15360
  const intent = params["intent"];
15029
15361
  const realm = params["realm"];
15030
15362
  const description = params["description"];
15031
15363
  const requestStr = params["request"];
15032
15364
  if (!paymentMethod || !intent || !realm || !requestStr) continue;
15033
- let request;
15034
- try {
15035
- const parsed = JSON.parse(requestStr);
15036
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) continue;
15037
- request = parsed;
15038
- } catch {
15039
- continue;
15040
- }
15365
+ const requestResult = parseBase64Json(requestStr);
15366
+ if (requestResult.isErr()) continue;
15367
+ const request = requestResult.value;
15041
15368
  const asset = typeof request["currency"] === "string" ? request["currency"] : void 0;
15042
15369
  const amountRaw = request["amount"];
15043
15370
  const amount = typeof amountRaw === "string" ? amountRaw : typeof amountRaw === "number" ? String(amountRaw) : void 0;
@@ -15219,7 +15546,8 @@ function getL3ForProbe(probe, path, method) {
15219
15546
  ...inputSchema ? { inputSchema } : {},
15220
15547
  ...outputSchema ? { outputSchema } : {},
15221
15548
  ...paymentOptions.length ? { paymentOptions } : {},
15222
- ...probeResult.paymentRequiredBody !== void 0 ? { paymentRequiredBody: probeResult.paymentRequiredBody } : {}
15549
+ ...probeResult.paymentRequiredBody !== void 0 ? { paymentRequiredBody: probeResult.paymentRequiredBody } : {},
15550
+ ...probeResult.wwwAuthenticate ? { wwwAuthenticate: probeResult.wwwAuthenticate } : {}
15223
15551
  };
15224
15552
  }
15225
15553
  async function attachProbePayload(url2, advisories) {
@@ -15410,12 +15738,14 @@ ${l4.guidance}`);
15410
15738
  warnings.push(...l3WarningArrays.flat());
15411
15739
  if (flags.json) {
15412
15740
  const meta3 = { origin, specUrl: wellKnown.fetchedUrl };
15741
+ if (l2.title) meta3.title = l2.title;
15742
+ if (l2.description) meta3.description = l2.description;
15413
15743
  if (l4 && flags.verbose) meta3.guidance = l4.guidance;
15414
15744
  console.log(
15415
15745
  JSON.stringify(
15416
15746
  {
15417
15747
  ok: true,
15418
- selectedStage: "well-known/x402",
15748
+ selectedStage: l2.source,
15419
15749
  resources: l2.routes.map(routeToResource),
15420
15750
  warnings,
15421
15751
  trace: [],
@@ -15427,12 +15757,15 @@ ${l4.guidance}`);
15427
15757
  );
15428
15758
  return 0;
15429
15759
  }
15430
- console.log(`Source: well-known/x402`);
15760
+ console.log(`Source: ${l2.source}`);
15431
15761
  console.log(`Spec: ${wellKnown.fetchedUrl}`);
15762
+ if (l2.title) console.log(`API: ${l2.title}`);
15432
15763
  console.log(`Routes: ${l2.routes.length}
15433
15764
  `);
15434
15765
  for (const route of l2.routes) {
15435
- console.log(` ${route.method.padEnd(7)} ${route.path} paid [x402]`);
15766
+ const price = route.price ? ` ${route.price}` : "";
15767
+ const protocols = route.protocols?.length ? ` [${route.protocols.join(", ")}]` : "";
15768
+ console.log(` ${route.method.padEnd(7)} ${route.path} paid${price}${protocols}`);
15436
15769
  }
15437
15770
  } else {
15438
15771
  if (flags.json) {