@zeroxyz/cli 1.32.0 → 1.34.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.
Files changed (2) hide show
  1. package/dist/index.js +329 -66
  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-4H5K6DCA.js
93046
+ // ../sdk/dist/chunk-C5F7JW77.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.25.0"
166855
+ version: "0.27.0"
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);
@@ -167631,6 +167652,17 @@ var withSynthesizedX402Header = (baseFetch) => async (input, init) => {
167631
167652
  headers
167632
167653
  });
167633
167654
  };
167655
+ var readPaymentRejectionReason = (body) => {
167656
+ if (!body || typeof body !== "object" || Array.isArray(body)) return null;
167657
+ const b = body;
167658
+ const str = (v) => typeof v === "string" && v.trim().length > 0 ? v.trim() : null;
167659
+ const code = str(b.reason) ?? str(b.error);
167660
+ if (!code) return null;
167661
+ const outer = str(b.error);
167662
+ const label = outer && outer !== code ? `${code} (${outer})` : code;
167663
+ const detail = str(b.detail) ?? str(b.message) ?? str(b.hint);
167664
+ return detail ? `${label} \u2014 ${detail}` : label;
167665
+ };
167634
167666
  var USDC_BASE2 = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
167635
167667
  var USDC_BASE_SEPOLIA = "0x036cbd53842c5426634e7929541ec2318f3dcf7e";
167636
167668
  var UINT_RE = /^[0-9]+$/;
@@ -167902,7 +167934,11 @@ var FETCH_WARNINGS = Object.freeze({
167902
167934
  // Response body exceeded maxResponseBytes — bodyRaw / body / bodyEncoding
167903
167935
  // reflect the clipped prefix; consumers that wrote the body to disk got
167904
167936
  // a truncated file. Particularly bad for paid binary fetches.
167905
- 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"
167906
167942
  });
167907
167943
  var FETCH_SKIP_REASONS = Object.freeze({
167908
167944
  // The body was lost, but the capability executed (and may have charged) —
@@ -168109,6 +168145,7 @@ var Payments = class {
168109
168145
  let pendingAmountUnits = 0n;
168110
168146
  let identityChallengeHandled = false;
168111
168147
  let paidChallengeHandled = false;
168148
+ let positivePaymentReplayAttempted = false;
168112
168149
  let capturedNetwork;
168113
168150
  let capturedScheme = null;
168114
168151
  let capturedCeilingUnits = null;
@@ -168280,10 +168317,23 @@ var Payments = class {
168280
168317
  if (text) body = JSON.parse(text);
168281
168318
  } catch {
168282
168319
  }
168283
- return httpClient.getPaymentRequiredResponse(
168284
- (name) => challengeResponse.headers.get(name),
168285
- body
168286
- );
168320
+ try {
168321
+ return httpClient.getPaymentRequiredResponse(
168322
+ (name) => challengeResponse.headers.get(name),
168323
+ body
168324
+ );
168325
+ } catch (err) {
168326
+ const reason = readPaymentRejectionReason(body);
168327
+ if (!reason) throw err;
168328
+ input.diagnostics?.fail(
168329
+ "paid_replay",
168330
+ FETCH_DIAGNOSTIC_CODES.paymentRejected
168331
+ );
168332
+ throw new ZeroPaymentError(
168333
+ `the seller rejected the payment: ${reason}`,
168334
+ { cause: err }
168335
+ );
168336
+ }
168287
168337
  };
168288
168338
  let paymentRequired2 = await parseChallenge(response);
168289
168339
  const hookHeaders = await httpClient.handlePaymentRequired(paymentRequired2);
@@ -168329,6 +168379,9 @@ var Payments = class {
168329
168379
  "Access-Control-Expose-Headers",
168330
168380
  "PAYMENT-RESPONSE,X-PAYMENT-RESPONSE"
168331
168381
  );
168382
+ if (pendingAmountUnits > 0n) {
168383
+ positivePaymentReplayAttempted = true;
168384
+ }
168332
168385
  response = await measureDiagnostic(
168333
168386
  input.diagnostics,
168334
168387
  "paid_replay",
@@ -168365,11 +168418,14 @@ var Payments = class {
168365
168418
  FETCH_DIAGNOSTIC_CODES.paymentFailed
168366
168419
  );
168367
168420
  }
168368
- if (err instanceof ZeroError) throw err;
168369
- throw new ZeroPaymentError(
168421
+ if (err instanceof ZeroError) {
168422
+ throw !positivePaymentReplayAttempted && !isCallerAbortError(err) ? markPaymentNotAttempted(err) : err;
168423
+ }
168424
+ const paymentError = new ZeroPaymentError(
168370
168425
  `x402 payment failed: ${err instanceof Error ? err.message : String(err)}`,
168371
168426
  { cause: err }
168372
168427
  );
168428
+ throw !positivePaymentReplayAttempted && !isCallerAbortError(err) ? markPaymentNotAttempted(paymentError) : paymentError;
168373
168429
  }
168374
168430
  const isUpto = capturedScheme === "upto" && paidChallengeHandled;
168375
168431
  let txHash = null;
@@ -169181,6 +169237,38 @@ var Payments = class {
169181
169237
  };
169182
169238
  };
169183
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
+ };
169184
169272
  var isShortToken = (id) => id.startsWith("z_") && id.indexOf(".", 2) !== -1;
169185
169273
  var MAX_402_PROBE_BYTES = 1024 * 1024;
169186
169274
  var MAX_RESPONSE_BYTES = 10 * 1024 * 1024;
@@ -169312,9 +169400,27 @@ var detectPaymentRequirement = async (response, preferredProtocol) => {
169312
169400
  const scheme = challenge2.trim().split(/\s+/)[0]?.toLowerCase() ?? "";
169313
169401
  return MPP_SCHEME_TOKENS.has(scheme);
169314
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
+ };
169315
169418
  if (preferredProtocol === "mpp") {
169316
- cancelBody2(response);
169317
- 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());
169318
169424
  }
169319
169425
  const canSettleX402 = (raw) => {
169320
169426
  if (!raw || typeof raw !== "object") return false;
@@ -169327,47 +169433,71 @@ var detectPaymentRequirement = async (response, preferredProtocol) => {
169327
169433
  return selectSettleableX402Requirement(accepts, void 0, x402Version2) !== null;
169328
169434
  };
169329
169435
  const preferMppFallback = (raw) => preferredProtocol === void 0 && advertisesMpp && !canSettleX402(raw);
169330
- const selectedX402 = (raw) => ({
169436
+ const selectedX402 = (raw, alternateBearerHeader) => ({
169331
169437
  protocol: "x402",
169332
169438
  raw,
169333
- ...preferredProtocol === void 0 && advertisesMpp ? { fallbackProtocol: "mpp" } : {}
169439
+ ...preferredProtocol === void 0 && advertisesMpp ? {
169440
+ fallbackProtocol: "mpp",
169441
+ ...alternateBearerHeader ? { alternateBearerHeader } : {}
169442
+ } : {}
169334
169443
  });
169335
169444
  const x402Header = response.headers.get("payment-required") ?? response.headers.get("x-payment-required");
169336
169445
  if (x402Header) {
169337
- cancelBody2(response);
169446
+ let decoded;
169447
+ let decodable = true;
169338
169448
  try {
169339
- const decoded = JSON.parse(
169340
- Buffer.from(x402Header, "base64").toString("utf8")
169341
- );
169342
- if (preferMppFallback(decoded)) {
169343
- return { protocol: "mpp", raw: { "www-authenticate": wwwAuth } };
169344
- }
169345
- return selectedX402(decoded);
169449
+ decoded = JSON.parse(Buffer.from(x402Header, "base64").toString("utf8"));
169346
169450
  } catch {
169451
+ decodable = false;
169452
+ }
169453
+ if (!decodable) {
169347
169454
  if (preferredProtocol === void 0 && advertisesMpp) {
169348
- 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
+ );
169349
169462
  }
169463
+ cancelBody2(response);
169350
169464
  return selectedX402({ encoded: x402Header });
169351
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);
169352
169477
  }
169353
169478
  const declaredLen = Number.parseInt(
169354
169479
  response.headers.get("content-length") ?? "",
169355
169480
  10
169356
169481
  );
169357
169482
  const bodyFits = !Number.isFinite(declaredLen) || declaredLen <= MAX_402_PROBE_BYTES;
169483
+ let bodyBearerHint;
169358
169484
  if (bodyFits) {
169359
169485
  try {
169360
169486
  const text = await readClippedText(response, MAX_402_PROBE_BYTES);
169361
169487
  if (text) {
169362
169488
  const parsed = JSON.parse(text);
169489
+ bodyBearerHint = alternateBearerHeaderFromChallengeBody(parsed);
169363
169490
  if (looksLikeX402Body(parsed)) {
169364
169491
  if (preferMppFallback(parsed)) {
169365
- return {
169366
- protocol: "mpp",
169367
- raw: { "www-authenticate": wwwAuth }
169368
- };
169492
+ return mppRequirement(
169493
+ bodyBearerHint,
169494
+ x402Fallback(
169495
+ "rail_select",
169496
+ FETCH_DIAGNOSTIC_CODES.unsupportedPaymentRail
169497
+ )
169498
+ );
169369
169499
  }
169370
- return selectedX402(parsed);
169500
+ return selectedX402(parsed, bodyBearerHint);
169371
169501
  }
169372
169502
  }
169373
169503
  } catch {
@@ -169379,7 +169509,7 @@ var detectPaymentRequirement = async (response, preferredProtocol) => {
169379
169509
  }
169380
169510
  if (advertisesMpp) {
169381
169511
  cancelBody2(response);
169382
- return { protocol: "mpp", raw: { "www-authenticate": wwwAuth } };
169512
+ return mppRequirement(bodyBearerHint);
169383
169513
  }
169384
169514
  cancelBody2(response);
169385
169515
  return { protocol: "unknown", raw: {} };
@@ -169568,6 +169698,9 @@ var computeFixHint = (status, message2, bodyRaw) => {
169568
169698
  if (status === 415 || /content-?type|unsupported media|media type/.test(hay)) {
169569
169699
  return "set the Content-Type header to what the capability expects (usually application/json), then retry";
169570
169700
  }
169701
+ if ((status === 401 || status === 403) && /bearer|identity|unauthorized|credential|agent_auth/.test(hay)) {
169702
+ return 'the seller requires an agent identity credential \u2014 run `zero auth identity <host>` and resend with `-H "Authorization: Bearer <token>"`';
169703
+ }
169571
169704
  if (/required|missing|must (include|provide|have|contain)|is expected/.test(hay)) {
169572
169705
  const field = extractFieldName(message2 ?? "");
169573
169706
  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";
@@ -169668,6 +169801,7 @@ var recordErrorFetchRun = async (client, opts, result, diagnostics, capabilityId
169668
169801
  failureStage: diagnostics.snapshot().failureStage ?? void 0,
169669
169802
  failureCode: diagnostics.snapshot().failureCode ?? void 0,
169670
169803
  paymentProtocol: diagnostics.snapshot().paymentProtocol ?? void 0,
169804
+ paymentFallback: diagnostics.snapshot().paymentFallback ?? void 0,
169671
169805
  paymentMode: diagnostics.snapshot().paymentMode ?? void 0,
169672
169806
  fundingSource: diagnostics.snapshot().fundingSource ?? void 0,
169673
169807
  stageDurationsMs: diagnostics.snapshot().stageDurationsMs,
@@ -169850,17 +169984,28 @@ var clientFetch = async (client, url4, opts = {}, diagnostics) => {
169850
169984
  });
169851
169985
  if (requirement?.protocol === "x402" || requirement?.protocol === "mpp") {
169852
169986
  diagnostics.selectPaymentProtocol(requirement.protocol);
169987
+ if (requirement.paymentFallback) {
169988
+ diagnostics.recordPaymentFallback(requirement.paymentFallback);
169989
+ }
169853
169990
  const payCall = requirement.protocol === "x402" ? client.payments.pay : client.payments.payMpp;
169854
169991
  try {
169992
+ const paidLegHeaders = withDefaultUserAgent(
169993
+ withDefaultContentType(opts.headers, requestBody)
169994
+ );
169995
+ const mppLegHeaders = () => {
169996
+ const relocation = relocateBearerForMpp(
169997
+ paidLegHeaders,
169998
+ requirement.alternateBearerHeader
169999
+ );
170000
+ if (relocation.dropped) {
170001
+ warnings.push(FETCH_WARNINGS.authorizationBearerDroppedByMpp);
170002
+ }
170003
+ return relocation.headers;
170004
+ };
169855
170005
  const paymentInput = {
169856
170006
  url: requestUrl,
169857
170007
  method,
169858
- // Fresh clone for the paid retry — same rationale as
169859
- // the probe-side clone above. Re-derives the default
169860
- // Content-Type so the paid leg matches the probe.
169861
- headers: withDefaultUserAgent(
169862
- withDefaultContentType(opts.headers, requestBody)
169863
- ),
170008
+ headers: requirement.protocol === "mpp" ? mppLegHeaders() : paidLegHeaders,
169864
170009
  body: requestBody,
169865
170010
  maxPay: opts.maxPay,
169866
170011
  account: opts.account,
@@ -169882,13 +170027,31 @@ var clientFetch = async (client, url4, opts = {}, diagnostics) => {
169882
170027
  try {
169883
170028
  paid = await payCall(paymentInput);
169884
170029
  } catch (error98) {
169885
- if ((error98 instanceof ZeroInsufficientFundsError || error98 instanceof ZeroPermit2AllowanceError) && requirement.protocol === "x402" && requirement.fallbackProtocol === "mpp") {
169886
- diagnostics.issue(
169887
- error98 instanceof ZeroInsufficientFundsError ? "balance_check" : "paid_replay",
169888
- error98 instanceof ZeroInsufficientFundsError ? FETCH_DIAGNOSTIC_CODES.insufficientFunds : FETCH_DIAGNOSTIC_CODES.permit2AllowanceRequired
169889
- );
170030
+ if ((error98 instanceof ZeroInsufficientFundsError || error98 instanceof ZeroPermit2AllowanceError || isPaymentNotAttemptedError(error98)) && requirement.protocol === "x402" && requirement.fallbackProtocol === "mpp") {
170031
+ if (error98 instanceof ZeroInsufficientFundsError) {
170032
+ diagnostics.issue(
170033
+ "balance_check",
170034
+ FETCH_DIAGNOSTIC_CODES.insufficientFunds
170035
+ );
170036
+ } else if (error98 instanceof ZeroPermit2AllowanceError) {
170037
+ diagnostics.issue(
170038
+ "paid_replay",
170039
+ FETCH_DIAGNOSTIC_CODES.permit2AllowanceRequired
170040
+ );
170041
+ }
170042
+ const failedX402 = diagnostics.snapshot();
170043
+ diagnostics.recordPaymentFallback({
170044
+ from: "x402",
170045
+ to: "mpp",
170046
+ stage: error98 instanceof ZeroInsufficientFundsError ? "balance_check" : error98 instanceof ZeroPermit2AllowanceError ? "paid_replay" : failedX402.failureStage ?? "paid_replay",
170047
+ code: error98 instanceof ZeroInsufficientFundsError ? FETCH_DIAGNOSTIC_CODES.insufficientFunds : error98 instanceof ZeroPermit2AllowanceError ? FETCH_DIAGNOSTIC_CODES.permit2AllowanceRequired : failedX402.failureCode ?? FETCH_DIAGNOSTIC_CODES.paymentFailed
170048
+ });
170049
+ diagnostics.recoverFailureForFallback();
169890
170050
  diagnostics.selectPaymentProtocol("mpp");
169891
- paid = await client.payments.payMpp(paymentInput);
170051
+ paid = await client.payments.payMpp({
170052
+ ...paymentInput,
170053
+ headers: mppLegHeaders()
170054
+ });
169892
170055
  } else {
169893
170056
  throw error98;
169894
170057
  }
@@ -170214,6 +170377,7 @@ var clientFetch = async (client, url4, opts = {}, diagnostics) => {
170214
170377
  ),
170215
170378
  failureStage: diagnostics.snapshot().failureStage ?? void 0,
170216
170379
  failureCode: diagnostics.snapshot().failureCode ?? void 0,
170380
+ paymentFallback: diagnostics.snapshot().paymentFallback ?? void 0,
170217
170381
  fundingSource: diagnostics.snapshot().fundingSource ?? void 0,
170218
170382
  stageDurationsMs: diagnostics.snapshot().stageDurationsMs,
170219
170383
  warningCodes: warnings.length > 0 ? warnings : void 0,
@@ -170874,11 +171038,25 @@ var idJagMintResponseSchema = external_exports3.object({
170874
171038
  issuedTokenType: raw.issued_token_type ?? ID_JAG_TOKEN_TYPE,
170875
171039
  expiresIn: raw.expires_in ?? null
170876
171040
  }));
171041
+ var alternateBearerHeaderSchema = external_exports3.object({
171042
+ scheme: external_exports3.string().optional(),
171043
+ header: external_exports3.string(),
171044
+ use_when: external_exports3.string().optional()
171045
+ }).loose();
170877
171046
  var protectedResourceMetadataSchema = external_exports3.object({
170878
171047
  resource: external_exports3.string().optional(),
170879
171048
  resource_name: external_exports3.string().optional(),
170880
- authorization_servers: external_exports3.array(external_exports3.string()).optional()
171049
+ authorization_servers: external_exports3.array(external_exports3.string()).optional(),
171050
+ zeroclick_agent_authorization: alternateBearerHeaderSchema.optional()
170881
171051
  }).loose();
171052
+ var HEADER_NAME = /^[A-Za-z0-9-]+$/;
171053
+ var alternateBearerHeaderFrom = (advertised) => {
171054
+ if (!advertised) return null;
171055
+ if (advertised.scheme && advertised.scheme.toLowerCase() !== "bearer") {
171056
+ return null;
171057
+ }
171058
+ return HEADER_NAME.test(advertised.header) ? advertised.header : null;
171059
+ };
170882
171060
  var serviceAuthMetadataSchema = external_exports3.object({
170883
171061
  resource: external_exports3.string().optional(),
170884
171062
  resource_name: external_exports3.string().optional(),
@@ -170973,7 +171151,10 @@ var AuthIdentity = class {
170973
171151
  tokenEndpoint: metadata.token_endpoint ?? `${trimSlash(server)}/oauth2/token`,
170974
171152
  identityAssertionSupported: (agentAuth.identity_types_supported ?? []).includes(
170975
171153
  IDENTITY_ASSERTION_TYPE
170976
- ) && (assertionTypes ? assertionTypes.includes(ID_JAG_TOKEN_TYPE) : true)
171154
+ ) && (assertionTypes ? assertionTypes.includes(ID_JAG_TOKEN_TYPE) : true),
171155
+ alternateBearerHeader: alternateBearerHeaderFrom(
171156
+ prm.zeroclick_agent_authorization
171157
+ )
170977
171158
  };
170978
171159
  } catch (err) {
170979
171160
  lastError = err;
@@ -171629,14 +171810,30 @@ var paymentSessionSchema = external_exports3.object({
171629
171810
  recipient: external_exports3.string().regex(/^0x[0-9a-fA-F]{40}$/).nullable(),
171630
171811
  cumulativeAmount: external_exports3.string().regex(/^(?:0|[1-9]\d*)$/)
171631
171812
  }).strict();
171813
+ var paymentFallbackSchema = external_exports3.object({
171814
+ from: external_exports3.string(),
171815
+ to: external_exports3.string(),
171816
+ stage: external_exports3.string(),
171817
+ code: external_exports3.string()
171818
+ }).strict();
171632
171819
  var createRunResponseSchema = external_exports3.object({
171633
171820
  runId: external_exports3.string()
171634
171821
  });
171635
171822
  var runListItemSchema = external_exports3.object({
171636
171823
  uid: external_exports3.string(),
171637
- capabilityUid: external_exports3.string(),
171638
- capabilitySlug: external_exports3.string(),
171639
- capabilityName: external_exports3.string(),
171824
+ // ZERO-844 — null on an unattributed (direct-URL) run. Those are only
171825
+ // returned when the caller passes `includeUnattributed`, so a caller that
171826
+ // doesn't opt in never sees a null here.
171827
+ capabilityUid: external_exports3.string().nullable(),
171828
+ capabilitySlug: external_exports3.string().nullable(),
171829
+ capabilityName: external_exports3.string().nullable(),
171830
+ // The redacted unindexed target, populated only when there is no capability.
171831
+ // Older servers omit these; default rather than require so the SDK stays
171832
+ // forward- and backward-compatible.
171833
+ requestHost: external_exports3.string().nullable().optional().default(null),
171834
+ requestPathTemplate: external_exports3.string().nullable().optional().default(null),
171835
+ requestMethod: external_exports3.string().nullable().optional().default(null),
171836
+ attributed: external_exports3.boolean().optional().default(true),
171640
171837
  status: external_exports3.number().nullable(),
171641
171838
  latencyMs: external_exports3.number().nullable(),
171642
171839
  cost: external_exports3.object({ amount: external_exports3.string(), asset: external_exports3.string().nullable() }).nullable(),
@@ -171647,6 +171844,7 @@ var runListItemSchema = external_exports3.object({
171647
171844
  mode: external_exports3.string().nullable(),
171648
171845
  session: paymentSessionSchema.nullable().optional().default(null)
171649
171846
  }).nullable(),
171847
+ paymentFallback: paymentFallbackSchema.nullable().optional().default(null),
171650
171848
  createdAt: external_exports3.coerce.date(),
171651
171849
  reviewed: external_exports3.boolean()
171652
171850
  });
@@ -171668,6 +171866,9 @@ var runDetailSchema = external_exports3.object({
171668
171866
  mode: external_exports3.string().nullable(),
171669
171867
  session: paymentSessionSchema.nullable().optional().default(null)
171670
171868
  }).nullable(),
171869
+ paymentFallback: paymentFallbackSchema.nullable().optional().default(null),
171870
+ // ZERO-844 — null on an unattributed (direct-URL) run, which the server only
171871
+ // returns when `includeUnattributed` is passed.
171671
171872
  capability: external_exports3.object({
171672
171873
  uid: external_exports3.string(),
171673
171874
  slug: external_exports3.string(),
@@ -171676,7 +171877,14 @@ var runDetailSchema = external_exports3.object({
171676
171877
  method: external_exports3.string(),
171677
171878
  whatItDoes: external_exports3.string().nullable(),
171678
171879
  tags: external_exports3.array(external_exports3.string())
171679
- }),
171880
+ }).nullable(),
171881
+ // The redacted unindexed target — the counterpart to `capability` for a run
171882
+ // that has none. Exactly one of the two is non-null.
171883
+ target: external_exports3.object({
171884
+ host: external_exports3.string().nullable(),
171885
+ pathTemplate: external_exports3.string().nullable(),
171886
+ method: external_exports3.string().nullable()
171887
+ }).nullable().optional().default(null),
171680
171888
  reviewed: external_exports3.boolean()
171681
171889
  });
171682
171890
  var createReviewResponseSchema = external_exports3.object({
@@ -171722,6 +171930,8 @@ var Runs = class _Runs {
171722
171930
  * unattributed runs, which it can't do if we strip the target as well.
171723
171931
  */
171724
171932
  static FIELD_GENERATIONS = [
171933
+ // Structured trace of a safe payment-rail fallback.
171934
+ ["paymentFallback"],
171725
171935
  // MPP channel anchor for close-failure reconciliation. Peels first so a
171726
171936
  // newer SDK still records all prior diagnostics against an older API.
171727
171937
  ["paymentSession"],
@@ -171817,6 +172027,8 @@ var Runs = class _Runs {
171817
172027
  if (params2.capabilityId !== void 0)
171818
172028
  query.capabilityId = params2.capabilityId;
171819
172029
  if (params2.unreviewed !== void 0) query.unreviewed = params2.unreviewed;
172030
+ if (params2.includeUnattributed !== void 0)
172031
+ query.includeUnattributed = params2.includeUnattributed;
171820
172032
  if (params2.limit !== void 0) query.limit = params2.limit;
171821
172033
  if (params2.cursor !== void 0) query.cursor = params2.cursor;
171822
172034
  if (params2.walletAddress !== void 0) {
@@ -171838,6 +172050,8 @@ var Runs = class _Runs {
171838
172050
  {
171839
172051
  method: "GET",
171840
172052
  path: `/v1/runs/${runId}`,
172053
+ // ZERO-844 — without this an unattributed (direct-URL) run 404s.
172054
+ query: opts.includeUnattributed !== void 0 ? { includeUnattributed: opts.includeUnattributed } : {},
171841
172055
  signal: opts.signal
171842
172056
  },
171843
172057
  runDetailSchema
@@ -172347,6 +172561,10 @@ var AnalyticsEmitter = class {
172347
172561
  latency_ms: res.latencyMs,
172348
172562
  has_payment: res.payment !== null,
172349
172563
  payment_protocol: res.payment?.protocol ?? res.diagnostics?.paymentProtocol ?? null,
172564
+ payment_fallback_from: res.diagnostics?.paymentFallback?.from ?? null,
172565
+ payment_fallback_to: res.diagnostics?.paymentFallback?.to ?? null,
172566
+ payment_fallback_stage: res.diagnostics?.paymentFallback?.stage ?? null,
172567
+ payment_fallback_code: res.diagnostics?.paymentFallback?.code ?? null,
172350
172568
  funding_source: res.diagnostics?.fundingSource ?? null,
172351
172569
  payment_amount: res.payment?.amount ?? null,
172352
172570
  payment_chain: res.payment?.chain ?? null,
@@ -172387,6 +172605,10 @@ var AnalyticsEmitter = class {
172387
172605
  failure_stage: diagnostics?.failureStage ?? null,
172388
172606
  failure_code: diagnostics?.failureCode ?? null,
172389
172607
  payment_protocol: diagnostics?.paymentProtocol ?? null,
172608
+ payment_fallback_from: diagnostics?.paymentFallback?.from ?? null,
172609
+ payment_fallback_to: diagnostics?.paymentFallback?.to ?? null,
172610
+ payment_fallback_stage: diagnostics?.paymentFallback?.stage ?? null,
172611
+ payment_fallback_code: diagnostics?.paymentFallback?.code ?? null,
172390
172612
  payment_mode: diagnostics?.paymentMode ?? null,
172391
172613
  funding_source: diagnostics?.fundingSource ?? null,
172392
172614
  diagnostic_codes: diagnostics?.issues.map((issue3) => issue3.code) ?? [],
@@ -176637,7 +176859,7 @@ var placeholderFor = (fieldName, propSchema) => String(sampleValueFor(fieldName,
176637
176859
  // package.json
176638
176860
  var package_default2 = {
176639
176861
  name: "@zeroxyz/cli",
176640
- version: "1.32.0",
176862
+ version: "1.34.0",
176641
176863
  type: "module",
176642
176864
  bin: {
176643
176865
  zero: "dist/index.js",
@@ -177378,6 +177600,7 @@ var emitAccessToken = (accessToken, discovery, host, json3, reused) => {
177378
177600
  resource: discovery.resource,
177379
177601
  resourceName: discovery.resourceName,
177380
177602
  tokenEndpoint: discovery.tokenEndpoint,
177603
+ alternateBearerHeader: discovery.alternateBearerHeader,
177381
177604
  reused
177382
177605
  })}
177383
177606
  `
@@ -177389,6 +177612,11 @@ var emitAccessToken = (accessToken, discovery, host, json3, reused) => {
177389
177612
  `Signed in to ${discovery.resourceName ?? host} with your Zero identity.`,
177390
177613
  "The bearer token below is short-lived \u2014 use it right away:",
177391
177614
  ` zero fetch <url> -H "Authorization: Bearer <token>"`,
177615
+ ...discovery.alternateBearerHeader ? [
177616
+ "Paying over MPP (a 402 answered with a Payment credential)? The payment takes Authorization, so send the token as:",
177617
+ ` zero fetch <url> -H "${discovery.alternateBearerHeader}: Bearer <token>"`,
177618
+ "(zero fetch moves a Bearer Authorization there itself when the 402 advertises it.)"
177619
+ ] : [],
177392
177620
  `Re-run this command for a fresh token; it reuses the stored registration.`,
177393
177621
  ""
177394
177622
  ].join("\n")
@@ -178636,7 +178864,7 @@ Bulk bug-report complete: ${ok} ok, ${failed} failed`
178636
178864
  const [latest] = list2.runs;
178637
178865
  if (latest) {
178638
178866
  run = latest.uid;
178639
- capability = capability ?? latest.capabilityUid;
178867
+ capability = capability ?? latest.capabilityUid ?? void 0;
178640
178868
  }
178641
178869
  } catch {
178642
178870
  }
@@ -178740,6 +178968,7 @@ init_esm_shims();
178740
178968
  var MAX_INLINE_REQUEST_BODY_BYTES = 10 * 1024 * 1024;
178741
178969
  var MAX_FILE_REQUEST_BODY_BYTES = 500 * 1024 * 1024;
178742
178970
  var MAX_RESPONSE_BYTES2 = MAX_FILE_REQUEST_BODY_BYTES;
178971
+ var paymentFallbackFor = (diagnostics) => diagnostics?.paymentFallback ?? null;
178743
178972
  var formatPaymentLine = (payment) => {
178744
178973
  const base2 = `Paid ${payment.amount} ${payment.asset} via ${payment.protocol} on ${payment.chain}`;
178745
178974
  return payment.authorizedAmount && payment.authorizedAmount !== payment.amount ? `${base2} (authorized up to ${payment.authorizedAmount})` : base2;
@@ -178962,7 +179191,6 @@ var fetchCommand = (appContext) => new Command("fetch").description(
178962
179191
  let searchId;
178963
179192
  let displayCostAmount;
178964
179193
  let fetchOrigin;
178965
- let runIsAttributed = true;
178966
179194
  if (fromToken) {
178967
179195
  capabilityUid = capFromNoUrl?.uid ?? null;
178968
179196
  capabilityId = options.capability ?? "";
@@ -179065,12 +179293,19 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179065
179293
  } catch (err) {
179066
179294
  const message2 = err instanceof Error ? err.message : "Fetch failed";
179067
179295
  const fetchContext = fetchErrorContext(err);
179296
+ const paymentFallback2 = paymentFallbackFor(
179297
+ fetchContext.diagnostics
179298
+ );
179068
179299
  analyticsService.capture("fetch_error", {
179069
179300
  cliErrorClass: "network",
179070
179301
  fetchId: fetchContext.fetchId,
179071
179302
  failureStage: fetchContext.diagnostics?.failureStage,
179072
179303
  failureCode: fetchContext.diagnostics?.failureCode,
179073
179304
  paymentProtocol: fetchContext.diagnostics?.paymentProtocol,
179305
+ paymentFallbackFrom: paymentFallback2?.from,
179306
+ paymentFallbackTo: paymentFallback2?.to,
179307
+ paymentFallbackStage: paymentFallback2?.stage,
179308
+ paymentFallbackCode: paymentFallback2?.code,
179074
179309
  paymentMode: fetchContext.diagnostics?.paymentMode,
179075
179310
  fundingSource: fetchContext.diagnostics?.fundingSource,
179076
179311
  diagnosticCodes: fetchContext.diagnostics?.issues?.map(
@@ -179102,11 +179337,17 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179102
179337
  settlementState,
179103
179338
  diagnostics
179104
179339
  } = result;
179340
+ const paymentFallback = paymentFallbackFor(diagnostics);
179105
179341
  const isBinary = bodyEncoding === "base64";
179106
179342
  const bodyBytes = isBinary && bodyRaw ? Buffer.from(bodyRaw, "base64") : void 0;
179107
179343
  if (payment && payment.amount !== "unknown" && outcome !== "payment_close_failed") {
179108
179344
  log2(formatPaymentLine(payment));
179109
179345
  }
179346
+ if (paymentFallback && !options.json) {
179347
+ console.error(
179348
+ ` Payment fallback: ${paymentFallback.from} \u2192 ${paymentFallback.to} (${paymentFallback.stage}: ${paymentFallback.code})`
179349
+ );
179350
+ }
179110
179351
  if (payment?.session && outcome === "success") {
179111
179352
  const recipient = payment.session.recipient;
179112
179353
  const recipientLabel = recipient ? `\u2192 ${recipient.slice(0, 8)}...` : "\u2192 (unknown recipient)";
@@ -179165,6 +179406,13 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179165
179406
  `
179166
179407
  );
179167
179408
  }
179409
+ if (sdkWarnings?.includes(
179410
+ FETCH_WARNINGS.authorizationBearerDroppedByMpp
179411
+ ) && !options.json) {
179412
+ console.error(
179413
+ "\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"
179414
+ );
179415
+ }
179168
179416
  if (sdkWarnings?.length && outcome !== "payment_close_failed" && !options.json) {
179169
179417
  for (const w of sdkWarnings) {
179170
179418
  if (w === FETCH_WARNINGS.bodyTruncated) continue;
@@ -179183,10 +179431,9 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179183
179431
  matchedVia: capabilityResolution.matchedVia
179184
179432
  });
179185
179433
  } else {
179186
- runIsAttributed = false;
179187
179434
  if (walletAddress && !runId) {
179188
179435
  cliSkipReasons.push(
179189
- "no capability resolved \u2014 pass --capability <uid|slug|token> or run `zero search` first so the URL can be matched"
179436
+ "no run was recorded for this call \u2014 retry, or pass --capability <uid|slug|token> so the URL can be matched"
179190
179437
  );
179191
179438
  }
179192
179439
  analyticsService.capture("capability_resolution_missed", {
@@ -179209,6 +179456,10 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179209
179456
  failureStage: diagnostics?.failureStage,
179210
179457
  failureCode: diagnostics?.failureCode,
179211
179458
  paymentProtocol: diagnostics?.paymentProtocol,
179459
+ paymentFallbackFrom: paymentFallback?.from,
179460
+ paymentFallbackTo: paymentFallback?.to,
179461
+ paymentFallbackStage: paymentFallback?.stage,
179462
+ paymentFallbackCode: paymentFallback?.code,
179212
179463
  paymentMode: diagnostics?.paymentMode,
179213
179464
  fundingSource: diagnostics?.fundingSource,
179214
179465
  diagnosticCodes: diagnostics?.issues.map((issue3) => issue3.code),
@@ -179308,7 +179559,7 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179308
179559
  ...sdkWarnings?.length && { warnings: sdkWarnings }
179309
179560
  })
179310
179561
  );
179311
- } else if (runId && outcomeInfo.reviewable && runIsAttributed) {
179562
+ } else if (runId && outcomeInfo.reviewable) {
179312
179563
  const isTTY = process.stderr.isTTY;
179313
179564
  const responded2xx = status !== null && status >= 200 && status < 300;
179314
179565
  console.error(`
@@ -179348,12 +179599,6 @@ var fetchCommand = (appContext) => new Command("fetch").description(
179348
179599
  } else {
179349
179600
  console.error(` zero review ${runId} --no-success`);
179350
179601
  }
179351
- } else if (runId && !runIsAttributed) {
179352
- console.error(`
179353
- Run ID: ${runId}`);
179354
- console.error(
179355
- ` 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.`
179356
- );
179357
179602
  } else if (!runId && cliSkipReasons.length > 0) {
179358
179603
  console.error(
179359
179604
  `
@@ -180872,12 +181117,19 @@ var formatDetail = (r) => {
180872
181117
  lines.push(`Result: ${r.errorClass ?? "\u2014"}`);
180873
181118
  lines.push(`Reviewed: ${r.reviewed ? "yes" : "no"}`);
180874
181119
  lines.push("");
180875
- lines.push(`Capability: ${r.capability.name} (${r.capability.slug})`);
180876
- lines.push(`URL: ${r.capability.method} ${r.capability.url}`);
180877
- if (r.capability.whatItDoes)
180878
- lines.push(`What: ${r.capability.whatItDoes}`);
180879
- if (r.capability.tags.length > 0)
180880
- lines.push(`Tags: ${r.capability.tags.join(", ")}`);
181120
+ if (r.capability) {
181121
+ lines.push(`Capability: ${r.capability.name} (${r.capability.slug})`);
181122
+ lines.push(`URL: ${r.capability.method} ${r.capability.url}`);
181123
+ if (r.capability.whatItDoes)
181124
+ lines.push(`What: ${r.capability.whatItDoes}`);
181125
+ if (r.capability.tags.length > 0)
181126
+ lines.push(`Tags: ${r.capability.tags.join(", ")}`);
181127
+ } else {
181128
+ lines.push(`Capability: \u2014 (direct URL, not indexed)`);
181129
+ lines.push(
181130
+ `Target: ${[r.target?.method, r.target?.host, r.target?.pathTemplate].filter(Boolean).join(" ") || "\u2014"}`
181131
+ );
181132
+ }
180881
181133
  if (r.cost) {
180882
181134
  const { amount: amount2, asset } = r.cost;
180883
181135
  lines.push(`Cost: ${asset ? `${amount2} ${asset}` : amount2}`);
@@ -180894,7 +181146,9 @@ var runsDetailCommand = (appContext) => new Command("detail").description("Show
180894
181146
  const { json: json3 } = cmd.opts();
180895
181147
  try {
180896
181148
  const { client } = appContext.services;
180897
- const run = await client.runs.get(runId);
181149
+ const run = await client.runs.get(runId, {
181150
+ includeUnattributed: true
181151
+ });
180898
181152
  if (json3) {
180899
181153
  console.log(JSON.stringify(run, null, 2));
180900
181154
  return;
@@ -180936,6 +181190,10 @@ Examples:
180936
181190
  const result = await client.runs.list({
180937
181191
  capabilityId: options.capability,
180938
181192
  unreviewed: options.unreviewed,
181193
+ // ZERO-844 — direct-URL runs are reviewable, so they belong in
181194
+ // the list an agent sweeps before finishing a task. Always on
181195
+ // here; the flag exists for older SDK consumers, not for us.
181196
+ includeUnattributed: true,
180939
181197
  ...options.walletAddress ? { walletAddress: options.walletAddress } : {},
180940
181198
  limit: options.limit
180941
181199
  });
@@ -180954,8 +181212,9 @@ Examples:
180954
181212
  const latency = r.latencyMs != null ? `${r.latencyMs}ms` : "\u2014";
180955
181213
  const cost = formatCost2(r.cost);
180956
181214
  const payment = formatPayment(r.payment);
181215
+ const label = r.capabilitySlug ?? [r.requestMethod, r.requestHost, r.requestPathTemplate].filter(Boolean).join(" ") ?? "(direct URL)";
180957
181216
  console.log(
180958
- `[${mark2}] ${r.uid} ${r.capabilitySlug} status=${status} ${latency} ${cost} ${payment} ${when}`
181217
+ `[${mark2}] ${r.uid} ${label} status=${status} ${latency} ${cost} ${payment} ${when}`
180959
181218
  );
180960
181219
  }
180961
181220
  if (result.nextCursor) {
@@ -185966,6 +186225,10 @@ var mapSdkEventToCliEvent = (event) => {
185966
186225
  latencyMs: p.latency_ms,
185967
186226
  hasPayment: p.has_payment,
185968
186227
  paymentProtocol: orUndef(p.payment_protocol),
186228
+ paymentFallbackFrom: orUndef(p.payment_fallback_from),
186229
+ paymentFallbackTo: orUndef(p.payment_fallback_to),
186230
+ paymentFallbackStage: orUndef(p.payment_fallback_stage),
186231
+ paymentFallbackCode: orUndef(p.payment_fallback_code),
185969
186232
  fundingSource: orUndef(p.funding_source),
185970
186233
  paymentAmount: dropUnknownAmount(p.payment_amount),
185971
186234
  paymentChain: orUndef(p.payment_chain),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroxyz/cli",
3
- "version": "1.32.0",
3
+ "version": "1.34.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "zero": "dist/index.js",