@haven_ai/sdk 0.1.15-alpha.0 → 0.1.17-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +78 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +69 -8
- package/dist/index.d.ts +69 -8
- package/dist/index.js +78 -6
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
package/dist/index.cjs
CHANGED
|
@@ -531,6 +531,7 @@ function stableStringify(value) {
|
|
|
531
531
|
const primitive = JSON.stringify(value);
|
|
532
532
|
return primitive === void 0 ? "undefined" : primitive;
|
|
533
533
|
}
|
|
534
|
+
if (value instanceof Date) return JSON.stringify(value.toISOString());
|
|
534
535
|
if (Array.isArray(value)) return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
535
536
|
const object = value;
|
|
536
537
|
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(object[key])}`).join(",")}}`;
|
|
@@ -632,11 +633,24 @@ var DEFAULT_REQUEST_TIMEOUT = 3e4;
|
|
|
632
633
|
var DEFAULT_CONFIRMATION_TIMEOUT = 9e4;
|
|
633
634
|
var DEFAULT_POLLING_INTERVAL = 3e3;
|
|
634
635
|
function formatAtomicAmount(atomic, decimals) {
|
|
636
|
+
if (atomic < 0n) return "0.0";
|
|
635
637
|
const s = atomic.toString().padStart(decimals + 1, "0");
|
|
636
638
|
const intPart = s.slice(0, s.length - decimals) || "0";
|
|
637
639
|
const fracPart = s.slice(s.length - decimals).replace(/0+$/, "") || "0";
|
|
638
640
|
return `${intPart}.${fracPart}`;
|
|
639
641
|
}
|
|
642
|
+
function safeBigInt(value) {
|
|
643
|
+
try {
|
|
644
|
+
return BigInt(value);
|
|
645
|
+
} catch {
|
|
646
|
+
return 0n;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
function deriveReadiness(status, allowances) {
|
|
650
|
+
if (status !== "active") return "revoked";
|
|
651
|
+
const hasSpendable = allowances.some((a) => safeBigInt(a.remainingAtomic) > 0n);
|
|
652
|
+
return hasSpendable ? "ready" : "needs_approval";
|
|
653
|
+
}
|
|
640
654
|
var MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
641
655
|
var MCP_ACCEPT = "application/json, text/event-stream";
|
|
642
656
|
var MCP_CLIENT_INFO = { name: "haven-sdk", version: "1" };
|
|
@@ -1003,6 +1017,32 @@ var HavenClient = class {
|
|
|
1003
1017
|
chainId: raw.chain_id
|
|
1004
1018
|
};
|
|
1005
1019
|
}
|
|
1020
|
+
/**
|
|
1021
|
+
* One-shot "am I ready?" bootstrap: identity + live spend authority + a
|
|
1022
|
+
* readiness signal, in a single call. Folds {@link getAgent} and
|
|
1023
|
+
* {@link getAllowances} together and derives a {@link HavenAgentReadiness}
|
|
1024
|
+
* so an agent can answer "who am I and can I pay right now" at session start
|
|
1025
|
+
* without two round trips and manual assembly.
|
|
1026
|
+
*/
|
|
1027
|
+
async getAgentSummary() {
|
|
1028
|
+
const [agent, allowanceSummary] = await Promise.all([
|
|
1029
|
+
this.getAgent(),
|
|
1030
|
+
this.getAllowances()
|
|
1031
|
+
]);
|
|
1032
|
+
const allowances = allowanceSummary.allowances.map((a) => {
|
|
1033
|
+
const token = resolveTokenFromAddress(a.tokenAddress);
|
|
1034
|
+
const remainingDisplay = token ? `${formatAtomicAmount(safeBigInt(a.onchain.remaining), token.decimals)} ${a.tokenSymbol}` : `${a.onchain.remaining} ${a.tokenSymbol} (atomic; unknown decimals)`;
|
|
1035
|
+
return {
|
|
1036
|
+
tokenSymbol: a.tokenSymbol,
|
|
1037
|
+
remainingAtomic: a.onchain.remaining,
|
|
1038
|
+
remainingDisplay,
|
|
1039
|
+
configuredAmount: a.configuredAmount,
|
|
1040
|
+
resetPeriodMin: a.resetPeriodMin,
|
|
1041
|
+
isResetPending: a.onchain.isResetPending
|
|
1042
|
+
};
|
|
1043
|
+
});
|
|
1044
|
+
return { ...agent, readiness: deriveReadiness(agent.status, allowances), allowances };
|
|
1045
|
+
}
|
|
1006
1046
|
/**
|
|
1007
1047
|
* Sweep stranded USDC and ETH from the delegate EOA back to the originating Safe.
|
|
1008
1048
|
*
|
|
@@ -1686,6 +1726,21 @@ var HavenClient = class {
|
|
|
1686
1726
|
* accepted), threads the session + wallet headers, sets `X-PAYMENT`, and
|
|
1687
1727
|
* collapses an SSE JSON-RPC response to its `result`.
|
|
1688
1728
|
*/
|
|
1729
|
+
/**
|
|
1730
|
+
* Wait for a payment's Safe→delegate funding tx to reach ≥1 on-chain
|
|
1731
|
+
* confirmation. The hosted x402 completion path MUST call this after funding
|
|
1732
|
+
* and before delivering the X-PAYMENT header, so the merchant's
|
|
1733
|
+
* balanceOf(delegate) / transferWithAuthorization verification sees the funded
|
|
1734
|
+
* balance — otherwise it rejects with "Payment verification failed". The
|
|
1735
|
+
* SDK's local path already does this (see authorizeStandardX402); the hosted
|
|
1736
|
+
* split flow regressed when the 5→3 collapse removed the incidental
|
|
1737
|
+
* inter-call latency that used to mask it. No-op when the funding tx hash or
|
|
1738
|
+
* a chain RPC (chainRpcs[chainId]) is unavailable.
|
|
1739
|
+
*/
|
|
1740
|
+
async ensureFundingConfirmed(paymentId, fundingTxHash) {
|
|
1741
|
+
const status = await this.getPaymentStatus(paymentId);
|
|
1742
|
+
await this.waitForFundingTx(fundingTxHash ?? status.txHash ?? void 0, status.chainId);
|
|
1743
|
+
}
|
|
1689
1744
|
async completeX402MerchantCall(input) {
|
|
1690
1745
|
const evidenceContext = await this.resolveX402MerchantCompletionContext({
|
|
1691
1746
|
paymentId: input.paymentId,
|
|
@@ -2961,8 +3016,9 @@ var toolDescriptions = {
|
|
|
2961
3016
|
nextActionGuidance: ""
|
|
2962
3017
|
},
|
|
2963
3018
|
getAgent: {
|
|
2964
|
-
summary: "Return the authenticated agent identity
|
|
2965
|
-
|
|
3019
|
+
summary: "Return the authenticated agent identity AND its live spend authority in one call: Haven wallet, delegate, chain, raw status, a readiness signal, and per-token remaining allowance (atomic + human-readable). The recommended first call in a new session to confirm who you are and whether you can pay right now.",
|
|
3020
|
+
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.",
|
|
3021
|
+
behavior: 'Reads identity plus the on-chain AllowanceModule snapshot in one shot. readiness is "ready" when at least one token has remaining on-chain allowance, "needs_approval" when the agent is active but has no remaining allowance to auto-spend (payments will be queued for the wallet owner to approve in Haven), and "revoked" when the credential is not active. allowances[] carries remainingAtomic and remainingDisplay per token. Identity fields (id, name, status, safeAddress, delegateAddress, chainId) are unchanged from before.',
|
|
2966
3022
|
nextActionGuidance: ""
|
|
2967
3023
|
},
|
|
2968
3024
|
getAllowances: {
|
|
@@ -3263,12 +3319,28 @@ the \`mcp__haven-signer__\` namespace and keep the delegate key on this machine.
|
|
|
3263
3319
|
- A request returns HTTP 402 (x402): use the Haven pay tools to settle it,
|
|
3264
3320
|
then retry the original request.
|
|
3265
3321
|
|
|
3266
|
-
## Identity and budget
|
|
3322
|
+
## Identity and budget
|
|
3323
|
+
|
|
3324
|
+
Do not guess the wallet address, network, or budget.
|
|
3325
|
+
|
|
3326
|
+
For instant orientation at the start of a session, read the non-secret
|
|
3327
|
+
\`agent.json\` the connector wrote to your Haven credential directory (typically
|
|
3328
|
+
\`~/.haven/agents/<agent-id>/agent.json\` \u2014 if you don't know the agent id, list
|
|
3329
|
+
\`~/.haven/agents/\` to find the folder). It
|
|
3330
|
+
holds your agent id, Haven wallet address, network, and *configured* per-token
|
|
3331
|
+
budget, and contains no keys \u2014 the fastest way to answer "who am I and what may
|
|
3332
|
+
I spend" with no round trip. If that file is absent (some setups don't write
|
|
3333
|
+
it), use the tools below instead.
|
|
3267
3334
|
|
|
3268
|
-
|
|
3335
|
+
Before any payment, confirm the *live remaining* budget with the tools \u2014
|
|
3336
|
+
\`agent.json\` shows the configured budget, not what is left after recent
|
|
3337
|
+
spending:
|
|
3269
3338
|
|
|
3270
|
-
- \`haven_get_agent\` \u2014
|
|
3271
|
-
|
|
3339
|
+
- \`haven_get_agent\` \u2014 the recommended first call: identity (wallet, network)
|
|
3340
|
+
plus a readiness signal (\`ready\` / \`needs_approval\` / \`revoked\`) and live
|
|
3341
|
+
remaining per-token allowance, in one shot.
|
|
3342
|
+
- \`haven_get_allowances\` \u2014 detailed per-token breakdown (configured, spent,
|
|
3343
|
+
reset window) when you need more than the summary.
|
|
3272
3344
|
|
|
3273
3345
|
Budgets reset on a period the user chose. If a payment exceeds the remaining
|
|
3274
3346
|
budget it is queued for the user to approve in the Haven dashboard \u2014 this is
|