@zeroxyz/cli 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +285 -33
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -76582,7 +76582,7 @@ init_esm_shims();
76582
76582
 
76583
76583
  // package.json
76584
76584
  var package_default = {
76585
- version: "1.1.0"};
76585
+ version: "1.3.0"};
76586
76586
 
76587
76587
  // src/app.ts
76588
76588
  init_esm_shims();
@@ -77578,7 +77578,7 @@ init_esm_shims();
77578
77578
  // ../sdk/dist/index.js
77579
77579
  init_esm_shims();
77580
77580
 
77581
- // ../sdk/dist/chunk-SE2M66VR.js
77581
+ // ../sdk/dist/chunk-RPL7VC32.js
77582
77582
  init_esm_shims();
77583
77583
 
77584
77584
  // ../../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
@@ -143021,6 +143021,16 @@ var ZeroPaymentError = class extends ZeroError {
143021
143021
  this.name = "ZeroPaymentError";
143022
143022
  }
143023
143023
  };
143024
+ var ZeroInsufficientFundsError = class extends ZeroError {
143025
+ have;
143026
+ need;
143027
+ constructor(message2, init) {
143028
+ super("insufficient_funds", message2, { cause: init.cause });
143029
+ this.name = "ZeroInsufficientFundsError";
143030
+ this.have = init.have;
143031
+ this.need = init.need;
143032
+ }
143033
+ };
143024
143034
  var ZeroSessionCloseFailedError = class extends ZeroError {
143025
143035
  session;
143026
143036
  response;
@@ -143361,7 +143371,12 @@ var FETCH_SKIP_REASONS = Object.freeze({
143361
143371
  bodyReadFailed: "body_read_failed",
143362
143372
  mppSessionCloseFailedNotRecorded: "mpp_session_close_failed_not_recorded",
143363
143373
  paidButStill402NotRecorded: FETCH_WARNINGS.paidButStill402NotRecorded,
143364
- paymentSettlementUnconfirmed: FETCH_WARNINGS.paymentSettlementUnconfirmed
143374
+ paymentSettlementUnconfirmed: FETCH_WARNINGS.paymentSettlementUnconfirmed,
143375
+ // Pre-sign abort: deliberately NOT recorded as a run — the wallet was
143376
+ // empty before we reached the capability, so charging it as a 402 would
143377
+ // corrupt cap reliability. The wallet funnel is tracked via the
143378
+ // fetch_executed.outcome analytics event instead.
143379
+ insufficientFunds: "insufficient_funds_not_recorded"
143365
143380
  });
143366
143381
  var MAX_RECEIPT_HEADER_BYTES = 8 * 1024;
143367
143382
  var decodeSessionReceiptHeader = (header) => {
@@ -143503,6 +143518,7 @@ var Payments = class {
143503
143518
  );
143504
143519
  let capturedAmount = null;
143505
143520
  let capturedNetwork;
143521
+ let preflightError = null;
143506
143522
  const x402 = registerExactEvmScheme(new x402Client(), { signer: account });
143507
143523
  x402.onBeforePaymentCreation(async (context) => {
143508
143524
  const selected = context.selectedRequirements;
@@ -143536,6 +143552,29 @@ var Payments = class {
143536
143552
  reason: `Payment of ${capturedAmount} USDC exceeds maxPay ${input.maxPay}`
143537
143553
  };
143538
143554
  }
143555
+ const detected = networkToChain(capturedNetwork);
143556
+ const balanceChain = detected === "base-sepolia" ? "base-sepolia" : "base";
143557
+ let balance = null;
143558
+ try {
143559
+ balance = await this.readUsdcBalance(account.address, balanceChain);
143560
+ } catch (readErr) {
143561
+ this.client.logger?.({
143562
+ level: "warn",
143563
+ message: "Pre-flight balance read failed; proceeding to attempt payment",
143564
+ meta: {
143565
+ chain: balanceChain,
143566
+ error: readErr instanceof Error ? readErr.message : String(readErr)
143567
+ }
143568
+ });
143569
+ }
143570
+ if (balance !== null && balance < rawAmountUnits) {
143571
+ const have = formatUnits(balance, 6);
143572
+ preflightError = new ZeroInsufficientFundsError(
143573
+ `wallet has ${have} USDC on Base, needs ${capturedAmount}.`,
143574
+ { have, need: capturedAmount }
143575
+ );
143576
+ return { abort: true, reason: preflightError.message };
143577
+ }
143539
143578
  });
143540
143579
  const configuredFetch = buildConfiguredFetch(this.client, {
143541
143580
  timeoutMs: input.timeoutMs
@@ -143556,6 +143595,7 @@ var Payments = class {
143556
143595
  signal: input.signal
143557
143596
  });
143558
143597
  } catch (err) {
143598
+ if (preflightError) throw preflightError;
143559
143599
  if (err instanceof ZeroError) throw err;
143560
143600
  throw new ZeroPaymentError(
143561
143601
  `x402 payment failed: ${err instanceof Error ? err.message : String(err)}`,
@@ -143800,23 +143840,29 @@ var Payments = class {
143800
143840
  );
143801
143841
  if (tempoBalance < requiredRaw) {
143802
143842
  if (coerced.chain === "tempo-testnet") {
143803
- throw new ZeroPaymentError(
143804
- `Insufficient pathUSD on Tempo testnet: have ${formatUnits(tempoBalance, 6)}, need ${capturedAmount}. Fund via the Tempo testnet faucet: https://docs.tempo.xyz/quickstart/faucet`
143843
+ const have = formatUnits(tempoBalance, 6);
143844
+ throw new ZeroInsufficientFundsError(
143845
+ `Insufficient pathUSD on Tempo testnet: have ${have}, need ${capturedAmount}. Fund via the Tempo testnet faucet: https://docs.tempo.xyz/quickstart/faucet`,
143846
+ { have, need: capturedAmount }
143805
143847
  );
143806
143848
  }
143807
- await this.bridgeBaseToTempo(account, requiredRaw - tempoBalance);
143849
+ await this.bridgeBaseToTempo(account, requiredRaw - tempoBalance, {
143850
+ isSessionDeposit: challenge2.intent === "session",
143851
+ depositTotal: capturedAmount
143852
+ });
143808
143853
  }
143809
143854
  return capturedAmount;
143810
143855
  };
143811
- bridgeBaseToTempo = async (account, requiredAmount) => {
143856
+ bridgeBaseToTempo = async (account, requiredAmount, depositContext) => {
143812
143857
  this.ensureRelayClient();
143813
143858
  const baseBalance = await this.readUsdcBalance(account.address, "base");
143814
143859
  const buffer3 = calculateBuffer(baseBalance);
143815
143860
  const bridgeAmount = requiredAmount + buffer3;
143816
143861
  if (baseBalance < bridgeAmount) {
143817
- throw new ZeroPaymentError(
143818
- `Insufficient Base USDC to bridge: have ${formatUnits(baseBalance, 6)}, need ${formatUnits(bridgeAmount, 6)} (${formatUnits(requiredAmount, 6)} + ${formatUnits(buffer3, 6)} buffer). This capability uses an MPP payment channel, which is pre-funded up front. Either fund your wallet on Base, or pass \`maxPay\` to size a smaller channel (e.g. \`maxPay: '0.05'\` for a ~5-cent channel sized for a single cheap call).`
143819
- );
143862
+ const have = formatUnits(baseBalance, 6);
143863
+ const need = formatUnits(bridgeAmount, 6);
143864
+ const message2 = depositContext?.isSessionDeposit ? `wallet has ${have} USDC on Base, but this capability pre-funds a ${depositContext.depositTotal} USDC MPP payment channel up front (the channel is deposited before the call, so it asks for more than a single charge). Needs ${need} on Base to open it \u2014 fund the wallet, or pass a smaller \`maxPay\` (e.g. '0.05') to size the channel down to one cheap call.` : `wallet has ${have} USDC on Base, needs ${need} to fund this capability's MPP payment channel (${formatUnits(requiredAmount, 6)} + ${formatUnits(buffer3, 6)} buffer). Tip: pass a smaller \`maxPay\` (e.g. '0.05') to size a cheaper channel.`;
143865
+ throw new ZeroInsufficientFundsError(message2, { have, need });
143820
143866
  }
143821
143867
  this.client.logger?.({
143822
143868
  level: "info",
@@ -144034,7 +144080,7 @@ var Payments = class {
144034
144080
  };
144035
144081
  };
144036
144082
  var package_default2 = {
144037
- version: "0.1.0"
144083
+ version: "0.4.0"
144038
144084
  };
144039
144085
  var SDK_VERSION2 = package_default2.version;
144040
144086
  var userWalletDtoSchema = external_exports3.object({
@@ -144999,7 +145045,7 @@ var Wallet = class {
144999
145045
  };
145000
145046
  };
145001
145047
  var DEFAULT_BASE_URL = "https://api.zero.xyz";
145002
- var DEFAULT_TIMEOUT_MS = 6e4;
145048
+ var DEFAULT_TIMEOUT_MS = 18e4;
145003
145049
  var DEFAULT_MAX_RETRIES = 2;
145004
145050
  var noopRefresh = async () => {
145005
145051
  };
@@ -145283,11 +145329,44 @@ var recordErrorFetchRun = async (client, opts, result) => {
145283
145329
  } catch {
145284
145330
  }
145285
145331
  };
145332
+ var recordTimeoutRun = async (client, opts, err, startedAt, capabilityIdRequested) => {
145333
+ const result = errorFetchResult(
145334
+ startedAt,
145335
+ err.message,
145336
+ "timeout",
145337
+ capabilityIdRequested,
145338
+ "network_error"
145339
+ );
145340
+ await recordErrorFetchRun(client, opts, result);
145341
+ };
145342
+ var sniffJsonShapeBytes = (buf) => {
145343
+ let i = 0;
145344
+ if (buf.length >= 3 && buf[0] === 239 && buf[1] === 187 && buf[2] === 191) {
145345
+ i = 3;
145346
+ }
145347
+ while (i < buf.length && (buf[i] === 32 || buf[i] === 9 || buf[i] === 10 || buf[i] === 13)) {
145348
+ i++;
145349
+ }
145350
+ if (i >= buf.length) return false;
145351
+ return buf[i] === 123 || buf[i] === 91;
145352
+ };
145353
+ var withDefaultContentType = (headers, body) => {
145354
+ if (!headers && body === void 0) return void 0;
145355
+ const next = headers ? { ...headers } : {};
145356
+ if (body === void 0) return next;
145357
+ const hasContentType = Object.keys(next).some(
145358
+ (k3) => k3.toLowerCase() === "content-type"
145359
+ );
145360
+ if (!hasContentType) {
145361
+ next["content-type"] = typeof body === "string" || sniffJsonShapeBytes(body) ? "application/json" : "application/octet-stream";
145362
+ }
145363
+ return next;
145364
+ };
145286
145365
  var clientFetch = async (client, url4, opts = {}) => {
145287
145366
  const startedAt = Date.now();
145288
145367
  const capabilityIdRequested = opts.capabilityId !== void 0;
145289
145368
  const method = opts.method ?? (opts.body !== void 0 ? "POST" : "GET");
145290
- const probeHeaders = opts.headers ? { ...opts.headers } : void 0;
145369
+ const probeHeaders = withDefaultContentType(opts.headers, opts.body);
145291
145370
  const requestInit = {
145292
145371
  method,
145293
145372
  headers: probeHeaders,
@@ -145304,6 +145383,16 @@ var clientFetch = async (client, url4, opts = {}) => {
145304
145383
  try {
145305
145384
  response = await configuredFetch(url4, requestInit);
145306
145385
  } catch (err) {
145386
+ if (err instanceof ZeroTimeoutError) {
145387
+ await recordTimeoutRun(
145388
+ client,
145389
+ opts,
145390
+ err,
145391
+ startedAt,
145392
+ capabilityIdRequested
145393
+ );
145394
+ throw err;
145395
+ }
145307
145396
  if (err instanceof ZeroError) throw err;
145308
145397
  const errMessage = err instanceof Error ? err.message : String(err);
145309
145398
  const result2 = errorFetchResult(
@@ -145325,8 +145414,9 @@ var clientFetch = async (client, url4, opts = {}) => {
145325
145414
  url: url4,
145326
145415
  method,
145327
145416
  // Fresh clone for the paid retry — same rationale as
145328
- // the probe-side clone above.
145329
- headers: opts.headers ? { ...opts.headers } : void 0,
145417
+ // the probe-side clone above. Re-derives the default
145418
+ // Content-Type so the paid leg matches the probe.
145419
+ headers: withDefaultContentType(opts.headers, opts.body),
145330
145420
  body: opts.body,
145331
145421
  maxPay: opts.maxPay,
145332
145422
  account: opts.account,
@@ -145351,6 +145441,15 @@ var clientFetch = async (client, url4, opts = {}) => {
145351
145441
  session: err.session
145352
145442
  };
145353
145443
  warnings.push(FETCH_WARNINGS.mppSessionCloseFailed);
145444
+ } else if (err instanceof ZeroInsufficientFundsError) {
145445
+ return errorFetchResult(
145446
+ startedAt,
145447
+ err.message,
145448
+ FETCH_SKIP_REASONS.insufficientFunds,
145449
+ capabilityIdRequested,
145450
+ "insufficient_funds",
145451
+ null
145452
+ );
145354
145453
  } else if (err instanceof ZeroPaymentError || err instanceof ZeroAuthError) {
145355
145454
  const result2 = errorFetchResult(
145356
145455
  startedAt,
@@ -145362,6 +145461,15 @@ var clientFetch = async (client, url4, opts = {}) => {
145362
145461
  );
145363
145462
  await recordErrorFetchRun(client, opts, result2);
145364
145463
  return result2;
145464
+ } else if (err instanceof ZeroTimeoutError) {
145465
+ await recordTimeoutRun(
145466
+ client,
145467
+ opts,
145468
+ err,
145469
+ startedAt,
145470
+ capabilityIdRequested
145471
+ );
145472
+ throw err;
145365
145473
  } else {
145366
145474
  throw err;
145367
145475
  }
@@ -145539,8 +145647,15 @@ var searchResultSchema = external_exports3.object({
145539
145647
  slug: external_exports3.string(),
145540
145648
  name: external_exports3.string(),
145541
145649
  canonicalName: external_exports3.string().nullable().optional(),
145650
+ brandName: external_exports3.string().nullable().optional(),
145542
145651
  description: external_exports3.string(),
145543
145652
  whatItDoes: external_exports3.string().nullable().optional(),
145653
+ // HTTP verb the capability expects. Surfaced on the search row so a caller
145654
+ // can tell GET from POST without a `capabilities.get()` round-trip — enough
145655
+ // to `fetch()` a no-body GET directly. POST bodies still need `get()` for
145656
+ // the `bodySchema`. Optional (not required) so a response that omits it —
145657
+ // an older API deploy — still parses rather than failing the whole search.
145658
+ method: external_exports3.string().optional(),
145544
145659
  url: external_exports3.string(),
145545
145660
  urlTemplate: external_exports3.string().nullable().optional(),
145546
145661
  cost: external_exports3.object({ amount: external_exports3.string(), asset: external_exports3.string() }),
@@ -146288,6 +146403,14 @@ var OUTCOMES = {
146288
146403
  errorClass: "payment_rejected",
146289
146404
  reviewable: false
146290
146405
  },
146406
+ // Wallet can't cover the call (pre-sign abort). A funding condition, not
146407
+ // a cap failure — the SDK records no run, so this is the only surviving
146408
+ // signal. Not reviewable (we never reached the capability).
146409
+ insufficient_funds: {
146410
+ exitCode: 1,
146411
+ errorClass: "insufficient_funds",
146412
+ reviewable: false
146413
+ },
146291
146414
  server_error: { exitCode: 0, errorClass: "upstream_4xx", reviewable: true }
146292
146415
  };
146293
146416
  var cliErrorClassFor = (outcome, status, walletAddress) => {
@@ -146367,7 +146490,7 @@ var fetchCommand = (appContext) => new Command("fetch").description(
146367
146490
  "Read the request body from stdin (equivalent to `-d @-`)."
146368
146491
  ).option("-H, --header <header...>", "Headers in Key:Value format").option("--max-pay <amount>", "Maximum per-call spend limit (USDC)").option(
146369
146492
  "--timeout <seconds>",
146370
- "Per-request timeout in seconds, overriding the default (60). Applies to each HTTP leg of the call (probe and paid retry), not as a wall-clock deadline."
146493
+ "Per-request timeout in seconds, overriding the default (180). Applies to each HTTP leg of the call (probe and paid retry), not as a wall-clock deadline."
146371
146494
  ).option(
146372
146495
  "--capability <id>",
146373
146496
  "Bind this fetch to a capability (uid or slug) so a reviewable run is recorded even without a prior `zero search`"
@@ -146704,6 +146827,16 @@ var fetchCommand = (appContext) => new Command("fetch").description(
146704
146827
  ` Payment failed: ${resultError ?? "could not complete payment"}`
146705
146828
  );
146706
146829
  if (legacyMigrateHint) console.error(` ${legacyMigrateHint}`);
146830
+ } else if (outcome === "insufficient_funds") {
146831
+ console.error(
146832
+ ` Insufficient funds: ${resultError ?? "wallet can't cover this call"}`
146833
+ );
146834
+ if (!resultError?.includes("faucet")) {
146835
+ console.error(
146836
+ " Top off your wallet with `zero wallet fund`, then retry."
146837
+ );
146838
+ }
146839
+ if (legacyMigrateHint) console.error(` ${legacyMigrateHint}`);
146707
146840
  } else if (outcome === "payment_rejected") {
146708
146841
  console.error(
146709
146842
  ` Upstream returned 402 after payment was sent \u2014 the seller's facilitator rejected the credential${messageSuffix}`
@@ -146858,29 +146991,140 @@ var formatRating = (rating) => {
146858
146991
  return `${successPct} success, ${reviews} reviews`;
146859
146992
  };
146860
146993
  var asNode = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : null;
146861
- var placeholderFor = (fieldName, propSchema) => {
146994
+ var schemaType = (node) => {
146995
+ const t = node?.type;
146996
+ if (typeof t === "string") return t;
146997
+ if (Array.isArray(t)) {
146998
+ const first = t.find((x2) => typeof x2 === "string" && x2 !== "null");
146999
+ return typeof first === "string" ? first : void 0;
147000
+ }
147001
+ return void 0;
147002
+ };
147003
+ var coerceToType = (value, type2) => {
147004
+ if (typeof value !== "string") return value;
147005
+ if (type2 === "number" || type2 === "integer") {
147006
+ const n = Number(value);
147007
+ return value.trim() !== "" && Number.isFinite(n) ? n : value;
147008
+ }
147009
+ if (type2 === "boolean") {
147010
+ if (value === "true") return true;
147011
+ if (value === "false") return false;
147012
+ }
147013
+ return value;
147014
+ };
147015
+ var sampleValueFor = (fieldName, propSchema) => {
146862
147016
  const node = asNode(propSchema);
147017
+ const type2 = schemaType(node);
146863
147018
  const example = node?.example ?? node?.default;
146864
- if (typeof example === "string") return example;
146865
- if (typeof example === "number" || typeof example === "boolean") {
146866
- return String(example);
147019
+ if (example !== void 0 && example !== null) {
147020
+ return coerceToType(example, type2);
147021
+ }
147022
+ switch (type2) {
147023
+ case "number":
147024
+ case "integer":
147025
+ return 0;
147026
+ case "boolean":
147027
+ return false;
147028
+ case "array":
147029
+ return [];
147030
+ case "object":
147031
+ return {};
147032
+ default:
147033
+ return `<${fieldName.toUpperCase()}>`;
146867
147034
  }
146868
- return `<${fieldName.toUpperCase()}>`;
146869
147035
  };
147036
+ var placeholderFor = (fieldName, propSchema) => String(sampleValueFor(fieldName, propSchema));
146870
147037
  var extractInputEnvelope = (bodySchema, method) => {
146871
- if (!bodySchema) return {};
146872
- const props = asNode(bodySchema.properties);
147038
+ const root = asNode(bodySchema);
147039
+ if (!root) return {};
147040
+ const props = asNode(root.properties);
146873
147041
  if (!props) return {};
146874
147042
  const inputProps = asNode(asNode(props.input)?.properties);
146875
147043
  if (inputProps) {
146876
147044
  return {
146877
- queryParams: asNode(asNode(inputProps.queryParams)?.properties) ?? void 0,
146878
- body: asNode(asNode(inputProps.body)?.properties) ?? void 0
147045
+ queryParams: asNode(inputProps.queryParams) ?? void 0,
147046
+ body: asNode(inputProps.body) ?? void 0
146879
147047
  };
146880
147048
  }
146881
147049
  const upperMethod = method.toUpperCase();
146882
147050
  const isGetLike = upperMethod === "GET" || upperMethod === "DELETE";
146883
- return isGetLike ? { queryParams: props } : { body: props };
147051
+ return isGetLike ? { queryParams: root } : { body: root };
147052
+ };
147053
+ var schemaTypeLabel = (node) => {
147054
+ const t = node.type;
147055
+ if (typeof t === "string") return t;
147056
+ if (Array.isArray(t)) {
147057
+ const parts = t.filter((x2) => typeof x2 === "string");
147058
+ return parts.length > 0 ? parts.join(" | ") : "any";
147059
+ }
147060
+ return "any";
147061
+ };
147062
+ var constraintHint = (node) => {
147063
+ const num2 = (k3) => typeof node[k3] === "number" ? node[k3] : void 0;
147064
+ const min = num2("minimum");
147065
+ const max = num2("maximum");
147066
+ if (min !== void 0 && max !== void 0) return `range: ${min}..${max}`;
147067
+ if (min !== void 0) return `min: ${min}`;
147068
+ if (max !== void 0) return `max: ${max}`;
147069
+ const minLen = num2("minLength");
147070
+ const maxLen = num2("maxLength");
147071
+ if (minLen !== void 0 && maxLen !== void 0)
147072
+ return `length: ${minLen}..${maxLen}`;
147073
+ if (maxLen !== void 0) return `maxLength: ${maxLen}`;
147074
+ if (minLen !== void 0) return `minLength: ${minLen}`;
147075
+ return null;
147076
+ };
147077
+ var renderParam = (name, propSchema, required3) => {
147078
+ const node = asNode(propSchema) ?? {};
147079
+ const attrs = [schemaTypeLabel(node)];
147080
+ if (required3) attrs.push("required");
147081
+ if (node.default !== void 0)
147082
+ attrs.push(`default: ${JSON.stringify(node.default)}`);
147083
+ if (Array.isArray(node.enum))
147084
+ attrs.push(`one of: ${node.enum.map((v) => String(v)).join(" | ")}`);
147085
+ const hint = constraintHint(node);
147086
+ if (hint) attrs.push(hint);
147087
+ const lines = [` ${name} (${attrs.join(", ")})`];
147088
+ const desc = typeof node.description === "string" ? node.description.trim() : "";
147089
+ if (desc) lines.push(` ${desc}`);
147090
+ return lines;
147091
+ };
147092
+ var renderProps = (node) => {
147093
+ const props = node ? asNode(node.properties) : null;
147094
+ if (!props) return [];
147095
+ const entries = Object.entries(props);
147096
+ if (entries.length === 0) return [];
147097
+ const requiredSet = new Set(
147098
+ Array.isArray(node?.required) ? node.required.filter((x2) => typeof x2 === "string") : []
147099
+ );
147100
+ return entries.flatMap(
147101
+ ([name, schema]) => renderParam(name, schema, requiredSet.has(name))
147102
+ );
147103
+ };
147104
+ var buildSchemaSection = (capability) => {
147105
+ const { queryParams, body } = extractInputEnvelope(
147106
+ capability.bodySchema,
147107
+ capability.method
147108
+ );
147109
+ return [...renderProps(queryParams), ...renderProps(body)];
147110
+ };
147111
+ var buildResponseSection = (capability) => {
147112
+ const rs = asNode(capability.responseSchema);
147113
+ if (!rs) return [];
147114
+ if (rs.example !== void 0) {
147115
+ const example = JSON.stringify(rs.example);
147116
+ const truncated = example.length > 300 ? `${example.slice(0, 300)}\u2026` : example;
147117
+ return [" Returns (example):", ` ${truncated}`];
147118
+ }
147119
+ const props = asNode(rs.properties);
147120
+ if (props) {
147121
+ const fields = Object.entries(props).map(
147122
+ ([k3, v]) => `${k3}: ${schemaTypeLabel(asNode(v) ?? {})}`
147123
+ );
147124
+ if (fields.length > 0)
147125
+ return [" Returns:", ` { ${fields.join(", ")} }`];
147126
+ }
147127
+ return [];
146884
147128
  };
146885
147129
  var buildTryItExample = (capability) => {
146886
147130
  const method = capability.method.toUpperCase();
@@ -146894,7 +147138,8 @@ var buildTryItExample = (capability) => {
146894
147138
  ([k3, v]) => `-H "${k3}: ${v}" # [caller-provided]`
146895
147139
  );
146896
147140
  if (method === "GET" || queryParams && !body) {
146897
- const qs = queryParams ? Object.entries(queryParams).map(
147141
+ const qpProps = queryParams ? asNode(queryParams.properties) : null;
147142
+ const qs = qpProps ? Object.entries(qpProps).map(
146898
147143
  ([k3, schema]) => `${encodeURIComponent(k3)}=${encodeURIComponent(placeholderFor(k3, schema))}`
146899
147144
  ).join("&") : "";
146900
147145
  const url4 = qs ? `${capability.url}?${qs}` : capability.url;
@@ -146908,15 +147153,16 @@ var buildTryItExample = (capability) => {
146908
147153
  }
146909
147154
  if (!queryParams && method === "GET") {
146910
147155
  lines.push(
146911
- " # bodySchema did not expose queryParams \u2014 call the URL as-is or inspect the raw schema above."
147156
+ " # bodySchema did not expose queryParams \u2014 call the URL as-is."
146912
147157
  );
146913
147158
  }
146914
147159
  return lines;
146915
147160
  }
146916
- const samplePayload = body ? Object.fromEntries(
146917
- Object.entries(body).map(([k3, schema]) => [
147161
+ const bodyProps = body ? asNode(body.properties) : null;
147162
+ const samplePayload = bodyProps ? Object.fromEntries(
147163
+ Object.entries(bodyProps).map(([k3, schema]) => [
146918
147164
  k3,
146919
- placeholderFor(k3, schema)
147165
+ sampleValueFor(k3, schema)
146920
147166
  ])
146921
147167
  ) : null;
146922
147168
  const bodyJson = samplePayload ? JSON.stringify(samplePayload) : "<BODY_JSON>";
@@ -146924,9 +147170,9 @@ var buildTryItExample = (capability) => {
146924
147170
  if (method !== "POST") lines.push(` -X ${method} \\`);
146925
147171
  for (const h2 of headerFlags) lines.push(` ${h2} \\`);
146926
147172
  lines.push(` -d '${bodyJson}'`);
146927
- if (!body) {
147173
+ if (!bodyProps) {
146928
147174
  lines.push(
146929
- " # bodySchema did not expose input.body \u2014 replace <BODY_JSON> with the exact shape shown above."
147175
+ " # bodySchema did not expose input.body \u2014 replace <BODY_JSON> with the documented request shape."
146930
147176
  );
146931
147177
  }
146932
147178
  return lines;
@@ -146948,6 +147194,12 @@ var formatCapability = (capability) => {
146948
147194
  lines.push(` ${promptLine}`);
146949
147195
  }
146950
147196
  }
147197
+ const schemaLines = buildSchemaSection(capability);
147198
+ if (schemaLines.length > 0) {
147199
+ lines.push("", "Parameters:");
147200
+ lines.push(...schemaLines);
147201
+ }
147202
+ lines.push(...buildResponseSection(capability));
146951
147203
  lines.push(...buildTryItExample(capability));
146952
147204
  return lines.join("\n");
146953
147205
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroxyz/cli",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "zero": "dist/index.js",