@zeroxyz/cli 1.15.0 → 1.16.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 +441 -342
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -78449,7 +78449,7 @@ init_esm_shims();
78449
78449
  // ../sdk/dist/index.js
78450
78450
  init_esm_shims();
78451
78451
 
78452
- // ../sdk/dist/chunk-EIQP6VGZ.js
78452
+ // ../sdk/dist/chunk-A7WZYQXS.js
78453
78453
  init_esm_shims();
78454
78454
 
78455
78455
  // ../../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
@@ -143831,7 +143831,7 @@ config(en_default2());
143831
143831
  // ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/index.js
143832
143832
  var zod_default = external_exports3;
143833
143833
 
143834
- // ../sdk/dist/chunk-EIQP6VGZ.js
143834
+ // ../sdk/dist/chunk-A7WZYQXS.js
143835
143835
  var createManagedAccount = (client, address2) => toAccount({
143836
143836
  address: address2,
143837
143837
  async signMessage({ message: message2 }) {
@@ -143910,6 +143910,25 @@ var ZeroAuthError = class extends ZeroError {
143910
143910
  this.name = "ZeroAuthError";
143911
143911
  }
143912
143912
  };
143913
+ var ZeroAgentAuthError = class extends ZeroError {
143914
+ status;
143915
+ body;
143916
+ constructor(message2, init) {
143917
+ super("auth_error", message2, { cause: init.cause });
143918
+ this.name = "ZeroAgentAuthError";
143919
+ this.status = init.status;
143920
+ this.body = init.body;
143921
+ }
143922
+ // The error code the SERVER sent, distinct from ZeroError's `code`
143923
+ // discriminator. WorkOS error bodies carry {code, message}; OAuth-style
143924
+ // ones carry {error}.
143925
+ get serverCode() {
143926
+ const body = this.body;
143927
+ if (typeof body?.code === "string") return body.code;
143928
+ if (typeof body?.error === "string") return body.error;
143929
+ return null;
143930
+ }
143931
+ };
143913
143932
  var ZeroPaymentError = class extends ZeroError {
143914
143933
  constructor(message2, options) {
143915
143934
  super("payment_error", message2, options);
@@ -145267,16 +145286,89 @@ var extractUpstreamErrorMessage = (body) => {
145267
145286
  }
145268
145287
  return void 0;
145269
145288
  };
145289
+ var extractFieldName = (message2) => {
145290
+ const patterns = [
145291
+ /(?:field|param(?:eter)?|property|key)[:\s]+["'`]?([a-z0-9_.[\]-]+)["'`]?/i,
145292
+ /["'`]([a-z0-9_.[\]-]+)["'`]\s*(?:is\s+)?(?:required|missing|expected)/i,
145293
+ // Quotes REQUIRED here — an unquoted token after "required"/"missing"
145294
+ // is usually a generic noun ("required parameters", "missing fields"),
145295
+ // not a field name. Only trust it when the seller quoted it.
145296
+ /(?:required|missing|expected)[:\s]+["'`]([a-z0-9_.[\]-]+)["'`]/i
145297
+ ];
145298
+ for (const p of patterns) {
145299
+ const match = message2.match(p);
145300
+ if (match?.[1]) return match[1];
145301
+ }
145302
+ return void 0;
145303
+ };
145304
+ var extractAllowedMethod = (text) => {
145305
+ const listed = text.match(
145306
+ /allowed[^[]*\[\s*["'`]?(GET|POST|PUT|PATCH|DELETE|HEAD)/i
145307
+ );
145308
+ if (listed?.[1]) return listed[1].toUpperCase();
145309
+ const useVerb = text.match(/\buse\s+(GET|POST|PUT|PATCH|DELETE|HEAD)\b/i);
145310
+ if (useVerb?.[1]) return useVerb[1].toUpperCase();
145311
+ return void 0;
145312
+ };
145313
+ var extractUnrecognizedKeys = (bodyRaw) => {
145314
+ if (!bodyRaw) return [];
145315
+ const parsed = tryParseJson(bodyRaw);
145316
+ if (parsed === null || typeof parsed !== "object") return [];
145317
+ const out = [];
145318
+ const visit = (node) => {
145319
+ if (!node || typeof node !== "object") return;
145320
+ const o = node;
145321
+ if (Array.isArray(o.keys)) {
145322
+ for (const k of o.keys) if (typeof k === "string") out.push(k);
145323
+ }
145324
+ for (const v of Object.values(o)) {
145325
+ if (Array.isArray(v)) v.forEach(visit);
145326
+ else if (v && typeof v === "object") visit(v);
145327
+ }
145328
+ };
145329
+ visit(parsed);
145330
+ return [...new Set(out)].slice(0, 8);
145331
+ };
145332
+ var computeFixHint = (status, message2, bodyRaw) => {
145333
+ if (status < 400 || status >= 500) return void 0;
145334
+ const hay = `${message2 ?? ""} ${bodyRaw ?? ""}`.toLowerCase();
145335
+ if (status === 405 || /method not allowed|method_not_allowed/.test(hay)) {
145336
+ const allowed = extractAllowedMethod(`${bodyRaw ?? ""} ${message2 ?? ""}`);
145337
+ 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";
145338
+ }
145339
+ if (/invalid json|not valid json|malformed|unexpected token|json ?parse|could not parse|failed to parse|jsondecode/.test(
145340
+ hay
145341
+ )) {
145342
+ return "the request body isn't valid JSON \u2014 check quoting/escaping (single-quote the -d value or use @file), then retry";
145343
+ }
145344
+ if (/unrecognized[_ ]?key|unexpected key|unknown (field|key|propert)|additional (?:propert|field)|not allowed in object/.test(
145345
+ hay
145346
+ )) {
145347
+ const keys = extractUnrecognizedKeys(bodyRaw ?? null);
145348
+ return keys.length ? `remove the unexpected field(s) ${keys.map((k) => `'${k}'`).join(", ")} from the request body, then retry` : "the request body has fields the capability doesn't accept \u2014 send only the documented fields, then retry";
145349
+ }
145350
+ if (status === 415 || /content-?type|unsupported media|media type/.test(hay)) {
145351
+ return "set the Content-Type header to what the capability expects (usually application/json), then retry";
145352
+ }
145353
+ if (/required|missing|must (include|provide|have|contain)|is expected/.test(hay)) {
145354
+ const field = extractFieldName(message2 ?? "");
145355
+ 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";
145356
+ }
145357
+ return void 0;
145358
+ };
145270
145359
  var buildUpstreamError = (status, bodyRaw, bodyEncoding) => {
145271
145360
  if (status >= 200 && status < 300) return void 0;
145272
145361
  if (bodyRaw === null || bodyRaw.length === 0) return void 0;
145273
145362
  if (bodyEncoding === "base64") return void 0;
145274
145363
  const snippet = bodyRaw.slice(0, ERROR_SNIPPET_BYTES);
145364
+ const message2 = extractUpstreamErrorMessage(bodyRaw);
145365
+ const fixHint = computeFixHint(status, message2, bodyRaw);
145275
145366
  return {
145276
145367
  status,
145277
- message: extractUpstreamErrorMessage(bodyRaw),
145368
+ message: message2,
145278
145369
  snippetHash: createHash("sha256").update(snippet).digest("hex"),
145279
- snippetLength: snippet.length
145370
+ snippetLength: snippet.length,
145371
+ ...fixHint && { fixHint }
145280
145372
  };
145281
145373
  };
145282
145374
  var computeOutcome = (status, payment, warnings) => {
@@ -145665,74 +145757,63 @@ var clientFetch = async (client, url4, opts = {}) => {
145665
145757
  return result;
145666
145758
  };
145667
145759
  var package_default = {
145668
- version: "0.9.0"
145760
+ version: "0.10.0"
145669
145761
  };
145670
145762
  var SDK_VERSION2 = package_default.version;
145671
- var userWalletDtoSchema = external_exports3.object({
145672
- walletAddress: external_exports3.string(),
145673
- source: external_exports3.enum(["self_custody", "privy_embedded"]),
145674
- isPrimary: external_exports3.boolean(),
145675
- linkedAt: external_exports3.union([external_exports3.string(), external_exports3.date()]).nullable().optional(),
145676
- delegationGranted: external_exports3.boolean(),
145677
- signerQuorumId: external_exports3.string().nullable(),
145678
- // Per-transaction USDC cap in base units (6 dp). null = unlimited, 0 = free-only.
145679
- maxTransactionUsdcBaseUnits: external_exports3.number().int().nullable()
145680
- });
145681
- var welcomeBonusSummarySchema = external_exports3.object({
145682
- status: external_exports3.string(),
145683
- amountUsd: external_exports3.number()
145684
- });
145685
- var internalUserDtoSchema = external_exports3.object({
145763
+ var agentAuthMetadataSchema = external_exports3.object({
145764
+ token_endpoint: external_exports3.string().optional(),
145765
+ agent_auth: external_exports3.object({
145766
+ identity_endpoint: external_exports3.string(),
145767
+ claim_endpoint: external_exports3.string().optional()
145768
+ }).loose()
145769
+ }).loose();
145770
+ var identityEnvelopeSchema = external_exports3.object({
145686
145771
  id: external_exports3.string(),
145687
- email: external_exports3.string().nullable(),
145688
- createdAt: external_exports3.union([external_exports3.string(), external_exports3.date()]).optional(),
145689
- lastLoginAt: external_exports3.union([external_exports3.string(), external_exports3.date()]).nullable().optional(),
145690
- onboardingCompleted: external_exports3.boolean().optional(),
145691
- delegationGranted: external_exports3.boolean().optional(),
145692
- wallets: external_exports3.array(userWalletDtoSchema).optional(),
145693
- balance: external_exports3.object({ amount: external_exports3.string(), asset: external_exports3.string() }).nullable().optional(),
145694
- welcomeBonus: welcomeBonusSummarySchema.nullable().optional()
145695
- });
145696
- var publicUserDtoSchema = external_exports3.object({
145697
- user: external_exports3.object({
145698
- id: external_exports3.string(),
145699
- email: external_exports3.string().nullable()
145700
- }),
145701
- walletAddress: external_exports3.string().nullable(),
145702
- balance: external_exports3.object({ amount: external_exports3.string(), asset: external_exports3.string() }).nullable(),
145703
- welcomeBonus: welcomeBonusSummarySchema.nullable()
145704
- });
145705
- var signResponseSchema = external_exports3.object({
145706
- signature: external_exports3.string().regex(/^0x[0-9a-fA-F]+$/, "must be 0x-prefixed hex"),
145707
- walletAddress: external_exports3.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be 0x-prefixed 40-char hex address")
145708
- });
145709
- var deviceStartResponseSchema = external_exports3.object({
145710
- deviceCode: external_exports3.string(),
145711
- userCode: external_exports3.string(),
145712
- verificationUri: external_exports3.string(),
145713
- pollInterval: external_exports3.number(),
145714
- expiresAt: external_exports3.number()
145715
- });
145716
- var devicePollResponseSchema = external_exports3.union([
145717
- // userCode + verificationUri are optional: older API deployments don't
145718
- // echo them on pending.
145719
- external_exports3.object({
145720
- error: external_exports3.literal("authorization_pending"),
145721
- userCode: external_exports3.string().optional(),
145722
- verificationUri: external_exports3.string().optional()
145723
- }),
145724
- external_exports3.object({ error: external_exports3.literal("expired_token") }),
145725
- external_exports3.object({
145726
- accessToken: external_exports3.string(),
145727
- refreshToken: external_exports3.string(),
145728
- expiresIn: external_exports3.number(),
145729
- user: internalUserDtoSchema
145730
- })
145731
- ]);
145732
- var sessionExchangeResponseSchema = external_exports3.object({
145733
- token: external_exports3.string(),
145734
- expiresAt: external_exports3.number()
145735
- });
145772
+ identity: external_exports3.object({
145773
+ assertion: external_exports3.string(),
145774
+ expires_at: external_exports3.string().optional(),
145775
+ refresh_token: external_exports3.object({ value: external_exports3.string() }).loose().optional()
145776
+ }).loose(),
145777
+ claim: external_exports3.object({
145778
+ token: external_exports3.string().optional(),
145779
+ expires_at: external_exports3.string().optional()
145780
+ }).loose().optional()
145781
+ }).loose().transform((raw) => ({
145782
+ registrationId: raw.id,
145783
+ identityAssertion: raw.identity.assertion,
145784
+ assertionExpires: raw.identity.expires_at ?? null,
145785
+ refreshToken: raw.identity.refresh_token?.value ?? null,
145786
+ claimToken: raw.claim?.token ?? null,
145787
+ claimTokenExpires: raw.claim?.expires_at ?? null
145788
+ }));
145789
+ var agentTokenResponseSchema = external_exports3.object({ access_token: external_exports3.string() }).loose().transform((raw) => ({ accessToken: raw.access_token }));
145790
+ var startClaimResponseSchema = external_exports3.object({
145791
+ attempt: external_exports3.object({
145792
+ verification_uri: external_exports3.string(),
145793
+ expires_at: external_exports3.string().optional()
145794
+ }).loose()
145795
+ }).loose().transform((raw) => ({
145796
+ verificationUri: raw.attempt.verification_uri,
145797
+ expiresAt: raw.attempt.expires_at ?? null
145798
+ }));
145799
+ var completeClaimResponseSchema = external_exports3.object({
145800
+ identity: external_exports3.object({
145801
+ assertion: external_exports3.string(),
145802
+ expires_at: external_exports3.string().optional(),
145803
+ refresh_token: external_exports3.object({ value: external_exports3.string() }).loose().optional()
145804
+ }).loose()
145805
+ }).loose().transform((raw) => ({
145806
+ identityAssertion: raw.identity.assertion,
145807
+ assertionExpires: raw.identity.expires_at ?? null,
145808
+ refreshToken: raw.identity.refresh_token?.value ?? null
145809
+ }));
145810
+ var agentZeroSessionSchema = external_exports3.object({
145811
+ accessToken: external_exports3.string(),
145812
+ refreshToken: external_exports3.string(),
145813
+ expiresIn: external_exports3.number(),
145814
+ user: external_exports3.object({ id: external_exports3.string() }).loose(),
145815
+ walletAddress: external_exports3.string().optional()
145816
+ }).loose();
145736
145817
  var refreshResponseSchema = external_exports3.object({
145737
145818
  accessToken: external_exports3.string(),
145738
145819
  refreshToken: external_exports3.string()
@@ -145965,6 +146046,263 @@ var request2 = async (client, opts, schema) => {
145965
146046
  cause: lastNetworkError
145966
146047
  });
145967
146048
  };
146049
+ var JWT_BEARER_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer";
146050
+ var trimSlash = (value) => value.replace(/\/$/, "");
146051
+ var wrapNetworkError = (url4, err) => {
146052
+ const cause = err?.cause;
146053
+ const causeMessage = cause instanceof Error ? cause.code ?? cause.message : err instanceof Error ? err.message : String(err);
146054
+ return new ZeroAgentAuthError(`Could not reach ${url4} (${causeMessage})`, {
146055
+ status: 0,
146056
+ cause: err
146057
+ });
146058
+ };
146059
+ var AuthAgent = class {
146060
+ constructor(client) {
146061
+ this.client = client;
146062
+ }
146063
+ endpointsPromise = null;
146064
+ // Fully autonomous signup: register anonymously at the AuthKit domain,
146065
+ // exchange the identity assertion for a WorkOS access token, exchange that
146066
+ // for a Zero session. The claim token and identity assertion are returned
146067
+ // exactly once — the caller persists them.
146068
+ signup = async () => {
146069
+ const registration = await this.register();
146070
+ const token = await this.exchangeAssertion(registration.identityAssertion);
146071
+ const session4 = await this.exchangeAtZero(token.accessToken);
146072
+ return { registration, session: session4 };
146073
+ };
146074
+ register = async () => {
146075
+ const endpoints = await this.endpoints();
146076
+ return this.postJson(
146077
+ endpoints.identityEndpoint,
146078
+ { type: "anonymous" },
146079
+ identityEnvelopeSchema
146080
+ );
146081
+ };
146082
+ exchangeAssertion = async (identityAssertion) => {
146083
+ const endpoints = await this.endpoints();
146084
+ return this.postForm(
146085
+ endpoints.tokenEndpoint,
146086
+ { grant_type: JWT_BEARER_GRANT_TYPE, assertion: identityAssertion },
146087
+ agentTokenResponseSchema
146088
+ );
146089
+ };
146090
+ // POST /v1/auth/agent/exchange — WorkOS agent access token → Zero session
146091
+ // pair (+ the implicitly provisioned wallet address). The post-claim token
146092
+ // goes through here too: the server binds the claiming human.
146093
+ exchangeAtZero = (accessToken, opts = {}) => request2(
146094
+ this.client,
146095
+ {
146096
+ method: "POST",
146097
+ path: "/v1/auth/agent/exchange",
146098
+ body: { accessToken },
146099
+ signal: opts.signal
146100
+ },
146101
+ agentZeroSessionSchema
146102
+ );
146103
+ // Mint a claim attempt. The human opens the returned verification URI,
146104
+ // signs in as `email`, and the page shows THEM a pairing code to read back
146105
+ // to the agent — completeClaim() submits it.
146106
+ startClaim = async (input) => {
146107
+ const endpoints = await this.endpoints();
146108
+ if (!endpoints.claimEndpoint) {
146109
+ throw new ZeroAgentAuthError(
146110
+ "The authorization server advertises no claim endpoint.",
146111
+ { status: 0 }
146112
+ );
146113
+ }
146114
+ return this.postJson(
146115
+ endpoints.claimEndpoint,
146116
+ {
146117
+ type: "service_auth",
146118
+ claim_token: input.claimToken,
146119
+ login_hint: input.email
146120
+ },
146121
+ startClaimResponseSchema
146122
+ );
146123
+ };
146124
+ // Submit the pairing code the human read off the hosted page. Terminal
146125
+ // states map to a typed result; anything unexpected throws.
146126
+ completeClaim = async (input) => {
146127
+ const endpoints = await this.endpoints();
146128
+ if (!endpoints.claimEndpoint) {
146129
+ throw new ZeroAgentAuthError(
146130
+ "The authorization server advertises no claim endpoint.",
146131
+ { status: 0 }
146132
+ );
146133
+ }
146134
+ try {
146135
+ const identity = await this.postJson(
146136
+ `${endpoints.claimEndpoint}/complete`,
146137
+ { claim_token: input.claimToken, user_code: input.userCode },
146138
+ completeClaimResponseSchema
146139
+ );
146140
+ return { status: "ok", ...identity };
146141
+ } catch (err) {
146142
+ if (err instanceof ZeroAgentAuthError && err.serverCode) {
146143
+ if (err.serverCode === "claim_not_confirmed") {
146144
+ return { status: "not_confirmed" };
146145
+ }
146146
+ if (err.serverCode === "invalid_user_code") {
146147
+ return { status: "invalid_code" };
146148
+ }
146149
+ if ([
146150
+ "user_code_expired",
146151
+ "claim_expired",
146152
+ "claim_revoked",
146153
+ "already_claimed",
146154
+ "claim_denied"
146155
+ ].includes(err.serverCode)) {
146156
+ return { status: "expired", code: err.serverCode };
146157
+ }
146158
+ }
146159
+ throw err;
146160
+ }
146161
+ };
146162
+ // Resolve (and cache) the agent-auth endpoints via discovery.
146163
+ endpoints = () => {
146164
+ if (!this.endpointsPromise) {
146165
+ this.endpointsPromise = this.discover().catch((err) => {
146166
+ this.endpointsPromise = null;
146167
+ throw err;
146168
+ });
146169
+ }
146170
+ return this.endpointsPromise;
146171
+ };
146172
+ discover = async () => {
146173
+ const resource = await this.getJson(
146174
+ `${trimSlash(this.client.baseUrl)}/.well-known/oauth-protected-resource`
146175
+ );
146176
+ let lastError = null;
146177
+ for (const server of resource.authorization_servers ?? []) {
146178
+ try {
146179
+ const raw = await this.getJson(
146180
+ `${trimSlash(server)}/.well-known/oauth-authorization-server`
146181
+ );
146182
+ const metadata = agentAuthMetadataSchema.parse(raw);
146183
+ return {
146184
+ authorizationServer: trimSlash(server),
146185
+ identityEndpoint: metadata.agent_auth.identity_endpoint,
146186
+ claimEndpoint: metadata.agent_auth.claim_endpoint ?? null,
146187
+ tokenEndpoint: metadata.token_endpoint ?? `${trimSlash(server)}/oauth2/token`
146188
+ };
146189
+ } catch (err) {
146190
+ lastError = err;
146191
+ }
146192
+ }
146193
+ throw new ZeroAgentAuthError(
146194
+ "No authorization server with an agent_auth block found \u2014 agent registration is not enabled for this service.",
146195
+ { status: 0, cause: lastError }
146196
+ );
146197
+ };
146198
+ getJson = async (url4) => {
146199
+ const response = await this.client.fetchImpl(url4).catch((err) => {
146200
+ throw wrapNetworkError(url4, err);
146201
+ });
146202
+ if (!response.ok) {
146203
+ throw new ZeroAgentAuthError(`GET ${url4} failed (${response.status})`, {
146204
+ status: response.status
146205
+ });
146206
+ }
146207
+ return await response.json();
146208
+ };
146209
+ postJson = (url4, body, schema) => this.post(url4, "application/json", JSON.stringify(body), schema);
146210
+ postForm = (url4, fields, schema) => this.post(
146211
+ url4,
146212
+ "application/x-www-form-urlencoded",
146213
+ new URLSearchParams(fields).toString(),
146214
+ schema
146215
+ );
146216
+ post = async (url4, contentType, body, schema) => {
146217
+ const response = await this.client.fetchImpl(url4, {
146218
+ method: "POST",
146219
+ headers: { "content-type": contentType },
146220
+ body
146221
+ }).catch((err) => {
146222
+ throw wrapNetworkError(url4, err);
146223
+ });
146224
+ const text = await response.text();
146225
+ let parsed = null;
146226
+ try {
146227
+ parsed = text ? JSON.parse(text) : null;
146228
+ } catch {
146229
+ }
146230
+ if (!response.ok) {
146231
+ const errBody = parsed;
146232
+ const code = errBody?.code ?? errBody?.error;
146233
+ throw new ZeroAgentAuthError(
146234
+ `Agent auth request to ${url4} failed (${response.status}${typeof code === "string" ? `: ${code}` : ""})`,
146235
+ { status: response.status, body: parsed ?? text }
146236
+ );
146237
+ }
146238
+ return schema.parse(parsed);
146239
+ };
146240
+ };
146241
+ var userWalletDtoSchema = external_exports3.object({
146242
+ walletAddress: external_exports3.string(),
146243
+ source: external_exports3.enum(["self_custody", "privy_embedded"]),
146244
+ isPrimary: external_exports3.boolean(),
146245
+ linkedAt: external_exports3.union([external_exports3.string(), external_exports3.date()]).nullable().optional(),
146246
+ delegationGranted: external_exports3.boolean(),
146247
+ signerQuorumId: external_exports3.string().nullable(),
146248
+ // Per-transaction USDC cap in base units (6 dp). null = unlimited, 0 = free-only.
146249
+ maxTransactionUsdcBaseUnits: external_exports3.number().int().nullable()
146250
+ });
146251
+ var welcomeBonusSummarySchema = external_exports3.object({
146252
+ status: external_exports3.string(),
146253
+ amountUsd: external_exports3.number()
146254
+ });
146255
+ var internalUserDtoSchema = external_exports3.object({
146256
+ id: external_exports3.string(),
146257
+ email: external_exports3.string().nullable(),
146258
+ createdAt: external_exports3.union([external_exports3.string(), external_exports3.date()]).optional(),
146259
+ lastLoginAt: external_exports3.union([external_exports3.string(), external_exports3.date()]).nullable().optional(),
146260
+ onboardingCompleted: external_exports3.boolean().optional(),
146261
+ delegationGranted: external_exports3.boolean().optional(),
146262
+ wallets: external_exports3.array(userWalletDtoSchema).optional(),
146263
+ balance: external_exports3.object({ amount: external_exports3.string(), asset: external_exports3.string() }).nullable().optional(),
146264
+ welcomeBonus: welcomeBonusSummarySchema.nullable().optional()
146265
+ });
146266
+ var publicUserDtoSchema = external_exports3.object({
146267
+ user: external_exports3.object({
146268
+ id: external_exports3.string(),
146269
+ email: external_exports3.string().nullable()
146270
+ }),
146271
+ walletAddress: external_exports3.string().nullable(),
146272
+ balance: external_exports3.object({ amount: external_exports3.string(), asset: external_exports3.string() }).nullable(),
146273
+ welcomeBonus: welcomeBonusSummarySchema.nullable()
146274
+ });
146275
+ var signResponseSchema = external_exports3.object({
146276
+ signature: external_exports3.string().regex(/^0x[0-9a-fA-F]+$/, "must be 0x-prefixed hex"),
146277
+ walletAddress: external_exports3.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be 0x-prefixed 40-char hex address")
146278
+ });
146279
+ var deviceStartResponseSchema = external_exports3.object({
146280
+ deviceCode: external_exports3.string(),
146281
+ userCode: external_exports3.string(),
146282
+ verificationUri: external_exports3.string(),
146283
+ pollInterval: external_exports3.number(),
146284
+ expiresAt: external_exports3.number()
146285
+ });
146286
+ var devicePollResponseSchema = external_exports3.union([
146287
+ // userCode + verificationUri are optional: older API deployments don't
146288
+ // echo them on pending.
146289
+ external_exports3.object({
146290
+ error: external_exports3.literal("authorization_pending"),
146291
+ userCode: external_exports3.string().optional(),
146292
+ verificationUri: external_exports3.string().optional()
146293
+ }),
146294
+ external_exports3.object({ error: external_exports3.literal("expired_token") }),
146295
+ external_exports3.object({
146296
+ accessToken: external_exports3.string(),
146297
+ refreshToken: external_exports3.string(),
146298
+ expiresIn: external_exports3.number(),
146299
+ user: internalUserDtoSchema
146300
+ })
146301
+ ]);
146302
+ var sessionExchangeResponseSchema = external_exports3.object({
146303
+ token: external_exports3.string(),
146304
+ expiresAt: external_exports3.number()
146305
+ });
145968
146306
  var AuthDevice = class {
145969
146307
  constructor(client) {
145970
146308
  this.client = client;
@@ -146025,8 +146363,10 @@ var repackageSignFailure = (err, op) => {
146025
146363
  var Auth = class {
146026
146364
  constructor(client) {
146027
146365
  this.client = client;
146366
+ this.agent = new AuthAgent(client);
146028
146367
  this.device = new AuthDevice(client);
146029
146368
  }
146369
+ agent;
146030
146370
  device;
146031
146371
  // The internal (web-app facing) user profile. Richer than profile(): full
146032
146372
  // wallet list with per-wallet delegation/signer/limit metadata.
@@ -146323,6 +146663,9 @@ var capabilityResponseSchema = external_exports3.object({
146323
146663
  "unknown_unparsed",
146324
146664
  "unprobed"
146325
146665
  ]).optional(),
146666
+ // ZERO-147 — provenance of displayCostAmount (settled | probe | registry |
146667
+ // unknown). `settled` means the shown price is reconciled from real charges.
146668
+ priceSource: external_exports3.string().nullable().optional(),
146326
146669
  requiresHandshake: external_exports3.boolean().optional(),
146327
146670
  reviewCount: external_exports3.number(),
146328
146671
  rating: ratingSchema,
@@ -147399,7 +147742,7 @@ var placeholderFor = (fieldName, propSchema) => String(sampleValueFor(fieldName,
147399
147742
 
147400
147743
  // package.json
147401
147744
  var package_default2 = {
147402
- version: "1.15.0"};
147745
+ version: "1.16.0"};
147403
147746
 
147404
147747
  // src/app.ts
147405
147748
  init_esm_shims();
@@ -148030,272 +148373,6 @@ defineLazyProperty(apps, "safari", () => detectPlatformBinary({
148030
148373
  }));
148031
148374
  var open_default = open2;
148032
148375
 
148033
- // src/services/agent-auth.ts
148034
- init_esm_shims();
148035
- var JWT_BEARER_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer";
148036
- var trimSlash = (value) => value.replace(/\/$/, "");
148037
- var AgentAuthHttpError = class extends Error {
148038
- constructor(message2, status, body) {
148039
- super(message2);
148040
- this.status = status;
148041
- this.body = body;
148042
- this.name = "AgentAuthHttpError";
148043
- }
148044
- // WorkOS error bodies carry {code, message}; OAuth-style ones carry {error}.
148045
- get code() {
148046
- const body = this.body;
148047
- if (typeof body?.code === "string") return body.code;
148048
- if (typeof body?.error === "string") return body.error;
148049
- return null;
148050
- }
148051
- };
148052
- var agentAuthMetadataSchema = external_exports3.object({
148053
- token_endpoint: external_exports3.string().optional(),
148054
- agent_auth: external_exports3.object({
148055
- identity_endpoint: external_exports3.string(),
148056
- claim_endpoint: external_exports3.string().optional()
148057
- }).loose()
148058
- }).loose();
148059
- var identityEnvelopeSchema = external_exports3.object({
148060
- id: external_exports3.string(),
148061
- identity: external_exports3.object({
148062
- assertion: external_exports3.string(),
148063
- expires_at: external_exports3.string().optional(),
148064
- refresh_token: external_exports3.object({ value: external_exports3.string() }).loose().optional()
148065
- }).loose(),
148066
- claim: external_exports3.object({
148067
- token: external_exports3.string().optional(),
148068
- expires_at: external_exports3.string().optional()
148069
- }).loose().optional()
148070
- }).loose().transform((raw) => ({
148071
- registrationId: raw.id,
148072
- identityAssertion: raw.identity.assertion,
148073
- assertionExpires: raw.identity.expires_at ?? null,
148074
- refreshToken: raw.identity.refresh_token?.value ?? null,
148075
- claimToken: raw.claim?.token ?? null,
148076
- claimTokenExpires: raw.claim?.expires_at ?? null
148077
- }));
148078
- var tokenResponseSchema = external_exports3.object({ access_token: external_exports3.string() }).loose().transform((raw) => ({ accessToken: raw.access_token }));
148079
- var startClaimResponseSchema = external_exports3.object({
148080
- attempt: external_exports3.object({
148081
- verification_uri: external_exports3.string(),
148082
- expires_at: external_exports3.string().optional()
148083
- }).loose()
148084
- }).loose().transform((raw) => ({
148085
- verificationUri: raw.attempt.verification_uri,
148086
- expiresAt: raw.attempt.expires_at ?? null
148087
- }));
148088
- var completeClaimResponseSchema = external_exports3.object({
148089
- identity: external_exports3.object({
148090
- assertion: external_exports3.string(),
148091
- expires_at: external_exports3.string().optional(),
148092
- refresh_token: external_exports3.object({ value: external_exports3.string() }).loose().optional()
148093
- }).loose()
148094
- }).loose().transform((raw) => ({
148095
- identityAssertion: raw.identity.assertion,
148096
- assertionExpires: raw.identity.expires_at ?? null,
148097
- refreshToken: raw.identity.refresh_token?.value ?? null
148098
- }));
148099
- var zeroExchangeResponseSchema = external_exports3.object({
148100
- accessToken: external_exports3.string(),
148101
- refreshToken: external_exports3.string(),
148102
- expiresIn: external_exports3.number(),
148103
- user: external_exports3.object({ id: external_exports3.string() }).loose(),
148104
- walletAddress: external_exports3.string().optional()
148105
- }).loose();
148106
- var AgentAuthClient = class {
148107
- constructor(apiBaseUrl, fetchImpl = (...args) => globalThis.fetch(...args)) {
148108
- this.fetchImpl = fetchImpl;
148109
- this.apiBaseUrl = trimSlash(apiBaseUrl);
148110
- }
148111
- apiBaseUrl;
148112
- endpointsPromise = null;
148113
- // Fully autonomous signup: register anonymously at the AuthKit domain,
148114
- // exchange the identity assertion for a WorkOS access token, exchange that
148115
- // for a Zero session. The claim token and identity assertion are returned
148116
- // exactly once — the caller persists them.
148117
- signup = async () => {
148118
- const registration = await this.register();
148119
- const token = await this.exchangeAssertion(registration.identityAssertion);
148120
- const session4 = await this.exchangeAtZero(token.accessToken);
148121
- return { registration, session: session4 };
148122
- };
148123
- register = async () => {
148124
- const endpoints = await this.endpoints();
148125
- return this.postJson(
148126
- endpoints.identityEndpoint,
148127
- { type: "anonymous" },
148128
- identityEnvelopeSchema
148129
- );
148130
- };
148131
- exchangeAssertion = async (identityAssertion) => {
148132
- const endpoints = await this.endpoints();
148133
- return this.postForm(
148134
- endpoints.tokenEndpoint,
148135
- { grant_type: JWT_BEARER_GRANT_TYPE, assertion: identityAssertion },
148136
- tokenResponseSchema
148137
- );
148138
- };
148139
- // POST /v1/auth/agent/exchange — WorkOS agent access token → Zero session
148140
- // pair (+ the implicitly provisioned wallet address). The post-claim token
148141
- // goes through here too: the server binds the claiming human.
148142
- exchangeAtZero = (accessToken) => this.postJson(
148143
- `${this.apiBaseUrl}/v1/auth/agent/exchange`,
148144
- { accessToken },
148145
- zeroExchangeResponseSchema
148146
- );
148147
- // Mint a claim attempt. The human opens the returned verification URI,
148148
- // signs in as `email`, and the page shows THEM a pairing code to read back
148149
- // to the agent — completeClaim() submits it.
148150
- startClaim = async (input) => {
148151
- const endpoints = await this.endpoints();
148152
- if (!endpoints.claimEndpoint) {
148153
- throw new AgentAuthHttpError(
148154
- "The authorization server advertises no claim endpoint.",
148155
- 0,
148156
- null
148157
- );
148158
- }
148159
- return this.postJson(
148160
- endpoints.claimEndpoint,
148161
- {
148162
- type: "service_auth",
148163
- claim_token: input.claimToken,
148164
- login_hint: input.email
148165
- },
148166
- startClaimResponseSchema
148167
- );
148168
- };
148169
- // Submit the pairing code the human read off the hosted page. Terminal
148170
- // states map to a typed result; anything unexpected throws.
148171
- completeClaim = async (input) => {
148172
- const endpoints = await this.endpoints();
148173
- if (!endpoints.claimEndpoint) {
148174
- throw new AgentAuthHttpError(
148175
- "The authorization server advertises no claim endpoint.",
148176
- 0,
148177
- null
148178
- );
148179
- }
148180
- try {
148181
- const identity = await this.postJson(
148182
- `${endpoints.claimEndpoint}/complete`,
148183
- { claim_token: input.claimToken, user_code: input.userCode },
148184
- completeClaimResponseSchema
148185
- );
148186
- return { status: "ok", ...identity };
148187
- } catch (err) {
148188
- if (err instanceof AgentAuthHttpError && err.code) {
148189
- if (err.code === "claim_not_confirmed") {
148190
- return { status: "not_confirmed" };
148191
- }
148192
- if (err.code === "invalid_user_code") {
148193
- return { status: "invalid_code" };
148194
- }
148195
- if ([
148196
- "user_code_expired",
148197
- "claim_expired",
148198
- "claim_revoked",
148199
- "already_claimed",
148200
- "claim_denied"
148201
- ].includes(err.code)) {
148202
- return { status: "expired", code: err.code };
148203
- }
148204
- }
148205
- throw err;
148206
- }
148207
- };
148208
- // Resolve (and cache) the agent-auth endpoints via discovery.
148209
- endpoints = () => {
148210
- if (!this.endpointsPromise) {
148211
- this.endpointsPromise = this.discover().catch((err) => {
148212
- this.endpointsPromise = null;
148213
- throw err;
148214
- });
148215
- }
148216
- return this.endpointsPromise;
148217
- };
148218
- discover = async () => {
148219
- const resource = await this.getJson(`${this.apiBaseUrl}/.well-known/oauth-protected-resource`);
148220
- let lastError = null;
148221
- for (const server of resource.authorization_servers ?? []) {
148222
- try {
148223
- const raw = await this.getJson(
148224
- `${trimSlash(server)}/.well-known/oauth-authorization-server`
148225
- );
148226
- const metadata = agentAuthMetadataSchema.parse(raw);
148227
- return {
148228
- authorizationServer: trimSlash(server),
148229
- identityEndpoint: metadata.agent_auth.identity_endpoint,
148230
- claimEndpoint: metadata.agent_auth.claim_endpoint ?? null,
148231
- tokenEndpoint: metadata.token_endpoint ?? `${trimSlash(server)}/oauth2/token`
148232
- };
148233
- } catch (err) {
148234
- lastError = err;
148235
- }
148236
- }
148237
- throw new AgentAuthHttpError(
148238
- "No authorization server with an agent_auth block found \u2014 agent registration is not enabled for this service.",
148239
- 0,
148240
- lastError
148241
- );
148242
- };
148243
- getJson = async (url4) => {
148244
- const response = await this.fetchImpl(url4).catch((err) => {
148245
- throw wrapNetworkError(url4, err);
148246
- });
148247
- if (!response.ok) {
148248
- throw new AgentAuthHttpError(
148249
- `GET ${url4} failed (${response.status})`,
148250
- response.status,
148251
- null
148252
- );
148253
- }
148254
- return await response.json();
148255
- };
148256
- postJson = (url4, body, schema) => this.post(url4, "application/json", JSON.stringify(body), schema);
148257
- postForm = (url4, fields, schema) => this.post(
148258
- url4,
148259
- "application/x-www-form-urlencoded",
148260
- new URLSearchParams(fields).toString(),
148261
- schema
148262
- );
148263
- post = async (url4, contentType, body, schema) => {
148264
- const response = await this.fetchImpl(url4, {
148265
- method: "POST",
148266
- headers: { "content-type": contentType },
148267
- body
148268
- }).catch((err) => {
148269
- throw wrapNetworkError(url4, err);
148270
- });
148271
- const text = await response.text();
148272
- let parsed = null;
148273
- try {
148274
- parsed = text ? JSON.parse(text) : null;
148275
- } catch {
148276
- }
148277
- if (!response.ok) {
148278
- const body2 = parsed;
148279
- const code = body2?.code ?? body2?.error;
148280
- throw new AgentAuthHttpError(
148281
- `Agent auth request to ${url4} failed (${response.status}${typeof code === "string" ? `: ${code}` : ""})`,
148282
- response.status,
148283
- parsed ?? text
148284
- );
148285
- }
148286
- return schema.parse(parsed);
148287
- };
148288
- };
148289
- var wrapNetworkError = (url4, err) => {
148290
- const cause = err?.cause;
148291
- const causeMessage = cause instanceof Error ? cause.code ?? cause.message : err instanceof Error ? err.message : String(err);
148292
- return new AgentAuthHttpError(
148293
- `Could not reach ${url4} (${causeMessage})`,
148294
- 0,
148295
- null
148296
- );
148297
- };
148298
-
148299
148376
  // src/util/secure-config.ts
148300
148377
  init_esm_shims();
148301
148378
  var SECURE_DIR_MODE = 448;
@@ -148642,7 +148719,7 @@ var authAgentRegisterCommand = (appContext) => new Command("register").descripti
148642
148719
  process.exitCode = 1;
148643
148720
  return;
148644
148721
  }
148645
- const agentAuth = new AgentAuthClient(client.baseUrl);
148722
+ const agentAuth = client.auth.agent;
148646
148723
  let result;
148647
148724
  try {
148648
148725
  result = await agentAuth.signup();
@@ -148809,7 +148886,7 @@ var authAgentClaimCommand = (appContext) => new Command("claim").description(
148809
148886
  return;
148810
148887
  }
148811
148888
  const claimToken = registration.claimToken;
148812
- const agentAuth = new AgentAuthClient(client.baseUrl);
148889
+ const agentAuth = client.auth.agent;
148813
148890
  if (opts.code) {
148814
148891
  const ok2 = await completeClaimAndExchange(
148815
148892
  agentAuth,
@@ -148822,7 +148899,7 @@ var authAgentClaimCommand = (appContext) => new Command("claim").description(
148822
148899
  return;
148823
148900
  }
148824
148901
  const started = await agentAuth.startClaim({ claimToken, email: email4 }).catch((err) => {
148825
- const code = err instanceof AgentAuthHttpError && err.code ? err.code : truncateError(err instanceof Error ? err.message : String(err));
148902
+ const code = err instanceof ZeroAgentAuthError && err.serverCode ? err.serverCode : truncateError(err instanceof Error ? err.message : String(err));
148826
148903
  process.stderr.write(
148827
148904
  `Could not start the claim (${code}). The claim token may be expired \u2014 check \`claimTokenExpires\` in ~/.zero/config.json.
148828
148905
  `
@@ -149225,7 +149302,11 @@ var OUTCOMES = {
149225
149302
  errorClass: "insufficient_funds",
149226
149303
  reviewable: false
149227
149304
  },
149228
- server_error: { exitCode: 0, errorClass: "upstream_4xx", reviewable: true }
149305
+ // A capability returned a non-2xx (4xx/5xx). Exit 2 — distinct from a
149306
+ // transport failure (1) — so `zero fetch … && next` stops instead of
149307
+ // feeding an error body downstream as if it were a result. The body is
149308
+ // still printed and the run is reviewable; only the success signal changes.
149309
+ server_error: { exitCode: 2, errorClass: "upstream_4xx", reviewable: true }
149229
149310
  };
149230
149311
  var cliErrorClassFor = (outcome, status, walletAddress) => {
149231
149312
  const info = OUTCOMES[outcome];
@@ -149657,6 +149738,9 @@ var fetchCommand = (appContext) => new Command("fetch").description(
149657
149738
  );
149658
149739
  } else if (outcome === "server_error" && typeof status === "number") {
149659
149740
  console.error(` Upstream returned ${status}${messageSuffix}`);
149741
+ if (upstreamError?.fixHint) {
149742
+ console.error(` \u21B3 Fix: ${upstreamError.fixHint}`);
149743
+ }
149660
149744
  }
149661
149745
  }
149662
149746
  if (options.json) {
@@ -149686,6 +149770,11 @@ var fetchCommand = (appContext) => new Command("fetch").description(
149686
149770
  bodyRaw: status === null ? null : bodyRaw,
149687
149771
  ...isBinary && { bodyEncoding: "base64" },
149688
149772
  ...resultError && { error: resultError },
149773
+ // A non-2xx from the capability: surface the structured
149774
+ // upstream detail (status, message, and the caller-
149775
+ // fixable `fixHint`) in the envelope too. Agents run
149776
+ // `--json`, so without this the fixHint is invisible.
149777
+ ...upstreamError && { upstreamError },
149689
149778
  ...legacyMigrateHint && { hint: legacyMigrateHint },
149690
149779
  ...combinedSkipReasons.length > 0 && {
149691
149780
  runTrackingSkipped: combinedSkipReasons
@@ -149695,9 +149784,10 @@ var fetchCommand = (appContext) => new Command("fetch").description(
149695
149784
  );
149696
149785
  } else if (runId && outcomeInfo.reviewable) {
149697
149786
  const isTTY = process.stderr.isTTY;
149787
+ const responded2xx = status !== null && status >= 200 && status < 300;
149698
149788
  console.error(`
149699
149789
  Run ID: ${runId}`);
149700
- if (isTTY) {
149790
+ if (isTTY && responded2xx) {
149701
149791
  console.error(
149702
149792
  ` Leave a review to help other agents discover great capabilities:`
149703
149793
  );
@@ -149718,10 +149808,19 @@ var fetchCommand = (appContext) => new Command("fetch").description(
149718
149808
  ``
149719
149809
  ].join("\n")
149720
149810
  );
149721
- } else {
149811
+ } else if (responded2xx) {
149722
149812
  console.error(
149723
149813
  ` zero review ${runId} --success --accuracy 5 --value 4 --reliability 5`
149724
149814
  );
149815
+ } else if (isTTY) {
149816
+ console.error(
149817
+ ` The call did not return a usable result. If the capability itself was at fault, record it:`
149818
+ );
149819
+ console.error(
149820
+ ` zero review ${runId} --no-success --content "what went wrong"`
149821
+ );
149822
+ } else {
149823
+ console.error(` zero review ${runId} --no-success`);
149725
149824
  }
149726
149825
  } else if (!runId && cliSkipReasons.length > 0) {
149727
149826
  console.error(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroxyz/cli",
3
- "version": "1.15.0",
3
+ "version": "1.16.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "zero": "dist/index.js",