@agent-score/commerce 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{_response-DmziuJz6.d.mts → _response-DS-LR590.d.mts} +13 -8
- package/dist/{_response-rbK0zM7y.d.ts → _response-RpEB7-vl.d.ts} +13 -8
- package/dist/challenge/index.js.map +1 -1
- package/dist/challenge/index.mjs.map +1 -1
- package/dist/core.js +86 -67
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +86 -67
- package/dist/core.mjs.map +1 -1
- package/dist/discovery/index.js +3 -3
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/index.mjs +3 -3
- package/dist/discovery/index.mjs.map +1 -1
- package/dist/identity/express.d.mts +1 -1
- package/dist/identity/express.d.ts +1 -1
- package/dist/identity/express.js +120 -71
- package/dist/identity/express.js.map +1 -1
- package/dist/identity/express.mjs +120 -71
- package/dist/identity/express.mjs.map +1 -1
- package/dist/identity/fastify.d.mts +1 -1
- package/dist/identity/fastify.d.ts +1 -1
- package/dist/identity/fastify.js +120 -71
- package/dist/identity/fastify.js.map +1 -1
- package/dist/identity/fastify.mjs +120 -71
- package/dist/identity/fastify.mjs.map +1 -1
- package/dist/identity/hono.d.mts +1 -1
- package/dist/identity/hono.d.ts +1 -1
- package/dist/identity/hono.js +120 -71
- package/dist/identity/hono.js.map +1 -1
- package/dist/identity/hono.mjs +120 -71
- package/dist/identity/hono.mjs.map +1 -1
- package/dist/identity/nextjs.d.mts +1 -1
- package/dist/identity/nextjs.d.ts +1 -1
- package/dist/identity/nextjs.js +120 -71
- package/dist/identity/nextjs.js.map +1 -1
- package/dist/identity/nextjs.mjs +120 -71
- package/dist/identity/nextjs.mjs.map +1 -1
- package/dist/identity/web.d.mts +1 -1
- package/dist/identity/web.d.ts +1 -1
- package/dist/identity/web.js +120 -71
- package/dist/identity/web.js.map +1 -1
- package/dist/identity/web.mjs +120 -71
- package/dist/identity/web.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +122 -81
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +122 -81
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,82 @@
|
|
|
1
|
+
// src/_denial.ts
|
|
2
|
+
var FIXABLE_DENIAL_REASONS = /* @__PURE__ */ new Set([
|
|
3
|
+
"kyc_required",
|
|
4
|
+
"kyc_pending",
|
|
5
|
+
"kyc_failed"
|
|
6
|
+
]);
|
|
7
|
+
function isFixableDenial(reasons) {
|
|
8
|
+
if (!reasons || reasons.length === 0) return false;
|
|
9
|
+
return reasons.every((r) => FIXABLE_DENIAL_REASONS.has(r));
|
|
10
|
+
}
|
|
11
|
+
function denialReasonStatus(reason) {
|
|
12
|
+
if (reason.code === "token_expired" || reason.code === "invalid_credential") return 401;
|
|
13
|
+
if (reason.code === "api_error") return 503;
|
|
14
|
+
return 403;
|
|
15
|
+
}
|
|
16
|
+
function buildSignerMismatchBody(input) {
|
|
17
|
+
const { result } = input;
|
|
18
|
+
if (result.kind === "pass" || result.kind === "api_error") return null;
|
|
19
|
+
const learnMoreUrl = input.learnMoreUrl ?? "https://docs.agentscore.sh/guides/agent-identity";
|
|
20
|
+
if (result.kind === "wallet_signer_mismatch") {
|
|
21
|
+
const linkedWallets = result.linkedWallets ?? [];
|
|
22
|
+
const userMessage = input.userMessage ?? (linkedWallets.length > 0 ? `Sign the payment with one of the wallets linked to this operator: ${linkedWallets.join(", ")}. Then retry.` : "Sign the payment with the same wallet you claimed via X-Wallet-Address, or switch to X-Operator-Token for rail-independent identity.");
|
|
23
|
+
return {
|
|
24
|
+
error: {
|
|
25
|
+
code: "wallet_signer_mismatch",
|
|
26
|
+
message: "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."
|
|
27
|
+
},
|
|
28
|
+
claimed_operator: result.claimedOperator,
|
|
29
|
+
actual_signer_operator: result.actualSignerOperator ?? null,
|
|
30
|
+
expected_signer: result.expectedSigner,
|
|
31
|
+
actual_signer: result.actualSigner,
|
|
32
|
+
linked_wallets: linkedWallets,
|
|
33
|
+
next_steps: {
|
|
34
|
+
action: "regenerate_payment_from_linked_wallet",
|
|
35
|
+
user_message: userMessage,
|
|
36
|
+
learn_more_url: learnMoreUrl
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
error: {
|
|
42
|
+
code: "wallet_auth_requires_wallet_signing",
|
|
43
|
+
message: "Wallet-auth requires a payment rail that carries a wallet signature (Tempo MPP, x402). Stripe SPT and card rails have no wallet signer; switch to X-Operator-Token to use those."
|
|
44
|
+
},
|
|
45
|
+
next_steps: {
|
|
46
|
+
action: "switch_to_operator_token",
|
|
47
|
+
user_message: input.userMessage ?? "Drop the X-Wallet-Address header and retry with X-Operator-Token (works on every payment rail).",
|
|
48
|
+
learn_more_url: learnMoreUrl
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function buildContactSupportNextSteps(supportEmail, message) {
|
|
53
|
+
return {
|
|
54
|
+
action: "contact_support",
|
|
55
|
+
support_email: supportEmail,
|
|
56
|
+
user_message: message ?? `If you believe this denial is in error, contact support at ${supportEmail} with your order details.`
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function verificationAgentInstructions(input = {}) {
|
|
60
|
+
const baseSteps = [
|
|
61
|
+
"Present the verify_url directly to the user \u2014 it is a complete, ready-to-open URL with the session token already embedded (e.g. https://agentscore.sh/verify?session=sess_...). Do NOT modify or construct the URL yourself.",
|
|
62
|
+
`Immediately begin polling poll_url every ${input.pollIntervalSeconds ?? 5} seconds with header X-Poll-Secret set to poll_secret. The user will complete verification in their browser while you poll in the background.`,
|
|
63
|
+
"The user visits the URL, signs in, completes identity verification (photo ID + selfie via Stripe Identity), and closes the tab. They do NOT need to copy or paste anything back to you.",
|
|
64
|
+
'When your poll returns status "verified", extract operator_token from the response. This is a one-time value \u2014 save it immediately. Subsequent polls return status "consumed" without the token.',
|
|
65
|
+
input.retryStep ?? "Retry the original merchant request with header X-Operator-Token set to the operator_token value."
|
|
66
|
+
];
|
|
67
|
+
return {
|
|
68
|
+
action: "poll_for_credential",
|
|
69
|
+
user_action: input.userAction ?? "The user must visit verify_url to complete identity verification before this request can proceed",
|
|
70
|
+
steps: input.extraSteps ? [...baseSteps, ...input.extraSteps] : baseSteps,
|
|
71
|
+
poll_interval_seconds: input.pollIntervalSeconds ?? 5,
|
|
72
|
+
poll_secret_header: "X-Poll-Secret",
|
|
73
|
+
retry_token_header: "X-Operator-Token",
|
|
74
|
+
timeout_seconds: input.timeoutSeconds ?? 3600,
|
|
75
|
+
...input.orderTtl ? { order_ttl: input.orderTtl } : {},
|
|
76
|
+
...input.extra ?? {}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
1
80
|
// src/core.ts
|
|
2
81
|
var CANONICAL_AGENTSCORE_API = "https://api.agentscore.sh";
|
|
3
82
|
var WALLET_SIGNER_MISMATCH_INSTRUCTIONS = JSON.stringify({
|
|
@@ -100,87 +179,48 @@ function readX402PaymentHeader(request) {
|
|
|
100
179
|
return request.headers.get("payment-signature") ?? request.headers.get("x-payment") ?? void 0;
|
|
101
180
|
}
|
|
102
181
|
|
|
103
|
-
// src/_denial.ts
|
|
104
|
-
var FIXABLE_DENIAL_REASONS = /* @__PURE__ */ new Set([
|
|
105
|
-
"kyc_required",
|
|
106
|
-
"kyc_pending",
|
|
107
|
-
"kyc_failed",
|
|
108
|
-
"jurisdiction_restricted"
|
|
109
|
-
]);
|
|
110
|
-
function isFixableDenial(reasons) {
|
|
111
|
-
if (!reasons || reasons.length === 0) return true;
|
|
112
|
-
return reasons.every((r) => FIXABLE_DENIAL_REASONS.has(r));
|
|
113
|
-
}
|
|
114
|
-
function denialReasonStatus(reason) {
|
|
115
|
-
if (reason.code === "token_expired" || reason.code === "invalid_credential") return 401;
|
|
116
|
-
if (reason.code === "api_error") return 503;
|
|
117
|
-
return 403;
|
|
118
|
-
}
|
|
119
|
-
function buildSignerMismatchBody(input) {
|
|
120
|
-
const { result } = input;
|
|
121
|
-
if (result.kind === "pass" || result.kind === "api_error") return null;
|
|
122
|
-
const learnMoreUrl = input.learnMoreUrl ?? "https://docs.agentscore.sh/guides/agent-identity";
|
|
123
|
-
if (result.kind === "wallet_signer_mismatch") {
|
|
124
|
-
const linkedWallets = result.linkedWallets ?? [];
|
|
125
|
-
const userMessage = input.userMessage ?? (linkedWallets.length > 0 ? `Sign the payment with one of the wallets linked to this operator: ${linkedWallets.join(", ")}. Then retry.` : "Sign the payment with the same wallet you claimed via X-Wallet-Address, or switch to X-Operator-Token for rail-independent identity.");
|
|
126
|
-
return {
|
|
127
|
-
error: {
|
|
128
|
-
code: "wallet_signer_mismatch",
|
|
129
|
-
message: "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."
|
|
130
|
-
},
|
|
131
|
-
claimed_operator: result.claimedOperator,
|
|
132
|
-
actual_signer_operator: result.actualSignerOperator ?? null,
|
|
133
|
-
expected_signer: result.expectedSigner,
|
|
134
|
-
actual_signer: result.actualSigner,
|
|
135
|
-
linked_wallets: linkedWallets,
|
|
136
|
-
next_steps: {
|
|
137
|
-
action: "regenerate_payment_from_linked_wallet",
|
|
138
|
-
user_message: userMessage,
|
|
139
|
-
learn_more_url: learnMoreUrl
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
return {
|
|
144
|
-
error: {
|
|
145
|
-
code: "wallet_auth_requires_wallet_signing",
|
|
146
|
-
message: "Wallet-auth requires a payment rail that carries a wallet signature (Tempo MPP, x402). Stripe SPT and card rails have no wallet signer; switch to X-Operator-Token to use those."
|
|
147
|
-
},
|
|
148
|
-
next_steps: {
|
|
149
|
-
action: "switch_to_operator_token",
|
|
150
|
-
user_message: input.userMessage ?? "Drop the X-Wallet-Address header and retry with X-Operator-Token (works on every payment rail).",
|
|
151
|
-
learn_more_url: learnMoreUrl
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
function buildContactSupportNextSteps(supportEmail, message) {
|
|
156
|
-
return {
|
|
157
|
-
action: "contact_support",
|
|
158
|
-
support_email: supportEmail,
|
|
159
|
-
user_message: message ?? `If you believe this denial is in error, contact support at ${supportEmail} with your order details.`
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
function verificationAgentInstructions(input = {}) {
|
|
163
|
-
const baseSteps = [
|
|
164
|
-
"Present the verify_url directly to the user \u2014 it is a complete, ready-to-open URL with the session token already embedded (e.g. https://agentscore.sh/verify?session=sess_...). Do NOT modify or construct the URL yourself.",
|
|
165
|
-
`Immediately begin polling poll_url every ${input.pollIntervalSeconds ?? 5} seconds with header X-Poll-Secret set to poll_secret. The user will complete verification in their browser while you poll in the background.`,
|
|
166
|
-
"The user visits the URL, signs in, completes identity verification (photo ID + selfie via Stripe Identity), and closes the tab. They do NOT need to copy or paste anything back to you.",
|
|
167
|
-
'When your poll returns status "verified", extract operator_token from the response. This is a one-time value \u2014 save it immediately. Subsequent polls return status "consumed" without the token.',
|
|
168
|
-
input.retryStep ?? "Retry the original merchant request with header X-Operator-Token set to the operator_token value."
|
|
169
|
-
];
|
|
170
|
-
return {
|
|
171
|
-
action: "poll_for_credential",
|
|
172
|
-
user_action: input.userAction ?? "The user must visit verify_url to complete identity verification before this request can proceed",
|
|
173
|
-
steps: input.extraSteps ? [...baseSteps, ...input.extraSteps] : baseSteps,
|
|
174
|
-
poll_interval_seconds: input.pollIntervalSeconds ?? 5,
|
|
175
|
-
poll_secret_header: "X-Poll-Secret",
|
|
176
|
-
retry_token_header: "X-Operator-Token",
|
|
177
|
-
timeout_seconds: input.timeoutSeconds ?? 3600,
|
|
178
|
-
...input.orderTtl ? { order_ttl: input.orderTtl } : {},
|
|
179
|
-
...input.extra ?? {}
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
|
|
183
182
|
// src/_response.ts
|
|
183
|
+
var WALLET_NOT_TRUSTED_INSTRUCTIONS = JSON.stringify({
|
|
184
|
+
action: "contact_support",
|
|
185
|
+
steps: [
|
|
186
|
+
"The wallet's operator failed an UNFIXABLE compliance check (sanctions, age, or jurisdiction). `reasons` lists which: `sanctions_flagged` / `age_insufficient` / `jurisdiction_restricted`. KYC re-verification won't change the outcome \u2014 the policy denial is structural.",
|
|
187
|
+
"Surface the denial to the user with the merchant's support contact. Do not retry the same merchant request; do not hand the user a verify_url (verification won't fix this code path).",
|
|
188
|
+
"Fixable compliance reasons (`kyc_required`, `kyc_pending`, `kyc_failed`) do NOT land on this code \u2014 the gate auto-mints a verification session for those and returns `identity_verification_required` with poll endpoints, same shape as `missing_identity`. `jurisdiction_restricted` IS in the unfixable bucket because the API only emits it after KYC is verified (the user's KYC'd country is in the blocked list \u2014 re-doing KYC won't change the country)."
|
|
189
|
+
],
|
|
190
|
+
user_message: "This purchase is denied by the merchant's compliance policy and cannot be resolved by re-verifying. Contact the merchant's support if you believe this is in error."
|
|
191
|
+
});
|
|
192
|
+
var PAYMENT_REQUIRED_INSTRUCTIONS = JSON.stringify({
|
|
193
|
+
action: "contact_merchant",
|
|
194
|
+
steps: [
|
|
195
|
+
"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.",
|
|
196
|
+
"Contact the merchant (their support channel \u2014 typically listed in /llms.txt or the OpenAPI servers metadata) and request they upgrade their AgentScore plan."
|
|
197
|
+
],
|
|
198
|
+
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."
|
|
199
|
+
});
|
|
200
|
+
var IDENTITY_VERIFICATION_REQUIRED_FALLBACK_INSTRUCTIONS = JSON.stringify({
|
|
201
|
+
action: "deliver_verify_url_and_poll",
|
|
202
|
+
steps: [
|
|
203
|
+
"Share verify_url with the user \u2014 they complete identity verification on AgentScore.",
|
|
204
|
+
"If session_id + poll_secret are present in the body, poll poll_url every 5 seconds with header `X-Poll-Secret: <poll_secret>` until status=verified. The poll returns a one-time operator_token.",
|
|
205
|
+
"Retry the original request with header `X-Operator-Token: <opc_...>`."
|
|
206
|
+
],
|
|
207
|
+
user_message: "Identity verification is required. Visit verify_url, then poll poll_url for the operator token and retry."
|
|
208
|
+
});
|
|
209
|
+
var TOKEN_EXPIRED_FALLBACK_INSTRUCTIONS = JSON.stringify({
|
|
210
|
+
action: "deliver_verify_url_and_poll",
|
|
211
|
+
steps: [
|
|
212
|
+
"The operator token is expired or revoked. AgentScore auto-mints a fresh verification session \u2014 complete it to receive a new opc_...",
|
|
213
|
+
"Share verify_url with the user, then poll poll_url every 5 seconds with header `X-Poll-Secret: <poll_secret>` until status=verified. The poll returns a fresh one-time operator_token.",
|
|
214
|
+
"Retry the original request with header `X-Operator-Token: <new_opc_...>`."
|
|
215
|
+
],
|
|
216
|
+
user_message: "Operator token is expired or revoked. A new verification session has been minted \u2014 visit verify_url to refresh."
|
|
217
|
+
});
|
|
218
|
+
var DEFAULT_AGENT_INSTRUCTIONS = {
|
|
219
|
+
wallet_not_trusted: WALLET_NOT_TRUSTED_INSTRUCTIONS,
|
|
220
|
+
payment_required: PAYMENT_REQUIRED_INSTRUCTIONS,
|
|
221
|
+
identity_verification_required: IDENTITY_VERIFICATION_REQUIRED_FALLBACK_INSTRUCTIONS,
|
|
222
|
+
token_expired: TOKEN_EXPIRED_FALLBACK_INSTRUCTIONS
|
|
223
|
+
};
|
|
184
224
|
var DEFAULT_MESSAGES = {
|
|
185
225
|
missing_identity: "No identity provided. Send X-Wallet-Address (wallet) or X-Operator-Token (credential).",
|
|
186
226
|
identity_verification_required: "Identity verification is required to access this resource. Visit verify_url to complete KYC.",
|
|
@@ -217,7 +257,8 @@ function denialReasonToBody(reason) {
|
|
|
217
257
|
if (reason.session_id) body.session_id = reason.session_id;
|
|
218
258
|
if (reason.poll_secret) body.poll_secret = reason.poll_secret;
|
|
219
259
|
if (reason.poll_url) body.poll_url = reason.poll_url;
|
|
220
|
-
|
|
260
|
+
const instructions = reason.agent_instructions ?? DEFAULT_AGENT_INSTRUCTIONS[reason.code];
|
|
261
|
+
if (instructions) body.agent_instructions = instructions;
|
|
221
262
|
if (reason.agent_memory) body.agent_memory = reason.agent_memory;
|
|
222
263
|
if (reason.claimed_operator) body.claimed_operator = reason.claimed_operator;
|
|
223
264
|
if (reason.code === "wallet_signer_mismatch") body.actual_signer_operator = reason.actual_signer_operator ?? null;
|