@haven_ai/sdk 0.11.0-alpha.0 → 0.13.0-alpha.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 (42) hide show
  1. package/README.md +37 -4
  2. package/dist/{base64-D4VZhgUg.d.ts → base64-C3mJNLYR.d.cts} +10 -2
  3. package/dist/{base64-DR4Gl8cD.d.cts → base64-CxzIc3KH.d.ts} +10 -2
  4. package/dist/{chunk-IKQIIMM6.cjs → chunk-4Z7PKLFD.cjs} +38 -37
  5. package/dist/chunk-4Z7PKLFD.cjs.map +1 -0
  6. package/dist/{chunk-34YJQFCM.js → chunk-CK6VRIPR.js} +3 -3
  7. package/dist/chunk-CK6VRIPR.js.map +1 -0
  8. package/dist/{chunk-ZDJ55LR7.js → chunk-CXQ42FOA.js} +7 -6
  9. package/dist/chunk-CXQ42FOA.js.map +1 -0
  10. package/dist/{chunk-MZKLAHBK.cjs → chunk-LZHCIK7L.cjs} +56 -4
  11. package/dist/chunk-LZHCIK7L.cjs.map +1 -0
  12. package/dist/{chunk-I7SL4A6X.js → chunk-MI7LVP56.js} +55 -5
  13. package/dist/chunk-MI7LVP56.js.map +1 -0
  14. package/dist/{chunk-DXBAN4SN.cjs → chunk-Z5MTKU6O.cjs} +4 -4
  15. package/dist/chunk-Z5MTKU6O.cjs.map +1 -0
  16. package/dist/edge.cjs +93 -93
  17. package/dist/edge.d.cts +11 -8
  18. package/dist/edge.d.ts +11 -8
  19. package/dist/edge.js +4 -4
  20. package/dist/index.cjs +456 -356
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +26 -15
  23. package/dist/index.d.ts +26 -15
  24. package/dist/index.js +140 -48
  25. package/dist/index.js.map +1 -1
  26. package/dist/{receipt-CbD8L0WL.d.ts → receipt-CTOPh2fm.d.ts} +5 -4
  27. package/dist/{receipt-_bWCELEH.d.cts → receipt-DwRqGjGb.d.cts} +5 -4
  28. package/dist/test-support.cjs +58 -21
  29. package/dist/test-support.cjs.map +1 -1
  30. package/dist/test-support.d.cts +47 -3
  31. package/dist/test-support.d.ts +47 -3
  32. package/dist/test-support.js +37 -3
  33. package/dist/test-support.js.map +1 -1
  34. package/dist/{types-DKmvjXK6.d.cts → types-3vUBmumz.d.cts} +163 -2
  35. package/dist/{types-DKmvjXK6.d.ts → types-3vUBmumz.d.ts} +163 -2
  36. package/package.json +2 -2
  37. package/dist/chunk-34YJQFCM.js.map +0 -1
  38. package/dist/chunk-DXBAN4SN.cjs.map +0 -1
  39. package/dist/chunk-I7SL4A6X.js.map +0 -1
  40. package/dist/chunk-IKQIIMM6.cjs.map +0 -1
  41. package/dist/chunk-MZKLAHBK.cjs.map +0 -1
  42. package/dist/chunk-ZDJ55LR7.js.map +0 -1
package/README.md CHANGED
@@ -273,7 +273,7 @@ const response = await haven.payX402Quote(quote)
273
273
  const data = await response.json()
274
274
  ```
275
275
 
276
- Merchant-verified x402 retries use the official EIP-3009 `exact` scheme on Base USDC (`base` / `eip155:8453`). `haven.fetch()` sends the payment under `PAYMENT-SIGNATURE` (the x402 v2 name), and on the EIP-3009 bridge also under `X-PAYMENT` (v1), so a merchant on either version reads it. **On erc7710 it sends the v2 name ALONE**: that payload is always x402 v2, and its header carries a whole delegation chain, so duplicating it overflows the merchant's header limit and the request is refused with HTTP 431. If you build the retry yourself, follow the same rule. Haven's older tx-hash proof helper remains exported for Haven-native integrations; it is a different payload that happens to have shared the v2 name, and it is not what `haven.fetch()` sends.
276
+ Merchant-verified x402 retries use the x402 `exact` scheme on Base USDC (`base` / `eip155:8453`, or Base Sepolia `eip155:84532`): the EIP-3009 `authorization` payload on the bridge, or a delegation when the merchant's entry carries `extra.assetTransferMethod: 'erc7710'`. `haven.fetch()` sends the payment under `PAYMENT-SIGNATURE` (the x402 v2 name), and on the EIP-3009 bridge also under `X-PAYMENT` (v1), so a merchant on either version reads it. **On erc7710 it sends the v2 name ALONE**: that payload is always x402 v2, and its header carries a whole delegation chain, so duplicating it overflows the merchant's header limit and the request is refused with HTTP 431. If you build the retry yourself, follow the same rule: `x402RetryHeadersFor(paymentHeader)` returns exactly those headers (#3727). Haven's older tx-hash proof helper remains exported for Haven-native integrations; it is a different payload that happens to have shared the v2 name, and it is not what `haven.fetch()` sends.
277
277
 
278
278
  For standard x402, the `x402-wallet` identity is the agent delegate wallet, because that is the wallet that signs and settles the merchant payment. Integrations that scope access by Haven wallet address should use a Haven-native flow instead of standard merchant x402.
279
279
 
@@ -412,6 +412,9 @@ x402 tool-window failures:
412
412
  expired funding/quote window → PAYMENT_WINDOW_EXPIRED → re-quote with same idempotency_key
413
413
  merchant rejection after funding → MERCHANT_REJECTED_AFTER_FUNDING → haven_sweep_delegate (eip3009 only; erc7710: nothing to sweep, follow the message)
414
414
  merchant timeout after funding → MERCHANT_UNRESPONSIVE_AFTER_FUNDING → check_status_later; eip3009: retry once, then haven_sweep_delegate; erc7710: no retry, check status after the window, re-quote only if unsettled
415
+ funding confirmation unreadable (eip3009, hosted) → FUNDING_CONFIRMATION_UNKNOWN → check_status_later; merchant not called; once funding shows confirmed, complete ONCE (#4470)
416
+ funding transaction reverted (eip3009, hosted) → FUNDING_REVERTED → stop_and_tell_user; nothing reached the delegate (#4470)
417
+ no answer to a submit (hosted haven_submit, and haven_settle_mcp_tool's erc7710 settle) → NO_ANSWER_OUTCOME_UNKNOWN → check_status_later; never re-submit, never a new payment (#4470)
415
418
  ```
416
419
 
417
420
  ### `phase` reference
@@ -428,6 +431,8 @@ x402 tool-window failures:
428
431
  | `rejected` | The payment was rejected and cannot proceed. | yes |
429
432
  | `expired` | Payment expired before completion. | yes |
430
433
  | `failed` | Haven could not complete the payment. | yes |
434
+ | `insufficient_funds` | Carried by the `delegation_budget_exceeded` refusal — `403` at prepare, or `502` when the budget ran out by the time the payment was signed — with `nextAction: fund_account_or_raise_allowance`. The budget must be raised, or the period reset, before a new payment can succeed. | yes |
435
+ | `funded_but_unsettled` | The EIP-3009 bridge's funding leg confirmed, but the merchant leg has not settled: either the merchant rejected the retry (`nextAction: sweep_stranded_funds`) or no merchant response was ever recorded (`nextAction: retry_original_x402_request`). Follow `nextAction`. | no |
431
436
  | `delivered_unverified` | **#3420: terminal.** The merchant delivered, but the settlement window and the sweep's last attribution chance have both passed with no verified on-chain evidence. Polling cannot change this; the only remedy is reporting a real settlement hash (`haven_report_settlement_evidence`). | yes |
432
437
 
433
438
  The merchant settlement leg of x402 (and the MPP retry) is the agent's own request to the merchant — it does not have a Haven `phase`. The payment is `funding_sent` until the agent retries with the payment header (`PAYMENT-SIGNATURE`, plus `X-PAYMENT` on this bridged path) (x402) or the MPP proof header; from Haven's perspective the payment becomes `executed` only after the agent successfully resumes.
@@ -445,6 +450,8 @@ The merchant settlement leg of x402 (and the MPP retry) is the agent's own reque
445
450
  | `retry_original_x402_request` | Haven's funding leg confirmed but no merchant response was ever recorded — most often because the process crashed between the funding confirmation and the merchant retry (a 15-minute grace window applies before this fires; a client-reported merchant rejection instead yields `sweep_stranded_funds`). Call `resumeX402Payment()` with the preserved `resumeState`, or rehydrate it first with `getResumeState(payment_id)`. Do not start a new payment for the same purchase. |
446
451
  | `stop_and_tell_user` | Stop retrying and tell the user what happened — the payment failed, was rejected, or (#3420) was delivered but its settlement can no longer be verified. |
447
452
  | `request_again_if_user_still_wants_it` | The request expired; ask again only if the user still wants the payment. |
453
+ | `retry_with_explicit_context` | #1307: retry the same tool call, passing `merchant_url`, `tool_name`, `arguments` and `mcp_transport` explicitly — the server had no stored context to rehydrate for this payment id. |
454
+ | `fund_account_or_raise_allowance` | Stop and tell the user the agent's budget must be raised (or its period reset) before a new payment can succeed; it rides on the `delegation_budget_exceeded` refusal. An approval will not fix it. |
448
455
  | `payment_window_expired` | The x402 funding/quote window expired. Re-quote the same paid MCP tool call with the same `idempotency_key`, then sign the fresh `payload_hash`. |
449
456
  | `sweep_stranded_funds` | A funding leg succeeded but the merchant/protocol leg did not settle. Stop retrying and use `haven_sweep_delegate` to recover stranded delegate funds. |
450
457
 
@@ -471,8 +478,10 @@ queue**: the queue-and-approve path belonged to the retired Safe rail, which now
471
478
  answers HTTP 410 at every agent-payment entry point.
472
479
 
473
480
  If an agent requests a payment outside that policy, Haven **declines it before
474
- any money moves** — during prepare, before anything is written and before the
475
- agent is asked to sign. `POST /payments` answers `403` when no active delegation
481
+ any money moves** — during prepare, before any payment intent is created and
482
+ before the agent is asked to sign. The one row written is the refusal itself,
483
+ in the `payment_refusals` ledger (#2945, migration 086; written through the
484
+ `refuse()` choke point since #3053). `POST /payments` answers `403` when no active delegation
476
485
  authorizes that token and recipient, `403 delegation_budget_exceeded` when the
477
486
  remaining period budget cannot cover the amount (#3503; the x402 authorize path
478
487
  answers the same), and `502` when the on-chain caveat check rejects a
@@ -609,7 +618,9 @@ For MCP/SSE x402 tools, keep the same MCP session and JSON-RPC payload where the
609
618
  merchant requires it: initialize, retain `mcp-session-id`, send the original
610
619
  `tools/call`, parse the 402 challenge, wait for the funding leg to confirm if
611
620
  the payment is bridged, then resume with the same `payment_id` and retry the
612
- original `tools/call`, setting BOTH `PAYMENT-SIGNATURE` (x402 v2) and `X-PAYMENT` (v1) to the header. Use a stable `idempotencyKey` for the
621
+ original `tools/call` with the headers `x402RetryHeadersFor(paymentHeader)`
622
+ returns — `PAYMENT-SIGNATURE` (x402 v2), plus `X-PAYMENT` (v1) only on the
623
+ EIP-3009 bridge; erc7710 sends the v2 name alone. Use a stable `idempotencyKey` for the
613
624
  user intent so fresh merchant quotes or sessions do not become duplicate Haven
614
625
  payments.
615
626
 
@@ -666,6 +677,28 @@ treat them as proof of purchase rather than retrying:
666
677
 
667
678
  See [Idempotency](#idempotency-what-the-key-guarantees-and-what-it-costs).
668
679
 
680
+ **Why a `HavenApiError` happened is `err.failureCause`, not only its status
681
+ (#4470).** The status alone misleads in two ways, so two causes are marked
682
+ where the SDK creates the error, and every other error leaves the field
683
+ `undefined`:
684
+
685
+ - `{ kind: 'no_answer', method }` — the transport got no usable answer: the
686
+ request timed out (`statusCode` 408), `fetch` threw, or the body was not
687
+ JSON (`statusCode` 0; a gateway's HTML 502 arrives this way). Whether the
688
+ call took effect is unknown. A `GET` may be retried; a `POST` should not
689
+ be — read the payment's status first. A server that answers 408 with a
690
+ JSON body is an answer and carries no cause.
691
+ - `{ kind: 'deterministic' }` — the SDK refused an answer it cannot use (a
692
+ missing field, the wrong shape). A retry gets the same answer, whatever the
693
+ 5xx status says. Built with `HavenApiError.deterministic(...)`.
694
+
695
+ The funding wait before a merchant retry has two typed outcomes, both
696
+ `HavenApiError` subclasses: `FundingConfirmationUnknownError` (status 504;
697
+ the confirmation could not be read in time, so funding may have moved — check
698
+ the payment's status) and `FundingRevertedError` (status 502; the funding
699
+ transaction reverted, nothing reached the delegate). Each carries `txHash`,
700
+ `chainId` and a `fundingErrorCode`.
701
+
669
702
  ## License
670
703
 
671
704
  MIT
@@ -1,4 +1,4 @@
1
- import { Q as AgentNextStep, Z as AgentPaymentNextAction, aM as X402PaymentOption, aL as X402ExpectedContext, X as X402PaymentRequired, I as HavenError, an as HavenSigningError } from './types-DKmvjXK6.js';
1
+ import { Q as AgentNextStep, Z as AgentPaymentNextAction, aP as X402PaymentOption, aO as X402ExpectedContext, X as X402PaymentRequired, I as HavenError, aq as HavenSigningError } from './types-3vUBmumz.cjs';
2
2
  import { PaymentRequirements } from 'x402/types';
3
3
  import { Hex, Address } from 'viem';
4
4
 
@@ -200,7 +200,7 @@ declare function buildSweepAuthorizationMessage(auth: SweepAuthorization): strin
200
200
  * This SDK's own version. Owned by `scripts/release-bump.mjs`, which rewrites
201
201
  * it with the package version on every release — never hand-edit it.
202
202
  */
203
- declare const SDK_VERSION = "0.11.0-alpha.0";
203
+ declare const SDK_VERSION = "0.13.0-alpha.0";
204
204
  /** The request header every published Haven client sends. */
205
205
  declare const HAVEN_CLIENT_HEADER = "X-Haven-Client";
206
206
  /** `<package>/<version>` — the value of {@link HAVEN_CLIENT_HEADER}. */
@@ -269,6 +269,14 @@ declare function parseNextTool(literal: string): {
269
269
  interface NextStepTarget<TArgs> {
270
270
  role: NextToolServerRole;
271
271
  validate: (input: unknown) => string | null;
272
+ /**
273
+ * #4449: the bare tool name to render, when the target-map key is not it.
274
+ * One hosted tool that takes several argument shapes is declared once per
275
+ * shape under `<tool>#<variant>` keys (the signer's `haven_submit#payment`
276
+ * beside `#task_budget` / `#sub_budget`): the key selects the shape, this
277
+ * names the tool. Absent → the key IS the name, which is every other target.
278
+ */
279
+ name?: string;
272
280
  /** Phantom carrier for the argument type; never read at runtime. */
273
281
  readonly _args?: TArgs;
274
282
  }
@@ -1,4 +1,4 @@
1
- import { Q as AgentNextStep, Z as AgentPaymentNextAction, aM as X402PaymentOption, aL as X402ExpectedContext, X as X402PaymentRequired, I as HavenError, an as HavenSigningError } from './types-DKmvjXK6.cjs';
1
+ import { Q as AgentNextStep, Z as AgentPaymentNextAction, aP as X402PaymentOption, aO as X402ExpectedContext, X as X402PaymentRequired, I as HavenError, aq as HavenSigningError } from './types-3vUBmumz.js';
2
2
  import { PaymentRequirements } from 'x402/types';
3
3
  import { Hex, Address } from 'viem';
4
4
 
@@ -200,7 +200,7 @@ declare function buildSweepAuthorizationMessage(auth: SweepAuthorization): strin
200
200
  * This SDK's own version. Owned by `scripts/release-bump.mjs`, which rewrites
201
201
  * it with the package version on every release — never hand-edit it.
202
202
  */
203
- declare const SDK_VERSION = "0.11.0-alpha.0";
203
+ declare const SDK_VERSION = "0.13.0-alpha.0";
204
204
  /** The request header every published Haven client sends. */
205
205
  declare const HAVEN_CLIENT_HEADER = "X-Haven-Client";
206
206
  /** `<package>/<version>` — the value of {@link HAVEN_CLIENT_HEADER}. */
@@ -269,6 +269,14 @@ declare function parseNextTool(literal: string): {
269
269
  interface NextStepTarget<TArgs> {
270
270
  role: NextToolServerRole;
271
271
  validate: (input: unknown) => string | null;
272
+ /**
273
+ * #4449: the bare tool name to render, when the target-map key is not it.
274
+ * One hosted tool that takes several argument shapes is declared once per
275
+ * shape under `<tool>#<variant>` keys (the signer's `haven_submit#payment`
276
+ * beside `#task_budget` / `#sub_budget`): the key selects the shape, this
277
+ * names the tool. Absent → the key IS the name, which is every other target.
278
+ */
279
+ name?: string;
272
280
  /** Phantom carrier for the argument type; never read at runtime. */
273
281
  readonly _args?: TArgs;
274
282
  }
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var chunkMZKLAHBK_cjs = require('./chunk-MZKLAHBK.cjs');
3
+ var chunkLZHCIK7L_cjs = require('./chunk-LZHCIK7L.cjs');
4
4
  var viem = require('viem');
5
5
  var crypto = require('crypto');
6
6
  var secp256k1 = require('@noble/curves/secp256k1');
7
7
  var accounts = require('viem/accounts');
8
8
 
9
9
  var TYPED_DATA_NOT_ALLOWED = "TYPED_DATA_NOT_ALLOWED";
10
- var HavenTypedDataRefusedError = class extends chunkMZKLAHBK_cjs.HavenSigningError {
10
+ var HavenTypedDataRefusedError = class extends chunkLZHCIK7L_cjs.HavenSigningError {
11
11
  constructor(message) {
12
12
  super(message);
13
13
  this.code = TYPED_DATA_NOT_ALLOWED;
@@ -48,7 +48,7 @@ function assertBoundDirectPaymentUserOp(typedData, delegateAddress) {
48
48
  `This signer only signs direct payments on chains the delegation rail has pinned contracts for (${[...DIRECT_PAYMENT_CHAIN_IDS].join(", ")}); this typed data names chain ${String(domain.chainId)}. Refusing.`
49
49
  );
50
50
  }
51
- const ownAccount = chunkMZKLAHBK_cjs.deriveDelegateAccountAddress(delegateAddress);
51
+ const ownAccount = chunkLZHCIK7L_cjs.deriveDelegateAccountAddress(delegateAddress);
52
52
  const sender = typeof message.sender === "string" ? message.sender : "";
53
53
  if (sender.toLowerCase() !== ownAccount.toLowerCase()) {
54
54
  throw new HavenTypedDataRefusedError(
@@ -78,9 +78,9 @@ function assertBoundDirectPaymentUserOp(typedData, delegateAddress) {
78
78
  "This UserOperation's execute() call does not re-encode to the exact callData bytes (trailing or non-canonical bytes). Refusing."
79
79
  );
80
80
  }
81
- if (decoded.target.toLowerCase() !== chunkMZKLAHBK_cjs.DELEGATION_MANAGER.toLowerCase()) {
81
+ if (decoded.target.toLowerCase() !== chunkLZHCIK7L_cjs.DELEGATION_MANAGER.toLowerCase()) {
82
82
  throw new HavenTypedDataRefusedError(
83
- `This UserOperation's execute() calls ${decoded.target}, not the DelegationManager (${chunkMZKLAHBK_cjs.DELEGATION_MANAGER}). A direct payment only ever redeems the agent's own budget delegation \u2014 refusing what looks like a self-call (e.g. transferOwnership, updateSigners, upgradeToAndCall) or a call to an unrelated contract.`
83
+ `This UserOperation's execute() calls ${decoded.target}, not the DelegationManager (${chunkLZHCIK7L_cjs.DELEGATION_MANAGER}). A direct payment only ever redeems the agent's own budget delegation \u2014 refusing what looks like a self-call (e.g. transferOwnership, updateSigners, upgradeToAndCall) or a call to an unrelated contract.`
84
84
  );
85
85
  }
86
86
  if (decoded.value !== 0n) {
@@ -89,20 +89,20 @@ function assertBoundDirectPaymentUserOp(typedData, delegateAddress) {
89
89
  );
90
90
  }
91
91
  try {
92
- chunkMZKLAHBK_cjs.assertRedeemsOwnBudgetDelegation(decoded.callData, ownAccount);
92
+ chunkLZHCIK7L_cjs.assertRedeemsOwnBudgetDelegation(decoded.callData, ownAccount);
93
93
  } catch (err) {
94
94
  throw new HavenTypedDataRefusedError(err instanceof Error ? err.message : String(err));
95
95
  }
96
96
  }
97
97
  function assertOwnSettlementChild(typedData, expectation, delegateAddress) {
98
98
  try {
99
- chunkMZKLAHBK_cjs.verifySettlementChild(typedData, {
99
+ chunkLZHCIK7L_cjs.verifySettlementChild(typedData, {
100
100
  ...expectation,
101
- delegatorAccount: chunkMZKLAHBK_cjs.deriveDelegateAccountAddress(delegateAddress)
101
+ delegatorAccount: chunkLZHCIK7L_cjs.deriveDelegateAccountAddress(delegateAddress)
102
102
  });
103
103
  } catch (err) {
104
104
  if (err instanceof HavenTypedDataRefusedError) throw err;
105
- if (err instanceof chunkMZKLAHBK_cjs.HavenSigningError) throw new HavenTypedDataRefusedError(err.message);
105
+ if (err instanceof chunkLZHCIK7L_cjs.HavenSigningError) throw new HavenTypedDataRefusedError(err.message);
106
106
  throw new HavenTypedDataRefusedError(
107
107
  `Refusing to sign the x402 settlement child: it is malformed (${err instanceof Error ? err.message : String(err)}).`
108
108
  );
@@ -131,7 +131,7 @@ function assertFundingLegPaysDelegate(typedData, expected) {
131
131
  try {
132
132
  const { args: executeArgs } = viem.decodeFunctionData({ abi: EXECUTE_ABI, data: message.callData });
133
133
  const inner = executeArgs[0].callData;
134
- const { args } = viem.decodeFunctionData({ abi: chunkMZKLAHBK_cjs.REDEEM_DELEGATIONS_ABI, data: inner });
134
+ const { args } = viem.decodeFunctionData({ abi: chunkLZHCIK7L_cjs.REDEEM_DELEGATIONS_ABI, data: inner });
135
135
  const executions = args[2];
136
136
  executionCallData = executions[0];
137
137
  } catch {
@@ -250,7 +250,7 @@ var TRANSFER_WITH_AUTHORIZATION_TYPES = {
250
250
  function sweepUsdcAddress(chainId) {
251
251
  const address = USDC_ADDRESS_BY_CHAIN[chainId];
252
252
  if (!address) {
253
- throw new chunkMZKLAHBK_cjs.HavenSigningError(
253
+ throw new chunkLZHCIK7L_cjs.HavenSigningError(
254
254
  `Sweep is not supported on chain ${chainId}. Supported: ${SWEEPABLE_CHAIN_IDS.join(", ")}.`
255
255
  );
256
256
  }
@@ -259,7 +259,7 @@ function sweepUsdcAddress(chainId) {
259
259
  function sweepUsdcDomain(chainId) {
260
260
  const domain = USDC_EIP712_DOMAIN_BY_CHAIN[chainId];
261
261
  if (!domain) {
262
- throw new chunkMZKLAHBK_cjs.HavenSigningError(
262
+ throw new chunkLZHCIK7L_cjs.HavenSigningError(
263
263
  `Sweep is not supported on chain ${chainId}. Supported: ${SWEEPABLE_CHAIN_IDS.join(", ")}.`
264
264
  );
265
265
  }
@@ -272,12 +272,12 @@ function buildSweepTypedData(auth) {
272
272
  const domain = sweepUsdcDomain(auth.chainId);
273
273
  const expectedToken = sweepUsdcAddress(auth.chainId);
274
274
  if (!sameAddress(auth.token, expectedToken)) {
275
- throw new chunkMZKLAHBK_cjs.HavenSigningError(
275
+ throw new chunkLZHCIK7L_cjs.HavenSigningError(
276
276
  `Sweep token ${auth.token} is not the canonical USDC contract for chain ${auth.chainId}.`
277
277
  );
278
278
  }
279
279
  if (!/^0x[0-9a-fA-F]{64}$/.test(auth.nonce)) {
280
- throw new chunkMZKLAHBK_cjs.HavenSigningError("Sweep nonce must be a 0x-prefixed 32-byte hex string.");
280
+ throw new chunkLZHCIK7L_cjs.HavenSigningError("Sweep nonce must be a 0x-prefixed 32-byte hex string.");
281
281
  }
282
282
  return {
283
283
  domain,
@@ -782,7 +782,7 @@ function stableStringify2(value) {
782
782
  }
783
783
 
784
784
  // src/client-identity.ts
785
- var SDK_VERSION = "0.11.0-alpha.0";
785
+ var SDK_VERSION = "0.13.0-alpha.0";
786
786
  var HAVEN_CLIENT_HEADER = "X-Haven-Client";
787
787
  function havenClientIdentity(pkg, version) {
788
788
  return `${pkg}/${version}`;
@@ -815,7 +815,7 @@ function addressFromKey(privateKey) {
815
815
  try {
816
816
  return accounts.privateKeyToAddress(`0x${hexBytes(privateKey, 32, "private key")}`);
817
817
  } catch (err) {
818
- throw new chunkMZKLAHBK_cjs.HavenSigningError(
818
+ throw new chunkLZHCIK7L_cjs.HavenSigningError(
819
819
  `Invalid private key: ${err instanceof Error ? err.message : String(err)}`
820
820
  );
821
821
  }
@@ -829,7 +829,7 @@ function signHash(privateKey, hash) {
829
829
  yParity: recovery
830
830
  });
831
831
  } catch (err) {
832
- throw new chunkMZKLAHBK_cjs.HavenSigningError(
832
+ throw new chunkLZHCIK7L_cjs.HavenSigningError(
833
833
  `Failed to sign hash: ${err instanceof Error ? err.message : String(err)}`
834
834
  );
835
835
  }
@@ -865,7 +865,7 @@ var TAX_DECLARATION_TYPES = {
865
865
  var X_TAX_DECLARATION_HEADER = "X-Tax-Declaration";
866
866
  function validateContent(content) {
867
867
  if (typeof content !== "object" || content === null || Array.isArray(content)) {
868
- throw new chunkMZKLAHBK_cjs.HavenSigningError("Tax declaration content must be an object.");
868
+ throw new chunkLZHCIK7L_cjs.HavenSigningError("Tax declaration content must be an object.");
869
869
  }
870
870
  const record = content;
871
871
  for (const field of ["principalId", "principalAttributionHash"]) {
@@ -918,7 +918,7 @@ function taxPrincipalId(network, delegateAddress) {
918
918
  if (network.startsWith("eip155:")) {
919
919
  return `did:pkh:${network}:${delegateAddress}`;
920
920
  }
921
- const chainId = chunkMZKLAHBK_cjs.chainIdForNetwork(network);
921
+ const chainId = chunkLZHCIK7L_cjs.chainIdForNetwork(network);
922
922
  if (chainId === void 0) {
923
923
  throw new TaxDeclarationRefusedError(
924
924
  `The accepted payment option's network '${network}' is not a CAIP-2 eip155 chain this SDK can name; refusing to build a tax principal without the settlement network.`
@@ -963,12 +963,12 @@ function addressFromKeyForTax(delegateKey) {
963
963
  try {
964
964
  return addressFromKey(delegateKey);
965
965
  } catch (err) {
966
- throw new chunkMZKLAHBK_cjs.HavenSigningError(
966
+ throw new chunkLZHCIK7L_cjs.HavenSigningError(
967
967
  `Invalid delegate key for tax declaration signing: ${err instanceof Error ? err.message : String(err)}`
968
968
  );
969
969
  }
970
970
  }
971
- var TaxDeclarationRefusedError = class extends chunkMZKLAHBK_cjs.HavenSigningError {
971
+ var TaxDeclarationRefusedError = class extends chunkLZHCIK7L_cjs.HavenSigningError {
972
972
  code = "TAX_DECLARATION_REFUSED";
973
973
  constructor(message) {
974
974
  super(message);
@@ -1027,11 +1027,12 @@ function createNextStepBuilder(targets) {
1027
1027
  if (problem) {
1028
1028
  return { ...base, next_tool_omitted_reason: `next_arguments do not parse under ${i.nextTool}: ${problem}` };
1029
1029
  }
1030
+ const name = target.name ?? i.nextTool;
1030
1031
  return {
1031
1032
  ...base,
1032
- next_tool: renderNextTool(target.role, i.nextTool),
1033
+ next_tool: renderNextTool(target.role, name),
1033
1034
  next_tool_server: NEXT_TOOL_SERVER_NAMES[target.role],
1034
- next_tool_name: i.nextTool,
1035
+ next_tool_name: name,
1035
1036
  next_tool_server_role: target.role,
1036
1037
  next_arguments: i.nextArguments
1037
1038
  };
@@ -1124,10 +1125,10 @@ function assertOwnTaskChild(typedData, expected, delegateAddress, now = Date.now
1124
1125
  if (td?.primaryType !== "Delegation") {
1125
1126
  refuseTaskChild("it is not a Delegation payload", `primaryType was '${String(td?.primaryType)}'.`);
1126
1127
  }
1127
- if (!same(td.domain?.verifyingContract, chunkMZKLAHBK_cjs.DELEGATION_MANAGER)) {
1128
+ if (!same(td.domain?.verifyingContract, chunkLZHCIK7L_cjs.DELEGATION_MANAGER)) {
1128
1129
  refuseTaskChild(
1129
1130
  "the EIP-712 domain names an unknown DelegationManager",
1130
- `Expected ${chunkMZKLAHBK_cjs.DELEGATION_MANAGER}, got ${td.domain?.verifyingContract}.`
1131
+ `Expected ${chunkLZHCIK7L_cjs.DELEGATION_MANAGER}, got ${td.domain?.verifyingContract}.`
1131
1132
  );
1132
1133
  }
1133
1134
  if (td.domain?.name !== DELEGATION_DOMAIN_NAME || td.domain?.version !== DELEGATION_DOMAIN_VERSION) {
@@ -1155,7 +1156,7 @@ function assertOwnTaskChild(typedData, expected, delegateAddress, now = Date.now
1155
1156
  `Expected chain ${expected.chainId}; the child says ${td.domain?.chainId}.`
1156
1157
  );
1157
1158
  }
1158
- const ownAccount = chunkMZKLAHBK_cjs.deriveDelegateAccountAddress(delegateAddress);
1159
+ const ownAccount = chunkLZHCIK7L_cjs.deriveDelegateAccountAddress(delegateAddress);
1159
1160
  const delegator = td.message?.delegator;
1160
1161
  if (typeof delegator !== "string" || !same(delegator, ownAccount)) {
1161
1162
  refuseTaskChild(
@@ -1174,7 +1175,7 @@ function assertOwnTaskChild(typedData, expected, delegateAddress, now = Date.now
1174
1175
  if (typeof authority !== "string" || !/^0x[0-9a-fA-F]{64}$/.test(authority)) {
1175
1176
  refuseTaskChild("its authority is not a 32-byte delegation hash", `Got ${String(authority)}.`);
1176
1177
  }
1177
- if (authority.toLowerCase() === chunkMZKLAHBK_cjs.ROOT_AUTHORITY) {
1178
+ if (authority.toLowerCase() === chunkLZHCIK7L_cjs.ROOT_AUTHORITY) {
1178
1179
  refuseTaskChild(
1179
1180
  "it is a ROOT delegation, not a re-delegation of the agent budget",
1180
1181
  "A task budget always chains under the agent budget delegation."
@@ -1187,7 +1188,7 @@ function assertOwnTaskChild(typedData, expected, delegateAddress, now = Date.now
1187
1188
  );
1188
1189
  }
1189
1190
  const caveats = td.message?.caveats ?? [];
1190
- const transfer = findCaveat(caveats, chunkMZKLAHBK_cjs.CAVEAT_ENFORCERS.erc20TransferAmount);
1191
+ const transfer = findCaveat(caveats, chunkLZHCIK7L_cjs.CAVEAT_ENFORCERS.erc20TransferAmount);
1191
1192
  if (!transfer) {
1192
1193
  refuseTaskChild(
1193
1194
  "it has no ERC-20 transfer-amount caveat",
@@ -1205,7 +1206,7 @@ function assertOwnTaskChild(typedData, expected, delegateAddress, now = Date.now
1205
1206
  `Expected ${expected.maxAmountAtomic}; the child allows ${amount.toString()}.`
1206
1207
  );
1207
1208
  }
1208
- const timestamp = findCaveat(caveats, chunkMZKLAHBK_cjs.CAVEAT_ENFORCERS.timestamp);
1209
+ const timestamp = findCaveat(caveats, chunkLZHCIK7L_cjs.CAVEAT_ENFORCERS.timestamp);
1209
1210
  if (!timestamp) {
1210
1211
  refuseTaskChild("it never expires", "A task-budget child without a timestamp caveat is open-ended.");
1211
1212
  }
@@ -1226,7 +1227,7 @@ function assertOwnTaskChild(typedData, expected, delegateAddress, now = Date.now
1226
1227
  `Expected ${expected.expiresAt}; the child says ${beforeThreshold}.`
1227
1228
  );
1228
1229
  }
1229
- const calldata = findCaveat(caveats, chunkMZKLAHBK_cjs.CAVEAT_ENFORCERS.allowedCalldata);
1230
+ const calldata = findCaveat(caveats, chunkLZHCIK7L_cjs.CAVEAT_ENFORCERS.allowedCalldata);
1230
1231
  if (expected.recipientAddress) {
1231
1232
  if (!calldata) {
1232
1233
  refuseTaskChild(
@@ -1263,7 +1264,7 @@ var DISABLE_DELEGATION_ABI = [
1263
1264
  {
1264
1265
  type: "function",
1265
1266
  name: "disableDelegation",
1266
- inputs: [{ name: "delegation", type: "tuple", components: chunkMZKLAHBK_cjs.DELEGATION_TUPLE_COMPONENTS }],
1267
+ inputs: [{ name: "delegation", type: "tuple", components: chunkLZHCIK7L_cjs.DELEGATION_TUPLE_COMPONENTS }],
1267
1268
  outputs: [],
1268
1269
  stateMutability: "nonpayable"
1269
1270
  }
@@ -1282,7 +1283,7 @@ function assertOwnTaskBudgetCloseUserOp(typedData, expected, delegateAddress) {
1282
1283
  `This signer only signs a task-budget close on chains the delegation rail has pinned contracts for (${[...DIRECT_PAYMENT_CHAIN_IDS].join(", ")}); this typed data names chain ${String(domain.chainId)}. Refusing.`
1283
1284
  );
1284
1285
  }
1285
- const ownAccount = chunkMZKLAHBK_cjs.deriveDelegateAccountAddress(delegateAddress);
1286
+ const ownAccount = chunkLZHCIK7L_cjs.deriveDelegateAccountAddress(delegateAddress);
1286
1287
  const sender = typeof message.sender === "string" ? message.sender : "";
1287
1288
  if (sender.toLowerCase() !== ownAccount.toLowerCase()) {
1288
1289
  throw new HavenTypedDataRefusedError(
@@ -1305,9 +1306,9 @@ function assertOwnTaskBudgetCloseUserOp(typedData, expected, delegateAddress) {
1305
1306
  "This close UserOperation's execute() call does not re-encode to the exact callData bytes (trailing or non-canonical bytes). Refusing."
1306
1307
  );
1307
1308
  }
1308
- if (decoded.target.toLowerCase() !== chunkMZKLAHBK_cjs.DELEGATION_MANAGER.toLowerCase()) {
1309
+ if (decoded.target.toLowerCase() !== chunkLZHCIK7L_cjs.DELEGATION_MANAGER.toLowerCase()) {
1309
1310
  throw new HavenTypedDataRefusedError(
1310
- `This close UserOperation's execute() calls ${decoded.target}, not the DelegationManager (${chunkMZKLAHBK_cjs.DELEGATION_MANAGER}). Refusing what looks like a self-call or a call to an unrelated contract.`
1311
+ `This close UserOperation's execute() calls ${decoded.target}, not the DelegationManager (${chunkLZHCIK7L_cjs.DELEGATION_MANAGER}). Refusing what looks like a self-call or a call to an unrelated contract.`
1311
1312
  );
1312
1313
  }
1313
1314
  if (decoded.value !== 0n) {
@@ -1344,7 +1345,7 @@ function assertOwnTaskBudgetCloseUserOp(typedData, expected, delegateAddress) {
1344
1345
  `This close UserOperation disables a delegation granted to ${delegation.delegate}, not this signer's own account (${ownAccount}) \u2014 a task-budget child is always self-delegated. Refusing.`
1345
1346
  );
1346
1347
  }
1347
- if (delegation.authority.toLowerCase() === chunkMZKLAHBK_cjs.ROOT_AUTHORITY) {
1348
+ if (delegation.authority.toLowerCase() === chunkLZHCIK7L_cjs.ROOT_AUTHORITY) {
1348
1349
  throw new HavenTypedDataRefusedError(
1349
1350
  "This close UserOperation disables a ROOT delegation, not a re-delegation of the agent budget. A task-budget child always chains under the agent budget delegation. Refusing."
1350
1351
  );
@@ -1477,5 +1478,5 @@ exports.x402PaymentHeaderNamesFor = x402PaymentHeaderNamesFor;
1477
1478
  exports.x402PaymentHeaderNamesSent = x402PaymentHeaderNamesSent;
1478
1479
  exports.x402RetryHeadersFor = x402RetryHeadersFor;
1479
1480
  exports.x402V2PaymentEnvelope = x402V2PaymentEnvelope;
1480
- //# sourceMappingURL=chunk-IKQIIMM6.cjs.map
1481
- //# sourceMappingURL=chunk-IKQIIMM6.cjs.map
1481
+ //# sourceMappingURL=chunk-4Z7PKLFD.cjs.map
1482
+ //# sourceMappingURL=chunk-4Z7PKLFD.cjs.map