@zeroxyz/cli 1.33.0 → 1.34.1

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.
Files changed (2) hide show
  1. package/dist/index.js +331 -63
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -93043,7 +93043,7 @@ init_esm_shims();
93043
93043
  // ../sdk/dist/index.js
93044
93044
  init_esm_shims();
93045
93045
 
93046
- // ../sdk/dist/chunk-QNTZREQD.js
93046
+ // ../sdk/dist/chunk-DU665LQG.js
93047
93047
  init_esm_shims();
93048
93048
 
93049
93049
  // ../../node_modules/.pnpm/viem@2.52.2_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@6.0.6_zod@4.3.6/node_modules/viem/_esm/index.js
@@ -166742,6 +166742,7 @@ var FetchDiagnosticContext = class {
166742
166742
  issues = [];
166743
166743
  stageDurationsMs = {};
166744
166744
  paymentProtocol = null;
166745
+ paymentFallback = null;
166745
166746
  paymentMode = null;
166746
166747
  fundingSource = null;
166747
166748
  constructor(fetchId) {
@@ -166771,6 +166772,17 @@ var FetchDiagnosticContext = class {
166771
166772
  this.failureCode = code;
166772
166773
  }
166773
166774
  };
166775
+ // A failed preferred rail is non-terminal when an advertised fallback is
166776
+ // still safe to try. Retain its issue for observability, but let a later MPP
166777
+ // failure become the primary failure (or leave the completed fetch clean).
166778
+ recoverFailureForFallback = () => {
166779
+ this.failureStage = null;
166780
+ this.failureCode = null;
166781
+ };
166782
+ recordPaymentFallback = (fallback2) => {
166783
+ this.issue(fallback2.stage, fallback2.code);
166784
+ this.paymentFallback ??= { ...fallback2 };
166785
+ };
166774
166786
  selectPaymentProtocol = (protocol) => {
166775
166787
  this.paymentProtocol = protocol;
166776
166788
  };
@@ -166785,6 +166797,7 @@ var FetchDiagnosticContext = class {
166785
166797
  failureCode: this.failureCode,
166786
166798
  issues: this.issues.map((issue3) => ({ ...issue3 })),
166787
166799
  paymentProtocol: this.paymentProtocol,
166800
+ paymentFallback: this.paymentFallback === null ? null : { ...this.paymentFallback },
166788
166801
  paymentMode: this.paymentMode,
166789
166802
  fundingSource: this.fundingSource,
166790
166803
  stageDurationsMs: { ...this.stageDurationsMs }
@@ -166839,7 +166852,7 @@ var redactUrl = (raw) => {
166839
166852
  };
166840
166853
  var truncateError = (raw) => raw.length > ERROR_MAX ? `${raw.slice(0, ERROR_MAX)}\u2026` : raw;
166841
166854
  var package_default = {
166842
- version: "0.26.0"
166855
+ version: "0.27.1"
166843
166856
  };
166844
166857
  var SDK_VERSION2 = package_default.version;
166845
166858
  var ZeroError = class extends Error {
@@ -166893,6 +166906,14 @@ var ZeroPaymentError = class extends ZeroError {
166893
166906
  this.name = "ZeroPaymentError";
166894
166907
  }
166895
166908
  };
166909
+ var PAYMENT_NOT_ATTEMPTED_ERRORS = /* @__PURE__ */ new WeakSet();
166910
+ var markPaymentNotAttempted = (error98) => {
166911
+ if (typeof error98 === "object" && error98 !== null || typeof error98 === "function") {
166912
+ PAYMENT_NOT_ATTEMPTED_ERRORS.add(error98);
166913
+ }
166914
+ return error98;
166915
+ };
166916
+ var isPaymentNotAttemptedError = (error98) => (typeof error98 === "object" && error98 !== null || typeof error98 === "function") && PAYMENT_NOT_ATTEMPTED_ERRORS.has(error98);
166896
166917
  var ZeroPermit2AllowanceError = class extends ZeroPaymentError {
166897
166918
  constructor(message2, options) {
166898
166919
  super(message2, options);
@@ -167913,7 +167934,11 @@ var FETCH_WARNINGS = Object.freeze({
167913
167934
  // Response body exceeded maxResponseBytes — bodyRaw / body / bodyEncoding
167914
167935
  // reflect the clipped prefix; consumers that wrote the body to disk got
167915
167936
  // a truncated file. Particularly bad for paid binary fetches.
167916
- bodyTruncated: "body_truncated"
167937
+ bodyTruncated: "body_truncated",
167938
+ // The caller's `Authorization: Bearer` could not ride the MPP paid retry:
167939
+ // the Payment credential replaces Authorization and the 402 advertised no
167940
+ // alternate header to move the bearer into, so it was dropped.
167941
+ authorizationBearerDroppedByMpp: "authorization_bearer_dropped_by_mpp"
167917
167942
  });
167918
167943
  var FETCH_SKIP_REASONS = Object.freeze({
167919
167944
  // The body was lost, but the capability executed (and may have charged) —
@@ -168120,6 +168145,7 @@ var Payments = class {
168120
168145
  let pendingAmountUnits = 0n;
168121
168146
  let identityChallengeHandled = false;
168122
168147
  let paidChallengeHandled = false;
168148
+ let positivePaymentReplayAttempted = false;
168123
168149
  let capturedNetwork;
168124
168150
  let capturedScheme = null;
168125
168151
  let capturedCeilingUnits = null;
@@ -168353,6 +168379,9 @@ var Payments = class {
168353
168379
  "Access-Control-Expose-Headers",
168354
168380
  "PAYMENT-RESPONSE,X-PAYMENT-RESPONSE"
168355
168381
  );
168382
+ if (pendingAmountUnits > 0n) {
168383
+ positivePaymentReplayAttempted = true;
168384
+ }
168356
168385
  response = await measureDiagnostic(
168357
168386
  input.diagnostics,
168358
168387
  "paid_replay",
@@ -168389,11 +168418,14 @@ var Payments = class {
168389
168418
  FETCH_DIAGNOSTIC_CODES.paymentFailed
168390
168419
  );
168391
168420
  }
168392
- if (err instanceof ZeroError) throw err;
168393
- throw new ZeroPaymentError(
168421
+ if (err instanceof ZeroError) {
168422
+ throw !positivePaymentReplayAttempted && !isCallerAbortError(err) ? markPaymentNotAttempted(err) : err;
168423
+ }
168424
+ const paymentError = new ZeroPaymentError(
168394
168425
  `x402 payment failed: ${err instanceof Error ? err.message : String(err)}`,
168395
168426
  { cause: err }
168396
168427
  );
168428
+ throw !positivePaymentReplayAttempted && !isCallerAbortError(err) ? markPaymentNotAttempted(paymentError) : paymentError;
168397
168429
  }
168398
168430
  const isUpto = capturedScheme === "upto" && paidChallengeHandled;
168399
168431
  let txHash = null;
@@ -169205,6 +169237,38 @@ var Payments = class {
169205
169237
  };
169206
169238
  };
169207
169239
  };
169240
+ var BEARER_VALUE = /^bearer\s+\S+$/i;
169241
+ var relocateBearerForMpp = (headers, alternateHeader) => {
169242
+ if (!headers) return { headers, relocated: false, dropped: false };
169243
+ const entries = Object.entries(headers);
169244
+ const authorization = entries.find(
169245
+ ([name]) => name.toLowerCase() === "authorization"
169246
+ );
169247
+ const value = authorization?.[1].trim();
169248
+ if (!value || !BEARER_VALUE.test(value)) {
169249
+ return { headers, relocated: false, dropped: false };
169250
+ }
169251
+ if (!alternateHeader) return { headers, relocated: false, dropped: true };
169252
+ const alternate = alternateHeader.toLowerCase();
169253
+ if (entries.some(([name]) => name.toLowerCase() === alternate)) {
169254
+ return { headers, relocated: false, dropped: false };
169255
+ }
169256
+ const next = Object.fromEntries(
169257
+ entries.filter(([name]) => name.toLowerCase() !== "authorization")
169258
+ );
169259
+ next[alternateHeader] = value;
169260
+ return { headers: next, relocated: true, dropped: false };
169261
+ };
169262
+ var alternateBearerHeaderFromChallengeBody = (body) => {
169263
+ if (!body || typeof body !== "object") return void 0;
169264
+ const presentation = body.auth?.presentation;
169265
+ if (!presentation || typeof presentation !== "object") return void 0;
169266
+ const { scheme, alternateHeader } = presentation;
169267
+ if (typeof scheme === "string" && scheme.toLowerCase() !== "bearer") {
169268
+ return void 0;
169269
+ }
169270
+ return typeof alternateHeader === "string" && /^[A-Za-z0-9-]+$/.test(alternateHeader) ? alternateHeader : void 0;
169271
+ };
169208
169272
  var isShortToken = (id) => id.startsWith("z_") && id.indexOf(".", 2) !== -1;
169209
169273
  var MAX_402_PROBE_BYTES = 1024 * 1024;
169210
169274
  var MAX_RESPONSE_BYTES = 10 * 1024 * 1024;
@@ -169336,9 +169400,27 @@ var detectPaymentRequirement = async (response, preferredProtocol) => {
169336
169400
  const scheme = challenge2.trim().split(/\s+/)[0]?.toLowerCase() ?? "";
169337
169401
  return MPP_SCHEME_TOKENS.has(scheme);
169338
169402
  }) : false;
169403
+ const mppRequirement = (alternateBearerHeader, paymentFallback) => ({
169404
+ protocol: "mpp",
169405
+ raw: { "www-authenticate": wwwAuth },
169406
+ ...alternateBearerHeader ? { alternateBearerHeader } : {},
169407
+ ...paymentFallback ? { paymentFallback } : {}
169408
+ });
169409
+ const x402Fallback = (stage, code) => ({ from: "x402", to: "mpp", stage, code });
169410
+ const readMppBearerHint = async () => {
169411
+ try {
169412
+ const text = await readClippedText(response, MAX_402_PROBE_BYTES);
169413
+ return text ? alternateBearerHeaderFromChallengeBody(JSON.parse(text)) : void 0;
169414
+ } catch {
169415
+ return void 0;
169416
+ }
169417
+ };
169339
169418
  if (preferredProtocol === "mpp") {
169340
- cancelBody2(response);
169341
- return advertisesMpp ? { protocol: "mpp", raw: { "www-authenticate": wwwAuth } } : { protocol: "unknown", raw: { requestedProtocol: "mpp" } };
169419
+ if (!advertisesMpp) {
169420
+ cancelBody2(response);
169421
+ return { protocol: "unknown", raw: { requestedProtocol: "mpp" } };
169422
+ }
169423
+ return mppRequirement(await readMppBearerHint());
169342
169424
  }
169343
169425
  const canSettleX402 = (raw) => {
169344
169426
  if (!raw || typeof raw !== "object") return false;
@@ -169351,47 +169433,71 @@ var detectPaymentRequirement = async (response, preferredProtocol) => {
169351
169433
  return selectSettleableX402Requirement(accepts, void 0, x402Version2) !== null;
169352
169434
  };
169353
169435
  const preferMppFallback = (raw) => preferredProtocol === void 0 && advertisesMpp && !canSettleX402(raw);
169354
- const selectedX402 = (raw) => ({
169436
+ const selectedX402 = (raw, alternateBearerHeader) => ({
169355
169437
  protocol: "x402",
169356
169438
  raw,
169357
- ...preferredProtocol === void 0 && advertisesMpp ? { fallbackProtocol: "mpp" } : {}
169439
+ ...preferredProtocol === void 0 && advertisesMpp ? {
169440
+ fallbackProtocol: "mpp",
169441
+ ...alternateBearerHeader ? { alternateBearerHeader } : {}
169442
+ } : {}
169358
169443
  });
169359
169444
  const x402Header = response.headers.get("payment-required") ?? response.headers.get("x-payment-required");
169360
169445
  if (x402Header) {
169361
- cancelBody2(response);
169446
+ let decoded;
169447
+ let decodable = true;
169362
169448
  try {
169363
- const decoded = JSON.parse(
169364
- Buffer.from(x402Header, "base64").toString("utf8")
169365
- );
169366
- if (preferMppFallback(decoded)) {
169367
- return { protocol: "mpp", raw: { "www-authenticate": wwwAuth } };
169368
- }
169369
- return selectedX402(decoded);
169449
+ decoded = JSON.parse(Buffer.from(x402Header, "base64").toString("utf8"));
169370
169450
  } catch {
169451
+ decodable = false;
169452
+ }
169453
+ if (!decodable) {
169371
169454
  if (preferredProtocol === void 0 && advertisesMpp) {
169372
- return { protocol: "mpp", raw: { "www-authenticate": wwwAuth } };
169455
+ return mppRequirement(
169456
+ await readMppBearerHint(),
169457
+ x402Fallback(
169458
+ "challenge_decode",
169459
+ FETCH_DIAGNOSTIC_CODES.challengeDecodeFailed
169460
+ )
169461
+ );
169373
169462
  }
169463
+ cancelBody2(response);
169374
169464
  return selectedX402({ encoded: x402Header });
169375
169465
  }
169466
+ if (preferMppFallback(decoded)) {
169467
+ return mppRequirement(
169468
+ await readMppBearerHint(),
169469
+ x402Fallback(
169470
+ "rail_select",
169471
+ FETCH_DIAGNOSTIC_CODES.unsupportedPaymentRail
169472
+ )
169473
+ );
169474
+ }
169475
+ cancelBody2(response);
169476
+ return selectedX402(decoded);
169376
169477
  }
169377
169478
  const declaredLen = Number.parseInt(
169378
169479
  response.headers.get("content-length") ?? "",
169379
169480
  10
169380
169481
  );
169381
169482
  const bodyFits = !Number.isFinite(declaredLen) || declaredLen <= MAX_402_PROBE_BYTES;
169483
+ let bodyBearerHint;
169382
169484
  if (bodyFits) {
169383
169485
  try {
169384
169486
  const text = await readClippedText(response, MAX_402_PROBE_BYTES);
169385
169487
  if (text) {
169386
169488
  const parsed = JSON.parse(text);
169489
+ bodyBearerHint = alternateBearerHeaderFromChallengeBody(parsed);
169387
169490
  if (looksLikeX402Body(parsed)) {
169388
169491
  if (preferMppFallback(parsed)) {
169389
- return {
169390
- protocol: "mpp",
169391
- raw: { "www-authenticate": wwwAuth }
169392
- };
169492
+ return mppRequirement(
169493
+ bodyBearerHint,
169494
+ x402Fallback(
169495
+ "rail_select",
169496
+ FETCH_DIAGNOSTIC_CODES.unsupportedPaymentRail
169497
+ )
169498
+ );
169393
169499
  }
169394
- return selectedX402(parsed);
169500
+ return selectedX402(parsed, bodyBearerHint);
169395
169501
  }
169396
169502
  }
169397
169503
  } catch {
@@ -169403,7 +169509,7 @@ var detectPaymentRequirement = async (response, preferredProtocol) => {
169403
169509
  }
169404
169510
  if (advertisesMpp) {
169405
169511
  cancelBody2(response);
169406
- return { protocol: "mpp", raw: { "www-authenticate": wwwAuth } };
169512
+ return mppRequirement(bodyBearerHint);
169407
169513
  }
169408
169514
  cancelBody2(response);
169409
169515
  return { protocol: "unknown", raw: {} };
@@ -169571,9 +169677,39 @@ var extractUnrecognizedKeys = (bodyRaw) => {
169571
169677
  visit(parsed);
169572
169678
  return [...new Set(out)].slice(0, 8);
169573
169679
  };
169680
+ var NOT_ACCEPTING_ORDERS_HINT = "this storefront isn't accepting orders yet \u2014 don't pay or retry; pick another capability";
169681
+ var STOREFRONT_GATE_HINTS = /* @__PURE__ */ new Map([
169682
+ [
169683
+ "plan_required",
169684
+ "the seller sells this call on a plan you don't hold \u2014 buy one of the plans listed in this response (POST its `purchase.url` with your identity bearer; a free trial costs nothing), then retry"
169685
+ ],
169686
+ [
169687
+ "verified_email_required",
169688
+ "the seller only serves buyers with a verified email \u2014 changing the request won't help; have the account owner verify their email on their Zero identity, then retry"
169689
+ ],
169690
+ [
169691
+ "usage_not_priced",
169692
+ "the seller hasn't priced this call on any plan, so it can't be bought right now \u2014 pick another capability"
169693
+ ],
169694
+ ["not_accepting_orders", NOT_ACCEPTING_ORDERS_HINT],
169695
+ ["signing_secret_required", NOT_ACCEPTING_ORDERS_HINT]
169696
+ ]);
169697
+ var STOREFRONT_GATE_CODE_RE = /\b(?:bearer|plan|verified_email|signing_secret|payment)_required\b/g;
169698
+ var storefrontGateCode = (bodyRaw) => {
169699
+ if (!bodyRaw) return void 0;
169700
+ try {
169701
+ const code = JSON.parse(bodyRaw)?.error;
169702
+ return typeof code === "string" ? code : void 0;
169703
+ } catch {
169704
+ return void 0;
169705
+ }
169706
+ };
169574
169707
  var computeFixHint = (status, message2, bodyRaw) => {
169575
169708
  if (status < 400 || status >= 500) return void 0;
169709
+ if (status === 402) return void 0;
169576
169710
  const hay = `${message2 ?? ""} ${bodyRaw ?? ""}`.toLowerCase();
169711
+ const gateHint = STOREFRONT_GATE_HINTS.get(storefrontGateCode(bodyRaw) ?? "");
169712
+ if (gateHint) return gateHint;
169577
169713
  if (status === 405 || /method not allowed|method_not_allowed/.test(hay)) {
169578
169714
  const allowed = extractAllowedMethod(`${bodyRaw ?? ""} ${message2 ?? ""}`);
169579
169715
  return allowed ? `the endpoint expects ${allowed}, not the method you used \u2014 retry with -X ${allowed}` : "the endpoint rejected this HTTP method \u2014 check the capability's method (`zero get <slug>`) and retry with the right -X";
@@ -169595,7 +169731,9 @@ var computeFixHint = (status, message2, bodyRaw) => {
169595
169731
  if ((status === 401 || status === 403) && /bearer|identity|unauthorized|credential|agent_auth/.test(hay)) {
169596
169732
  return 'the seller requires an agent identity credential \u2014 run `zero auth identity <host>` and resend with `-H "Authorization: Bearer <token>"`';
169597
169733
  }
169598
- if (/required|missing|must (include|provide|have|contain)|is expected/.test(hay)) {
169734
+ if (/required|missing|must (include|provide|have|contain)|is expected/.test(
169735
+ hay.replace(STOREFRONT_GATE_CODE_RE, "")
169736
+ )) {
169599
169737
  const field = extractFieldName(message2 ?? "");
169600
169738
  return field ? `add the required field '${field}' to the request body, then retry` : "the request is missing one or more required fields \u2014 check the capability schema (`zero get <slug>`), then retry";
169601
169739
  }
@@ -169695,6 +169833,7 @@ var recordErrorFetchRun = async (client, opts, result, diagnostics, capabilityId
169695
169833
  failureStage: diagnostics.snapshot().failureStage ?? void 0,
169696
169834
  failureCode: diagnostics.snapshot().failureCode ?? void 0,
169697
169835
  paymentProtocol: diagnostics.snapshot().paymentProtocol ?? void 0,
169836
+ paymentFallback: diagnostics.snapshot().paymentFallback ?? void 0,
169698
169837
  paymentMode: diagnostics.snapshot().paymentMode ?? void 0,
169699
169838
  fundingSource: diagnostics.snapshot().fundingSource ?? void 0,
169700
169839
  stageDurationsMs: diagnostics.snapshot().stageDurationsMs,
@@ -169877,17 +170016,28 @@ var clientFetch = async (client, url4, opts = {}, diagnostics) => {
169877
170016
  });
169878
170017
  if (requirement?.protocol === "x402" || requirement?.protocol === "mpp") {
169879
170018
  diagnostics.selectPaymentProtocol(requirement.protocol);
170019
+ if (requirement.paymentFallback) {
170020
+ diagnostics.recordPaymentFallback(requirement.paymentFallback);
170021
+ }
169880
170022
  const payCall = requirement.protocol === "x402" ? client.payments.pay : client.payments.payMpp;
169881
170023
  try {
170024
+ const paidLegHeaders = withDefaultUserAgent(
170025
+ withDefaultContentType(opts.headers, requestBody)
170026
+ );
170027
+ const mppLegHeaders = () => {
170028
+ const relocation = relocateBearerForMpp(
170029
+ paidLegHeaders,
170030
+ requirement.alternateBearerHeader
170031
+ );
170032
+ if (relocation.dropped) {
170033
+ warnings.push(FETCH_WARNINGS.authorizationBearerDroppedByMpp);
170034
+ }
170035
+ return relocation.headers;
170036
+ };
169882
170037
  const paymentInput = {
169883
170038
  url: requestUrl,
169884
170039
  method,
169885
- // Fresh clone for the paid retry — same rationale as
169886
- // the probe-side clone above. Re-derives the default
169887
- // Content-Type so the paid leg matches the probe.
169888
- headers: withDefaultUserAgent(
169889
- withDefaultContentType(opts.headers, requestBody)
169890
- ),
170040
+ headers: requirement.protocol === "mpp" ? mppLegHeaders() : paidLegHeaders,
169891
170041
  body: requestBody,
169892
170042
  maxPay: opts.maxPay,
169893
170043
  account: opts.account,
@@ -169909,13 +170059,31 @@ var clientFetch = async (client, url4, opts = {}, diagnostics) => {
169909
170059
  try {
169910
170060
  paid = await payCall(paymentInput);
169911
170061
  } catch (error98) {
169912
- if ((error98 instanceof ZeroInsufficientFundsError || error98 instanceof ZeroPermit2AllowanceError) && requirement.protocol === "x402" && requirement.fallbackProtocol === "mpp") {
169913
- diagnostics.issue(
169914
- error98 instanceof ZeroInsufficientFundsError ? "balance_check" : "paid_replay",
169915
- error98 instanceof ZeroInsufficientFundsError ? FETCH_DIAGNOSTIC_CODES.insufficientFunds : FETCH_DIAGNOSTIC_CODES.permit2AllowanceRequired
169916
- );
170062
+ if ((error98 instanceof ZeroInsufficientFundsError || error98 instanceof ZeroPermit2AllowanceError || isPaymentNotAttemptedError(error98)) && requirement.protocol === "x402" && requirement.fallbackProtocol === "mpp") {
170063
+ if (error98 instanceof ZeroInsufficientFundsError) {
170064
+ diagnostics.issue(
170065
+ "balance_check",
170066
+ FETCH_DIAGNOSTIC_CODES.insufficientFunds
170067
+ );
170068
+ } else if (error98 instanceof ZeroPermit2AllowanceError) {
170069
+ diagnostics.issue(
170070
+ "paid_replay",
170071
+ FETCH_DIAGNOSTIC_CODES.permit2AllowanceRequired
170072
+ );
170073
+ }
170074
+ const failedX402 = diagnostics.snapshot();
170075
+ diagnostics.recordPaymentFallback({
170076
+ from: "x402",
170077
+ to: "mpp",
170078
+ stage: error98 instanceof ZeroInsufficientFundsError ? "balance_check" : error98 instanceof ZeroPermit2AllowanceError ? "paid_replay" : failedX402.failureStage ?? "paid_replay",
170079
+ code: error98 instanceof ZeroInsufficientFundsError ? FETCH_DIAGNOSTIC_CODES.insufficientFunds : error98 instanceof ZeroPermit2AllowanceError ? FETCH_DIAGNOSTIC_CODES.permit2AllowanceRequired : failedX402.failureCode ?? FETCH_DIAGNOSTIC_CODES.paymentFailed
170080
+ });
170081
+ diagnostics.recoverFailureForFallback();
169917
170082
  diagnostics.selectPaymentProtocol("mpp");
169918
- paid = await client.payments.payMpp(paymentInput);
170083
+ paid = await client.payments.payMpp({
170084
+ ...paymentInput,
170085
+ headers: mppLegHeaders()
170086
+ });
169919
170087
  } else {
169920
170088
  throw error98;
169921
170089
  }
@@ -170241,6 +170409,7 @@ var clientFetch = async (client, url4, opts = {}, diagnostics) => {
170241
170409
  ),
170242
170410
  failureStage: diagnostics.snapshot().failureStage ?? void 0,
170243
170411
  failureCode: diagnostics.snapshot().failureCode ?? void 0,
170412
+ paymentFallback: diagnostics.snapshot().paymentFallback ?? void 0,
170244
170413
  fundingSource: diagnostics.snapshot().fundingSource ?? void 0,
170245
170414
  stageDurationsMs: diagnostics.snapshot().stageDurationsMs,
170246
170415
  warningCodes: warnings.length > 0 ? warnings : void 0,
@@ -170901,11 +171070,25 @@ var idJagMintResponseSchema = external_exports3.object({
170901
171070
  issuedTokenType: raw.issued_token_type ?? ID_JAG_TOKEN_TYPE,
170902
171071
  expiresIn: raw.expires_in ?? null
170903
171072
  }));
171073
+ var alternateBearerHeaderSchema = external_exports3.object({
171074
+ scheme: external_exports3.string().optional(),
171075
+ header: external_exports3.string(),
171076
+ use_when: external_exports3.string().optional()
171077
+ }).loose();
170904
171078
  var protectedResourceMetadataSchema = external_exports3.object({
170905
171079
  resource: external_exports3.string().optional(),
170906
171080
  resource_name: external_exports3.string().optional(),
170907
- authorization_servers: external_exports3.array(external_exports3.string()).optional()
171081
+ authorization_servers: external_exports3.array(external_exports3.string()).optional(),
171082
+ zeroclick_agent_authorization: alternateBearerHeaderSchema.optional()
170908
171083
  }).loose();
171084
+ var HEADER_NAME = /^[A-Za-z0-9-]+$/;
171085
+ var alternateBearerHeaderFrom = (advertised) => {
171086
+ if (!advertised) return null;
171087
+ if (advertised.scheme && advertised.scheme.toLowerCase() !== "bearer") {
171088
+ return null;
171089
+ }
171090
+ return HEADER_NAME.test(advertised.header) ? advertised.header : null;
171091
+ };
170909
171092
  var serviceAuthMetadataSchema = external_exports3.object({
170910
171093
  resource: external_exports3.string().optional(),
170911
171094
  resource_name: external_exports3.string().optional(),
@@ -171000,7 +171183,10 @@ var AuthIdentity = class {
171000
171183
  tokenEndpoint: metadata.token_endpoint ?? `${trimSlash(server)}/oauth2/token`,
171001
171184
  identityAssertionSupported: (agentAuth.identity_types_supported ?? []).includes(
171002
171185
  IDENTITY_ASSERTION_TYPE
171003
- ) && (assertionTypes ? assertionTypes.includes(ID_JAG_TOKEN_TYPE) : true)
171186
+ ) && (assertionTypes ? assertionTypes.includes(ID_JAG_TOKEN_TYPE) : true),
171187
+ alternateBearerHeader: alternateBearerHeaderFrom(
171188
+ prm.zeroclick_agent_authorization
171189
+ )
171004
171190
  };
171005
171191
  } catch (err) {
171006
171192
  lastError = err;
@@ -171656,14 +171842,30 @@ var paymentSessionSchema = external_exports3.object({
171656
171842
  recipient: external_exports3.string().regex(/^0x[0-9a-fA-F]{40}$/).nullable(),
171657
171843
  cumulativeAmount: external_exports3.string().regex(/^(?:0|[1-9]\d*)$/)
171658
171844
  }).strict();
171845
+ var paymentFallbackSchema = external_exports3.object({
171846
+ from: external_exports3.string(),
171847
+ to: external_exports3.string(),
171848
+ stage: external_exports3.string(),
171849
+ code: external_exports3.string()
171850
+ }).strict();
171659
171851
  var createRunResponseSchema = external_exports3.object({
171660
171852
  runId: external_exports3.string()
171661
171853
  });
171662
171854
  var runListItemSchema = external_exports3.object({
171663
171855
  uid: external_exports3.string(),
171664
- capabilityUid: external_exports3.string(),
171665
- capabilitySlug: external_exports3.string(),
171666
- capabilityName: external_exports3.string(),
171856
+ // ZERO-844 — null on an unattributed (direct-URL) run. Those are only
171857
+ // returned when the caller passes `includeUnattributed`, so a caller that
171858
+ // doesn't opt in never sees a null here.
171859
+ capabilityUid: external_exports3.string().nullable(),
171860
+ capabilitySlug: external_exports3.string().nullable(),
171861
+ capabilityName: external_exports3.string().nullable(),
171862
+ // The redacted unindexed target, populated only when there is no capability.
171863
+ // Older servers omit these; default rather than require so the SDK stays
171864
+ // forward- and backward-compatible.
171865
+ requestHost: external_exports3.string().nullable().optional().default(null),
171866
+ requestPathTemplate: external_exports3.string().nullable().optional().default(null),
171867
+ requestMethod: external_exports3.string().nullable().optional().default(null),
171868
+ attributed: external_exports3.boolean().optional().default(true),
171667
171869
  status: external_exports3.number().nullable(),
171668
171870
  latencyMs: external_exports3.number().nullable(),
171669
171871
  cost: external_exports3.object({ amount: external_exports3.string(), asset: external_exports3.string().nullable() }).nullable(),
@@ -171674,6 +171876,7 @@ var runListItemSchema = external_exports3.object({
171674
171876
  mode: external_exports3.string().nullable(),
171675
171877
  session: paymentSessionSchema.nullable().optional().default(null)
171676
171878
  }).nullable(),
171879
+ paymentFallback: paymentFallbackSchema.nullable().optional().default(null),
171677
171880
  createdAt: external_exports3.coerce.date(),
171678
171881
  reviewed: external_exports3.boolean()
171679
171882
  });
@@ -171695,6 +171898,9 @@ var runDetailSchema = external_exports3.object({
171695
171898
  mode: external_exports3.string().nullable(),
171696
171899
  session: paymentSessionSchema.nullable().optional().default(null)
171697
171900
  }).nullable(),
171901
+ paymentFallback: paymentFallbackSchema.nullable().optional().default(null),
171902
+ // ZERO-844 — null on an unattributed (direct-URL) run, which the server only
171903
+ // returns when `includeUnattributed` is passed.
171698
171904
  capability: external_exports3.object({
171699
171905
  uid: external_exports3.string(),
171700
171906
  slug: external_exports3.string(),
@@ -171703,7 +171909,14 @@ var runDetailSchema = external_exports3.object({
171703
171909
  method: external_exports3.string(),
171704
171910
  whatItDoes: external_exports3.string().nullable(),
171705
171911
  tags: external_exports3.array(external_exports3.string())
171706
- }),
171912
+ }).nullable(),
171913
+ // The redacted unindexed target — the counterpart to `capability` for a run
171914
+ // that has none. Exactly one of the two is non-null.
171915
+ target: external_exports3.object({
171916
+ host: external_exports3.string().nullable(),
171917
+ pathTemplate: external_exports3.string().nullable(),
171918
+ method: external_exports3.string().nullable()
171919
+ }).nullable().optional().default(null),
171707
171920
  reviewed: external_exports3.boolean()
171708
171921
  });
171709
171922
  var createReviewResponseSchema = external_exports3.object({
@@ -171749,6 +171962,8 @@ var Runs = class _Runs {
171749
171962
  * unattributed runs, which it can't do if we strip the target as well.
171750
171963
  */
171751
171964
  static FIELD_GENERATIONS = [
171965
+ // Structured trace of a safe payment-rail fallback.
171966
+ ["paymentFallback"],
171752
171967
  // MPP channel anchor for close-failure reconciliation. Peels first so a
171753
171968
  // newer SDK still records all prior diagnostics against an older API.
171754
171969
  ["paymentSession"],
@@ -171844,6 +172059,8 @@ var Runs = class _Runs {
171844
172059
  if (params2.capabilityId !== void 0)
171845
172060
  query.capabilityId = params2.capabilityId;
171846
172061
  if (params2.unreviewed !== void 0) query.unreviewed = params2.unreviewed;
172062
+ if (params2.includeUnattributed !== void 0)
172063
+ query.includeUnattributed = params2.includeUnattributed;
171847
172064
  if (params2.limit !== void 0) query.limit = params2.limit;
171848
172065
  if (params2.cursor !== void 0) query.cursor = params2.cursor;
171849
172066
  if (params2.walletAddress !== void 0) {
@@ -171865,6 +172082,8 @@ var Runs = class _Runs {
171865
172082
  {
171866
172083
  method: "GET",
171867
172084
  path: `/v1/runs/${runId}`,
172085
+ // ZERO-844 — without this an unattributed (direct-URL) run 404s.
172086
+ query: opts.includeUnattributed !== void 0 ? { includeUnattributed: opts.includeUnattributed } : {},
171868
172087
  signal: opts.signal
171869
172088
  },
171870
172089
  runDetailSchema
@@ -172374,6 +172593,10 @@ var AnalyticsEmitter = class {
172374
172593
  latency_ms: res.latencyMs,
172375
172594
  has_payment: res.payment !== null,
172376
172595
  payment_protocol: res.payment?.protocol ?? res.diagnostics?.paymentProtocol ?? null,
172596
+ payment_fallback_from: res.diagnostics?.paymentFallback?.from ?? null,
172597
+ payment_fallback_to: res.diagnostics?.paymentFallback?.to ?? null,
172598
+ payment_fallback_stage: res.diagnostics?.paymentFallback?.stage ?? null,
172599
+ payment_fallback_code: res.diagnostics?.paymentFallback?.code ?? null,
172377
172600
  funding_source: res.diagnostics?.fundingSource ?? null,
172378
172601
  payment_amount: res.payment?.amount ?? null,
172379
172602
  payment_chain: res.payment?.chain ?? null,
@@ -172414,6 +172637,10 @@ var AnalyticsEmitter = class {
172414
172637
  failure_stage: diagnostics?.failureStage ?? null,
172415
172638
  failure_code: diagnostics?.failureCode ?? null,
172416
172639
  payment_protocol: diagnostics?.paymentProtocol ?? null,
172640
+ payment_fallback_from: diagnostics?.paymentFallback?.from ?? null,
172641
+ payment_fallback_to: diagnostics?.paymentFallback?.to ?? null,
172642
+ payment_fallback_stage: diagnostics?.paymentFallback?.stage ?? null,
172643
+ payment_fallback_code: diagnostics?.paymentFallback?.code ?? null,
172417
172644
  payment_mode: diagnostics?.paymentMode ?? null,
172418
172645
  funding_source: diagnostics?.fundingSource ?? null,
172419
172646
  diagnostic_codes: diagnostics?.issues.map((issue3) => issue3.code) ?? [],
@@ -176664,7 +176891,7 @@ var placeholderFor = (fieldName, propSchema) => String(sampleValueFor(fieldName,
176664
176891
  // package.json
176665
176892
  var package_default2 = {
176666
176893
  name: "@zeroxyz/cli",
176667
- version: "1.33.0",
176894
+ version: "1.34.1",
176668
176895
  type: "module",
176669
176896
  bin: {
176670
176897
  zero: "dist/index.js",
@@ -177405,6 +177632,7 @@ var emitAccessToken = (accessToken, discovery, host, json3, reused) => {
177405
177632
  resource: discovery.resource,
177406
177633
  resourceName: discovery.resourceName,
177407
177634
  tokenEndpoint: discovery.tokenEndpoint,
177635
+ alternateBearerHeader: discovery.alternateBearerHeader,
177408
177636
  reused
177409
177637
  })}
177410
177638
  `
@@ -177416,6 +177644,11 @@ var emitAccessToken = (accessToken, discovery, host, json3, reused) => {
177416
177644
  `Signed in to ${discovery.resourceName ?? host} with your Zero identity.`,
177417
177645
  "The bearer token below is short-lived \u2014 use it right away:",
177418
177646
  ` zero fetch <url> -H "Authorization: Bearer <token>"`,
177647
+ ...discovery.alternateBearerHeader ? [
177648
+ "Paying over MPP (a 402 answered with a Payment credential)? The payment takes Authorization, so send the token as:",
177649
+ ` zero fetch <url> -H "${discovery.alternateBearerHeader}: Bearer <token>"`,
177650
+ "(zero fetch moves a Bearer Authorization there itself when the 402 advertises it.)"
177651
+ ] : [],
177419
177652
  `Re-run this command for a fresh token; it reuses the stored registration.`,
177420
177653
  ""
177421
177654
  ].join("\n")
@@ -178663,7 +178896,7 @@ Bulk bug-report complete: ${ok} ok, ${failed} failed`
178663
178896
  const [latest] = list2.runs;
178664
178897
  if (latest) {
178665
178898
  run = latest.uid;
178666
- capability = capability ?? latest.capabilityUid;
178899
+ capability = capability ?? latest.capabilityUid ?? void 0;
178667
178900
  }
178668
178901
  } catch {
178669
178902
  }
@@ -178767,6 +179000,7 @@ init_esm_shims();
178767
179000
  var MAX_INLINE_REQUEST_BODY_BYTES = 10 * 1024 * 1024;
178768
179001
  var MAX_FILE_REQUEST_BODY_BYTES = 500 * 1024 * 1024;
178769
179002
  var MAX_RESPONSE_BYTES2 = MAX_FILE_REQUEST_BODY_BYTES;
179003
+ var paymentFallbackFor = (diagnostics) => diagnostics?.paymentFallback ?? null;
178770
179004
  var formatPaymentLine = (payment) => {
178771
179005
  const base2 = `Paid ${payment.amount} ${payment.asset} via ${payment.protocol} on ${payment.chain}`;
178772
179006
  return payment.authorizedAmount && payment.authorizedAmount !== payment.amount ? `${base2} (authorized up to ${payment.authorizedAmount})` : base2;
@@ -178989,7 +179223,6 @@ var fetchCommand = (appContext) => new Command("fetch").description(
178989
179223
  let searchId;
178990
179224
  let displayCostAmount;
178991
179225
  let fetchOrigin;
178992
- let runIsAttributed = true;
178993
179226
  if (fromToken) {
178994
179227
  capabilityUid = capFromNoUrl?.uid ?? null;
178995
179228
  capabilityId = options.capability ?? "";
@@ -179092,12 +179325,19 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179092
179325
  } catch (err) {
179093
179326
  const message2 = err instanceof Error ? err.message : "Fetch failed";
179094
179327
  const fetchContext = fetchErrorContext(err);
179328
+ const paymentFallback2 = paymentFallbackFor(
179329
+ fetchContext.diagnostics
179330
+ );
179095
179331
  analyticsService.capture("fetch_error", {
179096
179332
  cliErrorClass: "network",
179097
179333
  fetchId: fetchContext.fetchId,
179098
179334
  failureStage: fetchContext.diagnostics?.failureStage,
179099
179335
  failureCode: fetchContext.diagnostics?.failureCode,
179100
179336
  paymentProtocol: fetchContext.diagnostics?.paymentProtocol,
179337
+ paymentFallbackFrom: paymentFallback2?.from,
179338
+ paymentFallbackTo: paymentFallback2?.to,
179339
+ paymentFallbackStage: paymentFallback2?.stage,
179340
+ paymentFallbackCode: paymentFallback2?.code,
179101
179341
  paymentMode: fetchContext.diagnostics?.paymentMode,
179102
179342
  fundingSource: fetchContext.diagnostics?.fundingSource,
179103
179343
  diagnosticCodes: fetchContext.diagnostics?.issues?.map(
@@ -179129,11 +179369,17 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179129
179369
  settlementState,
179130
179370
  diagnostics
179131
179371
  } = result;
179372
+ const paymentFallback = paymentFallbackFor(diagnostics);
179132
179373
  const isBinary = bodyEncoding === "base64";
179133
179374
  const bodyBytes = isBinary && bodyRaw ? Buffer.from(bodyRaw, "base64") : void 0;
179134
179375
  if (payment && payment.amount !== "unknown" && outcome !== "payment_close_failed") {
179135
179376
  log2(formatPaymentLine(payment));
179136
179377
  }
179378
+ if (paymentFallback && !options.json) {
179379
+ console.error(
179380
+ ` Payment fallback: ${paymentFallback.from} \u2192 ${paymentFallback.to} (${paymentFallback.stage}: ${paymentFallback.code})`
179381
+ );
179382
+ }
179137
179383
  if (payment?.session && outcome === "success") {
179138
179384
  const recipient = payment.session.recipient;
179139
179385
  const recipientLabel = recipient ? `\u2192 ${recipient.slice(0, 8)}...` : "\u2192 (unknown recipient)";
@@ -179192,6 +179438,13 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179192
179438
  `
179193
179439
  );
179194
179440
  }
179441
+ if (sdkWarnings?.includes(
179442
+ FETCH_WARNINGS.authorizationBearerDroppedByMpp
179443
+ ) && !options.json) {
179444
+ console.error(
179445
+ "\n WARNING: your `Authorization: Bearer` header did not reach the service: the MPP payment credential takes Authorization on the paid retry, and the 402 advertised no alternate header for the bearer. If the service accepts it elsewhere (its /.well-known/oauth-protected-resource or auth.md says where), send it in that header instead.\n"
179446
+ );
179447
+ }
179195
179448
  if (sdkWarnings?.length && outcome !== "payment_close_failed" && !options.json) {
179196
179449
  for (const w of sdkWarnings) {
179197
179450
  if (w === FETCH_WARNINGS.bodyTruncated) continue;
@@ -179210,10 +179463,9 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179210
179463
  matchedVia: capabilityResolution.matchedVia
179211
179464
  });
179212
179465
  } else {
179213
- runIsAttributed = false;
179214
179466
  if (walletAddress && !runId) {
179215
179467
  cliSkipReasons.push(
179216
- "no capability resolved \u2014 pass --capability <uid|slug|token> or run `zero search` first so the URL can be matched"
179468
+ "no run was recorded for this call \u2014 retry, or pass --capability <uid|slug|token> so the URL can be matched"
179217
179469
  );
179218
179470
  }
179219
179471
  analyticsService.capture("capability_resolution_missed", {
@@ -179236,6 +179488,10 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179236
179488
  failureStage: diagnostics?.failureStage,
179237
179489
  failureCode: diagnostics?.failureCode,
179238
179490
  paymentProtocol: diagnostics?.paymentProtocol,
179491
+ paymentFallbackFrom: paymentFallback?.from,
179492
+ paymentFallbackTo: paymentFallback?.to,
179493
+ paymentFallbackStage: paymentFallback?.stage,
179494
+ paymentFallbackCode: paymentFallback?.code,
179239
179495
  paymentMode: diagnostics?.paymentMode,
179240
179496
  fundingSource: diagnostics?.fundingSource,
179241
179497
  diagnosticCodes: diagnostics?.issues.map((issue3) => issue3.code),
@@ -179335,7 +179591,7 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179335
179591
  ...sdkWarnings?.length && { warnings: sdkWarnings }
179336
179592
  })
179337
179593
  );
179338
- } else if (runId && outcomeInfo.reviewable && runIsAttributed) {
179594
+ } else if (runId && outcomeInfo.reviewable) {
179339
179595
  const isTTY = process.stderr.isTTY;
179340
179596
  const responded2xx = status !== null && status >= 200 && status < 300;
179341
179597
  console.error(`
@@ -179375,12 +179631,6 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179375
179631
  } else {
179376
179632
  console.error(` zero review ${runId} --no-success`);
179377
179633
  }
179378
- } else if (runId && !runIsAttributed) {
179379
- console.error(`
179380
- Run ID: ${runId}`);
179381
- console.error(
179382
- ` This URL isn't an indexed capability, so the run can't be reviewed. Pass --capability <uid|slug> or run \`zero search\` first to bind it to one.`
179383
- );
179384
179634
  } else if (!runId && cliSkipReasons.length > 0) {
179385
179635
  console.error(
179386
179636
  `
@@ -180899,12 +181149,19 @@ var formatDetail = (r) => {
180899
181149
  lines.push(`Result: ${r.errorClass ?? "\u2014"}`);
180900
181150
  lines.push(`Reviewed: ${r.reviewed ? "yes" : "no"}`);
180901
181151
  lines.push("");
180902
- lines.push(`Capability: ${r.capability.name} (${r.capability.slug})`);
180903
- lines.push(`URL: ${r.capability.method} ${r.capability.url}`);
180904
- if (r.capability.whatItDoes)
180905
- lines.push(`What: ${r.capability.whatItDoes}`);
180906
- if (r.capability.tags.length > 0)
180907
- lines.push(`Tags: ${r.capability.tags.join(", ")}`);
181152
+ if (r.capability) {
181153
+ lines.push(`Capability: ${r.capability.name} (${r.capability.slug})`);
181154
+ lines.push(`URL: ${r.capability.method} ${r.capability.url}`);
181155
+ if (r.capability.whatItDoes)
181156
+ lines.push(`What: ${r.capability.whatItDoes}`);
181157
+ if (r.capability.tags.length > 0)
181158
+ lines.push(`Tags: ${r.capability.tags.join(", ")}`);
181159
+ } else {
181160
+ lines.push(`Capability: \u2014 (direct URL, not indexed)`);
181161
+ lines.push(
181162
+ `Target: ${[r.target?.method, r.target?.host, r.target?.pathTemplate].filter(Boolean).join(" ") || "\u2014"}`
181163
+ );
181164
+ }
180908
181165
  if (r.cost) {
180909
181166
  const { amount: amount2, asset } = r.cost;
180910
181167
  lines.push(`Cost: ${asset ? `${amount2} ${asset}` : amount2}`);
@@ -180921,7 +181178,9 @@ var runsDetailCommand = (appContext) => new Command("detail").description("Show
180921
181178
  const { json: json3 } = cmd.opts();
180922
181179
  try {
180923
181180
  const { client } = appContext.services;
180924
- const run = await client.runs.get(runId);
181181
+ const run = await client.runs.get(runId, {
181182
+ includeUnattributed: true
181183
+ });
180925
181184
  if (json3) {
180926
181185
  console.log(JSON.stringify(run, null, 2));
180927
181186
  return;
@@ -180963,6 +181222,10 @@ Examples:
180963
181222
  const result = await client.runs.list({
180964
181223
  capabilityId: options.capability,
180965
181224
  unreviewed: options.unreviewed,
181225
+ // ZERO-844 — direct-URL runs are reviewable, so they belong in
181226
+ // the list an agent sweeps before finishing a task. Always on
181227
+ // here; the flag exists for older SDK consumers, not for us.
181228
+ includeUnattributed: true,
180966
181229
  ...options.walletAddress ? { walletAddress: options.walletAddress } : {},
180967
181230
  limit: options.limit
180968
181231
  });
@@ -180981,8 +181244,9 @@ Examples:
180981
181244
  const latency = r.latencyMs != null ? `${r.latencyMs}ms` : "\u2014";
180982
181245
  const cost = formatCost2(r.cost);
180983
181246
  const payment = formatPayment(r.payment);
181247
+ const label = r.capabilitySlug ?? [r.requestMethod, r.requestHost, r.requestPathTemplate].filter(Boolean).join(" ") ?? "(direct URL)";
180984
181248
  console.log(
180985
- `[${mark2}] ${r.uid} ${r.capabilitySlug} status=${status} ${latency} ${cost} ${payment} ${when}`
181249
+ `[${mark2}] ${r.uid} ${label} status=${status} ${latency} ${cost} ${payment} ${when}`
180986
181250
  );
180987
181251
  }
180988
181252
  if (result.nextCursor) {
@@ -185993,6 +186257,10 @@ var mapSdkEventToCliEvent = (event) => {
185993
186257
  latencyMs: p.latency_ms,
185994
186258
  hasPayment: p.has_payment,
185995
186259
  paymentProtocol: orUndef(p.payment_protocol),
186260
+ paymentFallbackFrom: orUndef(p.payment_fallback_from),
186261
+ paymentFallbackTo: orUndef(p.payment_fallback_to),
186262
+ paymentFallbackStage: orUndef(p.payment_fallback_stage),
186263
+ paymentFallbackCode: orUndef(p.payment_fallback_code),
185996
186264
  fundingSource: orUndef(p.funding_source),
185997
186265
  paymentAmount: dropUnknownAmount(p.payment_amount),
185998
186266
  paymentChain: orUndef(p.payment_chain),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroxyz/cli",
3
- "version": "1.33.0",
3
+ "version": "1.34.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "zero": "dist/index.js",