@agent-score/commerce 1.0.3 → 1.2.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 (60) hide show
  1. package/README.md +28 -1
  2. package/dist/agent_instructions-d3UWTdam.d.mts +129 -0
  3. package/dist/agent_instructions-d3UWTdam.d.ts +129 -0
  4. package/dist/challenge/index.d.mts +3 -110
  5. package/dist/challenge/index.d.ts +3 -110
  6. package/dist/challenge/index.js +76 -5
  7. package/dist/challenge/index.js.map +1 -1
  8. package/dist/challenge/index.mjs +82 -5
  9. package/dist/challenge/index.mjs.map +1 -1
  10. package/dist/core.d.mts +28 -1
  11. package/dist/core.d.ts +28 -1
  12. package/dist/core.js +237 -157
  13. package/dist/core.js.map +1 -1
  14. package/dist/core.mjs +246 -157
  15. package/dist/core.mjs.map +1 -1
  16. package/dist/discovery/index.d.mts +120 -1
  17. package/dist/discovery/index.d.ts +120 -1
  18. package/dist/discovery/index.js +204 -0
  19. package/dist/discovery/index.js.map +1 -1
  20. package/dist/discovery/index.mjs +202 -0
  21. package/dist/discovery/index.mjs.map +1 -1
  22. package/dist/identity/express.d.mts +18 -2
  23. package/dist/identity/express.d.ts +18 -2
  24. package/dist/identity/express.js +227 -164
  25. package/dist/identity/express.js.map +1 -1
  26. package/dist/identity/express.mjs +232 -164
  27. package/dist/identity/express.mjs.map +1 -1
  28. package/dist/identity/fastify.d.mts +17 -2
  29. package/dist/identity/fastify.d.ts +17 -2
  30. package/dist/identity/fastify.js +227 -164
  31. package/dist/identity/fastify.js.map +1 -1
  32. package/dist/identity/fastify.mjs +232 -164
  33. package/dist/identity/fastify.mjs.map +1 -1
  34. package/dist/identity/hono.d.mts +22 -2
  35. package/dist/identity/hono.d.ts +22 -2
  36. package/dist/identity/hono.js +227 -164
  37. package/dist/identity/hono.js.map +1 -1
  38. package/dist/identity/hono.mjs +232 -164
  39. package/dist/identity/hono.mjs.map +1 -1
  40. package/dist/identity/nextjs.d.mts +8 -1
  41. package/dist/identity/nextjs.d.ts +8 -1
  42. package/dist/identity/nextjs.js +213 -166
  43. package/dist/identity/nextjs.js.map +1 -1
  44. package/dist/identity/nextjs.mjs +220 -166
  45. package/dist/identity/nextjs.mjs.map +1 -1
  46. package/dist/identity/web.d.mts +15 -1
  47. package/dist/identity/web.d.ts +15 -1
  48. package/dist/identity/web.js +213 -166
  49. package/dist/identity/web.js.map +1 -1
  50. package/dist/identity/web.mjs +220 -166
  51. package/dist/identity/web.mjs.map +1 -1
  52. package/dist/index.js +120 -101
  53. package/dist/index.js.map +1 -1
  54. package/dist/index.mjs +127 -101
  55. package/dist/index.mjs.map +1 -1
  56. package/dist/payment/index.js.map +1 -1
  57. package/dist/payment/index.mjs.map +1 -1
  58. package/dist/stripe-multichain/index.js.map +1 -1
  59. package/dist/stripe-multichain/index.mjs.map +1 -1
  60. package/package.json +3 -3
@@ -30,6 +30,8 @@ __export(fastify_exports, {
30
30
  denialReasonToBody: () => denialReasonToBody,
31
31
  extractPaymentSignerAddress: () => extractPaymentSignerAddress,
32
32
  getAgentScoreData: () => getAgentScoreData,
33
+ getGateDegradedState: () => getGateDegradedState,
34
+ getGateQuotaInfo: () => getGateQuotaInfo,
33
35
  isFixableDenial: () => isFixableDenial,
34
36
  readX402PaymentHeader: () => readX402PaymentHeader,
35
37
  verificationAgentInstructions: () => verificationAgentInstructions,
@@ -129,10 +131,10 @@ var WALLET_NOT_TRUSTED_INSTRUCTIONS = JSON.stringify({
129
131
  var PAYMENT_REQUIRED_INSTRUCTIONS = JSON.stringify({
130
132
  action: "contact_merchant",
131
133
  steps: [
132
- "The merchant's AgentScore tier does not include the assess feature, so agent identity cannot be evaluated. This is a merchant-side configuration gap \u2014 there is no agent-side recovery.",
133
- "Contact the merchant (their support channel \u2014 typically listed in /llms.txt or the OpenAPI servers metadata) and request they upgrade their AgentScore plan."
134
+ "The merchant's AgentScore account does not have the assess endpoint enabled, so agent identity cannot be evaluated. This is a merchant-side configuration gap \u2014 there is no agent-side recovery.",
135
+ "Contact the merchant (their support channel \u2014 typically listed in /llms.txt or the OpenAPI servers metadata) so they can resolve the configuration on their side."
134
136
  ],
135
- user_message: "This merchant's identity gate is misconfigured (AgentScore tier doesn't support assess). Contact the merchant \u2014 there's nothing to fix on the agent side."
137
+ user_message: "This merchant's identity gate is misconfigured. Contact the merchant \u2014 there's nothing to fix on the agent side."
136
138
  });
137
139
  var IDENTITY_VERIFICATION_REQUIRED_FALLBACK_INSTRUCTIONS = JSON.stringify({
138
140
  action: "deliver_verify_url_and_poll",
@@ -143,6 +145,24 @@ var IDENTITY_VERIFICATION_REQUIRED_FALLBACK_INSTRUCTIONS = JSON.stringify({
143
145
  ],
144
146
  user_message: "Identity verification is required. Visit verify_url, then poll poll_url for the operator token and retry."
145
147
  });
148
+ var API_ERROR_INSTRUCTIONS = JSON.stringify({
149
+ action: "retry_with_backoff",
150
+ steps: [
151
+ "Verification is temporarily unavailable. Retry the request after 5\u201330 seconds with exponential backoff.",
152
+ "This is NOT a compliance denial \u2014 the user does not need to re-verify their identity. Send the same identity headers (X-Wallet-Address or X-Operator-Token) on retry.",
153
+ "If the request continues to fail after 3+ retries (~60 seconds total), surface the error to the user with the merchant's support contact."
154
+ ],
155
+ user_message: "Verification is temporarily unavailable. Please try again in a moment \u2014 this is a transient issue, not a problem with your account."
156
+ });
157
+ var QUOTA_EXCEEDED_INSTRUCTIONS = JSON.stringify({
158
+ action: "contact_merchant",
159
+ steps: [
160
+ "AgentScore identity verification is unavailable for this merchant. This is a merchant-side issue and is NOT recoverable via retry.",
161
+ "Do not retry: the same 503 will be returned until the merchant resolves the issue on their side.",
162
+ "Surface to the user with the merchant's support contact. The merchant (not the agent) needs to act."
163
+ ],
164
+ user_message: "This merchant's identity verification is temporarily unavailable. Try again later, or contact the merchant directly."
165
+ });
146
166
  var TOKEN_EXPIRED_FALLBACK_INSTRUCTIONS = JSON.stringify({
147
167
  action: "deliver_verify_url_and_poll",
148
168
  steps: [
@@ -153,6 +173,7 @@ var TOKEN_EXPIRED_FALLBACK_INSTRUCTIONS = JSON.stringify({
153
173
  user_message: "Operator token is expired or revoked. A new verification session has been minted \u2014 visit verify_url to refresh."
154
174
  });
155
175
  var DEFAULT_AGENT_INSTRUCTIONS = {
176
+ api_error: API_ERROR_INSTRUCTIONS,
156
177
  wallet_not_trusted: WALLET_NOT_TRUSTED_INSTRUCTIONS,
157
178
  payment_required: PAYMENT_REQUIRED_INSTRUCTIONS,
158
179
  identity_verification_required: IDENTITY_VERIFICATION_REQUIRED_FALLBACK_INSTRUCTIONS,
@@ -163,7 +184,7 @@ var DEFAULT_MESSAGES = {
163
184
  identity_verification_required: "Identity verification is required to access this resource. Visit verify_url to complete KYC.",
164
185
  wallet_not_trusted: "The wallet does not meet the merchant compliance policy.",
165
186
  api_error: "AgentScore is unreachable. This is transient \u2014 retry in a few seconds.",
166
- payment_required: "AgentScore tier does not support assess. Contact support.",
187
+ payment_required: "Assess endpoint not enabled for this merchant. Contact support.",
167
188
  wallet_signer_mismatch: "Payment signer does not match the wallet claimed via X-Wallet-Address. The signer and the claimed wallet must both resolve to the same AgentScore operator.",
168
189
  wallet_auth_requires_wallet_signing: "X-Wallet-Address was sent with a rail that has no wallet signature (Stripe SPT / card). Switch to X-Operator-Token, or use a wallet-signing rail (Tempo MPP, x402).",
169
190
  token_expired: "The operator token is expired or revoked. A fresh verification session has been minted \u2014 visit verify_url to mint a new token.",
@@ -202,9 +223,6 @@ function denialReasonToBody(reason) {
202
223
  if (reason.expected_signer) body.expected_signer = reason.expected_signer;
203
224
  if (reason.actual_signer) body.actual_signer = reason.actual_signer;
204
225
  if (reason.linked_wallets && reason.linked_wallets.length > 0) body.linked_wallets = reason.linked_wallets;
205
- if (reason.code === "api_error" && !(reason.extra && reason.extra.next_steps)) {
206
- body.next_steps = { action: "retry", retry_after_seconds: 5 };
207
- }
208
226
  if (reason.extra) {
209
227
  for (const [key, value] of Object.entries(reason.extra)) {
210
228
  if (RESERVED_FIELDS.has(key)) {
@@ -217,6 +235,9 @@ function denialReasonToBody(reason) {
217
235
  return body;
218
236
  }
219
237
 
238
+ // src/core.ts
239
+ var import_sdk = require("@agent-score/sdk");
240
+
220
241
  // src/address.ts
221
242
  var SOLANA_BASE58_RE = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
222
243
  var isSolanaAddress = (address) => SOLANA_BASE58_RE.test(address) && !address.startsWith("0x");
@@ -345,9 +366,23 @@ function createAgentScoreCore(options) {
345
366
  } = options;
346
367
  const baseUrl = stripTrailingSlashes(rawBaseUrl);
347
368
  const agentMemoryHint = buildAgentMemoryHint();
348
- const defaultUa = `@agent-score/commerce@${"1.0.3"}`;
369
+ const defaultUa = `@agent-score/commerce@${"1.2.0"}`;
349
370
  const userAgentHeader = userAgent ? `${userAgent} (${defaultUa})` : defaultUa;
350
- const API_TIMEOUT_MS = 1e4;
371
+ const sdk = new import_sdk.AgentScore({ apiKey, baseUrl, userAgent: userAgentHeader });
372
+ const sessionSdkCache = /* @__PURE__ */ new Map();
373
+ function getSessionSdk(sessionApiKey, sessionBaseUrl) {
374
+ const key = `${sessionApiKey}|${sessionBaseUrl ?? ""}`;
375
+ let s = sessionSdkCache.get(key);
376
+ if (!s) {
377
+ s = new import_sdk.AgentScore({
378
+ apiKey: sessionApiKey,
379
+ baseUrl: sessionBaseUrl ?? baseUrl,
380
+ userAgent: userAgentHeader
381
+ });
382
+ sessionSdkCache.set(key, s);
383
+ }
384
+ return s;
385
+ }
351
386
  const cache = new TTLCache(cacheSeconds * 1e3);
352
387
  async function tryMintSessionDenial(ctx) {
353
388
  if (!createSessionOnMissing) return void 0;
@@ -364,20 +399,11 @@ function createAgentScoreCore(options) {
364
399
  console.warn("[gate] createSessionOnMissing.getSessionOptions hook failed:", err instanceof Error ? err.message : err);
365
400
  }
366
401
  }
367
- const sessionBaseUrl = stripTrailingSlashes(createSessionOnMissing.baseUrl ?? "https://api.agentscore.sh");
368
- const sessionRes = await fetch(`${sessionBaseUrl}/v1/sessions`, {
369
- method: "POST",
370
- headers: {
371
- "X-API-Key": createSessionOnMissing.apiKey,
372
- "Content-Type": "application/json",
373
- Accept: "application/json",
374
- "User-Agent": userAgentHeader
375
- },
376
- body: JSON.stringify(sessionBody),
377
- signal: AbortSignal.timeout(API_TIMEOUT_MS)
402
+ const sessionSdk = getSessionSdk(createSessionOnMissing.apiKey, createSessionOnMissing.baseUrl);
403
+ const data = await sessionSdk.createSession({
404
+ ...sessionBody.context !== void 0 ? { context: sessionBody.context } : {},
405
+ ...sessionBody.product_name !== void 0 ? { product_name: sessionBody.product_name } : {}
378
406
  });
379
- if (!sessionRes.ok) return void 0;
380
- const data = await sessionRes.json();
381
407
  if (typeof data.session_id !== "string" || typeof data.poll_secret !== "string" || typeof data.verify_url !== "string") {
382
408
  console.warn("[gate] /v1/sessions returned 200 without required fields \u2014 falling back to bare denial");
383
409
  return void 0;
@@ -441,7 +467,13 @@ function createAgentScoreCore(options) {
441
467
  const cached = cache.get(cacheKey);
442
468
  if (cached) {
443
469
  if (cached.allow) {
444
- return { kind: "allow", data: cached.raw };
470
+ const cachedRaw = cached.raw;
471
+ const cachedQuota = cachedRaw?.quota;
472
+ return {
473
+ kind: "allow",
474
+ data: cachedRaw,
475
+ ...cachedQuota !== void 0 && { quota: cachedQuota }
476
+ };
445
477
  }
446
478
  if (isFixableDenial(cached.reasons)) {
447
479
  const sessionReason = await tryMintSessionDenial(ctx);
@@ -458,130 +490,119 @@ function createAgentScoreCore(options) {
458
490
  }
459
491
  };
460
492
  }
493
+ const policy = {};
494
+ if (requireKyc != null) policy.require_kyc = requireKyc;
495
+ if (requireSanctionsClear != null) policy.require_sanctions_clear = requireSanctionsClear;
496
+ if (minAge != null) policy.min_age = minAge;
497
+ if (blockedJurisdictions != null) policy.blocked_jurisdictions = blockedJurisdictions;
498
+ if (allowedJurisdictions != null) policy.allowed_jurisdictions = allowedJurisdictions;
499
+ let data;
461
500
  try {
462
- const body = {};
463
- if (identity.address) body.address = identity.address;
464
- if (identity.operatorToken) body.operator_token = identity.operatorToken;
465
- if (gateChain) body.chain = gateChain;
466
- const policy = {};
467
- if (requireKyc != null) policy.require_kyc = requireKyc;
468
- if (requireSanctionsClear != null) policy.require_sanctions_clear = requireSanctionsClear;
469
- if (minAge != null) policy.min_age = minAge;
470
- if (blockedJurisdictions != null) policy.blocked_jurisdictions = blockedJurisdictions;
471
- if (allowedJurisdictions != null) policy.allowed_jurisdictions = allowedJurisdictions;
472
- if (Object.keys(policy).length > 0) body.policy = policy;
473
- const response = await fetch(`${baseUrl}/v1/assess`, {
474
- method: "POST",
475
- headers: {
476
- "X-API-Key": apiKey,
477
- "Content-Type": "application/json",
478
- Accept: "application/json",
479
- "User-Agent": userAgentHeader
480
- },
481
- body: JSON.stringify(body),
482
- signal: AbortSignal.timeout(API_TIMEOUT_MS)
483
- });
484
- if (response.status === 402) {
501
+ const opts = {
502
+ chain: gateChain,
503
+ ...Object.keys(policy).length > 0 ? { policy } : {}
504
+ };
505
+ const result = identity.address ? await sdk.assess(identity.address, { ...opts, operatorToken: identity.operatorToken }) : await sdk.assess(null, { ...opts, operatorToken: identity.operatorToken });
506
+ data = result;
507
+ } catch (err) {
508
+ if (err instanceof import_sdk.PaymentRequiredError) {
485
509
  if (failOpen) return { kind: "allow" };
486
510
  return { kind: "deny", reason: { code: "payment_required" } };
487
511
  }
488
- if (response.status === 401) {
489
- try {
490
- const errData = await response.clone().json();
491
- const code = errData?.error?.code;
492
- if (code === "token_expired") {
493
- return {
494
- kind: "deny",
495
- reason: {
496
- code,
497
- data: errData,
498
- ...typeof errData.verify_url === "string" ? { verify_url: errData.verify_url } : {},
499
- ...typeof errData.session_id === "string" ? { session_id: errData.session_id } : {},
500
- ...typeof errData.poll_secret === "string" ? { poll_secret: errData.poll_secret } : {},
501
- ...typeof errData.poll_url === "string" ? { poll_url: errData.poll_url } : {},
502
- ...errData.next_steps ? { agent_instructions: JSON.stringify(errData.next_steps) } : {},
503
- ...errData.agent_memory ? { agent_memory: errData.agent_memory } : {}
504
- }
505
- };
506
- }
507
- if (code === "invalid_credential") {
508
- return {
509
- kind: "deny",
510
- reason: {
511
- code: "invalid_credential",
512
- agent_instructions: INVALID_CREDENTIAL_INSTRUCTIONS,
513
- agent_memory: agentMemoryHint
514
- }
515
- };
516
- }
517
- if (code) {
518
- console.warn(`[gate] /v1/assess returned 401 ${code} \u2014 no specific handler, surfacing as api_error.`);
512
+ if (err instanceof import_sdk.TokenExpiredError) {
513
+ return {
514
+ kind: "deny",
515
+ reason: {
516
+ code: "token_expired",
517
+ data: err.details,
518
+ ...err.verifyUrl ? { verify_url: err.verifyUrl } : {},
519
+ ...err.sessionId ? { session_id: err.sessionId } : {},
520
+ ...err.pollSecret ? { poll_secret: err.pollSecret } : {},
521
+ ...err.pollUrl ? { poll_url: err.pollUrl } : {},
522
+ ...err.nextSteps ? { agent_instructions: JSON.stringify(err.nextSteps) } : {},
523
+ ...err.agentMemory ? { agent_memory: err.agentMemory } : {}
519
524
  }
520
- } catch (err) {
521
- console.warn("[gate] /v1/assess 401 body parse failed:", err instanceof Error ? err.message : err);
522
- }
525
+ };
523
526
  }
524
- if (response.status >= 400 && response.status < 500 && response.status !== 402) {
525
- try {
526
- const errData = await response.clone().json();
527
- const code = errData?.error?.code;
528
- if (code && code !== "token_expired" && code !== "invalid_credential") {
529
- console.warn(
530
- `[gate] /v1/assess returned ${response.status} ${code} \u2014 surfacing as api_error. Validate input shape before invoking the gate to avoid this.`
531
- );
527
+ if (err instanceof import_sdk.InvalidCredentialError) {
528
+ return {
529
+ kind: "deny",
530
+ reason: {
531
+ code: "invalid_credential",
532
+ agent_instructions: INVALID_CREDENTIAL_INSTRUCTIONS,
533
+ agent_memory: agentMemoryHint
532
534
  }
533
- } catch {
534
- }
535
+ };
535
536
  }
536
- if (!response.ok) {
537
- throw new Error(`AgentScore API returned ${response.status}`);
537
+ if (err instanceof import_sdk.QuotaExceededError) {
538
+ console.warn("[gate] /v1/assess returned 429 quota_exceeded");
539
+ if (failOpen) return { kind: "allow", degraded: true, infraReason: "quota_exceeded" };
540
+ return {
541
+ kind: "deny",
542
+ reason: { code: "api_error", agent_instructions: QUOTA_EXCEEDED_INSTRUCTIONS }
543
+ };
538
544
  }
539
- const data = await response.json();
540
- const decision = data.decision;
541
- const decisionReasons = data.decision_reasons ?? [];
542
- const allow = decision === "allow" || decision == null;
543
- cache.set(cacheKey, { allow, decision: decision ?? void 0, reasons: decisionReasons, raw: data });
544
- if (allow) {
545
- return { kind: "allow", data };
545
+ if (err instanceof import_sdk.TimeoutError) {
546
+ console.warn("[gate] /v1/assess timed out:", err.message);
547
+ if (failOpen) return { kind: "allow", degraded: true, infraReason: "network_timeout" };
548
+ return { kind: "deny", reason: { code: "api_error" } };
546
549
  }
547
- if (isFixableDenial(decisionReasons)) {
548
- const sessionReason = await tryMintSessionDenial(ctx);
549
- if (sessionReason) return { kind: "deny", reason: sessionReason };
550
+ const status = err?.status;
551
+ const errName = err instanceof Error ? err.name : "";
552
+ if (status === 429) {
553
+ console.warn("[gate] /v1/assess returned 429 (untyped \u2014 defensive)");
554
+ if (failOpen) return { kind: "allow", degraded: true, infraReason: "quota_exceeded" };
555
+ return {
556
+ kind: "deny",
557
+ reason: { code: "api_error", agent_instructions: QUOTA_EXCEEDED_INSTRUCTIONS }
558
+ };
559
+ }
560
+ if (errName === "TimeoutError" || errName === "AbortError") {
561
+ console.warn("[gate] /v1/assess timed out (by Error.name):", err instanceof Error ? err.message : err);
562
+ if (failOpen) return { kind: "allow", degraded: true, infraReason: "network_timeout" };
563
+ return { kind: "deny", reason: { code: "api_error" } };
550
564
  }
565
+ const errCode = err?.code;
566
+ const msg = err instanceof Error ? err.message : String(err);
567
+ const detail = errCode ? `${errCode}: ${msg}` : msg;
568
+ console.warn(`[gate] /v1/assess call failed \u2014 surfacing as api_error: ${detail}`);
569
+ if (failOpen) return { kind: "allow", degraded: true, infraReason: "api_error" };
570
+ return { kind: "deny", reason: { code: "api_error" } };
571
+ }
572
+ const decision = data.decision;
573
+ const decisionReasons = data.decision_reasons ?? [];
574
+ const allow = decision === "allow" || decision == null;
575
+ cache.set(cacheKey, { allow, decision: decision ?? void 0, reasons: decisionReasons, raw: data });
576
+ if (allow) {
577
+ const quota = data.quota;
551
578
  return {
552
- kind: "deny",
553
- reason: {
554
- code: "wallet_not_trusted",
555
- decision: decision ?? void 0,
556
- reasons: decisionReasons,
557
- verify_url: data.verify_url,
558
- data
559
- }
579
+ kind: "allow",
580
+ data,
581
+ ...quota !== void 0 && { quota }
560
582
  };
561
- } catch (err) {
562
- console.warn("[gate] /v1/assess call failed \u2014 surfacing as api_error:", err instanceof Error ? err.message : err);
563
- if (failOpen) return { kind: "allow" };
564
- return { kind: "deny", reason: { code: "api_error" } };
565
583
  }
584
+ if (isFixableDenial(decisionReasons)) {
585
+ const sessionReason = await tryMintSessionDenial(ctx);
586
+ if (sessionReason) return { kind: "deny", reason: sessionReason };
587
+ }
588
+ return {
589
+ kind: "deny",
590
+ reason: {
591
+ code: "wallet_not_trusted",
592
+ decision: decision ?? void 0,
593
+ reasons: decisionReasons,
594
+ verify_url: data.verify_url,
595
+ data
596
+ }
597
+ };
566
598
  }
567
599
  async function captureWallet2(options2) {
568
600
  try {
569
- const body = {
570
- operator_token: options2.operatorToken,
571
- wallet_address: options2.walletAddress,
572
- network: options2.network
573
- };
574
- if (options2.idempotencyKey) body.idempotency_key = options2.idempotencyKey;
575
- await fetch(`${baseUrl}/v1/credentials/wallets`, {
576
- method: "POST",
577
- headers: {
578
- "X-API-Key": apiKey,
579
- "Content-Type": "application/json",
580
- Accept: "application/json",
581
- "User-Agent": userAgentHeader
582
- },
583
- body: JSON.stringify(body),
584
- signal: AbortSignal.timeout(API_TIMEOUT_MS)
601
+ await sdk.associateWallet({
602
+ operatorToken: options2.operatorToken,
603
+ walletAddress: options2.walletAddress,
604
+ network: options2.network,
605
+ ...options2.idempotencyKey ? { idempotencyKey: options2.idempotencyKey } : {}
585
606
  });
586
607
  } catch (err) {
587
608
  console.warn("[agentscore-commerce] captureWallet failed:", err instanceof Error ? err.message : err);
@@ -606,19 +627,7 @@ function createAgentScoreCore(options) {
606
627
  return { ok: true, ...extractFromCached(resolveCached.raw) };
607
628
  }
608
629
  try {
609
- const response = await fetch(`${baseUrl}/v1/assess`, {
610
- method: "POST",
611
- headers: {
612
- "X-API-Key": apiKey,
613
- "Content-Type": "application/json",
614
- Accept: "application/json",
615
- "User-Agent": userAgentHeader
616
- },
617
- body: JSON.stringify({ address: walletAddress }),
618
- signal: AbortSignal.timeout(API_TIMEOUT_MS)
619
- });
620
- if (!response.ok) return { ok: false };
621
- const data = await response.json();
630
+ const data = await sdk.assess(walletAddress);
622
631
  cache.set(`resolve:${wallet}`, { allow: true, raw: data });
623
632
  return { ok: true, ...extractFromCached(data) };
624
633
  } catch (err) {
@@ -627,28 +636,37 @@ function createAgentScoreCore(options) {
627
636
  }
628
637
  }
629
638
  function reportSignerEvent(kind) {
630
- try {
631
- const pending = fetch(`${baseUrl}/v1/telemetry/signer-match`, {
632
- method: "POST",
633
- headers: {
634
- "X-API-Key": apiKey,
635
- "Content-Type": "application/json",
636
- Accept: "application/json",
637
- "User-Agent": userAgentHeader
638
- },
639
- body: JSON.stringify({ kind }),
640
- signal: AbortSignal.timeout(API_TIMEOUT_MS)
641
- });
642
- if (pending && typeof pending.catch === "function") {
643
- pending.catch((err) => {
644
- console.warn("[agentscore-commerce] signer-match telemetry failed:", err instanceof Error ? err.message : err);
645
- });
646
- }
647
- } catch {
639
+ void sdk.telemetrySignerMatch({ kind });
640
+ }
641
+ function projectSignerMatch(sm, claimedNorm, signerNorm) {
642
+ const kind = sm.kind;
643
+ if (kind === "pass") {
644
+ return {
645
+ kind: "pass",
646
+ claimedOperator: sm.claimed_operator ?? null,
647
+ signerOperator: sm.signer_operator ?? null
648
+ };
648
649
  }
650
+ if (kind === "wallet_auth_requires_wallet_signing") {
651
+ return {
652
+ kind: "wallet_auth_requires_wallet_signing",
653
+ claimedWallet: sm.claimed_wallet ?? claimedNorm,
654
+ agentInstructions: sm.agent_instructions ?? WALLET_AUTH_REQUIRES_WALLET_SIGNING_INSTRUCTIONS
655
+ };
656
+ }
657
+ const linked = sm.linked_wallets;
658
+ return {
659
+ kind: "wallet_signer_mismatch",
660
+ claimedOperator: sm.claimed_operator ?? null,
661
+ actualSignerOperator: sm.signer_operator ?? null,
662
+ expectedSigner: sm.expected_signer ?? claimedNorm,
663
+ actualSigner: sm.actual_signer ?? signerNorm,
664
+ linkedWallets: Array.isArray(linked) ? linked.filter((w) => typeof w === "string") : [],
665
+ agentInstructions: sm.agent_instructions ?? WALLET_SIGNER_MISMATCH_INSTRUCTIONS
666
+ };
649
667
  }
650
668
  async function verifyWalletSignerMatch2(options2) {
651
- const { claimedWallet, signer } = options2;
669
+ const { claimedWallet, signer, network } = options2;
652
670
  if (!signer) {
653
671
  reportSignerEvent("wallet_auth_requires_wallet_signing");
654
672
  return {
@@ -663,6 +681,35 @@ function createAgentScoreCore(options) {
663
681
  reportSignerEvent("pass");
664
682
  return { kind: "pass", claimedOperator: null, signerOperator: null };
665
683
  }
684
+ const cachedEntry = cache.get(claimedNorm);
685
+ const cachedMatch = cachedEntry?.signerMatchBySigner?.get(signerNorm);
686
+ if (cachedMatch) {
687
+ return projectSignerMatch(cachedMatch, claimedNorm, signerNorm);
688
+ }
689
+ const inferredNetwork = network ?? (signerNorm.startsWith("0x") ? "evm" : "solana");
690
+ let assessResponse;
691
+ try {
692
+ assessResponse = await sdk.assess(claimedNorm, {
693
+ resolveSigner: { address: signerNorm, network: inferredNetwork }
694
+ });
695
+ } catch (err) {
696
+ console.warn("[gate] verifyWalletSignerMatch assess failed:", err instanceof Error ? err.message : err);
697
+ reportSignerEvent("api_error");
698
+ return { kind: "api_error", claimedWallet: claimedNorm };
699
+ }
700
+ const signerMatch = assessResponse.signer_match;
701
+ if (signerMatch && typeof signerMatch === "object") {
702
+ if (cachedEntry) {
703
+ const map = cachedEntry.signerMatchBySigner ?? /* @__PURE__ */ new Map();
704
+ map.set(signerNorm, signerMatch);
705
+ cachedEntry.signerMatchBySigner = map;
706
+ } else {
707
+ const entry = { allow: true, raw: assessResponse };
708
+ entry.signerMatchBySigner = /* @__PURE__ */ new Map([[signerNorm, signerMatch]]);
709
+ cache.set(claimedNorm, entry);
710
+ }
711
+ return projectSignerMatch(signerMatch, claimedNorm, signerNorm);
712
+ }
666
713
  const [claimedResolve, signerResolve] = await Promise.all([
667
714
  resolveWalletToOperator(claimedNorm),
668
715
  resolveWalletToOperator(signerNorm)
@@ -684,8 +731,6 @@ function createAgentScoreCore(options) {
684
731
  actualSignerOperator: signerOperator,
685
732
  expectedSigner: claimedNorm,
686
733
  actualSigner: signerNorm,
687
- // Populated from /v1/assess.linked_wallets on the claimed wallet — the full set of
688
- // wallets the agent CAN sign with to satisfy the claim (same-operator rule).
689
734
  linkedWallets: claimedResolve.linkedWallets,
690
735
  agentInstructions: WALLET_SIGNER_MISMATCH_INSTRUCTIONS
691
736
  };
@@ -777,6 +822,14 @@ var agentscoreGatePlugin = async (fastify, options) => {
777
822
  };
778
823
  const outcome = await core.evaluate(identity, request);
779
824
  if (outcome.kind === "allow") {
825
+ const state = request[GATE_STATE_KEY];
826
+ if (state) {
827
+ if (outcome.degraded) {
828
+ state.degraded = true;
829
+ state.infraReason = outcome.infraReason;
830
+ }
831
+ if (outcome.quota) state.quota = outcome.quota;
832
+ }
780
833
  if (outcome.data) request.agentscore = outcome.data;
781
834
  return;
782
835
  }
@@ -786,6 +839,14 @@ var agentscoreGatePlugin = async (fastify, options) => {
786
839
  function getAgentScoreData(request) {
787
840
  return request.agentscore;
788
841
  }
842
+ function getGateDegradedState(request) {
843
+ const state = request[GATE_STATE_KEY];
844
+ return { degraded: state?.degraded ?? false, infraReason: state?.infraReason };
845
+ }
846
+ function getGateQuotaInfo(request) {
847
+ const state = request[GATE_STATE_KEY];
848
+ return state?.quota;
849
+ }
789
850
  async function captureWallet(request, options) {
790
851
  const state = request[GATE_STATE_KEY];
791
852
  if (!state?.operatorToken) return;
@@ -821,6 +882,8 @@ var fastify_default = agentscoreGatePlugin;
821
882
  denialReasonToBody,
822
883
  extractPaymentSignerAddress,
823
884
  getAgentScoreData,
885
+ getGateDegradedState,
886
+ getGateQuotaInfo,
824
887
  isFixableDenial,
825
888
  readX402PaymentHeader,
826
889
  verificationAgentInstructions,