@agentcash/discovery 1.6.2 → 1.6.4

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
@@ -13815,8 +13815,8 @@ var FixedPriceSchema = external_exports.object({
13815
13815
  var DynamicPriceSchema = external_exports.object({
13816
13816
  currency: Iso4217Schema,
13817
13817
  mode: external_exports.literal("dynamic"),
13818
- min: external_exports.string(),
13819
- max: external_exports.string()
13818
+ min: external_exports.string().optional(),
13819
+ max: external_exports.string().optional()
13820
13820
  });
13821
13821
  var PriceSchema = external_exports.union([FixedPriceSchema, DynamicPriceSchema]);
13822
13822
  var X402ProtocolSchema = external_exports.object({
@@ -13915,7 +13915,12 @@ function normalizeLegacy(raw) {
13915
13915
  function formatPrice(price) {
13916
13916
  const sym = price.currency ?? "USD";
13917
13917
  if (price.mode === "fixed") return `${price.amount} ${sym}`;
13918
- return `${price.min}-${price.max} ${sym}`;
13918
+ if (price.min !== void 0 && price.max !== void 0) {
13919
+ return `${price.min}-${price.max} ${sym}`;
13920
+ }
13921
+ if (price.min !== void 0) return `>=${price.min} ${sym}`;
13922
+ if (price.max !== void 0) return `<=${price.max} ${sym}`;
13923
+ return `dynamic ${sym}`;
13919
13924
  }
13920
13925
  function extractProtocolNames(protocols) {
13921
13926
  return protocols.map((p) => {
@@ -13967,10 +13972,13 @@ var OpenApiOperationSchema = external_exports.object({
13967
13972
  description: external_exports.string().optional(),
13968
13973
  tags: external_exports.array(external_exports.string()).optional(),
13969
13974
  security: external_exports.array(external_exports.record(external_exports.string(), external_exports.array(external_exports.string()))).optional(),
13975
+ // `in` / `name` are spec-required, but a single malformed parameter must not
13976
+ // abort the whole spec — keep them optional so discovery is resilient to
13977
+ // non-conformant OpenAPI documents in the wild.
13970
13978
  parameters: external_exports.array(
13971
13979
  external_exports.object({
13972
- in: external_exports.string(),
13973
- name: external_exports.string(),
13980
+ in: external_exports.string().optional(),
13981
+ name: external_exports.string().optional(),
13974
13982
  schema: external_exports.unknown().optional(),
13975
13983
  required: external_exports.boolean().optional()
13976
13984
  })
@@ -13980,7 +13988,8 @@ var OpenApiOperationSchema = external_exports.object({
13980
13988
  content: external_exports.record(external_exports.string(), external_exports.object({ schema: external_exports.unknown().optional() }))
13981
13989
  }).optional(),
13982
13990
  responses: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
13983
- "x-payment-info": OpenApiPaymentInfoSchema.optional()
13991
+ // Permissive: vendor extension shape is validated at runtime, never at parse time.
13992
+ "x-payment-info": external_exports.unknown().optional()
13984
13993
  });
13985
13994
  var OpenApiPathItemSchema = external_exports.object({
13986
13995
  get: OpenApiOperationSchema.optional(),
@@ -14124,20 +14133,27 @@ function fetchSafe(url2, init) {
14124
14133
  }
14125
14134
 
14126
14135
  // src/core/source/openapi/index.ts
14127
- function resolvePricingHint(p) {
14128
- const raw = p;
14129
- const info = resolvePaymentInfo(raw);
14136
+ function toRecord(raw) {
14137
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return void 0;
14138
+ return raw;
14139
+ }
14140
+ function resolvePricingHint(raw) {
14141
+ const record2 = toRecord(raw);
14142
+ if (!record2) return void 0;
14143
+ const info = resolvePaymentInfo(record2);
14130
14144
  if (!info) return void 0;
14131
14145
  return {
14132
14146
  pricingMode: info.price.mode,
14133
14147
  ...info.price.mode === "fixed" ? { price: info.price.amount } : {},
14134
- ...info.price.mode === "dynamic" ? { minPrice: info.price.min, maxPrice: info.price.max } : {},
14148
+ ...info.price.mode === "dynamic" && info.price.min !== void 0 ? { minPrice: info.price.min } : {},
14149
+ ...info.price.mode === "dynamic" && info.price.max !== void 0 ? { maxPrice: info.price.max } : {},
14135
14150
  ...info.price.currency ? { currency: info.price.currency } : {}
14136
14151
  };
14137
14152
  }
14138
- function resolveProtocols(p) {
14139
- const raw = p;
14140
- const info = resolvePaymentInfo(raw);
14153
+ function resolveProtocols(raw) {
14154
+ const record2 = toRecord(raw);
14155
+ if (!record2) return [];
14156
+ const info = resolvePaymentInfo(record2);
14141
14157
  if (!info) return [];
14142
14158
  return extractProtocolNames(info.protocols);
14143
14159
  }
@@ -14150,8 +14166,8 @@ var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
14150
14166
  if (!operation) continue;
14151
14167
  const authMode = inferAuthMode(operation, doc.security, doc.components?.securitySchemes) ?? void 0;
14152
14168
  const p = operation["x-payment-info"];
14153
- const protocols = resolveProtocols(p ?? {});
14154
- const pricing = (authMode === "paid" || authMode === "apiKey+paid") && p ? resolvePricingHint(p) : void 0;
14169
+ const protocols = resolveProtocols(p);
14170
+ const pricing = (authMode === "paid" || authMode === "apiKey+paid") && p !== void 0 ? resolvePricingHint(p) : void 0;
14155
14171
  const summary = operation.summary ?? operation.description;
14156
14172
  routes.push({
14157
14173
  path: normalizePath(serverBasePath + rawPath),
@@ -14392,28 +14408,29 @@ function getWellKnown(origin, headers, signal) {
14392
14408
  // src/core/layers/l2.ts
14393
14409
  function formatPrice2(pricing) {
14394
14410
  const sym = pricing.currency ?? "USD";
14395
- if (pricing.pricingMode === "fixed") return `${pricing.price} ${sym}`;
14411
+ if (pricing.pricingMode === "fixed" && pricing.price) return `${pricing.price} ${sym}`;
14396
14412
  if (pricing.pricingMode === "dynamic") {
14397
14413
  if (pricing.minPrice && pricing.maxPrice)
14398
14414
  return `${pricing.minPrice}-${pricing.maxPrice} ${sym}`;
14399
14415
  if (pricing.maxPrice) return `up to ${pricing.maxPrice} ${sym}`;
14400
- return "dynamic";
14416
+ if (pricing.minPrice) return `from ${pricing.minPrice} ${sym}`;
14401
14417
  }
14402
- return `unknown pricing mode: ${pricing.pricingMode}`;
14418
+ return void 0;
14403
14419
  }
14404
14420
  function checkL2ForOpenAPI(openApi) {
14405
- const routes = openApi.routes.map((route) => ({
14406
- path: route.path,
14407
- method: route.method,
14408
- summary: route.summary ?? `${route.method} ${route.path}`,
14409
- ...route.authMode ? { authMode: route.authMode } : {},
14410
- ...route.pricing ? {
14411
- price: formatPrice2(route.pricing),
14412
- pricingMode: route.pricing.pricingMode,
14413
- ...route.pricing.currency ? { currency: route.pricing.currency } : {}
14414
- } : {},
14415
- ...route.protocols?.length ? { protocols: route.protocols } : {}
14416
- }));
14421
+ const routes = openApi.routes.map((route) => {
14422
+ const priceHint = route.pricing ? formatPrice2(route.pricing) : void 0;
14423
+ return {
14424
+ path: route.path,
14425
+ method: route.method,
14426
+ summary: route.summary ?? `${route.method} ${route.path}`,
14427
+ ...route.authMode ? { authMode: route.authMode } : {},
14428
+ ...priceHint ? { price: priceHint } : {},
14429
+ ...route.pricing?.pricingMode ? { pricingMode: route.pricing.pricingMode } : {},
14430
+ ...route.pricing?.currency ? { currency: route.pricing.currency } : {},
14431
+ ...route.protocols?.length ? { protocols: route.protocols } : {}
14432
+ };
14433
+ });
14417
14434
  return {
14418
14435
  ...openApi.info.title ? { title: openApi.info.title } : {},
14419
14436
  ...openApi.info.description ? { description: openApi.info.description } : {},
@@ -14474,6 +14491,7 @@ var AUDIT_CODES = {
14474
14491
  L2_NO_PAID_ROUTES: "L2_NO_PAID_ROUTES",
14475
14492
  L2_PRICE_MISSING_ON_PAID: "L2_PRICE_MISSING_ON_PAID",
14476
14493
  L2_PRICING_MODE_UNKNOWN: "L2_PRICING_MODE_UNKNOWN",
14494
+ L2_DYNAMIC_PRICE_INCOMPLETE: "L2_DYNAMIC_PRICE_INCOMPLETE",
14477
14495
  L2_CURRENCY_INVALID: "L2_CURRENCY_INVALID",
14478
14496
  L2_PAYMENT_INFO_LEGACY: "L2_PAYMENT_INFO_LEGACY",
14479
14497
  L2_PROTOCOLS_MISSING_ON_PAID: "L2_PROTOCOLS_MISSING_ON_PAID",
@@ -14709,7 +14727,15 @@ function getWarningsForL2(l2) {
14709
14727
  });
14710
14728
  }
14711
14729
  if (route.authMode === "paid") {
14712
- if (!route.price) {
14730
+ if (route.pricingMode === "dynamic" && !route.price) {
14731
+ warnings.push({
14732
+ code: AUDIT_CODES.L2_DYNAMIC_PRICE_INCOMPLETE,
14733
+ severity: "warn",
14734
+ message: `Paid route ${loc} declares dynamic pricing but no min/max bounds.`,
14735
+ hint: "Add x-payment-info.price.min and .price.max so agents can budget before calling. Without bounds, agents have no safe upper limit to pre-authorize.",
14736
+ path: route.path
14737
+ });
14738
+ } else if (!route.price) {
14713
14739
  warnings.push({
14714
14740
  code: AUDIT_CODES.L2_PRICE_MISSING_ON_PAID,
14715
14741
  severity: "warn",
@@ -15600,7 +15626,7 @@ function getWarningsForFavicon(origin) {
15600
15626
  }
15601
15627
 
15602
15628
  // src/core/source/probe/index.ts
15603
- var import_neverthrow7 = require("neverthrow");
15629
+ var import_neverthrow8 = require("neverthrow");
15604
15630
 
15605
15631
  // src/core/protocols/x402/index.ts
15606
15632
  function parseVersion(payload) {
@@ -15650,11 +15676,36 @@ async function parsePaymentRequiredBody(response) {
15650
15676
  return payload;
15651
15677
  }
15652
15678
 
15679
+ // src/core/lib/base64.ts
15680
+ var import_neverthrow7 = require("neverthrow");
15681
+ function safeBase64DecodeUtf8(encoded) {
15682
+ return import_neverthrow7.Result.fromThrowable(
15683
+ () => {
15684
+ if (typeof Buffer !== "undefined") {
15685
+ return Buffer.from(encoded, "base64").toString("utf8");
15686
+ }
15687
+ const binaryString = atob(encoded);
15688
+ const bytes = new Uint8Array(binaryString.length);
15689
+ for (let i = 0; i < binaryString.length; i++) {
15690
+ bytes[i] = binaryString.charCodeAt(i);
15691
+ }
15692
+ return new TextDecoder("utf-8").decode(bytes);
15693
+ },
15694
+ (e) => e instanceof Error ? e : new Error(String(e))
15695
+ )();
15696
+ }
15697
+
15653
15698
  // src/core/protocols/x402/v2/parse-payment-required.ts
15654
15699
  function parsePaymentRequiredBody2(headerValue) {
15655
- const payload = JSON.parse(atob(headerValue));
15656
- if (!isRecord(payload) || payload.x402Version !== 2) return null;
15657
- return payload;
15700
+ const decoded = safeBase64DecodeUtf8(headerValue);
15701
+ if (decoded.isErr()) return null;
15702
+ try {
15703
+ const payload = JSON.parse(decoded.value);
15704
+ if (!isRecord(payload) || payload.x402Version !== 2) return null;
15705
+ return payload;
15706
+ } catch {
15707
+ return null;
15708
+ }
15658
15709
  }
15659
15710
 
15660
15711
  // src/core/source/probe/index.ts
@@ -15696,8 +15747,8 @@ function probeMethod(url2, method, path, headers, signal, inputBody) {
15696
15747
  ...hasBody ? { body: JSON.stringify(inputBody) } : {},
15697
15748
  signal
15698
15749
  }).andThen((response) => {
15699
- if (!isUsableStatus(response.status)) return import_neverthrow7.ResultAsync.fromSafePromise(Promise.resolve(null));
15700
- return import_neverthrow7.ResultAsync.fromSafePromise(
15750
+ if (!isUsableStatus(response.status)) return import_neverthrow8.ResultAsync.fromSafePromise(Promise.resolve(null));
15751
+ return import_neverthrow8.ResultAsync.fromSafePromise(
15701
15752
  (async () => {
15702
15753
  let authHint = response.status === 402 ? "paid" : "unprotected";
15703
15754
  let paymentRequiredBody;
@@ -15728,7 +15779,7 @@ function probeMethod(url2, method, path, headers, signal, inputBody) {
15728
15779
  }
15729
15780
  function getProbe(url2, headers, signal, inputBody) {
15730
15781
  const path = normalizePath(new URL(url2).pathname || "/");
15731
- return import_neverthrow7.ResultAsync.fromSafePromise(
15782
+ return import_neverthrow8.ResultAsync.fromSafePromise(
15732
15783
  Promise.all(
15733
15784
  [...HTTP_METHODS].map(
15734
15785
  (method) => probeMethod(url2, method, path, headers, signal, inputBody).match(
@@ -15741,12 +15792,13 @@ function getProbe(url2, headers, signal, inputBody) {
15741
15792
  }
15742
15793
 
15743
15794
  // src/core/protocols/mpp/index.ts
15744
- var import_neverthrow8 = require("neverthrow");
15795
+ var import_neverthrow9 = require("neverthrow");
15745
15796
  function parseBase64Json(encoded) {
15746
- return import_neverthrow8.Result.fromThrowable(
15797
+ return import_neverthrow9.Result.fromThrowable(
15747
15798
  () => {
15748
- const decoded = typeof Buffer !== "undefined" ? Buffer.from(encoded, "base64").toString("utf8") : atob(encoded);
15749
- const parsed = JSON.parse(decoded);
15799
+ const decoded = safeBase64DecodeUtf8(encoded);
15800
+ if (decoded.isErr()) throw decoded.error;
15801
+ const parsed = JSON.parse(decoded.value);
15750
15802
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
15751
15803
  throw new Error("not an object");
15752
15804
  }
package/dist/cli.js CHANGED
@@ -13785,8 +13785,8 @@ var FixedPriceSchema = external_exports.object({
13785
13785
  var DynamicPriceSchema = external_exports.object({
13786
13786
  currency: Iso4217Schema,
13787
13787
  mode: external_exports.literal("dynamic"),
13788
- min: external_exports.string(),
13789
- max: external_exports.string()
13788
+ min: external_exports.string().optional(),
13789
+ max: external_exports.string().optional()
13790
13790
  });
13791
13791
  var PriceSchema = external_exports.union([FixedPriceSchema, DynamicPriceSchema]);
13792
13792
  var X402ProtocolSchema = external_exports.object({
@@ -13885,7 +13885,12 @@ function normalizeLegacy(raw) {
13885
13885
  function formatPrice(price) {
13886
13886
  const sym = price.currency ?? "USD";
13887
13887
  if (price.mode === "fixed") return `${price.amount} ${sym}`;
13888
- return `${price.min}-${price.max} ${sym}`;
13888
+ if (price.min !== void 0 && price.max !== void 0) {
13889
+ return `${price.min}-${price.max} ${sym}`;
13890
+ }
13891
+ if (price.min !== void 0) return `>=${price.min} ${sym}`;
13892
+ if (price.max !== void 0) return `<=${price.max} ${sym}`;
13893
+ return `dynamic ${sym}`;
13889
13894
  }
13890
13895
  function extractProtocolNames(protocols) {
13891
13896
  return protocols.map((p) => {
@@ -13937,10 +13942,13 @@ var OpenApiOperationSchema = external_exports.object({
13937
13942
  description: external_exports.string().optional(),
13938
13943
  tags: external_exports.array(external_exports.string()).optional(),
13939
13944
  security: external_exports.array(external_exports.record(external_exports.string(), external_exports.array(external_exports.string()))).optional(),
13945
+ // `in` / `name` are spec-required, but a single malformed parameter must not
13946
+ // abort the whole spec — keep them optional so discovery is resilient to
13947
+ // non-conformant OpenAPI documents in the wild.
13940
13948
  parameters: external_exports.array(
13941
13949
  external_exports.object({
13942
- in: external_exports.string(),
13943
- name: external_exports.string(),
13950
+ in: external_exports.string().optional(),
13951
+ name: external_exports.string().optional(),
13944
13952
  schema: external_exports.unknown().optional(),
13945
13953
  required: external_exports.boolean().optional()
13946
13954
  })
@@ -13950,7 +13958,8 @@ var OpenApiOperationSchema = external_exports.object({
13950
13958
  content: external_exports.record(external_exports.string(), external_exports.object({ schema: external_exports.unknown().optional() }))
13951
13959
  }).optional(),
13952
13960
  responses: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
13953
- "x-payment-info": OpenApiPaymentInfoSchema.optional()
13961
+ // Permissive: vendor extension shape is validated at runtime, never at parse time.
13962
+ "x-payment-info": external_exports.unknown().optional()
13954
13963
  });
13955
13964
  var OpenApiPathItemSchema = external_exports.object({
13956
13965
  get: OpenApiOperationSchema.optional(),
@@ -14094,20 +14103,27 @@ function fetchSafe(url2, init) {
14094
14103
  }
14095
14104
 
14096
14105
  // src/core/source/openapi/index.ts
14097
- function resolvePricingHint(p) {
14098
- const raw = p;
14099
- const info = resolvePaymentInfo(raw);
14106
+ function toRecord(raw) {
14107
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return void 0;
14108
+ return raw;
14109
+ }
14110
+ function resolvePricingHint(raw) {
14111
+ const record2 = toRecord(raw);
14112
+ if (!record2) return void 0;
14113
+ const info = resolvePaymentInfo(record2);
14100
14114
  if (!info) return void 0;
14101
14115
  return {
14102
14116
  pricingMode: info.price.mode,
14103
14117
  ...info.price.mode === "fixed" ? { price: info.price.amount } : {},
14104
- ...info.price.mode === "dynamic" ? { minPrice: info.price.min, maxPrice: info.price.max } : {},
14118
+ ...info.price.mode === "dynamic" && info.price.min !== void 0 ? { minPrice: info.price.min } : {},
14119
+ ...info.price.mode === "dynamic" && info.price.max !== void 0 ? { maxPrice: info.price.max } : {},
14105
14120
  ...info.price.currency ? { currency: info.price.currency } : {}
14106
14121
  };
14107
14122
  }
14108
- function resolveProtocols(p) {
14109
- const raw = p;
14110
- const info = resolvePaymentInfo(raw);
14123
+ function resolveProtocols(raw) {
14124
+ const record2 = toRecord(raw);
14125
+ if (!record2) return [];
14126
+ const info = resolvePaymentInfo(record2);
14111
14127
  if (!info) return [];
14112
14128
  return extractProtocolNames(info.protocols);
14113
14129
  }
@@ -14120,8 +14136,8 @@ var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
14120
14136
  if (!operation) continue;
14121
14137
  const authMode = inferAuthMode(operation, doc.security, doc.components?.securitySchemes) ?? void 0;
14122
14138
  const p = operation["x-payment-info"];
14123
- const protocols = resolveProtocols(p ?? {});
14124
- const pricing = (authMode === "paid" || authMode === "apiKey+paid") && p ? resolvePricingHint(p) : void 0;
14139
+ const protocols = resolveProtocols(p);
14140
+ const pricing = (authMode === "paid" || authMode === "apiKey+paid") && p !== void 0 ? resolvePricingHint(p) : void 0;
14125
14141
  const summary = operation.summary ?? operation.description;
14126
14142
  routes.push({
14127
14143
  path: normalizePath(serverBasePath + rawPath),
@@ -14362,28 +14378,29 @@ function getWellKnown(origin, headers, signal) {
14362
14378
  // src/core/layers/l2.ts
14363
14379
  function formatPrice2(pricing) {
14364
14380
  const sym = pricing.currency ?? "USD";
14365
- if (pricing.pricingMode === "fixed") return `${pricing.price} ${sym}`;
14381
+ if (pricing.pricingMode === "fixed" && pricing.price) return `${pricing.price} ${sym}`;
14366
14382
  if (pricing.pricingMode === "dynamic") {
14367
14383
  if (pricing.minPrice && pricing.maxPrice)
14368
14384
  return `${pricing.minPrice}-${pricing.maxPrice} ${sym}`;
14369
14385
  if (pricing.maxPrice) return `up to ${pricing.maxPrice} ${sym}`;
14370
- return "dynamic";
14386
+ if (pricing.minPrice) return `from ${pricing.minPrice} ${sym}`;
14371
14387
  }
14372
- return `unknown pricing mode: ${pricing.pricingMode}`;
14388
+ return void 0;
14373
14389
  }
14374
14390
  function checkL2ForOpenAPI(openApi) {
14375
- const routes = openApi.routes.map((route) => ({
14376
- path: route.path,
14377
- method: route.method,
14378
- summary: route.summary ?? `${route.method} ${route.path}`,
14379
- ...route.authMode ? { authMode: route.authMode } : {},
14380
- ...route.pricing ? {
14381
- price: formatPrice2(route.pricing),
14382
- pricingMode: route.pricing.pricingMode,
14383
- ...route.pricing.currency ? { currency: route.pricing.currency } : {}
14384
- } : {},
14385
- ...route.protocols?.length ? { protocols: route.protocols } : {}
14386
- }));
14391
+ const routes = openApi.routes.map((route) => {
14392
+ const priceHint = route.pricing ? formatPrice2(route.pricing) : void 0;
14393
+ return {
14394
+ path: route.path,
14395
+ method: route.method,
14396
+ summary: route.summary ?? `${route.method} ${route.path}`,
14397
+ ...route.authMode ? { authMode: route.authMode } : {},
14398
+ ...priceHint ? { price: priceHint } : {},
14399
+ ...route.pricing?.pricingMode ? { pricingMode: route.pricing.pricingMode } : {},
14400
+ ...route.pricing?.currency ? { currency: route.pricing.currency } : {},
14401
+ ...route.protocols?.length ? { protocols: route.protocols } : {}
14402
+ };
14403
+ });
14387
14404
  return {
14388
14405
  ...openApi.info.title ? { title: openApi.info.title } : {},
14389
14406
  ...openApi.info.description ? { description: openApi.info.description } : {},
@@ -14444,6 +14461,7 @@ var AUDIT_CODES = {
14444
14461
  L2_NO_PAID_ROUTES: "L2_NO_PAID_ROUTES",
14445
14462
  L2_PRICE_MISSING_ON_PAID: "L2_PRICE_MISSING_ON_PAID",
14446
14463
  L2_PRICING_MODE_UNKNOWN: "L2_PRICING_MODE_UNKNOWN",
14464
+ L2_DYNAMIC_PRICE_INCOMPLETE: "L2_DYNAMIC_PRICE_INCOMPLETE",
14447
14465
  L2_CURRENCY_INVALID: "L2_CURRENCY_INVALID",
14448
14466
  L2_PAYMENT_INFO_LEGACY: "L2_PAYMENT_INFO_LEGACY",
14449
14467
  L2_PROTOCOLS_MISSING_ON_PAID: "L2_PROTOCOLS_MISSING_ON_PAID",
@@ -14679,7 +14697,15 @@ function getWarningsForL2(l2) {
14679
14697
  });
14680
14698
  }
14681
14699
  if (route.authMode === "paid") {
14682
- if (!route.price) {
14700
+ if (route.pricingMode === "dynamic" && !route.price) {
14701
+ warnings.push({
14702
+ code: AUDIT_CODES.L2_DYNAMIC_PRICE_INCOMPLETE,
14703
+ severity: "warn",
14704
+ message: `Paid route ${loc} declares dynamic pricing but no min/max bounds.`,
14705
+ hint: "Add x-payment-info.price.min and .price.max so agents can budget before calling. Without bounds, agents have no safe upper limit to pre-authorize.",
14706
+ path: route.path
14707
+ });
14708
+ } else if (!route.price) {
14683
14709
  warnings.push({
14684
14710
  code: AUDIT_CODES.L2_PRICE_MISSING_ON_PAID,
14685
14711
  severity: "warn",
@@ -15620,11 +15646,36 @@ async function parsePaymentRequiredBody(response) {
15620
15646
  return payload;
15621
15647
  }
15622
15648
 
15649
+ // src/core/lib/base64.ts
15650
+ import { Result as Result2 } from "neverthrow";
15651
+ function safeBase64DecodeUtf8(encoded) {
15652
+ return Result2.fromThrowable(
15653
+ () => {
15654
+ if (typeof Buffer !== "undefined") {
15655
+ return Buffer.from(encoded, "base64").toString("utf8");
15656
+ }
15657
+ const binaryString = atob(encoded);
15658
+ const bytes = new Uint8Array(binaryString.length);
15659
+ for (let i = 0; i < binaryString.length; i++) {
15660
+ bytes[i] = binaryString.charCodeAt(i);
15661
+ }
15662
+ return new TextDecoder("utf-8").decode(bytes);
15663
+ },
15664
+ (e) => e instanceof Error ? e : new Error(String(e))
15665
+ )();
15666
+ }
15667
+
15623
15668
  // src/core/protocols/x402/v2/parse-payment-required.ts
15624
15669
  function parsePaymentRequiredBody2(headerValue) {
15625
- const payload = JSON.parse(atob(headerValue));
15626
- if (!isRecord(payload) || payload.x402Version !== 2) return null;
15627
- return payload;
15670
+ const decoded = safeBase64DecodeUtf8(headerValue);
15671
+ if (decoded.isErr()) return null;
15672
+ try {
15673
+ const payload = JSON.parse(decoded.value);
15674
+ if (!isRecord(payload) || payload.x402Version !== 2) return null;
15675
+ return payload;
15676
+ } catch {
15677
+ return null;
15678
+ }
15628
15679
  }
15629
15680
 
15630
15681
  // src/core/source/probe/index.ts
@@ -15711,12 +15762,13 @@ function getProbe(url2, headers, signal, inputBody) {
15711
15762
  }
15712
15763
 
15713
15764
  // src/core/protocols/mpp/index.ts
15714
- import { Result as Result2 } from "neverthrow";
15765
+ import { Result as Result3 } from "neverthrow";
15715
15766
  function parseBase64Json(encoded) {
15716
- return Result2.fromThrowable(
15767
+ return Result3.fromThrowable(
15717
15768
  () => {
15718
- const decoded = typeof Buffer !== "undefined" ? Buffer.from(encoded, "base64").toString("utf8") : atob(encoded);
15719
- const parsed = JSON.parse(decoded);
15769
+ const decoded = safeBase64DecodeUtf8(encoded);
15770
+ if (decoded.isErr()) throw decoded.error;
15771
+ const parsed = JSON.parse(decoded.value);
15720
15772
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
15721
15773
  throw new Error("not an object");
15722
15774
  }