@haven_ai/sdk 0.2.0-alpha.0 → 0.3.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/README.md +13 -6
- package/dist/index.cjs +230 -85
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +284 -191
- package/dist/index.d.ts +284 -191
- package/dist/index.js +229 -80
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,65 +1,5 @@
|
|
|
1
1
|
import { PaymentRequirements } from 'x402/types';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Verifiable payment receipts.
|
|
5
|
-
*
|
|
6
|
-
* A self-contained proof bundle for a settled Haven payment that anyone can
|
|
7
|
-
* verify **independently of Haven**. The anchor is the agent delegate's
|
|
8
|
-
* signature over the on-chain transfer hash: recover the signer and confirm it
|
|
9
|
-
* is the agent's delegate, and you have cryptographic proof the agent authorised
|
|
10
|
-
* exactly this transfer — no need to trust Haven's backend. The on-chain
|
|
11
|
-
* `txHash` is the settlement source of truth (verify on any explorer).
|
|
12
|
-
*
|
|
13
|
-
* This lives in the SDK so agents and users can verify receipts client-side
|
|
14
|
-
* with zero Haven trust.
|
|
15
|
-
*/
|
|
16
|
-
declare const RECEIPT_VERSION = "haven-receipt-1";
|
|
17
|
-
interface PaymentReceipt {
|
|
18
|
-
version: typeof RECEIPT_VERSION;
|
|
19
|
-
paymentId: string;
|
|
20
|
-
payment: {
|
|
21
|
-
token: string;
|
|
22
|
-
tokenAddress: string;
|
|
23
|
-
amount: string;
|
|
24
|
-
amountSek: string | null;
|
|
25
|
-
recipient: string;
|
|
26
|
-
/** @deprecated since #2907 — read `account`; removed in #2914 (the release after the naming window). Same value as `account`. */
|
|
27
|
-
safe: string;
|
|
28
|
-
/**
|
|
29
|
-
* The payer's smart-account address (#2907 twin of `safe`). Optional for
|
|
30
|
-
* the window: a server from before the twin emits `safe` only.
|
|
31
|
-
*/
|
|
32
|
-
account?: string;
|
|
33
|
-
chainId: number;
|
|
34
|
-
settledAt: string | null;
|
|
35
|
-
resourceUrl: string | null;
|
|
36
|
-
};
|
|
37
|
-
/** The agent's cryptographic authorisation — what makes the receipt verifiable. */
|
|
38
|
-
authorization: {
|
|
39
|
-
delegate: string;
|
|
40
|
-
signHash: string;
|
|
41
|
-
signature: string | null;
|
|
42
|
-
};
|
|
43
|
-
onChain: {
|
|
44
|
-
txHash: string | null;
|
|
45
|
-
chainId: number;
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
type ReceiptVerification = {
|
|
49
|
-
verified: true;
|
|
50
|
-
recoveredSigner: string;
|
|
51
|
-
} | {
|
|
52
|
-
verified: false;
|
|
53
|
-
reason: 'missing_signature' | 'bad_signature' | 'signer_mismatch';
|
|
54
|
-
recoveredSigner?: string;
|
|
55
|
-
};
|
|
56
|
-
/**
|
|
57
|
-
* Verify a receipt independently: recover the signer from the authorisation and
|
|
58
|
-
* confirm it is the agent's delegate. Pure — `recover` is injectable but
|
|
59
|
-
* defaults to standard ECDSA recovery, so this runs anywhere (no Haven backend).
|
|
60
|
-
*/
|
|
61
|
-
declare function verifyPaymentReceipt(receipt: PaymentReceipt, recover?: (hash: string, signature: string) => string): ReceiptVerification;
|
|
62
|
-
|
|
63
3
|
interface HavenClientConfig {
|
|
64
4
|
/** Haven API key (sk_agent_xxx) */
|
|
65
5
|
apiKey: string;
|
|
@@ -144,12 +84,10 @@ interface SignData {
|
|
|
144
84
|
};
|
|
145
85
|
/** Breakdown of values that were hashed — useful for debugging */
|
|
146
86
|
components: {
|
|
147
|
-
/** @deprecated #2908 — same value as `payer_account`; the server drops it at #2914. */
|
|
148
|
-
safe: string;
|
|
149
87
|
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
88
|
+
* The PAYER account (the user's smart account). Not to be confused with
|
|
89
|
+
* `account`, which on the funding shapes holds the DELEGATE account
|
|
90
|
+
* address.
|
|
153
91
|
*/
|
|
154
92
|
payer_account?: string;
|
|
155
93
|
token: string;
|
|
@@ -535,16 +473,8 @@ interface HavenAgent {
|
|
|
535
473
|
id: string;
|
|
536
474
|
name: string;
|
|
537
475
|
status: string;
|
|
538
|
-
/**
|
|
539
|
-
* The agent's Haven account (smart account) address — #2908, the
|
|
540
|
-
* account-vocabulary name. Same value as {@link HavenAgent.safeAddress}.
|
|
541
|
-
*/
|
|
476
|
+
/** The agent's Haven account (smart account) address. */
|
|
542
477
|
accountAddress: string;
|
|
543
|
-
/**
|
|
544
|
-
* @deprecated #2908 — same value as {@link HavenAgent.accountAddress}.
|
|
545
|
-
* Removed in the release after the one carrying #2908 (#2914).
|
|
546
|
-
*/
|
|
547
|
-
safeAddress: string;
|
|
548
478
|
delegateAddress: string;
|
|
549
479
|
chainId: number;
|
|
550
480
|
/**
|
|
@@ -585,13 +515,7 @@ interface HavenAllowance {
|
|
|
585
515
|
}
|
|
586
516
|
interface HavenAllowanceSummary {
|
|
587
517
|
agentId: string;
|
|
588
|
-
/** #2908 — the account-vocabulary name; same value as `safeAddress`. */
|
|
589
518
|
accountAddress: string;
|
|
590
|
-
/**
|
|
591
|
-
* @deprecated #2908 — same value as {@link HavenAllowanceSummary.accountAddress}.
|
|
592
|
-
* Removed in the release after the one carrying #2908 (#2914).
|
|
593
|
-
*/
|
|
594
|
-
safeAddress: string;
|
|
595
519
|
delegateAddress: string;
|
|
596
520
|
chainId: number;
|
|
597
521
|
allowances: HavenAllowance[];
|
|
@@ -684,6 +608,25 @@ interface HavenAgentSummary extends HavenAgent {
|
|
|
684
608
|
spend_authority_readiness: HavenAgentReadiness;
|
|
685
609
|
allowances: HavenAgentAllowanceSummary[];
|
|
686
610
|
}
|
|
611
|
+
/**
|
|
612
|
+
* #2960 — one party vocabulary for "who paid" a Haven payment, additive
|
|
613
|
+
* alongside every existing lone `payer*`/`*Address` field (same discipline
|
|
614
|
+
* as the #2907 `safe`/`account` dual-emit, except these four are DISTINCT
|
|
615
|
+
* addresses, not same-value twins of one old field).
|
|
616
|
+
*/
|
|
617
|
+
interface PaymentParties {
|
|
618
|
+
treasuryAccount: string | null;
|
|
619
|
+
delegate: string | null;
|
|
620
|
+
delegateAccount: string | null;
|
|
621
|
+
merchant: string | null;
|
|
622
|
+
}
|
|
623
|
+
/** @internal wire shape of {@link PaymentParties}. */
|
|
624
|
+
interface RawPaymentParties {
|
|
625
|
+
treasury_account: string | null;
|
|
626
|
+
delegate: string | null;
|
|
627
|
+
delegate_account: string | null;
|
|
628
|
+
merchant: string | null;
|
|
629
|
+
}
|
|
687
630
|
interface HavenPaymentReceipt {
|
|
688
631
|
id: string;
|
|
689
632
|
paymentId: string;
|
|
@@ -691,11 +634,28 @@ interface HavenPaymentReceipt {
|
|
|
691
634
|
approvalRequestId?: string | null;
|
|
692
635
|
rail: string;
|
|
693
636
|
proofStatus: string;
|
|
637
|
+
/**
|
|
638
|
+
* @deprecated (#2998) meaning depends on the settlement scheme — the
|
|
639
|
+
* account → delegate funding transaction on eip3009, the (only) settlement
|
|
640
|
+
* transaction on erc7710. Prefer {@link fundingTxHash} / {@link settlementTxHash}, which
|
|
641
|
+
* name which is which.
|
|
642
|
+
*/
|
|
694
643
|
txHash: string;
|
|
644
|
+
/** The account → delegate funding transaction, relayed by Haven (#2998); null on erc7710 (no funding leg) and on retired mpp-rail rows. */
|
|
645
|
+
fundingTxHash: string | null;
|
|
646
|
+
/**
|
|
647
|
+
* The delegate → merchant settlement transaction (#2998). Trust level differs
|
|
648
|
+
* by scheme: on erc7710 it is `txHash` itself and Haven VERIFIED it on-chain
|
|
649
|
+
* before the receipt existed; on eip3009 it is the merchant's claim as relayed
|
|
650
|
+
* (PAYMENT-RESPONSE), NOT verified on-chain by Haven — cite it as such.
|
|
651
|
+
*/
|
|
652
|
+
settlementTxHash: string | null;
|
|
695
653
|
chainId: number;
|
|
696
654
|
resourceUrl: string;
|
|
697
655
|
merchantAddress: string | null;
|
|
698
656
|
payerAddress: string;
|
|
657
|
+
/** #2960: additive alongside `payerAddress` above (`parties.treasury_account` only). */
|
|
658
|
+
parties?: PaymentParties;
|
|
699
659
|
settlementAddress: string;
|
|
700
660
|
tokenSymbol: string;
|
|
701
661
|
tokenAddress: string;
|
|
@@ -875,64 +835,52 @@ declare const AgentPaymentNextAction: {
|
|
|
875
835
|
* the agent's per-token allowance needs to be raised before the payment
|
|
876
836
|
* can succeed. A user approval will not fix this state on its own.
|
|
877
837
|
*
|
|
878
|
-
* #
|
|
879
|
-
*
|
|
880
|
-
*
|
|
881
|
-
*
|
|
838
|
+
* #2914: the account-vocabulary spelling, and the only one — the
|
|
839
|
+
* pre-#2907 `fund_safe_or_raise_allowance` wire value (and the
|
|
840
|
+
* `AgentPaymentNextActionAccountAlias` seam #2908 added to bridge it) are
|
|
841
|
+
* retired along with the rest of the #2908 compatibility window.
|
|
882
842
|
*/
|
|
883
|
-
readonly
|
|
843
|
+
readonly FundAccountOrRaiseAllowance: "fund_account_or_raise_allowance";
|
|
884
844
|
/**
|
|
885
845
|
* The delegate wallet may hold funds that were sent from the Safe but never
|
|
886
846
|
* settled to the merchant. The wallet owner should initiate a sweep to
|
|
887
847
|
* return those funds to the originating Safe.
|
|
888
848
|
*/
|
|
889
849
|
readonly SweepStrandedFunds: "sweep_stranded_funds";
|
|
850
|
+
/**
|
|
851
|
+
* #2970: a `submitted` erc7710 x402 intent whose settlement window has
|
|
852
|
+
* passed with no on-chain settlement evidence Haven could verify. Distinct
|
|
853
|
+
* from {@link CheckStatusLater}, which this REPLACES once the window is
|
|
854
|
+
* past — but it is not futile: Haven's settlement sweep (120s tick) scans
|
|
855
|
+
* each candidate over its own window plus a 120s clock-skew allowance, so
|
|
856
|
+
* it can still attribute the settlement for a short while after this value
|
|
857
|
+
* first appears. Poll {@link CheckStatusLater}'s tool
|
|
858
|
+
* (`haven_get_payment_status`) once more, roughly two minutes later; if it
|
|
859
|
+
* still shows no evidence, tell the user the goods were delivered but
|
|
860
|
+
* Haven holds no verified settlement evidence for this payment. If the
|
|
861
|
+
* agent holds the merchant's real settlement transaction hash (from
|
|
862
|
+
* `PAYMENT-RESPONSE`'s `transaction` field, or a prior settle/complete
|
|
863
|
+
* result's `settlement_tx_hash`), report it with the hosted
|
|
864
|
+
* `haven_report_settlement_evidence` tool instead of waiting —
|
|
865
|
+
* `haven_report_x402_outcome` takes no hash and refuses a non-`confirmed`
|
|
866
|
+
* intent.
|
|
867
|
+
*/
|
|
868
|
+
readonly AwaitingSettlementEvidence: "awaiting_settlement_evidence";
|
|
890
869
|
};
|
|
891
870
|
type AgentPaymentNextAction = (typeof AgentPaymentNextAction)[keyof typeof AgentPaymentNextAction];
|
|
892
|
-
/**
|
|
893
|
-
* #2908 (naming epic #2906): the account-vocabulary twin of
|
|
894
|
-
* {@link AgentPaymentNextAction.FundSafeOrRaiseAllowance}. The server ACCEPTS
|
|
895
|
-
* and DOCUMENTS this value from #2907 but keeps EMITTING the old one through
|
|
896
|
-
* the compatibility window; the emitted value flips at #2914.
|
|
897
|
-
*
|
|
898
|
-
* Deliberately declared beside `AgentPaymentNextAction` rather than inside
|
|
899
|
-
* it: the backend keeps a hand-mirror of that const, parity-pinned key-for-key
|
|
900
|
-
* and value-for-value (`agent-payment-taxonomy.parity.test.ts`), and the
|
|
901
|
-
* served `x-enumDescriptions` are the SDK's strings verbatim. Both consts
|
|
902
|
-
* move together at #2914; until then this alias is how a client handles both
|
|
903
|
-
* wire values without forking the taxonomy.
|
|
904
|
-
*/
|
|
905
|
-
declare const AgentPaymentNextActionAccountAlias: {
|
|
906
|
-
/** Account-vocabulary twin of `fund_safe_or_raise_allowance`; same meaning. */
|
|
907
|
-
readonly FundAccountOrRaiseAllowance: "fund_account_or_raise_allowance";
|
|
908
|
-
};
|
|
909
|
-
type AgentPaymentNextActionAccountAlias = (typeof AgentPaymentNextActionAccountAlias)[keyof typeof AgentPaymentNextActionAccountAlias];
|
|
910
|
-
/** Every `next_action` value a server may put on the wire during the #2908 window. */
|
|
911
|
-
type AgentPaymentNextActionWire = AgentPaymentNextAction | AgentPaymentNextActionAccountAlias;
|
|
912
|
-
/**
|
|
913
|
-
* Collapse the #2908 account-vocabulary alias onto its canonical taxonomy
|
|
914
|
-
* value, and pass every other value through untouched.
|
|
915
|
-
*
|
|
916
|
-
* This is the one seam a `switch` over `AgentPaymentNextAction` needs: a
|
|
917
|
-
* case on `FundSafeOrRaiseAllowance` matches a server that emits either
|
|
918
|
-
* spelling, and no case falls through because the alias arrived. Unknown
|
|
919
|
-
* strings are returned as-is (the SDK never invents a value), so the return
|
|
920
|
-
* type is exactly the input type widened by the canonical value.
|
|
921
|
-
*/
|
|
922
|
-
declare function canonicalAgentPaymentNextAction<T extends string | null | undefined>(value: T): Exclude<T, AgentPaymentNextActionAccountAlias> | typeof AgentPaymentNextAction.FundSafeOrRaiseAllowance;
|
|
923
|
-
/** True for EITHER spelling of the fund-or-raise-allowance next action (#2908). */
|
|
924
|
-
declare function isFundAccountOrRaiseAllowance(value: string | null | undefined): boolean;
|
|
925
871
|
declare const AgentPaymentFailureCode: {
|
|
926
872
|
/** A merchant-authoritative x402 price exceeds the caller's pre-funding max_amount cap. */
|
|
927
873
|
readonly PriceExceedsMax: "PRICE_EXCEEDS_MAX";
|
|
928
874
|
/** The x402 funding/quote window expired before the signer or hosted settle step could finish. */
|
|
929
875
|
readonly PaymentWindowExpired: "PAYMENT_WINDOW_EXPIRED";
|
|
930
|
-
/** The
|
|
876
|
+
/** The merchant rejected the paid retry. On eip3009 the funding leg had succeeded (sweep);
|
|
877
|
+
* on erc7710 there is no funding leg — nothing to sweep, follow the message (#2983). */
|
|
931
878
|
readonly MerchantRejectedAfterFunding: "MERCHANT_REJECTED_AFTER_FUNDING";
|
|
932
879
|
/** #1300 review: funding is on-chain but the merchant never ANSWERED the
|
|
933
880
|
* paid retry within the timeout. NOT proof of rejection — the merchant
|
|
934
|
-
*
|
|
935
|
-
*
|
|
881
|
+
* may still settle late, so the guidance is verify-then-act. On eip3009
|
|
882
|
+
* the funding leg had succeeded (verify-then-sweep); on erc7710 there is
|
|
883
|
+
* no funding leg — nothing to sweep, follow the message (#3000). */
|
|
936
884
|
readonly MerchantUnresponsiveAfterFunding: "MERCHANT_UNRESPONSIVE_AFTER_FUNDING";
|
|
937
885
|
/**
|
|
938
886
|
* #1307: the caller omitted merchant_url/tool_name (asking Haven to
|
|
@@ -959,6 +907,16 @@ declare const AgentPaymentFailureCode: {
|
|
|
959
907
|
* The fallback is the exact atomic `max_amount`.
|
|
960
908
|
*/
|
|
961
909
|
readonly MaxAmountUnconvertible: "MAX_AMOUNT_UNCONVERTIBLE";
|
|
910
|
+
/**
|
|
911
|
+
* #2979: the merchant answered a `tools/call` probe with its own
|
|
912
|
+
* machine-readable "cannot settle right now" refusal (HTTP 503,
|
|
913
|
+
* `{ error: 'merchant_not_ready', reason_code, ... }`) instead of a 402
|
|
914
|
+
* challenge — e.g. its settlement wallet is out of gas. No 402 was ever
|
|
915
|
+
* issued and no payment was created; this is honest and (per
|
|
916
|
+
* `retry_after_s`, when present) usually transient, unlike a permanent
|
|
917
|
+
* endpoint miss.
|
|
918
|
+
*/
|
|
919
|
+
readonly MerchantNotReady: "MERCHANT_NOT_READY";
|
|
962
920
|
};
|
|
963
921
|
type AgentPaymentFailureCode = (typeof AgentPaymentFailureCode)[keyof typeof AgentPaymentFailureCode];
|
|
964
922
|
/**
|
|
@@ -1001,8 +959,8 @@ type AgentPaymentRail = (typeof AgentPaymentRail)[keyof typeof AgentPaymentRail]
|
|
|
1001
959
|
type PaymentPhase = AgentPaymentPhase;
|
|
1002
960
|
type PaymentNextAction = AgentPaymentNextAction;
|
|
1003
961
|
declare const AGENT_PAYMENT_PHASE_VALUES: ("rejected" | "expired" | "failed" | "agent_signature_required" | "payment_submitted" | "payment_confirmed" | "user_approval_required" | "user_execution_required" | "waiting_for_additional_approvals" | "funding_sent" | "insufficient_funds" | "funded_but_unsettled")[];
|
|
1004
|
-
declare const AGENT_PAYMENT_NEXT_ACTION_VALUES: ("sign_and_submit_payment" | "check_status_later" | "none" | "wait_for_user_approval" | "wait_for_user_to_complete_payment" | "retry_original_x402_request" | "stop_and_tell_user" | "request_again_if_user_still_wants_it" | "retry_with_explicit_context" | "payment_window_expired" | "
|
|
1005
|
-
declare const AGENT_PAYMENT_FAILURE_CODE_VALUES: ("PRICE_EXCEEDS_MAX" | "PAYMENT_WINDOW_EXPIRED" | "MERCHANT_REJECTED_AFTER_FUNDING" | "MERCHANT_UNRESPONSIVE_AFTER_FUNDING" | "MERCHANT_CALL_CONTEXT_UNAVAILABLE" | "AMBIGUOUS_MAX_AMOUNT" | "MAX_AMOUNT_UNCONVERTIBLE")[];
|
|
962
|
+
declare const AGENT_PAYMENT_NEXT_ACTION_VALUES: ("sign_and_submit_payment" | "check_status_later" | "none" | "wait_for_user_approval" | "wait_for_user_to_complete_payment" | "retry_original_x402_request" | "stop_and_tell_user" | "request_again_if_user_still_wants_it" | "retry_with_explicit_context" | "payment_window_expired" | "fund_account_or_raise_allowance" | "sweep_stranded_funds" | "awaiting_settlement_evidence")[];
|
|
963
|
+
declare const AGENT_PAYMENT_FAILURE_CODE_VALUES: ("PRICE_EXCEEDS_MAX" | "PAYMENT_WINDOW_EXPIRED" | "MERCHANT_REJECTED_AFTER_FUNDING" | "MERCHANT_UNRESPONSIVE_AFTER_FUNDING" | "MERCHANT_CALL_CONTEXT_UNAVAILABLE" | "AMBIGUOUS_MAX_AMOUNT" | "MAX_AMOUNT_UNCONVERTIBLE" | "MERCHANT_NOT_READY")[];
|
|
1006
964
|
declare const AGENT_PAYMENT_RAIL_VALUES: ("x402" | "mpp_demo" | "mpp_crypto" | "stripe_deposit" | "spt" | "direct" | "mpp")[];
|
|
1007
965
|
declare const AgentPaymentPhaseDescriptions: Record<AgentPaymentPhase, string>;
|
|
1008
966
|
declare const AgentPaymentNextActionDescriptions: Record<AgentPaymentNextAction, string>;
|
|
@@ -1044,6 +1002,23 @@ declare const AgentPaymentWarningCode: {
|
|
|
1044
1002
|
* guidance shown here may be optimistic.
|
|
1045
1003
|
*/
|
|
1046
1004
|
readonly AllowanceReadOptimistic: "ALLOWANCE_READ_OPTIMISTIC";
|
|
1005
|
+
/**
|
|
1006
|
+
* #2991: the quote tools' `expected_settlement_scheme` prediction of what
|
|
1007
|
+
* `haven_prepare_catalog_purchase` / `haven_pay_mcp_tool` will actually
|
|
1008
|
+
* select could not be computed — the agent's execution rail could not be
|
|
1009
|
+
* read from Haven, so `expected_settlement_scheme` is `null` rather than a
|
|
1010
|
+
* guess. `accepted_scheme` (the merchant's offer) is unaffected.
|
|
1011
|
+
*/
|
|
1012
|
+
readonly X402SchemeUnknown: "X402_SCHEME_UNKNOWN";
|
|
1013
|
+
/**
|
|
1014
|
+
* #2968: the merchant answered 200 and handed over goods, but Haven holds NO
|
|
1015
|
+
* on-chain evidence that the payment moved. `settled: false` beside this code
|
|
1016
|
+
* is not a failure — it is the absence of proof, and the two must travel
|
|
1017
|
+
* together so an agent can tell "the user has the goods" apart from "the
|
|
1018
|
+
* money moved". Carries the intent's `expires_at`: after that instant the
|
|
1019
|
+
* settlement can no longer land at all.
|
|
1020
|
+
*/
|
|
1021
|
+
readonly SettlementUnconfirmed: "SETTLEMENT_UNCONFIRMED";
|
|
1047
1022
|
};
|
|
1048
1023
|
type AgentPaymentWarningCode = (typeof AgentPaymentWarningCode)[keyof typeof AgentPaymentWarningCode];
|
|
1049
1024
|
interface AgentPaymentWarning {
|
|
@@ -1058,15 +1033,8 @@ interface AgentPaymentWarning {
|
|
|
1058
1033
|
* (payment_required) are named in `reason` and taken from the SAME response.
|
|
1059
1034
|
*/
|
|
1060
1035
|
interface AgentNextStep {
|
|
1061
|
-
/**
|
|
1062
|
-
|
|
1063
|
-
* alias for the compatibility window: the hosted server keeps emitting
|
|
1064
|
-
* `fund_safe_or_raise_allowance` until #2914, but a client compiled against
|
|
1065
|
-
* this type must not reject `fund_account_or_raise_allowance` when the flip
|
|
1066
|
-
* lands. Compare through {@link canonicalAgentPaymentNextAction} or
|
|
1067
|
-
* {@link isFundAccountOrRaiseAllowance}, never by one literal.
|
|
1068
|
-
*/
|
|
1069
|
-
next_action: AgentPaymentNextActionWire;
|
|
1036
|
+
/** From `AgentPaymentNextAction`. */
|
|
1037
|
+
next_action: AgentPaymentNextAction;
|
|
1070
1038
|
/**
|
|
1071
1039
|
* Claude-family namespaced tool name for the next call
|
|
1072
1040
|
* (`mcp__<server>__<tool>`), when one exists.
|
|
@@ -1164,6 +1132,8 @@ interface PaymentStatusResult {
|
|
|
1164
1132
|
merchantAddress: string | null;
|
|
1165
1133
|
/** Delegate EOA captured on the payment intent when it was created. */
|
|
1166
1134
|
payerAddress?: string | null;
|
|
1135
|
+
/** #2960: additive alongside `payerAddress` above (`parties.delegate` only). */
|
|
1136
|
+
parties?: PaymentParties;
|
|
1167
1137
|
txHash: string | null;
|
|
1168
1138
|
expiresAt: string;
|
|
1169
1139
|
chainId: number;
|
|
@@ -1241,13 +1211,21 @@ interface HavenCatalogEntry {
|
|
|
1241
1211
|
verifiedAt: string | null;
|
|
1242
1212
|
/**
|
|
1243
1213
|
* Where the entry came from. `operator` = curated in migrations/scripts
|
|
1244
|
-
* (the operator vouches;
|
|
1214
|
+
* (the operator vouches for the listing; the catalog refresh probe still
|
|
1215
|
+
* checks the endpoint, see `verifiedPayable`). `ingestion` = submitted
|
|
1245
1216
|
* through the Verified Payable Directory and passed domain-ownership proof
|
|
1246
1217
|
* plus the read-only quote probe.
|
|
1247
1218
|
*/
|
|
1248
1219
|
source: 'operator' | 'ingestion';
|
|
1249
|
-
/** True only for `ingestion` entries. See the epic's trust claim (never merchant honesty or quality). */
|
|
1220
|
+
/** True only for `ingestion` entries — the one ownership claim. See the epic's trust claim (never merchant honesty or quality). */
|
|
1250
1221
|
domainVerified: boolean;
|
|
1222
|
+
/**
|
|
1223
|
+
* True when Haven watched this endpoint answer a live quote (#2978): the
|
|
1224
|
+
* directory probe for `ingestion` rows, the periodic catalog refresh probe
|
|
1225
|
+
* for `operator` rows (`status === 'active'` with `verifiedAt` set). False
|
|
1226
|
+
* for a degraded row of either source. `discoverTools({ verified:
|
|
1227
|
+
* 'verified' })` filters on this field, not on `source`.
|
|
1228
|
+
*/
|
|
1251
1229
|
verifiedPayable: boolean;
|
|
1252
1230
|
}
|
|
1253
1231
|
/** @internal */
|
|
@@ -1291,7 +1269,17 @@ declare class MerchantTimeoutError extends HavenApiError {
|
|
|
1291
1269
|
}
|
|
1292
1270
|
declare class X402UnexpectedStatusError extends HavenApiError {
|
|
1293
1271
|
readonly x402ErrorCode: "unexpected_non_402_status";
|
|
1294
|
-
|
|
1272
|
+
/**
|
|
1273
|
+
* #2979: `body` is the merchant's own JSON, when the non-402 response
|
|
1274
|
+
* carried one — e.g. the demo merchant's `/mcp` readiness gate answers
|
|
1275
|
+
* `503 { error: 'merchant_not_ready', reason_code, ... }`. Optional and
|
|
1276
|
+
* best-effort: a non-JSON or unreadable body leaves this `undefined`, same
|
|
1277
|
+
* as before this field existed. Consumers key on it (not on the message
|
|
1278
|
+
* string) to distinguish an honest, machine-readable merchant refusal from
|
|
1279
|
+
* a genuine "this is not the x402 endpoint" miss, which otherwise look
|
|
1280
|
+
* identical — both are just "some non-402 status".
|
|
1281
|
+
*/
|
|
1282
|
+
constructor(message: string, statusCode: number, body?: unknown);
|
|
1295
1283
|
}
|
|
1296
1284
|
/**
|
|
1297
1285
|
* #1521: the idempotency key resolved to a payment that has already settled,
|
|
@@ -1340,6 +1328,19 @@ declare class HavenPaymentStateError extends HavenApiError {
|
|
|
1340
1328
|
declare class HavenSigningError extends HavenError {
|
|
1341
1329
|
constructor(message: string);
|
|
1342
1330
|
}
|
|
1331
|
+
/**
|
|
1332
|
+
* #2972: `MerchantCompletion.reportSettlementEvidence` /
|
|
1333
|
+
* `HavenClient.reportSettlementEvidence` refuse a `0x00…00` settlement hash
|
|
1334
|
+
* BEFORE any network call — see `isZeroSettlementTxHash`. That marker is
|
|
1335
|
+
* never a real transaction (the demo merchant's own "delivered, not settled"
|
|
1336
|
+
* value), so posting it to `POST /machine-payments/evidence` could only ever
|
|
1337
|
+
* come back refused, at the cost of a real round trip. A typed error rather
|
|
1338
|
+
* than a `HavenApiError`-shaped 400: no request was ever attempted, so there
|
|
1339
|
+
* is no HTTP status or response body to carry.
|
|
1340
|
+
*/
|
|
1341
|
+
declare class HavenZeroSettlementHashError extends HavenError {
|
|
1342
|
+
constructor(paymentId: string);
|
|
1343
|
+
}
|
|
1343
1344
|
/**
|
|
1344
1345
|
* Refusal codes the local signer returns when it does not recognise the
|
|
1345
1346
|
* VERSION of a Haven-signed binding it was asked to sign (#1309). Distinct
|
|
@@ -1401,6 +1402,68 @@ declare class HavenTimeoutError extends HavenError {
|
|
|
1401
1402
|
constructor(paymentId: string);
|
|
1402
1403
|
}
|
|
1403
1404
|
|
|
1405
|
+
/**
|
|
1406
|
+
* Verifiable payment receipts.
|
|
1407
|
+
*
|
|
1408
|
+
* A self-contained proof bundle for a settled Haven payment that anyone can
|
|
1409
|
+
* verify **independently of Haven**. The anchor is the agent delegate's
|
|
1410
|
+
* signature over the on-chain transfer hash: recover the signer and confirm it
|
|
1411
|
+
* is the agent's delegate, and you have cryptographic proof the agent authorised
|
|
1412
|
+
* exactly this transfer — no need to trust Haven's backend. The on-chain
|
|
1413
|
+
* `txHash` is the settlement source of truth (verify on any explorer).
|
|
1414
|
+
*
|
|
1415
|
+
* This lives in the SDK so agents and users can verify receipts client-side
|
|
1416
|
+
* with zero Haven trust.
|
|
1417
|
+
*/
|
|
1418
|
+
declare const RECEIPT_VERSION = "haven-receipt-1";
|
|
1419
|
+
interface PaymentReceipt {
|
|
1420
|
+
version: typeof RECEIPT_VERSION;
|
|
1421
|
+
paymentId: string;
|
|
1422
|
+
payment: {
|
|
1423
|
+
token: string;
|
|
1424
|
+
tokenAddress: string;
|
|
1425
|
+
amount: string;
|
|
1426
|
+
amountSek: string | null;
|
|
1427
|
+
recipient: string;
|
|
1428
|
+
/** The payer's smart-account address. */
|
|
1429
|
+
account: string;
|
|
1430
|
+
/**
|
|
1431
|
+
* #2960: one party vocabulary for "who paid", additive alongside `account`
|
|
1432
|
+
* above (which is `parties.treasury_account` only). Optional: a server
|
|
1433
|
+
* from before #2960 emits neither. Ignored by `verifyPaymentReceipt`,
|
|
1434
|
+
* which reads only `authorization`.
|
|
1435
|
+
*/
|
|
1436
|
+
parties?: RawPaymentParties;
|
|
1437
|
+
chainId: number;
|
|
1438
|
+
settledAt: string | null;
|
|
1439
|
+
resourceUrl: string | null;
|
|
1440
|
+
};
|
|
1441
|
+
/** The agent's cryptographic authorisation — what makes the receipt verifiable. */
|
|
1442
|
+
authorization: {
|
|
1443
|
+
delegate: string;
|
|
1444
|
+
signHash: string;
|
|
1445
|
+
signature: string | null;
|
|
1446
|
+
};
|
|
1447
|
+
onChain: {
|
|
1448
|
+
txHash: string | null;
|
|
1449
|
+
chainId: number;
|
|
1450
|
+
};
|
|
1451
|
+
}
|
|
1452
|
+
type ReceiptVerification = {
|
|
1453
|
+
verified: true;
|
|
1454
|
+
recoveredSigner: string;
|
|
1455
|
+
} | {
|
|
1456
|
+
verified: false;
|
|
1457
|
+
reason: 'missing_signature' | 'bad_signature' | 'signer_mismatch';
|
|
1458
|
+
recoveredSigner?: string;
|
|
1459
|
+
};
|
|
1460
|
+
/**
|
|
1461
|
+
* Verify a receipt independently: recover the signer from the authorisation and
|
|
1462
|
+
* confirm it is the agent's delegate. Pure — `recover` is injectable but
|
|
1463
|
+
* defaults to standard ECDSA recovery, so this runs anywhere (no Haven backend).
|
|
1464
|
+
*/
|
|
1465
|
+
declare function verifyPaymentReceipt(receipt: PaymentReceipt, recover?: (hash: string, signature: string) => string): ReceiptVerification;
|
|
1466
|
+
|
|
1404
1467
|
/**
|
|
1405
1468
|
* Gasless delegate-sweep primitives — the single source of truth shared by the
|
|
1406
1469
|
* edge signer (which signs) and the Haven backend (which relays).
|
|
@@ -1616,6 +1679,38 @@ interface X402MerchantOutcomeReport {
|
|
|
1616
1679
|
resourceUrl: string;
|
|
1617
1680
|
recorded: 'reconciliation_event' | 'evidence';
|
|
1618
1681
|
}
|
|
1682
|
+
/**
|
|
1683
|
+
* #2970: what `reportEvidence` learned about the report it just made.
|
|
1684
|
+
*
|
|
1685
|
+
* `confirmed` mirrors the backend's 202 (`modules/mpp/evidence.ts`) — the
|
|
1686
|
+
* intent is now `confirmed` (or was already, on the funding-leg path) with
|
|
1687
|
+
* THIS hash recorded. `retryable` mirrors its 503 (`settlement_unobservable`,
|
|
1688
|
+
* exhausted the retry budget above): the chain could not be read, or the
|
|
1689
|
+
* transaction is not mined yet — ask again later. `refused` mirrors every
|
|
1690
|
+
* terminal refusal (409 `settlement_unverified`, a validation error, an
|
|
1691
|
+
* unknown payment id, or a transport failure with no HTTP status at all,
|
|
1692
|
+
* reported as `statusCode: 0`) — reporting the same hash again will not
|
|
1693
|
+
* change the answer.
|
|
1694
|
+
*/
|
|
1695
|
+
type EvidenceReportOutcome = {
|
|
1696
|
+
outcome: 'confirmed';
|
|
1697
|
+
} | {
|
|
1698
|
+
outcome: 'retryable';
|
|
1699
|
+
statusCode: number | undefined;
|
|
1700
|
+
} | {
|
|
1701
|
+
outcome: 'refused';
|
|
1702
|
+
statusCode: number;
|
|
1703
|
+
};
|
|
1704
|
+
/**
|
|
1705
|
+
* #2970: a hash of the form `0x00…00` is never a real transaction — it is the
|
|
1706
|
+
* demo merchant's own "delivered, not settled" marker (`ZERO_TX_HASH` in
|
|
1707
|
+
* `packages/demo-merchant-mcp/src/x402.ts`), reused rather than invented here
|
|
1708
|
+
* so the hosted gate and any other consumer recognise it the same way. Treated
|
|
1709
|
+
* as equivalent to "no hash was reported": there is nothing on-chain to verify,
|
|
1710
|
+
* so asking the backend to look is a wasted round trip that can only ever
|
|
1711
|
+
* resolve to a refusal.
|
|
1712
|
+
*/
|
|
1713
|
+
declare function isZeroSettlementTxHash(hash: string | null | undefined): boolean;
|
|
1619
1714
|
|
|
1620
1715
|
declare class HavenClient {
|
|
1621
1716
|
private readonly delegateKey;
|
|
@@ -1840,10 +1935,13 @@ declare class HavenClient {
|
|
|
1840
1935
|
search?: string;
|
|
1841
1936
|
rail?: 'x402' | 'mpp';
|
|
1842
1937
|
/**
|
|
1843
|
-
*
|
|
1844
|
-
*
|
|
1845
|
-
*
|
|
1846
|
-
*
|
|
1938
|
+
* `'verified'` (epic #1717, #2978) returns entries whose endpoint Haven
|
|
1939
|
+
* watched answer a live quote — `verifiedPayable === true` — from
|
|
1940
|
+
* EITHER source: an operator-curated row that keeps passing its
|
|
1941
|
+
* periodic 402 probe, or a self-submitted row that also passed
|
|
1942
|
+
* domain-ownership proof. It is not a provenance filter; `'operator'`
|
|
1943
|
+
* still filters on provenance (`source === 'operator'`) regardless of
|
|
1944
|
+
* badge state, and `'any'` (the default) returns the merged listing.
|
|
1847
1945
|
*/
|
|
1848
1946
|
verified?: 'any' | 'verified' | 'operator';
|
|
1849
1947
|
}): Promise<HavenCatalogEntry[]>;
|
|
@@ -2093,6 +2191,15 @@ declare class HavenClient {
|
|
|
2093
2191
|
ok: boolean;
|
|
2094
2192
|
body: unknown;
|
|
2095
2193
|
settlementTxHash?: string;
|
|
2194
|
+
/**
|
|
2195
|
+
* #2970: what the evidence report (below) learned, when one was made.
|
|
2196
|
+
* `undefined` when there was no hash to report at all — no funding tx on
|
|
2197
|
+
* the erc7710 branch and no (or a zero) merchant-reported settlement hash.
|
|
2198
|
+
* The hosted erc7710 settle/complete gate reads this to decide whether
|
|
2199
|
+
* `settled: true` is honest; the 3009 branch's `settled: true` does not
|
|
2200
|
+
* need it — see `paid-mcp-completion.ts` for why.
|
|
2201
|
+
*/
|
|
2202
|
+
evidenceOutcome?: EvidenceReportOutcome;
|
|
2096
2203
|
}>;
|
|
2097
2204
|
/**
|
|
2098
2205
|
* #2292: report the outcome of a merchant retry the AGENT performed.
|
|
@@ -2109,6 +2216,17 @@ declare class HavenClient {
|
|
|
2109
2216
|
merchantStatus: number;
|
|
2110
2217
|
merchantBody?: string;
|
|
2111
2218
|
}): Promise<X402MerchantOutcomeReport>;
|
|
2219
|
+
/**
|
|
2220
|
+
* #2972: report the merchant's real settlement transaction hash for an
|
|
2221
|
+
* erc7710 x402 payment — the remedy for `DELIVERED_UNSETTLED` /
|
|
2222
|
+
* `SETTLEMENT_PENDING` / `awaiting_settlement_evidence` when the agent
|
|
2223
|
+
* holds the hash (`PAYMENT-RESPONSE.transaction`, or a prior settle/
|
|
2224
|
+
* complete result's `settlement_tx_hash`) and Haven does not. See
|
|
2225
|
+
* `MerchantCompletion.reportSettlementEvidence` for the fail-closed
|
|
2226
|
+
* verification this posts into (`observeErc7710Settlement`) and the
|
|
2227
|
+
* client-side zero-hash refusal.
|
|
2228
|
+
*/
|
|
2229
|
+
reportSettlementEvidence(paymentId: string, settlementTxHash: string): Promise<EvidenceReportOutcome>;
|
|
2112
2230
|
/**
|
|
2113
2231
|
* GET /x402/:id/merchant-call-context — the settle-leg twin of #1263's
|
|
2114
2232
|
* sign-context fetch (#1307). Re-serves the stored merchant MCP-tool call
|
|
@@ -2296,8 +2414,8 @@ declare const toolDescriptions: {
|
|
|
2296
2414
|
readonly nextActionGuidance: string;
|
|
2297
2415
|
};
|
|
2298
2416
|
readonly getPaymentStatus: {
|
|
2299
|
-
readonly summary: "Fetch structured Haven payment status
|
|
2300
|
-
readonly behavior: "
|
|
2417
|
+
readonly summary: "Fetch structured Haven payment status for agent recovery.";
|
|
2418
|
+
readonly behavior: "State: phase, nextAction, rail, amount, merchant, resource, idempotency, message; parties: treasury/delegate/delegateAccount/merchant. awaiting_settlement_evidence: poll once, else unverified.";
|
|
2301
2419
|
readonly nextActionGuidance: "";
|
|
2302
2420
|
};
|
|
2303
2421
|
readonly getResumeState: {
|
|
@@ -2308,7 +2426,7 @@ declare const toolDescriptions: {
|
|
|
2308
2426
|
readonly getAgent: {
|
|
2309
2427
|
readonly 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.";
|
|
2310
2428
|
readonly 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.";
|
|
2311
|
-
readonly behavior: "Reads identity plus the live spend-authority snapshot in one shot — 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 — 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
|
|
2429
|
+
readonly behavior: "Reads identity plus the live spend-authority snapshot in one shot — 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 — 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, delegateAddress, chainId.";
|
|
2312
2430
|
readonly nextActionGuidance: "";
|
|
2313
2431
|
};
|
|
2314
2432
|
readonly getAllowances: {
|
|
@@ -2359,6 +2477,11 @@ declare const toolDescriptions: {
|
|
|
2359
2477
|
readonly behavior: string;
|
|
2360
2478
|
readonly nextActionGuidance: string;
|
|
2361
2479
|
};
|
|
2480
|
+
readonly reportSettlementEvidence: {
|
|
2481
|
+
readonly summary: "Report an erc7710 payment's real settlement transaction hash so Haven can verify it on-chain and confirm the payment.";
|
|
2482
|
+
readonly behavior: "Pass payment_id and settlement_tx_hash (0x + 64 hex chars) — from PAYMENT-RESPONSE or a prior settlement_tx_hash. Haven verifies on-chain before confirming; a zero, mismatched, or reverted hash is refused. Your own payments only.";
|
|
2483
|
+
readonly nextActionGuidance: "code DELIVERED_UNSETTLED: did not verify, do not retry — poll haven_get_payment_status. code SETTLEMENT_PENDING (retryable:true): not mined or RPC unreachable — report the same hash again shortly.";
|
|
2484
|
+
};
|
|
2362
2485
|
};
|
|
2363
2486
|
type SharedToolKey = keyof typeof toolDescriptions;
|
|
2364
2487
|
|
|
@@ -2404,7 +2527,7 @@ type SharedToolKey = keyof typeof toolDescriptions;
|
|
|
2404
2527
|
* live sibling constant not pulled in here; if it ever is, this applies to it
|
|
2405
2528
|
* too (design review, #2537).
|
|
2406
2529
|
*/
|
|
2407
|
-
declare const HAVEN_SKILL_MD = "---\nname: haven-pay\ndescription: Pay for things from the user's Haven wallet within their agent rules, and set Haven up when it is not yet connected. Use when the user asks to send, pay, tip, or transfer crypto; when a request hits an HTTP 402 (x402) paywall; or when they ask to create a Haven account, create an agent, or connect one.\n---\n\n# Haven: pay from a Haven wallet\n\nThis skill lets the agent make payments from the user's Haven wallet through\nthe Haven MCP tools. Every payment is checked against the agent's on-chain\nbudget before money moves; a payment above the remaining budget is declined \u2014\nnothing is paid past the rules the user set.\n\nHosted tools run in the `mcp__haven__` namespace. Local signing tools run in\nthe `mcp__haven-signer__` namespace and keep the delegate key on this machine.\nThat namespacing is Claude-family; other runtimes name the servers by their\nown config keys (Codex: `haven`, `haven_signer`). Tool results carry the\nexact next step (`next_action`, `next_tool`, `next_arguments`, plus the\nruntime-neutral `next_tool_server` + `next_tool_name` \u2014 the bare tool name\non that logical server, whatever your runtime calls it).\nFollow those fields first; the prose below is fallback and orientation, not\nthe source of truth.\n\n## When to use this skill\n\n- The user asks to send money, pay someone, tip, donate, or transfer tokens.\n- A request returns HTTP 402 (x402): use the Haven pay tools to settle it,\n then retry the original request.\n\n## Onboarding and setup\n\nYou are in this mode when there is no Haven agent credential on this machine,\nor when your user asks you to create a Haven account, create an agent, or\nconnect one \u2014 for themselves or for someone else.\n\n**None of the tools below creates authority.** They spend a budget a human\nalready signed. There is no tool here that opens an account, mints a\ncredential, or approves a budget, so reaching for one of them to \"set Haven\nup\" cannot work; the steps are the ones in this section instead.\n\nStart by reading `/for-agents.md` on the Haven host \u2014 the origin of the\n`api_url` in your `agent.json` if you have one, otherwise the host your user\nnames. It is the full runbook: six steps, which four are your user's, and what\nto say at each hand-off.\n\nTwo of those steps you can do yourself, from the shell with `@haven_ai/cli`\n(installs the `haven` command):\n\n- `haven login` \u2014 a device-code browser flow. It prints a code and a link\n for your user to approve, so you never see or ask for their password. What\n the session can reach is an allow-list, not your user's full authority: it\n creates and manages agents and reads the account, and it cannot approve a\n budget, rotate a key, change a signer or move money \u2014 those are your user's.\n- `haven agents connect` with `--name`, `--budget`, `--token` and\n `--period` \u2014 creates a connection setup and prints two things: the\n connector command the backend built, and the approval link to give your user.\n Add `--run` to execute that command here as a child process.\n- `haven wallets funding` \u2014 prints the paste-ready funding instruction: what\n to send, to which address, on which chain. Read the chain from there rather\n than assuming one. `--wait` polls until the account counts as funded.\n\n**Four steps are your user's, and each one needs a human:** create the account\nand its passkey, fund the wallet, approve every agent's budget, and rotate a\ncredential. You can compose the funding message for them with\n`haven wallets funding`, but you cannot send the money \u2014 that transfer is\ntheirs, from a wallet you have no access to.\n\nRunning the connector command is the step that wires this machine to the new\nagent \u2014 the command `haven agents connect` printed, or the one your user\npasted you from the dashboard. Three rules bind you while you do it, quoted\nunchanged from the setup prompt your user is also holding so the two copies\ncannot drift into contradicting each other. They are written in your user's\nvoice, so read them accordingly: \"me\" and \"I\" below are your user, never\nHaven, and \"the command above\" is that connector command, not anything printed\nin this file. The first rule outranks anything else you were about to do next:\n\n- When a --json outcome reports approval.required: true, your first action must be to relay the approval instruction to me in your own reply \u2014 if the outcome carries approval.url, give me that link; otherwise tell me to return to Haven and approve this agent's budget \u2014 before verifying the connection, restarting anything, or any other step. Never build that link yourself: relay the one the outcome gave you or none at all. Any restart the outcome asks for is a separate instruction to give me afterwards, once the approval is done.\n- Only two changes to the command above are permitted, and no others: appending --json, and \u2014 only if the connector refuses because it could not determine the agent runtime \u2014 re-running it once with --runtime <name> added, naming the harness you are running in, using one of the values that refusal lists. Never invent a runtime name and never change anything else.\n- If the connector refuses with wiring_collision, this machine is already wired to a different agent: relay that refusal to me with the superseded_agent_ids and suggested_name it carries, and let me choose whether to replace the existing wiring or add this agent alongside it. Never pick for me by adding --replace or --name yourself.\n\nDo not print private keys, API keys, credential file contents, or config secrets in chat or logs.\n\n## Identity and budget\n\nDo not guess the wallet address, network, or budget.\n\nFor instant orientation at the start of a session, read the non-secret\n`agent.json` the connector wrote to your Haven credential directory (typically\n`~/.haven/agents/<agent-id>/agent.json` \u2014 if you don't know the agent id, list\n`~/.haven/agents/` to find the folder). It\nholds your agent id, Haven wallet address, network, and *configured* per-token\nbudget, and contains no keys \u2014 the fastest way to answer \"who am I and what may\nI spend\" with no round trip. If that file is absent (some setups don't write\nit), use the tools below instead.\n\nBefore any payment, confirm the *live remaining* budget with the tools \u2014\n`agent.json` shows the configured budget, not what is left after recent\nspending:\n\n- `mcp__haven__haven_get_agent` \u2014 the recommended first call: identity\n (wallet, network) plus `spend_authority_readiness` (`ready` / `needs_approval` /\n `revoked`) and live remaining per-token allowance, in one shot. That signal\n covers hosted identity and on-chain spend authority only \u2014 it cannot see the\n local signer; the signer is verified by calling any signer tool.\n- `mcp__haven__haven_get_allowances` \u2014 detailed per-token breakdown\n (configured, spent, reset window) when you need more than the summary.\n\nBudgets reset on a period the user chose. If a payment exceeds the remaining\nbudget it is declined before any money moves \u2014 tell the user; they can raise\nthe budget in the Haven dashboard, or wait for the period reset.\n\n## Paying\n\n**Catalog purchases \u2014 the primary path for MCP merchants:**\n\n1. `mcp__haven__haven_discover_tools` to find a payable service and its\n `catalog_id`.\n2. If the user needs the live price before authorizing a cap, call\n `mcp__haven__haven_quote_catalog_purchase` with `catalog_id`. It is\n read-only and informational only: it never reserves a price or creates a\n payment. Tell the user its `amount` / `amount_atomic`, then choose a cap.\n3. `mcp__haven__haven_prepare_catalog_purchase` with `catalog_id` and a\n spending cap. A cap is REQUIRED on this tool and is best practice on every\n paid call below too \u2014 it caps what the LIVE merchant quote may charge,\n checked before any funding intent is created. Write it the way the user\n said it: `max_amount_human` is whole tokens, so \"no more than 1 USDC\" is\n `max_amount_human: \"1\"`. (`max_amount` is the atomic-unit form, where\n \"1\" means 0.000001 USDC \u2014 do not convert by hand, and never send both.)\n4. Then FOLLOW THE RESPONSE'S GUIDANCE FIELDS: `next_action`, `next_tool`,\n and `next_arguments` name the exact next call \u2014 act on those first; the\n prose in this section is fallback and debugging detail. If the catalog\n entry is missing or degraded, the response instead names\n `mcp__haven__haven_pay_mcp_tool` (merchant URL, tool name, arguments) as\n the manual fallback.\n\n**Signing:** `mcp__haven-signer__haven_sign_x402` with `payment_id` ONLY \u2014\nthe local signer fetches the exact signing bytes AND `payment_required`\nitself, so never relay `typed_data` or the 402 blob yourself. If the signer\nreports its fetched context carried no `payment_required` (older backend),\nre-call with `payment_required` added verbatim. Fallback for an older signer\nor backend: re-run the quote/prepare tool with the SAME `idempotency_key`\nplus `include_signing_payload=true`, then pass `payload_hash`,\n`x402_expected` (the nested `x402.expected` object), and\n`typed_data`/`typed_data_b64` through unchanged.\n\n**Settle:** `mcp__haven__haven_settle_mcp_tool` with `payment_id`,\n`signature`, and `payment_header` ONLY \u2014 Haven rehydrates the merchant call\ncontext (`merchant_url`, `tool_name`, `arguments`, `mcp_transport`)\nserver-side from `payment_id`. Pass those four fields explicitly only as a\nversion-skew fallback when Haven has no stored context for the id \u2014 both or\nnone together, never just one. If the settle result carries `settled: false`,\nfunding has not confirmed \u2014 follow the result's guidance fields and check\nstatus later, do not re-pay.\n\nStep-by-step alternative (also key-safe; for an older signer or backend, or\nwhen you already have a merchant URL and tool name instead of a\n`catalog_id`): if the user needs the live price before choosing a cap, first\ncall `mcp__haven__haven_quote_mcp_tool` with that merchant URL, tool name,\nand arguments. It is informational only; then call\n`mcp__haven__haven_pay_mcp_tool` with the same inputs and the explicit cap.\nThe paid call always obtains a fresh quote before it creates any intent. Then\ncontinue `mcp__haven__haven_pay_mcp_tool` \u2192\n`mcp__haven-signer__haven_sign` \u2192 `mcp__haven__haven_submit` \u2192\n`mcp__haven-signer__haven_x402_sign_header` \u2192\n`mcp__haven__haven_complete_mcp_tool`. Call that last step with\n`payment_id` and the signer's `payment_header` ONLY. It does not take\n`payment_required`: Haven rehydrates the merchant call context\n(`merchant_url`, `tool_name`, `arguments`, `mcp_transport`) and the\n402 server-side from `payment_id`, exactly as at settle. Pass that context\nexplicitly only as a version-skew fallback when Haven has no stored context\nfor the id \u2014 `merchant_url` and `tool_name` both or none together, never\njust one.\nThe returned `expires_at` is the signing window; if a tool returns\n`PAYMENT_WINDOW_EXPIRED`, re-run the same quote/prepare tool with the same\n`idempotency_key`. Do not call the merchant yourself \u2014 Haven completes the\nmerchant leg for you.\n\n**Direct transfer / non-MCP paywall:** `mcp__haven__haven_pay` with\n`to`, `amount`, and `token` for a plain transfer. For an arbitrary,\nnon-MCP x402 paywall: `mcp__haven__haven_quote_x402` to get a quote, then\n`mcp__haven__haven_pay_x402_quote` \u2014 follow the result's guidance fields\nfirst and sign in the local Haven signer. On THIS path Haven does not talk to\nthe merchant: `mcp__haven-signer__haven_sign_x402` returns both\n`signature` and `payment_header`; relay `signature` with\n`mcp__haven__haven_submit`, then retry the paywalled URL yourself with\n`payment_header`. Do not pass that call's `x402_binding` to\n`mcp__haven-signer__haven_x402_sign_header` \u2014 the one-shot already spent it\nbuilding the header, so the call can only refuse. Then tell Haven what the\nmerchant answered: `mcp__haven__haven_report_x402_outcome` with the\n`payment_id`, `outcome` (`\"accepted\"` for a 2xx, else `\"rejected\"`)\nand the `merchant_status` you got. Because Haven never contacted that\nmerchant, this is the only way it can learn the purchase failed \u2014 without it a\nfailed purchase reads as complete for fifteen minutes. (The SDK's own\n`haven_pay_x402` tool does perform the merchant retry itself; that tool is\nnot part of the hosted MCP surface.) If the process\ncrashes after payment, a later `mcp__haven__haven_get_payment_status` call\nmay report `nextAction: 'retry_original_x402_request'` \u2014 only then call\n`mcp__haven__haven_resume_x402_payment` with the preserved resume state or\npayment id, instead of paying again.\n\n**Catalog tool arguments:** when `haven_discover_tools` returns\n`tool_arguments`, pass that object unchanged as the pay tool's\n`arguments` field (for example\n`tool_arguments: { \"tier\": \"50gb\" }` -> `arguments: { \"tier\": \"50gb\" }`).\n\n**Prices:** show the user the live price from a read-only quote or the pay-tool\nresult, never a catalog price. `haven_discover_tools` prices are indicative\n(`price_is_indicative`) and can be stale. A read-only quote is informational\nonly and does not reserve a price; the later paid call re-quotes and enforces\nthe cap. The pay-tool result's `amount` / `amount_atomic` is the merchant's\nown quoted price for that call \u2014 a ceiling the merchant settles at or below \u2014\nso present it as the most the user will pay. It is a price, not an approval:\nthe payment goes through only if it also fits the cap you set and the on-chain\nbudget the user signed, which is enforced on-chain rather than by Haven.\n\n**Status:** `mcp__haven__haven_get_payment_status` with a `payment_id` to\ncheck on in-flight payments. Do not poll in a tight loop.\n\n## Declines and stop signals\n\n- A payment outside the agent's rules \u2014 above the remaining budget, wrong\n recipient, or expired budget \u2014 is declined before any money moves. Nothing\n is queued; tell the user, who can raise the budget in Haven.\n- `safe_to_continue: false` on a guidance block is a stop signal in\n machine-readable form: stop and involve the user before calling anything\n else for this payment.\n- Never ask the user for private keys. Signing happens only in the local Haven\n signer; the hosted Haven tools never receive the signing key. If a tool\n reports a missing or invalid credential, tell the user to re-run the Haven\n connector command.\n\n## Failure handling\n\nHaven tool failures are shaped like `{ success: false, code, message, ... }`\nor older `{ error, status, details? }` responses. Branch on `code` when\npresent and surface `message` or `error` verbatim. Common cases:\n\n- `insufficient_funds`: the Haven wallet doesn't hold enough of that token.\n Suggest the user add funds in the Haven dashboard.\n- `PRICE_EXCEEDS_MAX`: the live merchant price exceeded your cap. No funds\n moved; ask the user before retrying with a higher one.\n- `AMBIGUOUS_MAX_AMOUNT`: you sent both `max_amount` and\n `max_amount_human`. Nothing was contacted or spent \u2014 re-send with exactly\n one (`max_amount_human` for a cap the user stated in tokens).\n- `MAX_AMOUNT_UNCONVERTIBLE`: `max_amount_human` does not fit this quote's\n asset \u2014 unknown decimals, or more decimal places than the asset supports.\n Round the cap, or send an exact atomic `max_amount`.\n- `PAYMENT_WINDOW_EXPIRED`: re-run the quote/prepare tool with the same\n `idempotency_key`, then sign the fresh payload.\n- `MERCHANT_REJECTED_AFTER_FUNDING`: the merchant refused the paid retry.\n Stop-and-sweep \u2014 stop retrying the merchant and use\n `mcp__haven__haven_sweep_delegate` to recover stranded delegate funds.\n- `MERCHANT_UNRESPONSIVE_AFTER_FUNDING`: funding confirmed on-chain, but the\n merchant never answered the paid retry. This is NOT proof of rejection \u2014 the\n merchant may still settle late. Verify-then-sweep, never a blind sweep:\n check `mcp__haven__haven_get_payment_status`, retry\n `mcp__haven__haven_complete_mcp_tool` ONCE, and only sweep with\n `mcp__haven__haven_sweep_delegate` if no settlement appears.\n- Budget exceeded: tell the user how much remains (from\n `mcp__haven__haven_get_allowances`) and that they can raise the budget in\n Haven.\n\n## Reporting after a purchase\n\nA settled `mcp__haven__haven_settle_mcp_tool` response carries\n`agent_summary.purchase_summary` and the remaining post-purchase allowance\nin `allowance` \u2014 report the product, Haven-derived payment/transaction\nfields, and what is left from those fields directly. `result` is optional\nraw merchant evidence; never use it to decide whether the purchase was paid.\nDo not call `haven_get_agent` or `haven_get_allowances` again just to\nreport a purchase you already made.\n\n## Revoke\n\nIf this agent's credential may have leaked, tell the user to pause or revoke\nthe agent in the Haven dashboard under Agents. New requests stop immediately\nfor that credential.\n";
|
|
2530
|
+
declare const HAVEN_SKILL_MD = "---\nname: haven-pay\ndescription: Pay for things from the user's Haven wallet within their agent rules, and set Haven up when it is not yet connected. Use when the user asks to send, pay, tip, or transfer crypto; when a request hits an HTTP 402 (x402) paywall; or when they ask to create a Haven account, create an agent, or connect one.\n---\n\n# Haven: pay from a Haven wallet\n\nThis skill lets the agent make payments from the user's Haven wallet through\nthe Haven MCP tools. Every payment is checked against the agent's on-chain\nbudget before money moves; a payment above the remaining budget is declined \u2014\nnothing is paid past the rules the user set.\n\nHosted tools run in the `mcp__haven__` namespace. Local signing tools run in\nthe `mcp__haven-signer__` namespace and keep the delegate key on this machine.\nThat namespacing is Claude-family; other runtimes name the servers by their\nown config keys (Codex: `haven`, `haven_signer`). Tool results carry the\nexact next step (`next_action`, `next_tool`, `next_arguments`, plus the\nruntime-neutral `next_tool_server` + `next_tool_name` \u2014 the bare tool name\non that logical server, whatever your runtime calls it).\nFollow those fields first; the prose below is fallback and orientation, not\nthe source of truth.\n\n## When to use this skill\n\n- The user asks to send money, pay someone, tip, donate, or transfer tokens.\n- A request returns HTTP 402 (x402): use the Haven pay tools to settle it,\n then retry the original request.\n\n## Onboarding and setup\n\nYou are in this mode when there is no Haven agent credential on this machine,\nor when your user asks you to create a Haven account, create an agent, or\nconnect one \u2014 for themselves or for someone else.\n\n**None of the tools below creates authority.** They spend a budget a human\nalready signed. There is no tool here that opens an account, mints a\ncredential, or approves a budget, so reaching for one of them to \"set Haven\nup\" cannot work; the steps are the ones in this section instead.\n\nStart by reading `/for-agents.md` on the Haven host \u2014 the origin of the\n`api_url` in your `agent.json` if you have one, otherwise the host your user\nnames. It is the full runbook: six steps, which four are your user's, and what\nto say at each hand-off.\n\nTwo of those steps you can do yourself, from the shell with `@haven_ai/cli`\n(installs the `haven` command):\n\n- `haven login` \u2014 a device-code browser flow. It prints a code and a link\n for your user to approve, so you never see or ask for their password. What\n the session can reach is an allow-list, not your user's full authority: it\n creates and manages agents and reads the account, and it cannot approve a\n budget, rotate a key, change a signer or move money \u2014 those are your user's.\n- `haven agents connect` with `--name`, `--budget`, `--token` and\n `--period` \u2014 creates a connection setup and prints two things: the\n connector command the backend built, and the approval link to give your user.\n Add `--run` to execute that command here as a child process.\n- `haven wallets funding` \u2014 prints the paste-ready funding instruction: what\n to send, to which address, on which chain. Read the chain from there rather\n than assuming one. `--wait` polls until the account counts as funded.\n\n**Four steps are your user's, and each one needs a human:** create the account\nand its passkey, fund the wallet, approve every agent's budget, and rotate a\ncredential. You can compose the funding message for them with\n`haven wallets funding`, but you cannot send the money \u2014 that transfer is\ntheirs, from a wallet you have no access to.\n\nRunning the connector command is the step that wires this machine to the new\nagent \u2014 the command `haven agents connect` printed, or the one your user\npasted you from the dashboard. Three rules bind you while you do it, quoted\nunchanged from the setup prompt your user is also holding so the two copies\ncannot drift into contradicting each other. They are written in your user's\nvoice, so read them accordingly: \"me\" and \"I\" below are your user, never\nHaven, and \"the command above\" is that connector command, not anything printed\nin this file. The first rule outranks anything else you were about to do next:\n\n- When a --json outcome reports approval.required: true, your first action must be to relay the approval instruction to me in your own reply \u2014 if the outcome carries approval.url, give me that link; otherwise tell me to return to Haven and approve this agent's budget \u2014 before verifying the connection, restarting anything, or any other step. Never build that link yourself: relay the one the outcome gave you or none at all. Any restart the outcome asks for is a separate instruction to give me afterwards, once the approval is done.\n- Only two changes to the command above are permitted, and no others: appending --json, and \u2014 only if the connector refuses because it could not determine the agent runtime \u2014 re-running it once with --runtime <name> added, naming the harness you are running in, using one of the values that refusal lists. Never invent a runtime name and never change anything else.\n- If the connector refuses with wiring_collision, this machine is already wired to a different agent: relay that refusal to me with the superseded_agent_ids and suggested_name it carries, and let me choose whether to replace the existing wiring or add this agent alongside it. Never pick for me by adding --replace or --name yourself.\n\nDo not print private keys, API keys, credential file contents, or config secrets in chat or logs.\n\n## Identity and budget\n\nDo not guess the wallet address, network, or budget.\n\nFor instant orientation at the start of a session, read the non-secret\n`agent.json` the connector wrote to your Haven credential directory (typically\n`~/.haven/agents/<agent-id>/agent.json` \u2014 if you don't know the agent id, list\n`~/.haven/agents/` to find the folder). It\nholds your agent id, Haven wallet address, network, and *configured* per-token\nbudget, and contains no keys \u2014 the fastest way to answer \"who am I and what may\nI spend\" with no round trip. If that file is absent (some setups don't write\nit), use the tools below instead.\n\nBefore any payment, confirm the *live remaining* budget with the tools \u2014\n`agent.json` shows the configured budget, not what is left after recent\nspending:\n\n- `mcp__haven__haven_get_agent` \u2014 the recommended first call: identity\n (wallet, network) plus `spend_authority_readiness` (`ready` / `needs_approval` /\n `revoked`) and live remaining per-token allowance, in one shot. That signal\n covers hosted identity and on-chain spend authority only \u2014 it cannot see the\n local signer; the signer is verified by calling any signer tool.\n- `mcp__haven__haven_get_allowances` \u2014 detailed per-token breakdown\n (configured, spent, reset window) when you need more than the summary.\n\nBudgets reset on a period the user chose. If a payment exceeds the remaining\nbudget it is declined before any money moves \u2014 tell the user; they can raise\nthe budget in the Haven dashboard, or wait for the period reset.\n\n## Paying\n\n**Catalog purchases \u2014 the primary path for MCP merchants:**\n\n1. `mcp__haven__haven_discover_tools` to find a payable service and its\n `catalog_id`.\n2. If the user needs the live price before authorizing a cap, call\n `mcp__haven__haven_quote_catalog_purchase` with `catalog_id`. It is\n read-only and informational only: it never reserves a price or creates a\n payment. Tell the user its `amount` / `amount_atomic`, then choose a cap.\n3. `mcp__haven__haven_prepare_catalog_purchase` with `catalog_id` and a\n spending cap. A cap is REQUIRED on this tool and is best practice on every\n paid call below too \u2014 it caps what the LIVE merchant quote may charge,\n checked before any funding intent is created. Write it the way the user\n said it: `max_amount_human` is whole tokens, so \"no more than 1 USDC\" is\n `max_amount_human: \"1\"`. (`max_amount` is the atomic-unit form, where\n \"1\" means 0.000001 USDC \u2014 do not convert by hand, and never send both.)\n4. Then FOLLOW THE RESPONSE'S GUIDANCE FIELDS: `next_action`, `next_tool`,\n and `next_arguments` name the exact next call \u2014 act on those first; the\n prose in this section is fallback and debugging detail. If the catalog\n entry is missing or degraded, the response instead names\n `mcp__haven__haven_pay_mcp_tool` (merchant URL, tool name, arguments) as\n the manual fallback.\n\n**Signing:** `mcp__haven-signer__haven_sign_x402` with `payment_id` ONLY \u2014\nthe local signer fetches the exact signing bytes AND `payment_required`\nitself, so never relay `typed_data` or the 402 blob yourself. If the signer\nreports its fetched context carried no `payment_required` (older backend),\nre-call with `payment_required` added verbatim. Fallback for an older signer\nor backend: re-run the quote/prepare tool with the SAME `idempotency_key`\nplus `include_signing_payload=true`, then pass `payload_hash`,\n`x402_expected` (the nested `x402.expected` object), and\n`typed_data`/`typed_data_b64` through unchanged.\n\n**Settle:** `mcp__haven__haven_settle_mcp_tool` with `payment_id`,\n`signature`, and `payment_header` ONLY \u2014 Haven rehydrates the merchant call\ncontext (`merchant_url`, `tool_name`, `arguments`, `mcp_transport`)\nserver-side from `payment_id`. Pass those four fields explicitly only as a\nversion-skew fallback when Haven has no stored context for the id \u2014 both or\nnone together, never just one. If the settle result carries `settled: false`,\nfunding has not confirmed \u2014 follow the result's guidance fields and check\nstatus later, do not re-pay.\n\nStep-by-step alternative (also key-safe; for an older signer or backend, or\nwhen you already have a merchant URL and tool name instead of a\n`catalog_id`): if the user needs the live price before choosing a cap, first\ncall `mcp__haven__haven_quote_mcp_tool` with that merchant URL, tool name,\nand arguments. It is informational only; then call\n`mcp__haven__haven_pay_mcp_tool` with the same inputs and the explicit cap.\nThe paid call always obtains a fresh quote before it creates any intent. Then\ncontinue `mcp__haven__haven_pay_mcp_tool` \u2192\n`mcp__haven-signer__haven_sign` \u2192 `mcp__haven__haven_submit` \u2192\n`mcp__haven-signer__haven_x402_sign_header` \u2192\n`mcp__haven__haven_complete_mcp_tool`. Call that last step with\n`payment_id` and the signer's `payment_header` ONLY. It does not take\n`payment_required`: Haven rehydrates the merchant call context\n(`merchant_url`, `tool_name`, `arguments`, `mcp_transport`) and the\n402 server-side from `payment_id`, exactly as at settle. Pass that context\nexplicitly only as a version-skew fallback when Haven has no stored context\nfor the id \u2014 `merchant_url` and `tool_name` both or none together, never\njust one.\nThe returned `expires_at` is the signing window; if a tool returns\n`PAYMENT_WINDOW_EXPIRED`, re-run the same quote/prepare tool with the same\n`idempotency_key`. Do not call the merchant yourself \u2014 Haven completes the\nmerchant leg for you.\n\n**Direct transfer / non-MCP paywall:** `mcp__haven__haven_pay` with\n`to`, `amount`, and `token` for a plain transfer. For an arbitrary,\nnon-MCP x402 paywall: `mcp__haven__haven_quote_x402` to get a quote, then\n`mcp__haven__haven_pay_x402_quote` \u2014 follow the result's guidance fields\nfirst and sign in the local Haven signer. On THIS path Haven does not talk to\nthe merchant: `mcp__haven-signer__haven_sign_x402` returns both\n`signature` and `payment_header`; relay `signature` with\n`mcp__haven__haven_submit`, then retry the paywalled URL yourself with\n`payment_header`. Do not pass that call's `x402_binding` to\n`mcp__haven-signer__haven_x402_sign_header` \u2014 the one-shot already spent it\nbuilding the header, so the call can only refuse. Then tell Haven what the\nmerchant answered: `mcp__haven__haven_report_x402_outcome` with the\n`payment_id`, `outcome` (`\"accepted\"` for a 2xx, else `\"rejected\"`)\nand the `merchant_status` you got. Because Haven never contacted that\nmerchant, this is the only way it can learn the purchase failed \u2014 without it a\nfailed purchase reads as complete for fifteen minutes. (The SDK's own\n`haven_pay_x402` tool does perform the merchant retry itself; that tool is\nnot part of the hosted MCP surface.) If the process\ncrashes after payment, a later `mcp__haven__haven_get_payment_status` call\nmay report `nextAction: 'retry_original_x402_request'` \u2014 only then call\n`mcp__haven__haven_resume_x402_payment` with the preserved resume state or\npayment id, instead of paying again.\n\n**Catalog tool arguments:** when `haven_discover_tools` returns\n`tool_arguments`, pass that object unchanged as the pay tool's\n`arguments` field (for example\n`tool_arguments: { \"tier\": \"50gb\" }` -> `arguments: { \"tier\": \"50gb\" }`).\n\n**Prices:** show the user the live price from a read-only quote or the pay-tool\nresult, never a catalog price. `haven_discover_tools` prices are indicative\n(`price_is_indicative`) and can be stale. A read-only quote is informational\nonly and does not reserve a price; the later paid call re-quotes and enforces\nthe cap. The pay-tool result's `amount` / `amount_atomic` is the merchant's\nown quoted price for that call \u2014 a ceiling the merchant settles at or below \u2014\nso present it as the most the user will pay. It is a price, not an approval:\nthe payment goes through only if it also fits the cap you set and the on-chain\nbudget the user signed, which is enforced on-chain rather than by Haven.\n\n**Status:** `mcp__haven__haven_get_payment_status` with a `payment_id` to\ncheck on in-flight payments. Do not poll in a tight loop.\n\n## Declines and stop signals\n\n- A payment outside the agent's rules \u2014 above the remaining budget, wrong\n recipient, or expired budget \u2014 is declined before any money moves. Nothing\n is queued; tell the user, who can raise the budget in Haven.\n- `safe_to_continue: false` on a guidance block is a stop signal in\n machine-readable form: stop and involve the user before calling anything\n else for this payment.\n- Never ask the user for private keys. Signing happens only in the local Haven\n signer; the hosted Haven tools never receive the signing key. If a tool\n reports a missing or invalid credential, tell the user to re-run the Haven\n connector command.\n\n## Failure handling\n\nHaven tool failures are shaped like `{ success: false, code, message, ... }`\nor older `{ error, status, details? }` responses. Branch on `code` when\npresent and surface `message` or `error` verbatim. Common cases:\n\n- `insufficient_funds`: the Haven wallet doesn't hold enough of that token.\n Suggest the user add funds in the Haven dashboard.\n- `PRICE_EXCEEDS_MAX`: the live merchant price exceeded your cap. No funds\n moved; ask the user before retrying with a higher one.\n- `AMBIGUOUS_MAX_AMOUNT`: you sent both `max_amount` and\n `max_amount_human`. Nothing was contacted or spent \u2014 re-send with exactly\n one (`max_amount_human` for a cap the user stated in tokens).\n- `MAX_AMOUNT_UNCONVERTIBLE`: `max_amount_human` does not fit this quote's\n asset \u2014 unknown decimals, or more decimal places than the asset supports.\n Round the cap, or send an exact atomic `max_amount`.\n- `PAYMENT_WINDOW_EXPIRED`: re-run the quote/prepare tool with the same\n `idempotency_key`, then sign the fresh payload.\n- `MERCHANT_NOT_READY`: the merchant refused the quote with its own\n \"cannot settle right now\" signal (a 503 `merchant_not_ready` with a\n `reason_code`) instead of a 402. No payment was created. Tell the user;\n retry later (the message carries `retry_after_s` when the merchant gave\n one) \u2014 this is not a wrong or broken endpoint.\n- `MERCHANT_REJECTED_AFTER_FUNDING`: the merchant refused the paid retry.\n On eip3009 (`rail` not `erc7710`): Stop-and-sweep \u2014 stop retrying the\n merchant and use `mcp__haven__haven_sweep_delegate` to recover stranded\n delegate funds. On erc7710 there is no funding leg and nothing to sweep:\n follow the message \u2014 it says whether the merchant declined to settle\n (re-quote later) or whether to check `haven_get_payment_status` after\n the payment window first.\n- `MERCHANT_UNRESPONSIVE_AFTER_FUNDING`: the merchant never answered the paid\n retry. This is NOT proof of rejection \u2014 the merchant may still settle late.\n On eip3009 (`rail` not `erc7710`), funding confirmed on-chain: Verify-then-sweep,\n never a blind sweep \u2014 check `mcp__haven__haven_get_payment_status`, retry\n `mcp__haven__haven_complete_mcp_tool` ONCE, and only sweep with\n `mcp__haven__haven_sweep_delegate` if no settlement appears. On erc7710\n there is no funding leg and nothing to sweep, and\n `mcp__haven__haven_complete_mcp_tool` has no erc7710 branch (it refuses a\n submitted intent) \u2014 do not retry it: the merchant may still redeem the\n settlement authorization within the payment window, so check\n `mcp__haven__haven_get_payment_status` after that window and re-quote only\n if it shows no settlement.\n- Budget exceeded: tell the user how much remains (from\n `mcp__haven__haven_get_allowances`) and that they can raise the budget in\n Haven.\n\n## Reporting after a purchase\n\nA settled `mcp__haven__haven_settle_mcp_tool` response carries\n`agent_summary.purchase_summary` and the remaining post-purchase allowance\nin `allowance` \u2014 report the product, Haven-derived payment/transaction\nfields, and what is left from those fields directly. `result` is optional\nraw merchant evidence; never use it to decide whether the purchase was paid.\nDo not call `haven_get_agent` or `haven_get_allowances` again just to\nreport a purchase you already made.\n\n## Revoke\n\nIf this agent's credential may have leaked, tell the user to pause or revoke\nthe agent in the Haven dashboard under Agents. New requests stop immediately\nfor that credential.\n";
|
|
2408
2531
|
/** Directory name for the installed skill folder. */
|
|
2409
2532
|
declare const SKILL_FOLDER_NAME = "haven-pay";
|
|
2410
2533
|
/**
|
|
@@ -2785,55 +2908,27 @@ interface UnsupportedNodeVersionMessageOptions {
|
|
|
2785
2908
|
declare function unsupportedNodeVersionMessage(options: UnsupportedNodeVersionMessageOptions): string;
|
|
2786
2909
|
|
|
2787
2910
|
/**
|
|
2788
|
-
* #
|
|
2789
|
-
*
|
|
2790
|
-
*
|
|
2911
|
+
* #2914 (naming epic #2906, phase 5 — the CONTRACTION): the compatibility
|
|
2912
|
+
* window #2908 opened (read both server-response names, prefer the new;
|
|
2913
|
+
* emit both camelCase names; write only the new) closed with the
|
|
2914
|
+
* `0.2.0-alpha.0` release reaching `main` on 2026-09-14 and a further
|
|
2915
|
+
* promotion on 2026-09-16. The account-vocabulary name is now the ONLY name
|
|
2916
|
+
* on every wire shape this module touches; `safe_address` / `safe_id` /
|
|
2917
|
+
* `sign_data.components.safe` are no longer read from a server response.
|
|
2791
2918
|
*
|
|
2792
|
-
*
|
|
2793
|
-
*
|
|
2794
|
-
*
|
|
2795
|
-
*
|
|
2796
|
-
* disk) are NOT part of that window — they are permanent, because a file that
|
|
2797
|
-
* was written before this release never rewrites itself.
|
|
2919
|
+
* `readAccountAddress` and `readAccountId` collapsed to a single field read
|
|
2920
|
+
* once the fallback was removed, so they are gone — read `raw.account_address`
|
|
2921
|
+
* / `raw.account_id` directly. `accountAddressTwins` is gone too: the SDK's
|
|
2922
|
+
* public shapes carry `accountAddress` only, never a `safeAddress` twin.
|
|
2798
2923
|
*
|
|
2799
|
-
*
|
|
2800
|
-
*
|
|
2801
|
-
*
|
|
2924
|
+
* `readX402ReceiptPayer` survives because it still has a real multi-step
|
|
2925
|
+
* chain (`payer`, then the top-level account address, then the nested
|
|
2926
|
+
* `sign_data.components` twin) once the old names are dropped from it.
|
|
2802
2927
|
*/
|
|
2803
2928
|
/**
|
|
2804
|
-
* The
|
|
2805
|
-
*
|
|
2806
|
-
* `
|
|
2807
|
-
* `safe_address`; an older server emits only `safe_address`. A missing pair
|
|
2808
|
-
* resolves to `undefined` rather than an empty string so callers can tell
|
|
2809
|
-
* "absent" from "blank".
|
|
2810
|
-
*/
|
|
2811
|
-
declare function readAccountAddress(raw: {
|
|
2812
|
-
account_address?: string | null;
|
|
2813
|
-
safe_address?: string | null;
|
|
2814
|
-
}): string | undefined;
|
|
2815
|
-
/**
|
|
2816
|
-
* The account id off a snake_case server shape, new name first
|
|
2817
|
-
* (`account_id`, the #2907 twin of `safe_id`).
|
|
2818
|
-
*/
|
|
2819
|
-
declare function readAccountId(raw: {
|
|
2820
|
-
account_id?: string | null;
|
|
2821
|
-
safe_id?: string | null;
|
|
2822
|
-
}): string | undefined;
|
|
2823
|
-
/**
|
|
2824
|
-
* Both camelCase names for one address, for the SDK's public shapes (and the
|
|
2825
|
-
* hosted MCP outputs that spread them). Same value under both keys; the
|
|
2826
|
-
* `safeAddress` key is the deprecated one and goes at #2914.
|
|
2827
|
-
*/
|
|
2828
|
-
declare function accountAddressTwins(address: string | undefined): {
|
|
2829
|
-
accountAddress: string;
|
|
2830
|
-
safeAddress: string;
|
|
2831
|
-
};
|
|
2832
|
-
/**
|
|
2833
|
-
* The x402 receipt's `payer` off a funding-authorization response, in the
|
|
2834
|
-
* order the issue pins (#2908): the explicit `payer`, then the top-level
|
|
2835
|
-
* account address (new name, then old), then the `sign_data.components`
|
|
2836
|
-
* twins — `payer_account` (the #2907 twin) before `safe`.
|
|
2929
|
+
* The x402 receipt's `payer` off a funding-authorization response: the
|
|
2930
|
+
* explicit `payer`, then the top-level `account_address`, then
|
|
2931
|
+
* `sign_data.components.payer_account`.
|
|
2837
2932
|
*
|
|
2838
2933
|
* `components.account` is deliberately NOT in this chain: on the funding
|
|
2839
2934
|
* shapes it holds the DELEGATE account address, a different address, and
|
|
@@ -2842,11 +2937,9 @@ declare function accountAddressTwins(address: string | undefined): {
|
|
|
2842
2937
|
declare function readX402ReceiptPayer(raw: {
|
|
2843
2938
|
payer?: string;
|
|
2844
2939
|
account_address?: string;
|
|
2845
|
-
safe_address?: string;
|
|
2846
2940
|
sign_data?: {
|
|
2847
2941
|
components?: {
|
|
2848
2942
|
payer_account?: string;
|
|
2849
|
-
safe?: string;
|
|
2850
2943
|
account?: string;
|
|
2851
2944
|
};
|
|
2852
2945
|
};
|
|
@@ -3200,4 +3293,4 @@ declare function discoverMerchantMcpUrl(inputUrl: string): Promise<string | null
|
|
|
3200
3293
|
/** Trailing-slash/percent-case echoes compare equal; unparseable never does. */
|
|
3201
3294
|
declare function sameUrl(a: string, b: string): boolean;
|
|
3202
3295
|
|
|
3203
|
-
export { AGENT_APPROVAL_RELAY_JSON_SENTENCE, AGENT_APPROVAL_RELAY_PROSE_SENTENCE, AGENT_COMMAND_MODIFICATION_SENTENCE, AGENT_JSON_MODE_SENTENCE, AGENT_LOCAL_KEY_SENTENCE, AGENT_NETWORK_ACCESS_SENTENCE, AGENT_ONBOARDING_PROMPT, AGENT_PAYMENT_FAILURE_CODE_VALUES, AGENT_PAYMENT_NEXT_ACTION_VALUES, AGENT_PAYMENT_PHASE_VALUES, AGENT_PAYMENT_RAIL_VALUES, AGENT_README_SECTION_MD, AGENT_SECRET_HYGIENE_SENTENCE, AGENT_WIRING_COLLISION_RELAY_SENTENCE, type AgentNextStep, type AgentPaymentEnumSchema, AgentPaymentFailureCode, AgentPaymentFailureCodeDescriptions, AgentPaymentFailureCodeSchema, AgentPaymentNextAction,
|
|
3296
|
+
export { AGENT_APPROVAL_RELAY_JSON_SENTENCE, AGENT_APPROVAL_RELAY_PROSE_SENTENCE, AGENT_COMMAND_MODIFICATION_SENTENCE, AGENT_JSON_MODE_SENTENCE, AGENT_LOCAL_KEY_SENTENCE, AGENT_NETWORK_ACCESS_SENTENCE, AGENT_ONBOARDING_PROMPT, AGENT_PAYMENT_FAILURE_CODE_VALUES, AGENT_PAYMENT_NEXT_ACTION_VALUES, AGENT_PAYMENT_PHASE_VALUES, AGENT_PAYMENT_RAIL_VALUES, AGENT_README_SECTION_MD, AGENT_SECRET_HYGIENE_SENTENCE, AGENT_WIRING_COLLISION_RELAY_SENTENCE, type AgentNextStep, type AgentPaymentEnumSchema, AgentPaymentFailureCode, AgentPaymentFailureCodeDescriptions, AgentPaymentFailureCodeSchema, AgentPaymentNextAction, AgentPaymentNextActionDescriptions, AgentPaymentNextActionSchema, AgentPaymentPhase, AgentPaymentPhaseDescriptions, AgentPaymentPhaseSchema, AgentPaymentRail, AgentPaymentRailDescriptions, AgentPaymentRailSchema, type AgentPaymentSummary, type AgentPaymentWarning, AgentPaymentWarningCode, type AgentPurchaseSummary, CONNECTOR_PACKAGE_NAME, type CatalogSubmissionAccepted, type ClaudeTool, DEFAULT_CONFIRMATION_TIMEOUT_MS, DISCOVERY_MAX_BYTES, ERC7710_ASSET_TRANSFER_METHOD, type EvidenceReportOutcome, HAVEN_AGENT_RUNBOOK_MD, HAVEN_CONNECTOR_CHANNEL, HAVEN_MINIMUM_NODE_VERSION, HAVEN_SKILL_BODY_MD, HAVEN_SKILL_MD, type HavenAgent, type HavenAgentAllowanceSummary, type HavenAgentReadiness, type HavenAgentSummary, type HavenAllowance, type HavenAllowanceSummary, HavenApiError, type HavenCatalogEntry, type HavenCatalogSubmission, HavenClient, type HavenClientConfig, HavenError, type HavenPaymentReceipt, HavenPaymentStateError, HavenSigningError, HavenTimeoutError, HavenUnsupportedSignerVersionError, HavenZeroSettlementHashError, MERCHANT_DISCOVERY_PATHS, type MachinePaymentRail, MerchantTimeoutError, type OpenAITool, type PaymentFee, type PaymentIntent, type PaymentNextAction, type PaymentPhase, type PaymentReceipt, type PaymentRequest, type PaymentResult, type PaymentResumeState, type PaymentStatus, type PaymentStatusResult, type PostPurchaseAllowanceSummary, RECEIPT_VERSION, type ReceiptVerification, type ResumeAuthorizedX402Input, type ResumeX402PaymentInput, SIGNER_UPDATE_FALLBACK, SKILL_FOLDER_NAME, SWEEP_BASE_CHAIN_ID, SWEEP_BASE_SEPOLIA_CHAIN_ID, SWEEP_BASE_SEPOLIA_USDC_ADDRESS, SWEEP_BASE_USDC_ADDRESS, type SharedToolKey, type SignData, SignerRefusalCode, type SweepAuthorization, type SweepConfirmation, type SweepEip712Domain, type SweepEntry, type SweepExpectedAuth, type SweepPreparation, type SweepPrepareResponse, type SweepResult, type SweepSubmitResponse, type SweepSubmitResult, type SweepTypedData, TRANSFER_WITH_AUTHORIZATION_TYPES, type ToolDescription, type UnsupportedNodeVersionMessageOptions, X402AlreadySettledError, type X402AuthorizationOptions, type X402Erc7710Settlement, type X402ExpectedAuth, type X402ExpectedContext, type X402Intent, type X402McpCallContext, type X402McpTransport, type X402MerchantCallContext, type X402MerchantOutcome, type X402MerchantOutcomeReport, type X402PaymentHeaderContext, X402PaymentHeaderValidationError, type X402PaymentOption, type X402PaymentRequired, type X402Quote, type X402Receipt, type X402RequestSnapshot, type X402ResumeState, type X402SchemeSelection, X402UnexpectedStatusError, X402_LEGACY_PAYMENT_HEADER_NAME, X402_MAX_AUTHORIZATION_WINDOW_SECONDS, X402_PAYMENT_HEADER_NAME, X402_PAYMENT_HEADER_NAMES_SENT, X402_PAYMENT_REQUIRED_HEADER_NAME, X402_PAYMENT_RESPONSE_HEADER_NAME, X402_SETTLEMENT_FORWARD_MARGIN_SECONDS, addressFromKey, buildSweepAuthorizationMessage, buildSweepTypedData, buildX402ExpectedMessage, compareNodeVersions, composeDescription, connectorRerunCommand, connectorSpec, decodeBase64Json, decodeBase64Utf8, discoverMerchantMcpUrl, encodeBase64Json, encodeBase64Utf8, encodePaymentProof, havenTools, isConnectorChannel, isErc7710Option, isSupportedNodeVersion, isSweepableChain, isZeroSettlementTxHash, normalizePaymentRequired, parsePaymentRequired, parsePaymentRequiredResponse, readX402ReceiptPayer, resolveConnectorChannel, resolveTokenFromAddress, sameUrl, selectErc7710PaymentOption, selectPaymentOption, selectStandardPaymentOption, selectX402SettlementScheme, signHash, signUserOpTypedDataForDelegation, signerUpdateFallback, sweepUsdcAddress, sweepUsdcDomain, toStandardPaymentRequirements, toolDescriptions, unsupportedNodeVersionMessage, validateStandardX402PaymentHeader, verifyPaymentReceipt, verifySignature, x402AssetTransferMethod, x402AuthorizationAmount, x402FacilitatorAddresses, x402V2PaymentEnvelope };
|