@haven_ai/sdk 0.1.37-alpha.0 → 0.2.1-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 +263 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +400 -74
- package/dist/index.d.ts +400 -74
- package/dist/index.js +255 -45
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,59 +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
|
-
safe: string;
|
|
27
|
-
chainId: number;
|
|
28
|
-
settledAt: string | null;
|
|
29
|
-
resourceUrl: string | null;
|
|
30
|
-
};
|
|
31
|
-
/** The agent's cryptographic authorisation — what makes the receipt verifiable. */
|
|
32
|
-
authorization: {
|
|
33
|
-
delegate: string;
|
|
34
|
-
signHash: string;
|
|
35
|
-
signature: string | null;
|
|
36
|
-
};
|
|
37
|
-
onChain: {
|
|
38
|
-
txHash: string | null;
|
|
39
|
-
chainId: number;
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
type ReceiptVerification = {
|
|
43
|
-
verified: true;
|
|
44
|
-
recoveredSigner: string;
|
|
45
|
-
} | {
|
|
46
|
-
verified: false;
|
|
47
|
-
reason: 'missing_signature' | 'bad_signature' | 'signer_mismatch';
|
|
48
|
-
recoveredSigner?: string;
|
|
49
|
-
};
|
|
50
|
-
/**
|
|
51
|
-
* Verify a receipt independently: recover the signer from the authorisation and
|
|
52
|
-
* confirm it is the agent's delegate. Pure — `recover` is injectable but
|
|
53
|
-
* defaults to standard ECDSA recovery, so this runs anywhere (no Haven backend).
|
|
54
|
-
*/
|
|
55
|
-
declare function verifyPaymentReceipt(receipt: PaymentReceipt, recover?: (hash: string, signature: string) => string): ReceiptVerification;
|
|
56
|
-
|
|
57
3
|
interface HavenClientConfig {
|
|
58
4
|
/** Haven API key (sk_agent_xxx) */
|
|
59
5
|
apiKey: string;
|
|
@@ -138,7 +84,14 @@ interface SignData {
|
|
|
138
84
|
};
|
|
139
85
|
/** Breakdown of values that were hashed — useful for debugging */
|
|
140
86
|
components: {
|
|
87
|
+
/** @deprecated #2908 — same value as `payer_account`; the server drops it at #2914. */
|
|
141
88
|
safe: string;
|
|
89
|
+
/**
|
|
90
|
+
* #2907 — the account-vocabulary twin of `safe`: the PAYER account
|
|
91
|
+
* (the user's smart account). Not to be confused with `account`, which on
|
|
92
|
+
* the funding shapes holds the DELEGATE account address.
|
|
93
|
+
*/
|
|
94
|
+
payer_account?: string;
|
|
142
95
|
token: string;
|
|
143
96
|
to: string;
|
|
144
97
|
amount: string;
|
|
@@ -522,6 +475,15 @@ interface HavenAgent {
|
|
|
522
475
|
id: string;
|
|
523
476
|
name: string;
|
|
524
477
|
status: string;
|
|
478
|
+
/**
|
|
479
|
+
* The agent's Haven account (smart account) address — #2908, the
|
|
480
|
+
* account-vocabulary name. Same value as {@link HavenAgent.safeAddress}.
|
|
481
|
+
*/
|
|
482
|
+
accountAddress: string;
|
|
483
|
+
/**
|
|
484
|
+
* @deprecated #2908 — same value as {@link HavenAgent.accountAddress}.
|
|
485
|
+
* Removed in the release after the one carrying #2908 (#2914).
|
|
486
|
+
*/
|
|
525
487
|
safeAddress: string;
|
|
526
488
|
delegateAddress: string;
|
|
527
489
|
chainId: number;
|
|
@@ -563,6 +525,12 @@ interface HavenAllowance {
|
|
|
563
525
|
}
|
|
564
526
|
interface HavenAllowanceSummary {
|
|
565
527
|
agentId: string;
|
|
528
|
+
/** #2908 — the account-vocabulary name; same value as `safeAddress`. */
|
|
529
|
+
accountAddress: string;
|
|
530
|
+
/**
|
|
531
|
+
* @deprecated #2908 — same value as {@link HavenAllowanceSummary.accountAddress}.
|
|
532
|
+
* Removed in the release after the one carrying #2908 (#2914).
|
|
533
|
+
*/
|
|
566
534
|
safeAddress: string;
|
|
567
535
|
delegateAddress: string;
|
|
568
536
|
chainId: number;
|
|
@@ -656,6 +624,25 @@ interface HavenAgentSummary extends HavenAgent {
|
|
|
656
624
|
spend_authority_readiness: HavenAgentReadiness;
|
|
657
625
|
allowances: HavenAgentAllowanceSummary[];
|
|
658
626
|
}
|
|
627
|
+
/**
|
|
628
|
+
* #2960 — one party vocabulary for "who paid" a Haven payment, additive
|
|
629
|
+
* alongside every existing lone `payer*`/`*Address` field (same discipline
|
|
630
|
+
* as the #2907 `safe`/`account` dual-emit, except these four are DISTINCT
|
|
631
|
+
* addresses, not same-value twins of one old field).
|
|
632
|
+
*/
|
|
633
|
+
interface PaymentParties {
|
|
634
|
+
treasuryAccount: string | null;
|
|
635
|
+
delegate: string | null;
|
|
636
|
+
delegateAccount: string | null;
|
|
637
|
+
merchant: string | null;
|
|
638
|
+
}
|
|
639
|
+
/** @internal wire shape of {@link PaymentParties}. */
|
|
640
|
+
interface RawPaymentParties {
|
|
641
|
+
treasury_account: string | null;
|
|
642
|
+
delegate: string | null;
|
|
643
|
+
delegate_account: string | null;
|
|
644
|
+
merchant: string | null;
|
|
645
|
+
}
|
|
659
646
|
interface HavenPaymentReceipt {
|
|
660
647
|
id: string;
|
|
661
648
|
paymentId: string;
|
|
@@ -663,11 +650,28 @@ interface HavenPaymentReceipt {
|
|
|
663
650
|
approvalRequestId?: string | null;
|
|
664
651
|
rail: string;
|
|
665
652
|
proofStatus: string;
|
|
653
|
+
/**
|
|
654
|
+
* @deprecated (#2998) meaning depends on the settlement scheme — the
|
|
655
|
+
* account → delegate funding transaction on eip3009, the (only) settlement
|
|
656
|
+
* transaction on erc7710. Prefer {@link fundingTxHash} / {@link settlementTxHash}, which
|
|
657
|
+
* name which is which.
|
|
658
|
+
*/
|
|
666
659
|
txHash: string;
|
|
660
|
+
/** The account → delegate funding transaction, relayed by Haven (#2998); null on erc7710 (no funding leg) and on retired mpp-rail rows. */
|
|
661
|
+
fundingTxHash: string | null;
|
|
662
|
+
/**
|
|
663
|
+
* The delegate → merchant settlement transaction (#2998). Trust level differs
|
|
664
|
+
* by scheme: on erc7710 it is `txHash` itself and Haven VERIFIED it on-chain
|
|
665
|
+
* before the receipt existed; on eip3009 it is the merchant's claim as relayed
|
|
666
|
+
* (PAYMENT-RESPONSE), NOT verified on-chain by Haven — cite it as such.
|
|
667
|
+
*/
|
|
668
|
+
settlementTxHash: string | null;
|
|
667
669
|
chainId: number;
|
|
668
670
|
resourceUrl: string;
|
|
669
671
|
merchantAddress: string | null;
|
|
670
672
|
payerAddress: string;
|
|
673
|
+
/** #2960: additive alongside `payerAddress` above (`parties.treasury_account` only). */
|
|
674
|
+
parties?: PaymentParties;
|
|
671
675
|
settlementAddress: string;
|
|
672
676
|
tokenSymbol: string;
|
|
673
677
|
tokenAddress: string;
|
|
@@ -843,9 +847,14 @@ declare const AgentPaymentNextAction: {
|
|
|
843
847
|
*/
|
|
844
848
|
readonly PaymentWindowExpired: "payment_window_expired";
|
|
845
849
|
/**
|
|
846
|
-
* Stop and tell the user that the originating
|
|
850
|
+
* Stop and tell the user that the originating account needs to be funded or
|
|
847
851
|
* the agent's per-token allowance needs to be raised before the payment
|
|
848
852
|
* can succeed. A user approval will not fix this state on its own.
|
|
853
|
+
*
|
|
854
|
+
* #2908: the wire twin `fund_account_or_raise_allowance`
|
|
855
|
+
* ({@link AgentPaymentNextActionAccountAlias}) means the same thing; the
|
|
856
|
+
* server keeps emitting THIS value until #2914. Compare via
|
|
857
|
+
* {@link canonicalAgentPaymentNextAction}.
|
|
849
858
|
*/
|
|
850
859
|
readonly FundSafeOrRaiseAllowance: "fund_safe_or_raise_allowance";
|
|
851
860
|
/**
|
|
@@ -854,19 +863,73 @@ declare const AgentPaymentNextAction: {
|
|
|
854
863
|
* return those funds to the originating Safe.
|
|
855
864
|
*/
|
|
856
865
|
readonly SweepStrandedFunds: "sweep_stranded_funds";
|
|
866
|
+
/**
|
|
867
|
+
* #2970: a `submitted` erc7710 x402 intent whose settlement window has
|
|
868
|
+
* passed with no on-chain settlement evidence Haven could verify. Distinct
|
|
869
|
+
* from {@link CheckStatusLater}, which this REPLACES once the window is
|
|
870
|
+
* past — but it is not futile: Haven's settlement sweep (120s tick) scans
|
|
871
|
+
* each candidate over its own window plus a 120s clock-skew allowance, so
|
|
872
|
+
* it can still attribute the settlement for a short while after this value
|
|
873
|
+
* first appears. Poll {@link CheckStatusLater}'s tool
|
|
874
|
+
* (`haven_get_payment_status`) once more, roughly two minutes later; if it
|
|
875
|
+
* still shows no evidence, tell the user the goods were delivered but
|
|
876
|
+
* Haven holds no verified settlement evidence for this payment. If the
|
|
877
|
+
* agent holds the merchant's real settlement transaction hash (from
|
|
878
|
+
* `PAYMENT-RESPONSE`'s `transaction` field, or a prior settle/complete
|
|
879
|
+
* result's `settlement_tx_hash`), report it with the hosted
|
|
880
|
+
* `haven_report_settlement_evidence` tool instead of waiting —
|
|
881
|
+
* `haven_report_x402_outcome` takes no hash and refuses a non-`confirmed`
|
|
882
|
+
* intent.
|
|
883
|
+
*/
|
|
884
|
+
readonly AwaitingSettlementEvidence: "awaiting_settlement_evidence";
|
|
857
885
|
};
|
|
858
886
|
type AgentPaymentNextAction = (typeof AgentPaymentNextAction)[keyof typeof AgentPaymentNextAction];
|
|
887
|
+
/**
|
|
888
|
+
* #2908 (naming epic #2906): the account-vocabulary twin of
|
|
889
|
+
* {@link AgentPaymentNextAction.FundSafeOrRaiseAllowance}. The server ACCEPTS
|
|
890
|
+
* and DOCUMENTS this value from #2907 but keeps EMITTING the old one through
|
|
891
|
+
* the compatibility window; the emitted value flips at #2914.
|
|
892
|
+
*
|
|
893
|
+
* Deliberately declared beside `AgentPaymentNextAction` rather than inside
|
|
894
|
+
* it: the backend keeps a hand-mirror of that const, parity-pinned key-for-key
|
|
895
|
+
* and value-for-value (`agent-payment-taxonomy.parity.test.ts`), and the
|
|
896
|
+
* served `x-enumDescriptions` are the SDK's strings verbatim. Both consts
|
|
897
|
+
* move together at #2914; until then this alias is how a client handles both
|
|
898
|
+
* wire values without forking the taxonomy.
|
|
899
|
+
*/
|
|
900
|
+
declare const AgentPaymentNextActionAccountAlias: {
|
|
901
|
+
/** Account-vocabulary twin of `fund_safe_or_raise_allowance`; same meaning. */
|
|
902
|
+
readonly FundAccountOrRaiseAllowance: "fund_account_or_raise_allowance";
|
|
903
|
+
};
|
|
904
|
+
type AgentPaymentNextActionAccountAlias = (typeof AgentPaymentNextActionAccountAlias)[keyof typeof AgentPaymentNextActionAccountAlias];
|
|
905
|
+
/** Every `next_action` value a server may put on the wire during the #2908 window. */
|
|
906
|
+
type AgentPaymentNextActionWire = AgentPaymentNextAction | AgentPaymentNextActionAccountAlias;
|
|
907
|
+
/**
|
|
908
|
+
* Collapse the #2908 account-vocabulary alias onto its canonical taxonomy
|
|
909
|
+
* value, and pass every other value through untouched.
|
|
910
|
+
*
|
|
911
|
+
* This is the one seam a `switch` over `AgentPaymentNextAction` needs: a
|
|
912
|
+
* case on `FundSafeOrRaiseAllowance` matches a server that emits either
|
|
913
|
+
* spelling, and no case falls through because the alias arrived. Unknown
|
|
914
|
+
* strings are returned as-is (the SDK never invents a value), so the return
|
|
915
|
+
* type is exactly the input type widened by the canonical value.
|
|
916
|
+
*/
|
|
917
|
+
declare function canonicalAgentPaymentNextAction<T extends string | null | undefined>(value: T): Exclude<T, AgentPaymentNextActionAccountAlias> | typeof AgentPaymentNextAction.FundSafeOrRaiseAllowance;
|
|
918
|
+
/** True for EITHER spelling of the fund-or-raise-allowance next action (#2908). */
|
|
919
|
+
declare function isFundAccountOrRaiseAllowance(value: string | null | undefined): boolean;
|
|
859
920
|
declare const AgentPaymentFailureCode: {
|
|
860
921
|
/** A merchant-authoritative x402 price exceeds the caller's pre-funding max_amount cap. */
|
|
861
922
|
readonly PriceExceedsMax: "PRICE_EXCEEDS_MAX";
|
|
862
923
|
/** The x402 funding/quote window expired before the signer or hosted settle step could finish. */
|
|
863
924
|
readonly PaymentWindowExpired: "PAYMENT_WINDOW_EXPIRED";
|
|
864
|
-
/** The
|
|
925
|
+
/** The merchant rejected the paid retry. On eip3009 the funding leg had succeeded (sweep);
|
|
926
|
+
* on erc7710 there is no funding leg — nothing to sweep, follow the message (#2983). */
|
|
865
927
|
readonly MerchantRejectedAfterFunding: "MERCHANT_REJECTED_AFTER_FUNDING";
|
|
866
928
|
/** #1300 review: funding is on-chain but the merchant never ANSWERED the
|
|
867
929
|
* paid retry within the timeout. NOT proof of rejection — the merchant
|
|
868
|
-
*
|
|
869
|
-
*
|
|
930
|
+
* may still settle late, so the guidance is verify-then-act. On eip3009
|
|
931
|
+
* the funding leg had succeeded (verify-then-sweep); on erc7710 there is
|
|
932
|
+
* no funding leg — nothing to sweep, follow the message (#3000). */
|
|
870
933
|
readonly MerchantUnresponsiveAfterFunding: "MERCHANT_UNRESPONSIVE_AFTER_FUNDING";
|
|
871
934
|
/**
|
|
872
935
|
* #1307: the caller omitted merchant_url/tool_name (asking Haven to
|
|
@@ -893,6 +956,16 @@ declare const AgentPaymentFailureCode: {
|
|
|
893
956
|
* The fallback is the exact atomic `max_amount`.
|
|
894
957
|
*/
|
|
895
958
|
readonly MaxAmountUnconvertible: "MAX_AMOUNT_UNCONVERTIBLE";
|
|
959
|
+
/**
|
|
960
|
+
* #2979: the merchant answered a `tools/call` probe with its own
|
|
961
|
+
* machine-readable "cannot settle right now" refusal (HTTP 503,
|
|
962
|
+
* `{ error: 'merchant_not_ready', reason_code, ... }`) instead of a 402
|
|
963
|
+
* challenge — e.g. its settlement wallet is out of gas. No 402 was ever
|
|
964
|
+
* issued and no payment was created; this is honest and (per
|
|
965
|
+
* `retry_after_s`, when present) usually transient, unlike a permanent
|
|
966
|
+
* endpoint miss.
|
|
967
|
+
*/
|
|
968
|
+
readonly MerchantNotReady: "MERCHANT_NOT_READY";
|
|
896
969
|
};
|
|
897
970
|
type AgentPaymentFailureCode = (typeof AgentPaymentFailureCode)[keyof typeof AgentPaymentFailureCode];
|
|
898
971
|
/**
|
|
@@ -935,8 +1008,8 @@ type AgentPaymentRail = (typeof AgentPaymentRail)[keyof typeof AgentPaymentRail]
|
|
|
935
1008
|
type PaymentPhase = AgentPaymentPhase;
|
|
936
1009
|
type PaymentNextAction = AgentPaymentNextAction;
|
|
937
1010
|
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")[];
|
|
938
|
-
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_safe_or_raise_allowance" | "sweep_stranded_funds")[];
|
|
939
|
-
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")[];
|
|
1011
|
+
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_safe_or_raise_allowance" | "sweep_stranded_funds" | "awaiting_settlement_evidence")[];
|
|
1012
|
+
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")[];
|
|
940
1013
|
declare const AGENT_PAYMENT_RAIL_VALUES: ("x402" | "mpp_demo" | "mpp_crypto" | "stripe_deposit" | "spt" | "direct" | "mpp")[];
|
|
941
1014
|
declare const AgentPaymentPhaseDescriptions: Record<AgentPaymentPhase, string>;
|
|
942
1015
|
declare const AgentPaymentNextActionDescriptions: Record<AgentPaymentNextAction, string>;
|
|
@@ -978,6 +1051,23 @@ declare const AgentPaymentWarningCode: {
|
|
|
978
1051
|
* guidance shown here may be optimistic.
|
|
979
1052
|
*/
|
|
980
1053
|
readonly AllowanceReadOptimistic: "ALLOWANCE_READ_OPTIMISTIC";
|
|
1054
|
+
/**
|
|
1055
|
+
* #2991: the quote tools' `expected_settlement_scheme` prediction of what
|
|
1056
|
+
* `haven_prepare_catalog_purchase` / `haven_pay_mcp_tool` will actually
|
|
1057
|
+
* select could not be computed — the agent's execution rail could not be
|
|
1058
|
+
* read from Haven, so `expected_settlement_scheme` is `null` rather than a
|
|
1059
|
+
* guess. `accepted_scheme` (the merchant's offer) is unaffected.
|
|
1060
|
+
*/
|
|
1061
|
+
readonly X402SchemeUnknown: "X402_SCHEME_UNKNOWN";
|
|
1062
|
+
/**
|
|
1063
|
+
* #2968: the merchant answered 200 and handed over goods, but Haven holds NO
|
|
1064
|
+
* on-chain evidence that the payment moved. `settled: false` beside this code
|
|
1065
|
+
* is not a failure — it is the absence of proof, and the two must travel
|
|
1066
|
+
* together so an agent can tell "the user has the goods" apart from "the
|
|
1067
|
+
* money moved". Carries the intent's `expires_at`: after that instant the
|
|
1068
|
+
* settlement can no longer land at all.
|
|
1069
|
+
*/
|
|
1070
|
+
readonly SettlementUnconfirmed: "SETTLEMENT_UNCONFIRMED";
|
|
981
1071
|
};
|
|
982
1072
|
type AgentPaymentWarningCode = (typeof AgentPaymentWarningCode)[keyof typeof AgentPaymentWarningCode];
|
|
983
1073
|
interface AgentPaymentWarning {
|
|
@@ -992,7 +1082,15 @@ interface AgentPaymentWarning {
|
|
|
992
1082
|
* (payment_required) are named in `reason` and taken from the SAME response.
|
|
993
1083
|
*/
|
|
994
1084
|
interface AgentNextStep {
|
|
995
|
-
|
|
1085
|
+
/**
|
|
1086
|
+
* From `AgentPaymentNextAction`, widened by the #2908 account-vocabulary
|
|
1087
|
+
* alias for the compatibility window: the hosted server keeps emitting
|
|
1088
|
+
* `fund_safe_or_raise_allowance` until #2914, but a client compiled against
|
|
1089
|
+
* this type must not reject `fund_account_or_raise_allowance` when the flip
|
|
1090
|
+
* lands. Compare through {@link canonicalAgentPaymentNextAction} or
|
|
1091
|
+
* {@link isFundAccountOrRaiseAllowance}, never by one literal.
|
|
1092
|
+
*/
|
|
1093
|
+
next_action: AgentPaymentNextActionWire;
|
|
996
1094
|
/**
|
|
997
1095
|
* Claude-family namespaced tool name for the next call
|
|
998
1096
|
* (`mcp__<server>__<tool>`), when one exists.
|
|
@@ -1090,6 +1188,8 @@ interface PaymentStatusResult {
|
|
|
1090
1188
|
merchantAddress: string | null;
|
|
1091
1189
|
/** Delegate EOA captured on the payment intent when it was created. */
|
|
1092
1190
|
payerAddress?: string | null;
|
|
1191
|
+
/** #2960: additive alongside `payerAddress` above (`parties.delegate` only). */
|
|
1192
|
+
parties?: PaymentParties;
|
|
1093
1193
|
txHash: string | null;
|
|
1094
1194
|
expiresAt: string;
|
|
1095
1195
|
chainId: number;
|
|
@@ -1167,13 +1267,21 @@ interface HavenCatalogEntry {
|
|
|
1167
1267
|
verifiedAt: string | null;
|
|
1168
1268
|
/**
|
|
1169
1269
|
* Where the entry came from. `operator` = curated in migrations/scripts
|
|
1170
|
-
* (the operator vouches;
|
|
1270
|
+
* (the operator vouches for the listing; the catalog refresh probe still
|
|
1271
|
+
* checks the endpoint, see `verifiedPayable`). `ingestion` = submitted
|
|
1171
1272
|
* through the Verified Payable Directory and passed domain-ownership proof
|
|
1172
1273
|
* plus the read-only quote probe.
|
|
1173
1274
|
*/
|
|
1174
1275
|
source: 'operator' | 'ingestion';
|
|
1175
|
-
/** True only for `ingestion` entries. See the epic's trust claim (never merchant honesty or quality). */
|
|
1276
|
+
/** True only for `ingestion` entries — the one ownership claim. See the epic's trust claim (never merchant honesty or quality). */
|
|
1176
1277
|
domainVerified: boolean;
|
|
1278
|
+
/**
|
|
1279
|
+
* True when Haven watched this endpoint answer a live quote (#2978): the
|
|
1280
|
+
* directory probe for `ingestion` rows, the periodic catalog refresh probe
|
|
1281
|
+
* for `operator` rows (`status === 'active'` with `verifiedAt` set). False
|
|
1282
|
+
* for a degraded row of either source. `discoverTools({ verified:
|
|
1283
|
+
* 'verified' })` filters on this field, not on `source`.
|
|
1284
|
+
*/
|
|
1177
1285
|
verifiedPayable: boolean;
|
|
1178
1286
|
}
|
|
1179
1287
|
/** @internal */
|
|
@@ -1217,7 +1325,17 @@ declare class MerchantTimeoutError extends HavenApiError {
|
|
|
1217
1325
|
}
|
|
1218
1326
|
declare class X402UnexpectedStatusError extends HavenApiError {
|
|
1219
1327
|
readonly x402ErrorCode: "unexpected_non_402_status";
|
|
1220
|
-
|
|
1328
|
+
/**
|
|
1329
|
+
* #2979: `body` is the merchant's own JSON, when the non-402 response
|
|
1330
|
+
* carried one — e.g. the demo merchant's `/mcp` readiness gate answers
|
|
1331
|
+
* `503 { error: 'merchant_not_ready', reason_code, ... }`. Optional and
|
|
1332
|
+
* best-effort: a non-JSON or unreadable body leaves this `undefined`, same
|
|
1333
|
+
* as before this field existed. Consumers key on it (not on the message
|
|
1334
|
+
* string) to distinguish an honest, machine-readable merchant refusal from
|
|
1335
|
+
* a genuine "this is not the x402 endpoint" miss, which otherwise look
|
|
1336
|
+
* identical — both are just "some non-402 status".
|
|
1337
|
+
*/
|
|
1338
|
+
constructor(message: string, statusCode: number, body?: unknown);
|
|
1221
1339
|
}
|
|
1222
1340
|
/**
|
|
1223
1341
|
* #1521: the idempotency key resolved to a payment that has already settled,
|
|
@@ -1266,6 +1384,19 @@ declare class HavenPaymentStateError extends HavenApiError {
|
|
|
1266
1384
|
declare class HavenSigningError extends HavenError {
|
|
1267
1385
|
constructor(message: string);
|
|
1268
1386
|
}
|
|
1387
|
+
/**
|
|
1388
|
+
* #2972: `MerchantCompletion.reportSettlementEvidence` /
|
|
1389
|
+
* `HavenClient.reportSettlementEvidence` refuse a `0x00…00` settlement hash
|
|
1390
|
+
* BEFORE any network call — see `isZeroSettlementTxHash`. That marker is
|
|
1391
|
+
* never a real transaction (the demo merchant's own "delivered, not settled"
|
|
1392
|
+
* value), so posting it to `POST /machine-payments/evidence` could only ever
|
|
1393
|
+
* come back refused, at the cost of a real round trip. A typed error rather
|
|
1394
|
+
* than a `HavenApiError`-shaped 400: no request was ever attempted, so there
|
|
1395
|
+
* is no HTTP status or response body to carry.
|
|
1396
|
+
*/
|
|
1397
|
+
declare class HavenZeroSettlementHashError extends HavenError {
|
|
1398
|
+
constructor(paymentId: string);
|
|
1399
|
+
}
|
|
1269
1400
|
/**
|
|
1270
1401
|
* Refusal codes the local signer returns when it does not recognise the
|
|
1271
1402
|
* VERSION of a Haven-signed binding it was asked to sign (#1309). Distinct
|
|
@@ -1327,6 +1458,73 @@ declare class HavenTimeoutError extends HavenError {
|
|
|
1327
1458
|
constructor(paymentId: string);
|
|
1328
1459
|
}
|
|
1329
1460
|
|
|
1461
|
+
/**
|
|
1462
|
+
* Verifiable payment receipts.
|
|
1463
|
+
*
|
|
1464
|
+
* A self-contained proof bundle for a settled Haven payment that anyone can
|
|
1465
|
+
* verify **independently of Haven**. The anchor is the agent delegate's
|
|
1466
|
+
* signature over the on-chain transfer hash: recover the signer and confirm it
|
|
1467
|
+
* is the agent's delegate, and you have cryptographic proof the agent authorised
|
|
1468
|
+
* exactly this transfer — no need to trust Haven's backend. The on-chain
|
|
1469
|
+
* `txHash` is the settlement source of truth (verify on any explorer).
|
|
1470
|
+
*
|
|
1471
|
+
* This lives in the SDK so agents and users can verify receipts client-side
|
|
1472
|
+
* with zero Haven trust.
|
|
1473
|
+
*/
|
|
1474
|
+
declare const RECEIPT_VERSION = "haven-receipt-1";
|
|
1475
|
+
interface PaymentReceipt {
|
|
1476
|
+
version: typeof RECEIPT_VERSION;
|
|
1477
|
+
paymentId: string;
|
|
1478
|
+
payment: {
|
|
1479
|
+
token: string;
|
|
1480
|
+
tokenAddress: string;
|
|
1481
|
+
amount: string;
|
|
1482
|
+
amountSek: string | null;
|
|
1483
|
+
recipient: string;
|
|
1484
|
+
/** @deprecated since #2907 — read `account`; removed in #2914 (the release after the naming window). Same value as `account`. */
|
|
1485
|
+
safe: string;
|
|
1486
|
+
/**
|
|
1487
|
+
* The payer's smart-account address (#2907 twin of `safe`). Optional for
|
|
1488
|
+
* the window: a server from before the twin emits `safe` only.
|
|
1489
|
+
*/
|
|
1490
|
+
account?: string;
|
|
1491
|
+
/**
|
|
1492
|
+
* #2960: one party vocabulary for "who paid", additive alongside `safe`/
|
|
1493
|
+
* `account` above (which are `parties.treasury_account` only). Optional
|
|
1494
|
+
* for the window: a server from before #2960 emits neither. Ignored by
|
|
1495
|
+
* `verifyPaymentReceipt`, which reads only `authorization`.
|
|
1496
|
+
*/
|
|
1497
|
+
parties?: RawPaymentParties;
|
|
1498
|
+
chainId: number;
|
|
1499
|
+
settledAt: string | null;
|
|
1500
|
+
resourceUrl: string | null;
|
|
1501
|
+
};
|
|
1502
|
+
/** The agent's cryptographic authorisation — what makes the receipt verifiable. */
|
|
1503
|
+
authorization: {
|
|
1504
|
+
delegate: string;
|
|
1505
|
+
signHash: string;
|
|
1506
|
+
signature: string | null;
|
|
1507
|
+
};
|
|
1508
|
+
onChain: {
|
|
1509
|
+
txHash: string | null;
|
|
1510
|
+
chainId: number;
|
|
1511
|
+
};
|
|
1512
|
+
}
|
|
1513
|
+
type ReceiptVerification = {
|
|
1514
|
+
verified: true;
|
|
1515
|
+
recoveredSigner: string;
|
|
1516
|
+
} | {
|
|
1517
|
+
verified: false;
|
|
1518
|
+
reason: 'missing_signature' | 'bad_signature' | 'signer_mismatch';
|
|
1519
|
+
recoveredSigner?: string;
|
|
1520
|
+
};
|
|
1521
|
+
/**
|
|
1522
|
+
* Verify a receipt independently: recover the signer from the authorisation and
|
|
1523
|
+
* confirm it is the agent's delegate. Pure — `recover` is injectable but
|
|
1524
|
+
* defaults to standard ECDSA recovery, so this runs anywhere (no Haven backend).
|
|
1525
|
+
*/
|
|
1526
|
+
declare function verifyPaymentReceipt(receipt: PaymentReceipt, recover?: (hash: string, signature: string) => string): ReceiptVerification;
|
|
1527
|
+
|
|
1330
1528
|
/**
|
|
1331
1529
|
* Gasless delegate-sweep primitives — the single source of truth shared by the
|
|
1332
1530
|
* edge signer (which signs) and the Haven backend (which relays).
|
|
@@ -1542,6 +1740,38 @@ interface X402MerchantOutcomeReport {
|
|
|
1542
1740
|
resourceUrl: string;
|
|
1543
1741
|
recorded: 'reconciliation_event' | 'evidence';
|
|
1544
1742
|
}
|
|
1743
|
+
/**
|
|
1744
|
+
* #2970: what `reportEvidence` learned about the report it just made.
|
|
1745
|
+
*
|
|
1746
|
+
* `confirmed` mirrors the backend's 202 (`modules/mpp/evidence.ts`) — the
|
|
1747
|
+
* intent is now `confirmed` (or was already, on the funding-leg path) with
|
|
1748
|
+
* THIS hash recorded. `retryable` mirrors its 503 (`settlement_unobservable`,
|
|
1749
|
+
* exhausted the retry budget above): the chain could not be read, or the
|
|
1750
|
+
* transaction is not mined yet — ask again later. `refused` mirrors every
|
|
1751
|
+
* terminal refusal (409 `settlement_unverified`, a validation error, an
|
|
1752
|
+
* unknown payment id, or a transport failure with no HTTP status at all,
|
|
1753
|
+
* reported as `statusCode: 0`) — reporting the same hash again will not
|
|
1754
|
+
* change the answer.
|
|
1755
|
+
*/
|
|
1756
|
+
type EvidenceReportOutcome = {
|
|
1757
|
+
outcome: 'confirmed';
|
|
1758
|
+
} | {
|
|
1759
|
+
outcome: 'retryable';
|
|
1760
|
+
statusCode: number | undefined;
|
|
1761
|
+
} | {
|
|
1762
|
+
outcome: 'refused';
|
|
1763
|
+
statusCode: number;
|
|
1764
|
+
};
|
|
1765
|
+
/**
|
|
1766
|
+
* #2970: a hash of the form `0x00…00` is never a real transaction — it is the
|
|
1767
|
+
* demo merchant's own "delivered, not settled" marker (`ZERO_TX_HASH` in
|
|
1768
|
+
* `packages/demo-merchant-mcp/src/x402.ts`), reused rather than invented here
|
|
1769
|
+
* so the hosted gate and any other consumer recognise it the same way. Treated
|
|
1770
|
+
* as equivalent to "no hash was reported": there is nothing on-chain to verify,
|
|
1771
|
+
* so asking the backend to look is a wasted round trip that can only ever
|
|
1772
|
+
* resolve to a refusal.
|
|
1773
|
+
*/
|
|
1774
|
+
declare function isZeroSettlementTxHash(hash: string | null | undefined): boolean;
|
|
1545
1775
|
|
|
1546
1776
|
declare class HavenClient {
|
|
1547
1777
|
private readonly delegateKey;
|
|
@@ -1766,10 +1996,13 @@ declare class HavenClient {
|
|
|
1766
1996
|
search?: string;
|
|
1767
1997
|
rail?: 'x402' | 'mpp';
|
|
1768
1998
|
/**
|
|
1769
|
-
*
|
|
1770
|
-
*
|
|
1771
|
-
*
|
|
1772
|
-
*
|
|
1999
|
+
* `'verified'` (epic #1717, #2978) returns entries whose endpoint Haven
|
|
2000
|
+
* watched answer a live quote — `verifiedPayable === true` — from
|
|
2001
|
+
* EITHER source: an operator-curated row that keeps passing its
|
|
2002
|
+
* periodic 402 probe, or a self-submitted row that also passed
|
|
2003
|
+
* domain-ownership proof. It is not a provenance filter; `'operator'`
|
|
2004
|
+
* still filters on provenance (`source === 'operator'`) regardless of
|
|
2005
|
+
* badge state, and `'any'` (the default) returns the merged listing.
|
|
1773
2006
|
*/
|
|
1774
2007
|
verified?: 'any' | 'verified' | 'operator';
|
|
1775
2008
|
}): Promise<HavenCatalogEntry[]>;
|
|
@@ -2019,6 +2252,15 @@ declare class HavenClient {
|
|
|
2019
2252
|
ok: boolean;
|
|
2020
2253
|
body: unknown;
|
|
2021
2254
|
settlementTxHash?: string;
|
|
2255
|
+
/**
|
|
2256
|
+
* #2970: what the evidence report (below) learned, when one was made.
|
|
2257
|
+
* `undefined` when there was no hash to report at all — no funding tx on
|
|
2258
|
+
* the erc7710 branch and no (or a zero) merchant-reported settlement hash.
|
|
2259
|
+
* The hosted erc7710 settle/complete gate reads this to decide whether
|
|
2260
|
+
* `settled: true` is honest; the 3009 branch's `settled: true` does not
|
|
2261
|
+
* need it — see `paid-mcp-completion.ts` for why.
|
|
2262
|
+
*/
|
|
2263
|
+
evidenceOutcome?: EvidenceReportOutcome;
|
|
2022
2264
|
}>;
|
|
2023
2265
|
/**
|
|
2024
2266
|
* #2292: report the outcome of a merchant retry the AGENT performed.
|
|
@@ -2035,6 +2277,17 @@ declare class HavenClient {
|
|
|
2035
2277
|
merchantStatus: number;
|
|
2036
2278
|
merchantBody?: string;
|
|
2037
2279
|
}): Promise<X402MerchantOutcomeReport>;
|
|
2280
|
+
/**
|
|
2281
|
+
* #2972: report the merchant's real settlement transaction hash for an
|
|
2282
|
+
* erc7710 x402 payment — the remedy for `DELIVERED_UNSETTLED` /
|
|
2283
|
+
* `SETTLEMENT_PENDING` / `awaiting_settlement_evidence` when the agent
|
|
2284
|
+
* holds the hash (`PAYMENT-RESPONSE.transaction`, or a prior settle/
|
|
2285
|
+
* complete result's `settlement_tx_hash`) and Haven does not. See
|
|
2286
|
+
* `MerchantCompletion.reportSettlementEvidence` for the fail-closed
|
|
2287
|
+
* verification this posts into (`observeErc7710Settlement`) and the
|
|
2288
|
+
* client-side zero-hash refusal.
|
|
2289
|
+
*/
|
|
2290
|
+
reportSettlementEvidence(paymentId: string, settlementTxHash: string): Promise<EvidenceReportOutcome>;
|
|
2038
2291
|
/**
|
|
2039
2292
|
* GET /x402/:id/merchant-call-context — the settle-leg twin of #1263's
|
|
2040
2293
|
* sign-context fetch (#1307). Re-serves the stored merchant MCP-tool call
|
|
@@ -2222,8 +2475,8 @@ declare const toolDescriptions: {
|
|
|
2222
2475
|
readonly nextActionGuidance: string;
|
|
2223
2476
|
};
|
|
2224
2477
|
readonly getPaymentStatus: {
|
|
2225
|
-
readonly summary: "Fetch structured Haven payment status
|
|
2226
|
-
readonly behavior: "
|
|
2478
|
+
readonly summary: "Fetch structured Haven payment status for agent recovery.";
|
|
2479
|
+
readonly behavior: "State: phase, nextAction, rail, amount, merchant, resource, idempotency, message; parties: treasury/delegate/delegateAccount/merchant. awaiting_settlement_evidence: poll once, else unverified.";
|
|
2227
2480
|
readonly nextActionGuidance: "";
|
|
2228
2481
|
};
|
|
2229
2482
|
readonly getResumeState: {
|
|
@@ -2234,7 +2487,7 @@ declare const toolDescriptions: {
|
|
|
2234
2487
|
readonly getAgent: {
|
|
2235
2488
|
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.";
|
|
2236
2489
|
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.";
|
|
2237
|
-
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
|
|
2490
|
+
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 (safeAddress: deprecated alias, same value), delegateAddress, chainId.";
|
|
2238
2491
|
readonly nextActionGuidance: "";
|
|
2239
2492
|
};
|
|
2240
2493
|
readonly getAllowances: {
|
|
@@ -2274,7 +2527,7 @@ declare const toolDescriptions: {
|
|
|
2274
2527
|
readonly 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.";
|
|
2275
2528
|
};
|
|
2276
2529
|
readonly sweep_delegate: {
|
|
2277
|
-
readonly summary: "Sweep stranded USDC and/or ETH from the delegate wallet back to the originating
|
|
2530
|
+
readonly summary: "Sweep stranded USDC and/or ETH from the delegate wallet back to the originating account.";
|
|
2278
2531
|
readonly selectionGuidance: string;
|
|
2279
2532
|
readonly behavior: string;
|
|
2280
2533
|
readonly nextActionGuidance: string;
|
|
@@ -2285,6 +2538,11 @@ declare const toolDescriptions: {
|
|
|
2285
2538
|
readonly behavior: string;
|
|
2286
2539
|
readonly nextActionGuidance: string;
|
|
2287
2540
|
};
|
|
2541
|
+
readonly reportSettlementEvidence: {
|
|
2542
|
+
readonly summary: "Report an erc7710 payment's real settlement transaction hash so Haven can verify it on-chain and confirm the payment.";
|
|
2543
|
+
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.";
|
|
2544
|
+
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.";
|
|
2545
|
+
};
|
|
2288
2546
|
};
|
|
2289
2547
|
type SharedToolKey = keyof typeof toolDescriptions;
|
|
2290
2548
|
|
|
@@ -2330,7 +2588,7 @@ type SharedToolKey = keyof typeof toolDescriptions;
|
|
|
2330
2588
|
* live sibling constant not pulled in here; if it ever is, this applies to it
|
|
2331
2589
|
* too (design review, #2537).
|
|
2332
2590
|
*/
|
|
2333
|
-
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";
|
|
2591
|
+
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";
|
|
2334
2592
|
/** Directory name for the installed skill folder. */
|
|
2335
2593
|
declare const SKILL_FOLDER_NAME = "haven-pay";
|
|
2336
2594
|
/**
|
|
@@ -2710,6 +2968,74 @@ interface UnsupportedNodeVersionMessageOptions {
|
|
|
2710
2968
|
*/
|
|
2711
2969
|
declare function unsupportedNodeVersionMessage(options: UnsupportedNodeVersionMessageOptions): string;
|
|
2712
2970
|
|
|
2971
|
+
/**
|
|
2972
|
+
* #2908 (naming epic #2906, phase 1): the account-vocabulary reads and the
|
|
2973
|
+
* dual-name emissions every published package shares during the one-release
|
|
2974
|
+
* compatibility window.
|
|
2975
|
+
*
|
|
2976
|
+
* The rule, stated once: READ both names and prefer the new; EMIT both names
|
|
2977
|
+
* with the same value; WRITE only the new. The old names on server responses
|
|
2978
|
+
* are removed by #2914, one release after the one that carries this module.
|
|
2979
|
+
* The credential-FILE fallbacks (`safe_address` / `safeAddress` in a file on
|
|
2980
|
+
* disk) are NOT part of that window — they are permanent, because a file that
|
|
2981
|
+
* was written before this release never rewrites itself.
|
|
2982
|
+
*
|
|
2983
|
+
* Kept as tiny pure functions so a reader has exactly one fallback chain per
|
|
2984
|
+
* shape and a test can mutate it: dropping the new name fails the new-shape
|
|
2985
|
+
* test, dropping the old name fails the old-shape test.
|
|
2986
|
+
*/
|
|
2987
|
+
/**
|
|
2988
|
+
* The account address off a snake_case server shape, new name first.
|
|
2989
|
+
*
|
|
2990
|
+
* `account_address` is the P0 (#2907) twin the server emits beside
|
|
2991
|
+
* `safe_address`; an older server emits only `safe_address`. A missing pair
|
|
2992
|
+
* resolves to `undefined` rather than an empty string so callers can tell
|
|
2993
|
+
* "absent" from "blank".
|
|
2994
|
+
*/
|
|
2995
|
+
declare function readAccountAddress(raw: {
|
|
2996
|
+
account_address?: string | null;
|
|
2997
|
+
safe_address?: string | null;
|
|
2998
|
+
}): string | undefined;
|
|
2999
|
+
/**
|
|
3000
|
+
* The account id off a snake_case server shape, new name first
|
|
3001
|
+
* (`account_id`, the #2907 twin of `safe_id`).
|
|
3002
|
+
*/
|
|
3003
|
+
declare function readAccountId(raw: {
|
|
3004
|
+
account_id?: string | null;
|
|
3005
|
+
safe_id?: string | null;
|
|
3006
|
+
}): string | undefined;
|
|
3007
|
+
/**
|
|
3008
|
+
* Both camelCase names for one address, for the SDK's public shapes (and the
|
|
3009
|
+
* hosted MCP outputs that spread them). Same value under both keys; the
|
|
3010
|
+
* `safeAddress` key is the deprecated one and goes at #2914.
|
|
3011
|
+
*/
|
|
3012
|
+
declare function accountAddressTwins(address: string | undefined): {
|
|
3013
|
+
accountAddress: string;
|
|
3014
|
+
safeAddress: string;
|
|
3015
|
+
};
|
|
3016
|
+
/**
|
|
3017
|
+
* The x402 receipt's `payer` off a funding-authorization response, in the
|
|
3018
|
+
* order the issue pins (#2908): the explicit `payer`, then the top-level
|
|
3019
|
+
* account address (new name, then old), then the `sign_data.components`
|
|
3020
|
+
* twins — `payer_account` (the #2907 twin) before `safe`.
|
|
3021
|
+
*
|
|
3022
|
+
* `components.account` is deliberately NOT in this chain: on the funding
|
|
3023
|
+
* shapes it holds the DELEGATE account address, a different address, and
|
|
3024
|
+
* reading it here would silently corrupt the receipt's payer.
|
|
3025
|
+
*/
|
|
3026
|
+
declare function readX402ReceiptPayer(raw: {
|
|
3027
|
+
payer?: string;
|
|
3028
|
+
account_address?: string;
|
|
3029
|
+
safe_address?: string;
|
|
3030
|
+
sign_data?: {
|
|
3031
|
+
components?: {
|
|
3032
|
+
payer_account?: string;
|
|
3033
|
+
safe?: string;
|
|
3034
|
+
account?: string;
|
|
3035
|
+
};
|
|
3036
|
+
};
|
|
3037
|
+
}): string | undefined;
|
|
3038
|
+
|
|
2713
3039
|
/**
|
|
2714
3040
|
* x402 protocol support for the Haven SDK.
|
|
2715
3041
|
*
|
|
@@ -3058,4 +3384,4 @@ declare function discoverMerchantMcpUrl(inputUrl: string): Promise<string | null
|
|
|
3058
3384
|
/** Trailing-slash/percent-case echoes compare equal; unparseable never does. */
|
|
3059
3385
|
declare function sameUrl(a: string, b: string): boolean;
|
|
3060
3386
|
|
|
3061
|
-
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, 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, 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, normalizePaymentRequired, parsePaymentRequired, parsePaymentRequiredResponse, resolveConnectorChannel, resolveTokenFromAddress, sameUrl, selectErc7710PaymentOption, selectPaymentOption, selectStandardPaymentOption, selectX402SettlementScheme, signHash, signUserOpTypedDataForDelegation, signerUpdateFallback, sweepUsdcAddress, sweepUsdcDomain, toStandardPaymentRequirements, toolDescriptions, unsupportedNodeVersionMessage, validateStandardX402PaymentHeader, verifyPaymentReceipt, verifySignature, x402AssetTransferMethod, x402AuthorizationAmount, x402FacilitatorAddresses, x402V2PaymentEnvelope };
|
|
3387
|
+
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, AgentPaymentNextActionAccountAlias, AgentPaymentNextActionDescriptions, AgentPaymentNextActionSchema, type AgentPaymentNextActionWire, 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, accountAddressTwins, addressFromKey, buildSweepAuthorizationMessage, buildSweepTypedData, buildX402ExpectedMessage, canonicalAgentPaymentNextAction, compareNodeVersions, composeDescription, connectorRerunCommand, connectorSpec, decodeBase64Json, decodeBase64Utf8, discoverMerchantMcpUrl, encodeBase64Json, encodeBase64Utf8, encodePaymentProof, havenTools, isConnectorChannel, isErc7710Option, isFundAccountOrRaiseAllowance, isSupportedNodeVersion, isSweepableChain, isZeroSettlementTxHash, normalizePaymentRequired, parsePaymentRequired, parsePaymentRequiredResponse, readAccountAddress, readAccountId, readX402ReceiptPayer, resolveConnectorChannel, resolveTokenFromAddress, sameUrl, selectErc7710PaymentOption, selectPaymentOption, selectStandardPaymentOption, selectX402SettlementScheme, signHash, signUserOpTypedDataForDelegation, signerUpdateFallback, sweepUsdcAddress, sweepUsdcDomain, toStandardPaymentRequirements, toolDescriptions, unsupportedNodeVersionMessage, validateStandardX402PaymentHeader, verifyPaymentReceipt, verifySignature, x402AssetTransferMethod, x402AuthorizationAmount, x402FacilitatorAddresses, x402V2PaymentEnvelope };
|