@haven_ai/sdk 0.0.0-dev.202609142030.8358774 → 0.0.0-dev.202609142145.5df01af
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/README.md +1 -0
- package/dist/index.cjs +38 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -3
- package/dist/index.d.ts +23 -3
- package/dist/index.js +38 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -406,6 +406,7 @@ Hosted MCP and signer tools also return stable `code` values on recoverable x402
|
|
|
406
406
|
| `PRICE_EXCEEDS_MAX` | The merchant-authoritative x402 price is above the caller's spending cap. No funding transfer was created. | Tell the user the live price exceeded the cap and retry only after they confirm a higher one. Payloads carry `next_action: stop_and_tell_user` and `retry_with_new_quote: true` — the latter means any retry needs a fresh quote, not that one should be attempted unattended. |
|
|
407
407
|
| `AMBIGUOUS_MAX_AMOUNT` | Both `max_amount` (atomic units) and `max_amount_human` (whole tokens) were sent for one purchase. Nothing was contacted and nothing was spent. | Re-send with exactly one — `max_amount_human` for a cap the user stated in tokens, `max_amount` for an exact atomic figure. |
|
|
408
408
|
| `MAX_AMOUNT_UNCONVERTIBLE` | `max_amount_human` could not be converted against this quote's asset — its decimals are unknown to Haven, or the cap has more decimal places than the asset supports. Nothing was spent. | Round the cap to the asset's decimals, or re-send it as an exact atomic `max_amount`. |
|
|
409
|
+
| `MERCHANT_NOT_READY` | The merchant answered the quote probe with its own `503 { error: 'merchant_not_ready', reason_code, retry_after_s }` instead of a 402 — it cannot settle right now (e.g. its settlement wallet is out of gas). No payment was created. | Tell the user and retry later (`retry_after_s` in the message when given); do not treat it as a wrong endpoint. Payloads carry `next_action: stop_and_tell_user` and `retry_with_new_quote: true`. |
|
|
409
410
|
| `PAYMENT_WINDOW_EXPIRED` | The funding/quote window closed before `haven_x402_sign_header`, `haven_submit`, or `haven_complete_mcp_tool` could finish. | Re-run `haven_pay_mcp_tool` with the same `idempotency_key`, then sign and complete the fresh quote. Payloads include `retry_with_new_quote: true`. |
|
|
410
411
|
| `MERCHANT_REJECTED_AFTER_FUNDING` | Haven's funding leg succeeded, but the merchant rejected the paid retry. | Stop retrying the merchant and call `haven_sweep_delegate` so the user can recover stranded delegate USDC. |
|
|
411
412
|
|
package/dist/index.cjs
CHANGED
|
@@ -195,7 +195,17 @@ var AgentPaymentFailureCode = {
|
|
|
195
195
|
* asset can represent (truncating it would silently change the user's cap).
|
|
196
196
|
* The fallback is the exact atomic `max_amount`.
|
|
197
197
|
*/
|
|
198
|
-
MaxAmountUnconvertible: "MAX_AMOUNT_UNCONVERTIBLE"
|
|
198
|
+
MaxAmountUnconvertible: "MAX_AMOUNT_UNCONVERTIBLE",
|
|
199
|
+
/**
|
|
200
|
+
* #2979: the merchant answered a `tools/call` probe with its own
|
|
201
|
+
* machine-readable "cannot settle right now" refusal (HTTP 503,
|
|
202
|
+
* `{ error: 'merchant_not_ready', reason_code, ... }`) instead of a 402
|
|
203
|
+
* challenge — e.g. its settlement wallet is out of gas. No 402 was ever
|
|
204
|
+
* issued and no payment was created; this is honest and (per
|
|
205
|
+
* `retry_after_s`, when present) usually transient, unlike a permanent
|
|
206
|
+
* endpoint miss.
|
|
207
|
+
*/
|
|
208
|
+
MerchantNotReady: "MERCHANT_NOT_READY"
|
|
199
209
|
};
|
|
200
210
|
var AgentPaymentRail = {
|
|
201
211
|
/** Standard Haven payment from the user's Safe through an approved delegate allowance. */
|
|
@@ -253,7 +263,8 @@ var AgentPaymentFailureCodeDescriptions = {
|
|
|
253
263
|
[AgentPaymentFailureCode.MerchantUnresponsiveAfterFunding]: "The Haven funding leg succeeded, but the merchant did not answer the paid retry before the timeout. The merchant may still settle late \u2014 check haven_get_payment_status (and retry haven_complete_mcp_tool once) BEFORE sweeping; sweep only if no settlement appears.",
|
|
254
264
|
[AgentPaymentFailureCode.MerchantCallContextUnavailable]: "merchant_url/tool_name were omitted and no stored merchant call context is available for this payment_id. Re-send merchant_url, tool_name, arguments, and mcp_transport explicitly.",
|
|
255
265
|
[AgentPaymentFailureCode.AmbiguousMaxAmount]: "Both max_amount (atomic units) and max_amount_human (whole tokens) were supplied for one purchase. Nothing was contacted and nothing was spent. Re-send with exactly ONE: max_amount_human for a cap the user stated in tokens, max_amount for an exact atomic figure.",
|
|
256
|
-
[AgentPaymentFailureCode.MaxAmountUnconvertible]: "max_amount_human could not be converted to atomic units against this quote's asset \u2014 either its decimals are unknown to Haven or the cap has more decimal places than the asset supports. Nothing was spent. Round the cap, or re-send it as an exact atomic max_amount."
|
|
266
|
+
[AgentPaymentFailureCode.MaxAmountUnconvertible]: "max_amount_human could not be converted to atomic units against this quote's asset \u2014 either its decimals are unknown to Haven or the cap has more decimal places than the asset supports. Nothing was spent. Round the cap, or re-send it as an exact atomic max_amount.",
|
|
267
|
+
[AgentPaymentFailureCode.MerchantNotReady]: 'The merchant refused the probe with its own "cannot settle right now" signal instead of a 402 challenge. No payment was created. Often transient \u2014 retry later (see retry_after_s in the message, if given) rather than treating this as a broken or wrong endpoint.'
|
|
257
268
|
};
|
|
258
269
|
var AgentPaymentWarningCode = {
|
|
259
270
|
/** No max_amount cap was supplied — the live quoted price was accepted as-is. */
|
|
@@ -348,8 +359,18 @@ var MerchantTimeoutError = class extends HavenApiError {
|
|
|
348
359
|
};
|
|
349
360
|
var X402UnexpectedStatusError = class extends HavenApiError {
|
|
350
361
|
x402ErrorCode = "unexpected_non_402_status";
|
|
351
|
-
|
|
352
|
-
|
|
362
|
+
/**
|
|
363
|
+
* #2979: `body` is the merchant's own JSON, when the non-402 response
|
|
364
|
+
* carried one — e.g. the demo merchant's `/mcp` readiness gate answers
|
|
365
|
+
* `503 { error: 'merchant_not_ready', reason_code, ... }`. Optional and
|
|
366
|
+
* best-effort: a non-JSON or unreadable body leaves this `undefined`, same
|
|
367
|
+
* as before this field existed. Consumers key on it (not on the message
|
|
368
|
+
* string) to distinguish an honest, machine-readable merchant refusal from
|
|
369
|
+
* a genuine "this is not the x402 endpoint" miss, which otherwise look
|
|
370
|
+
* identical — both are just "some non-402 status".
|
|
371
|
+
*/
|
|
372
|
+
constructor(message, statusCode, body) {
|
|
373
|
+
super(message, statusCode, body);
|
|
353
374
|
this.name = "X402UnexpectedStatusError";
|
|
354
375
|
}
|
|
355
376
|
};
|
|
@@ -3646,9 +3667,16 @@ var HavenClient = class {
|
|
|
3646
3667
|
const request = snapshotX402Request(url, initialInit);
|
|
3647
3668
|
const response = await this.merchantTransport.fetch(url, initialInit);
|
|
3648
3669
|
if (response.status !== 402) {
|
|
3670
|
+
let body;
|
|
3671
|
+
try {
|
|
3672
|
+
body = await response.clone().json();
|
|
3673
|
+
} catch {
|
|
3674
|
+
body = void 0;
|
|
3675
|
+
}
|
|
3649
3676
|
throw new X402UnexpectedStatusError(
|
|
3650
3677
|
`Expected an x402 quote response with HTTP 402, got HTTP ${response.status}.`,
|
|
3651
|
-
response.status || 400
|
|
3678
|
+
response.status || 400,
|
|
3679
|
+
body
|
|
3652
3680
|
);
|
|
3653
3681
|
}
|
|
3654
3682
|
if (response.headers.get("MACHINE-PAYMENT-CHALLENGE")) {
|
|
@@ -4850,6 +4878,11 @@ present and surface \`message\` or \`error\` verbatim. Common cases:
|
|
|
4850
4878
|
Round the cap, or send an exact atomic \`max_amount\`.
|
|
4851
4879
|
- \`PAYMENT_WINDOW_EXPIRED\`: re-run the quote/prepare tool with the same
|
|
4852
4880
|
\`idempotency_key\`, then sign the fresh payload.
|
|
4881
|
+
- \`MERCHANT_NOT_READY\`: the merchant refused the quote with its own
|
|
4882
|
+
"cannot settle right now" signal (a 503 \`merchant_not_ready\` with a
|
|
4883
|
+
\`reason_code\`) instead of a 402. No payment was created. Tell the user;
|
|
4884
|
+
retry later (the message carries \`retry_after_s\` when the merchant gave
|
|
4885
|
+
one) \u2014 this is not a wrong or broken endpoint.
|
|
4853
4886
|
- \`MERCHANT_REJECTED_AFTER_FUNDING\`: the merchant refused the paid retry.
|
|
4854
4887
|
Stop-and-sweep \u2014 stop retrying the merchant and use
|
|
4855
4888
|
\`mcp__haven__haven_sweep_delegate\` to recover stranded delegate funds.
|