@haven_ai/sdk 0.1.37-alpha.0 → 0.2.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.
package/dist/index.cjs CHANGED
@@ -110,9 +110,14 @@ var AgentPaymentNextAction = {
110
110
  */
111
111
  PaymentWindowExpired: "payment_window_expired",
112
112
  /**
113
- * Stop and tell the user that the originating Safe needs to be funded or
113
+ * Stop and tell the user that the originating account needs to be funded or
114
114
  * the agent's per-token allowance needs to be raised before the payment
115
115
  * can succeed. A user approval will not fix this state on its own.
116
+ *
117
+ * #2908: the wire twin `fund_account_or_raise_allowance`
118
+ * ({@link AgentPaymentNextActionAccountAlias}) means the same thing; the
119
+ * server keeps emitting THIS value until #2914. Compare via
120
+ * {@link canonicalAgentPaymentNextAction}.
116
121
  */
117
122
  FundSafeOrRaiseAllowance: "fund_safe_or_raise_allowance",
118
123
  /**
@@ -122,6 +127,19 @@ var AgentPaymentNextAction = {
122
127
  */
123
128
  SweepStrandedFunds: "sweep_stranded_funds"
124
129
  };
130
+ var AgentPaymentNextActionAccountAlias = {
131
+ /** Account-vocabulary twin of `fund_safe_or_raise_allowance`; same meaning. */
132
+ FundAccountOrRaiseAllowance: "fund_account_or_raise_allowance"
133
+ };
134
+ function canonicalAgentPaymentNextAction(value) {
135
+ if (value === AgentPaymentNextActionAccountAlias.FundAccountOrRaiseAllowance) {
136
+ return AgentPaymentNextAction.FundSafeOrRaiseAllowance;
137
+ }
138
+ return value;
139
+ }
140
+ function isFundAccountOrRaiseAllowance(value) {
141
+ return value === AgentPaymentNextAction.FundSafeOrRaiseAllowance || value === AgentPaymentNextActionAccountAlias.FundAccountOrRaiseAllowance;
142
+ }
125
143
  var AgentPaymentFailureCode = {
126
144
  /** A merchant-authoritative x402 price exceeds the caller's pre-funding max_amount cap. */
127
145
  PriceExceedsMax: "PRICE_EXCEEDS_MAX",
@@ -1128,7 +1146,10 @@ function mapPaymentStatusResult(raw) {
1128
1146
  rail: raw.rail,
1129
1147
  status: raw.status,
1130
1148
  phase: raw.phase,
1131
- nextAction: raw.next_action,
1149
+ // #2908: the account-vocabulary alias collapses onto the canonical value
1150
+ // so every `=== AgentPaymentNextAction.X` downstream keeps working when
1151
+ // the server flips its emit at #2914.
1152
+ nextAction: canonicalAgentPaymentNextAction(raw.next_action),
1132
1153
  amount: raw.amount,
1133
1154
  token: raw.token,
1134
1155
  resourceUrl: raw.resource_url,
@@ -1260,7 +1281,7 @@ function messageForState(label, status, paymentId, nextAction) {
1260
1281
  function paymentStateFromRaw(label, raw) {
1261
1282
  if (!raw.payment_id || !raw.status) return null;
1262
1283
  const phase = raw.phase ?? phaseForStatus(raw.status);
1263
- const nextAction = raw.next_action ?? nextActionForStatus(raw.status);
1284
+ const nextAction = canonicalAgentPaymentNextAction(raw.next_action) ?? nextActionForStatus(raw.status);
1264
1285
  if (!phase || !nextAction) return null;
1265
1286
  const amount = raw.amount ?? raw.requested ?? "";
1266
1287
  const token = raw.token ?? "";
@@ -1583,6 +1604,20 @@ function verifyPaymentReceipt(receipt, recover = defaultRecover) {
1583
1604
  return { verified: true, recoveredSigner: recovered };
1584
1605
  }
1585
1606
 
1607
+ // src/account-naming.ts
1608
+ function readAccountAddress(raw) {
1609
+ return raw.account_address ?? raw.safe_address ?? void 0;
1610
+ }
1611
+ function readAccountId(raw) {
1612
+ return raw.account_id ?? raw.safe_id ?? void 0;
1613
+ }
1614
+ function accountAddressTwins(address) {
1615
+ return { accountAddress: address, safeAddress: address };
1616
+ }
1617
+ function readX402ReceiptPayer(raw) {
1618
+ return raw.payer ?? raw.account_address ?? raw.sign_data?.components?.payer_account ?? raw.safe_address ?? raw.sign_data?.components?.safe;
1619
+ }
1620
+
1586
1621
  // src/account-reads.ts
1587
1622
  function safeBigInt(value) {
1588
1623
  try {
@@ -1641,7 +1676,10 @@ var AccountReads = class {
1641
1676
  const raw = await this.transport.get("/machine-payments/allowances");
1642
1677
  return {
1643
1678
  agentId: raw.agent_id,
1644
- safeAddress: raw.safe_address,
1679
+ // #2908: one mapper, both names, same value — `readAccountAddress`
1680
+ // prefers the server's `account_address` twin and falls back to
1681
+ // `safe_address` for a pre-#2907 server.
1682
+ ...accountAddressTwins(readAccountAddress(raw)),
1645
1683
  delegateAddress: raw.delegate_address,
1646
1684
  chainId: raw.chain_id,
1647
1685
  allowances: raw.allowances.map((allowance) => ({
@@ -1730,7 +1768,10 @@ var AccountReads = class {
1730
1768
  id: raw.id,
1731
1769
  name: raw.name,
1732
1770
  status: raw.status,
1733
- safeAddress: raw.safe_address,
1771
+ // #2908: both camelCase names off whichever snake_case name the server
1772
+ // sent (new first). The hosted MCP's `haven_get_agent` spreads this
1773
+ // object, so this is also the hosted output's dual-emit point.
1774
+ ...accountAddressTwins(readAccountAddress(raw)),
1734
1775
  delegateAddress: raw.delegate_address,
1735
1776
  chainId: raw.chain_id,
1736
1777
  executionRail: raw.execution_rail === "delegation" ? "delegation" : "legacy"
@@ -1780,7 +1821,7 @@ var DelegateSweepApi = class {
1780
1821
  const contract = createErc20Contract(sweepUsdcAddress(agent.chainId), ["function balanceOf(address) view returns (uint256)", "function transfer(address to, uint256 amount) returns (bool)"], wallet);
1781
1822
  const balance2 = await contract.balanceOf(agent.delegateAddress);
1782
1823
  if (balance2 > 0n) {
1783
- const tx = await contract.transfer(agent.safeAddress, balance2);
1824
+ const tx = await contract.transfer(agent.accountAddress, balance2);
1784
1825
  const { txHash, confirmation } = await waitForSweepTx(tx);
1785
1826
  transfers.push({ asset: "USDC", amount: format(balance2, 6), amountAtomic: balance2.toString(), txHash, explorerUrl: this.options.buildExplorerUrl(agent.chainId, txHash), confirmation });
1786
1827
  }
@@ -1790,12 +1831,12 @@ var DelegateSweepApi = class {
1790
1831
  const fee = await provider.getFeeData();
1791
1832
  const send = balance - (fee.maxFeePerGas ?? fee.gasPrice ?? 1000000n) * 21000n * 2n;
1792
1833
  if (send > 0n) {
1793
- const tx = await wallet.sendTransaction({ to: agent.safeAddress, value: send });
1834
+ const tx = await wallet.sendTransaction({ to: agent.accountAddress, value: send });
1794
1835
  const { txHash, confirmation } = await waitForSweepTx(tx);
1795
1836
  transfers.push({ asset: "ETH", amount: format(send, 18), amountAtomic: send.toString(), txHash, explorerUrl: this.options.buildExplorerUrl(agent.chainId, txHash), confirmation });
1796
1837
  }
1797
1838
  }
1798
- return { fromAddress: agent.delegateAddress, toAddress: agent.safeAddress, chainId: agent.chainId, transfers, unconfirmed: transfers.some((t) => t.confirmation === "unconfirmed") };
1839
+ return { fromAddress: agent.delegateAddress, toAddress: agent.accountAddress, chainId: agent.chainId, transfers, unconfirmed: transfers.some((t) => t.confirmation === "unconfirmed") };
1799
1840
  }
1800
1841
  prepareSweep() {
1801
1842
  return this.options.transport.post("/machine-payments/sweep/prepare", {});
@@ -2189,7 +2230,7 @@ var X402FundingLeg = class {
2189
2230
  const to = execResult?.to ?? raw.to ?? this.delegateAddress ?? "";
2190
2231
  const explorerUrl = execResult?.explorer_url ?? raw.explorer_url ?? explorerUrlOrEmpty(chainId, txHash);
2191
2232
  const merchantTo = execResult?.merchant_to ?? raw.merchant_to ?? option.payTo;
2192
- const payer = raw.payer ?? raw.safe_address ?? raw.sign_data?.components.safe;
2233
+ const payer = readX402ReceiptPayer(raw);
2193
2234
  return buildX402Receipt({
2194
2235
  paymentId: raw.payment_id,
2195
2236
  txHash,
@@ -4022,13 +4063,13 @@ var toolDescriptions = {
4022
4063
  summary: "Pay an inspected x402 quote. The delegate key signs locally; Haven only validates and relays signed, on-chain-constrained payment transactions.",
4023
4064
  selectionGuidance: "Do not use this for read-only allowance, budget, spend-limit, remaining-amount, reset-period, or what-can-I-spend questions; use the allowance lookup tool instead.",
4024
4065
  behavior: "Signs the payment locally and returns the merchant response. Settlement is either direct account-to-merchant with no funding leg, or a bridge that first redeems the agent's budget delegation to fund the delegate wallet for an EIP-3009 authorization. A payment outside the on-chain budget is declined before any money moves; nothing is queued for a human to approve later.",
4025
- nextActionGuidance: "Preserve the returned resume_state \u2014 it identifies this payment if you need to ask about it later. This tool performs the merchant retry itself, so do not wait on a signal while the call is in flight. If the process crashes after this call and a later haven_get_payment_status reports nextAction=retry_original_x402_request, Haven's funding leg confirmed but no merchant response was ever recorded \u2014 call the resume tool with the preserved resume_state or payment_id instead of paying again. If the response carries phase=insufficient_funds and nextAction=fund_safe_or_raise_allowance, the payment cannot be retried until the account is funded or the agent budget raised \u2014 stop and tell the user the shortfall reported on the response."
4066
+ nextActionGuidance: "Preserve the returned resume_state \u2014 it identifies this payment if you need to ask about it later. This tool performs the merchant retry itself, so do not wait on a signal while the call is in flight. If the process crashes after this call and a later haven_get_payment_status reports nextAction=retry_original_x402_request, Haven's funding leg confirmed but no merchant response was ever recorded \u2014 call the resume tool with the preserved resume_state or payment_id instead of paying again. If the response carries phase=insufficient_funds and nextAction=fund_safe_or_raise_allowance (or fund_account_or_raise_allowance), the payment cannot be retried until the account is funded or the agent budget raised \u2014 stop and tell the user the shortfall reported on the response."
4026
4067
  },
4027
4068
  payX402OneShot: {
4028
4069
  summary: "Fetch an x402 paid HTTP resource in a single call. Handles the full probe -> pay -> retry round trip and returns the merchant response.",
4029
4070
  selectionGuidance: "Prefer this over the quote+pay split when the agent just wants the paid resource and does not need to inspect the price first. If you already have a quote from haven_quote_x402, use haven_pay_x402_quote instead. Do not use for read-only allowance, budget, spend-limit, remaining-amount, reset-period, or what-can-I-spend questions; use the allowance lookup tool instead.",
4030
4071
  behavior: "Calls the URL, parses any HTTP 402 x402 challenge, signs the payment locally, then retries the original request with the signed payment header (sent under PAYMENT-SIGNATURE, plus the legacy X-PAYMENT on the EIP-3009 path only) and returns the merchant response. Settlement is either direct account-to-merchant with no funding leg, or a bridge that first redeems the agent's budget delegation to fund the delegate wallet for an EIP-3009 authorization. A payment outside the on-chain budget is declined before any money moves; nothing is queued for a human to approve later. If the resource returns a non-402 status, returns it unchanged without contacting Haven.",
4031
- nextActionGuidance: "Preserve the returned resume_state or paymentId \u2014 either identifies this payment if you need to ask about it later. This tool performs the merchant retry itself, so do not wait on a signal while the call is in flight. If the process crashes after this call and a later haven_get_payment_status reports nextAction=retry_original_x402_request, Haven's funding leg confirmed but no merchant response was ever recorded \u2014 call the resume tool with the preserved resume_state or payment_id instead of paying again. If the response carries phase=insufficient_funds and nextAction=fund_safe_or_raise_allowance, the payment cannot be retried until the account is funded or the agent budget raised \u2014 stop and tell the user the shortfall reported on the response."
4072
+ nextActionGuidance: "Preserve the returned resume_state or paymentId \u2014 either identifies this payment if you need to ask about it later. This tool performs the merchant retry itself, so do not wait on a signal while the call is in flight. If the process crashes after this call and a later haven_get_payment_status reports nextAction=retry_original_x402_request, Haven's funding leg confirmed but no merchant response was ever recorded \u2014 call the resume tool with the preserved resume_state or payment_id instead of paying again. If the response carries phase=insufficient_funds and nextAction=fund_safe_or_raise_allowance (or fund_account_or_raise_allowance), the payment cannot be retried until the account is funded or the agent budget raised \u2014 stop and tell the user the shortfall reported on the response."
4032
4073
  },
4033
4074
  resumeX402: {
4034
4075
  summary: "Resume an x402 payment whose Haven-side authorization already succeeded but whose merchant retry did not complete.",
@@ -4052,7 +4093,7 @@ var toolDescriptions = {
4052
4093
  getAgent: {
4053
4094
  summary: "Return the authenticated agent identity AND its live spend authority in one call: Haven wallet, delegate, chain, raw status, spend_authority_readiness, and per-token remaining allowance (atomic + human-readable). The recommended first call in a new session to confirm who you are and whether Haven will let you spend right now.",
4054
4095
  selectionGuidance: "Use this as the one-shot orientation/bootstrap at the start of a session, or whenever you need to confirm identity together with whether the agent can spend right now. For a detailed per-token breakdown (configured vs spent vs reset window) use haven_get_allowances.",
4055
- behavior: `Reads identity plus the live spend-authority snapshot in one shot \u2014 the agent's active on-chain budget delegation. spend_authority_readiness (readiness is a deprecated alias, same value) is "ready" when at least one token has remaining spend authority, "needs_approval" when the agent is active but has none, and "revoked" when the credential is not active. It covers hosted identity + on-chain spend authority ONLY \u2014 the hosted server cannot see the LOCAL signer, so "ready" does not mean the signer can start; verify the signer with a signer tool call or connect --doctor. An over-budget payment is declined before any money moves: there is no approval queue, so ask the owner to grant or raise the budget in Haven rather than waiting for an approval. allowances[] carries remainingAtomic and remainingDisplay per token. Identity fields (id, name, status, safeAddress, delegateAddress, chainId) are unchanged from before.`,
4096
+ behavior: `Reads identity plus the live spend-authority snapshot in one shot \u2014 the agent's active on-chain budget delegation. spend_authority_readiness (readiness is a deprecated alias, same value) is "ready" when at least one token has remaining spend authority, "needs_approval" when the agent is active but has none, and "revoked" when the credential is not active. It covers hosted identity + on-chain spend authority ONLY \u2014 the hosted server cannot see the LOCAL signer, so "ready" does not mean the signer can start; verify the signer with a signer tool call or connect --doctor. An over-budget payment is declined before any money moves: there is no approval queue, so ask the owner to grant or raise the budget in Haven rather than waiting for an approval. allowances[] carries remainingAtomic and remainingDisplay per token. Identity fields: id, name, status, accountAddress (safeAddress: deprecated alias, same value), delegateAddress, chainId.`,
4056
4097
  nextActionGuidance: ""
4057
4098
  },
4058
4099
  getAllowances: {
@@ -4092,9 +4133,9 @@ var toolDescriptions = {
4092
4133
  nextActionGuidance: "Give the verify_token and the well-known instructions (from getCatalogSubmissionStatus) to the merchant so they can publish the proof line, then poll the submission status until it reaches verified_payable or failed."
4093
4134
  },
4094
4135
  sweep_delegate: {
4095
- summary: "Sweep stranded USDC and/or ETH from the delegate wallet back to the originating Safe.",
4136
+ summary: "Sweep stranded USDC and/or ETH from the delegate wallet back to the originating account.",
4096
4137
  selectionGuidance: "Use this when the user instructs you to recover stranded funds on the delegate wallet, or when a payment status returns nextAction=sweep_stranded_funds. Do NOT use for normal payments \u2014 use haven_pay_x402. Do NOT use to read balances only \u2014 use haven_get_allowances.",
4097
- behavior: `Reads the delegate EOA's on-chain USDC and ETH balances. For each non-zero balance, signs and submits a transfer from the delegate EOA to the originating Safe (hardcoded destination). The delegate key signs locally \u2014 Haven never sees it and the backend never constructs signed transactions (CASP/MiCA Red Line #2). Returns tx hashes and recovered amounts. Returns an empty transfers list when nothing is stranded. Each transfer carries confirmation: "confirmed" (a receipt was seen \u2014 the funds are in the Safe) or "unconfirmed" (broadcast but not confirmed within 90 seconds \u2014 still in the mempool, may still land). The top-level unconfirmed flag is true when any transfer is unconfirmed.`,
4138
+ behavior: `Reads the delegate EOA's on-chain USDC and ETH balances. For each non-zero balance, signs and submits a transfer from the delegate EOA to the originating account (hardcoded destination). The delegate key signs locally \u2014 Haven never sees it and the backend never constructs signed transactions (CASP/MiCA Red Line #2). Returns tx hashes and recovered amounts. Returns an empty transfers list when nothing is stranded. Each transfer carries confirmation: "confirmed" (a receipt was seen \u2014 the funds are in the account) or "unconfirmed" (broadcast but not confirmed within 90 seconds \u2014 still in the mempool, may still land). The top-level unconfirmed flag is true when any transfer is unconfirmed.`,
4098
4139
  nextActionGuidance: 'If transfers is non-empty, confirm the amounts with the user. Report a transfer as recovered ONLY when its confirmation is "confirmed". For an "unconfirmed" transfer, tell the user it was submitted but not yet confirmed, give them its txHash and explorerUrl to check, and do not re-run the sweep immediately \u2014 a re-run after it lands will simply find nothing stranded.'
4099
4140
  },
4100
4141
  send: {
@@ -4837,6 +4878,7 @@ exports.AgentPaymentFailureCode = AgentPaymentFailureCode;
4837
4878
  exports.AgentPaymentFailureCodeDescriptions = AgentPaymentFailureCodeDescriptions;
4838
4879
  exports.AgentPaymentFailureCodeSchema = AgentPaymentFailureCodeSchema;
4839
4880
  exports.AgentPaymentNextAction = AgentPaymentNextAction;
4881
+ exports.AgentPaymentNextActionAccountAlias = AgentPaymentNextActionAccountAlias;
4840
4882
  exports.AgentPaymentNextActionDescriptions = AgentPaymentNextActionDescriptions;
4841
4883
  exports.AgentPaymentNextActionSchema = AgentPaymentNextActionSchema;
4842
4884
  exports.AgentPaymentPhase = AgentPaymentPhase;
@@ -4883,10 +4925,12 @@ exports.X402_PAYMENT_HEADER_NAMES_SENT = X402_PAYMENT_HEADER_NAMES_SENT;
4883
4925
  exports.X402_PAYMENT_REQUIRED_HEADER_NAME = X402_PAYMENT_REQUIRED_HEADER_NAME;
4884
4926
  exports.X402_PAYMENT_RESPONSE_HEADER_NAME = X402_PAYMENT_RESPONSE_HEADER_NAME;
4885
4927
  exports.X402_SETTLEMENT_FORWARD_MARGIN_SECONDS = X402_SETTLEMENT_FORWARD_MARGIN_SECONDS;
4928
+ exports.accountAddressTwins = accountAddressTwins;
4886
4929
  exports.addressFromKey = addressFromKey;
4887
4930
  exports.buildSweepAuthorizationMessage = buildSweepAuthorizationMessage;
4888
4931
  exports.buildSweepTypedData = buildSweepTypedData;
4889
4932
  exports.buildX402ExpectedMessage = buildX402ExpectedMessage;
4933
+ exports.canonicalAgentPaymentNextAction = canonicalAgentPaymentNextAction;
4890
4934
  exports.compareNodeVersions = compareNodeVersions;
4891
4935
  exports.composeDescription = composeDescription;
4892
4936
  exports.connectorRerunCommand = connectorRerunCommand;
@@ -4900,11 +4944,15 @@ exports.encodePaymentProof = encodePaymentProof;
4900
4944
  exports.havenTools = havenTools;
4901
4945
  exports.isConnectorChannel = isConnectorChannel;
4902
4946
  exports.isErc7710Option = isErc7710Option;
4947
+ exports.isFundAccountOrRaiseAllowance = isFundAccountOrRaiseAllowance;
4903
4948
  exports.isSupportedNodeVersion = isSupportedNodeVersion;
4904
4949
  exports.isSweepableChain = isSweepableChain;
4905
4950
  exports.normalizePaymentRequired = normalizePaymentRequired;
4906
4951
  exports.parsePaymentRequired = parsePaymentRequired;
4907
4952
  exports.parsePaymentRequiredResponse = parsePaymentRequiredResponse;
4953
+ exports.readAccountAddress = readAccountAddress;
4954
+ exports.readAccountId = readAccountId;
4955
+ exports.readX402ReceiptPayer = readX402ReceiptPayer;
4908
4956
  exports.resolveConnectorChannel = resolveConnectorChannel;
4909
4957
  exports.resolveTokenFromAddress = resolveTokenFromAddress;
4910
4958
  exports.sameUrl = sameUrl;