@haven_ai/sdk 0.6.0-alpha.0 → 0.8.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,6 +28,9 @@ function connectorRerunCommand(args, options) {
28
28
  const command = `npx ${flags}${connectorSpec(channel)}`;
29
29
  return args ? `${command} ${args}` : command;
30
30
  }
31
+ function connectorUpgradeCommand(options) {
32
+ return connectorRerunCommand("--doctor", { channel: options?.channel, npxFlags: "-y" });
33
+ }
31
34
 
32
35
  // src/types.ts
33
36
  var DEFAULT_CONFIRMATION_TIMEOUT_MS = 9e4;
@@ -73,7 +76,21 @@ var AgentPaymentPhase = {
73
76
  * agent should stop, tell the user, and wait for the sweep flow to reclaim
74
77
  * the funds.
75
78
  */
76
- FundedButUnsettled: "funded_but_unsettled"
79
+ FundedButUnsettled: "funded_but_unsettled",
80
+ /**
81
+ * #3420: TERMINAL — a `submitted` erc7710 x402 intent whose settlement
82
+ * window AND the sweep's last attribution chance have both passed with no
83
+ * verified evidence. The sweep's tick (120s) only ever confirms a
84
+ * transaction mined inside the payment's own settlement window (the child
85
+ * delegation's on-chain `timestamp` caveat, plus the verifier's 120s
86
+ * clock-skew allowance), so once authorize + window + skew is behind the
87
+ * payment, no poll — and no sweep tick — can ever change the answer.
88
+ * The paired `next_action` is `stop_and_tell_user`: tell the user the goods
89
+ * were delivered but Haven holds no verified settlement evidence; reporting
90
+ * a real settlement hash (`haven_report_settlement_evidence`) still works
91
+ * at any age.
92
+ */
93
+ DeliveredUnverified: "delivered_unverified"
77
94
  };
78
95
  var AgentPaymentNextAction = {
79
96
  /** Sign with the delegate key and submit the payment to Haven. */
@@ -221,7 +238,8 @@ var AgentPaymentPhaseDescriptions = {
221
238
  [AgentPaymentPhase.Expired]: "The payment expired before completion.",
222
239
  [AgentPaymentPhase.Failed]: "Haven could not complete the payment; the agent should stop and surface the failure.",
223
240
  [AgentPaymentPhase.InsufficientFunds]: "Pre-flight check determined the delegate balance plus the remaining on-chain budget cannot cover the requested amount, so no payment was created. The account must be funded or the agent budget raised before retrying.",
224
- [AgentPaymentPhase.FundedButUnsettled]: "Haven's funding leg confirmed on-chain but the merchant rejected the x402 retry. The delegate wallet may hold stranded funds. The agent should stop and wait for the wallet owner to sweep the stranded funds back to the account."
241
+ [AgentPaymentPhase.FundedButUnsettled]: "Haven's funding leg confirmed on-chain but the merchant rejected the x402 retry. The delegate wallet may hold stranded funds. The agent should stop and wait for the wallet owner to sweep the stranded funds back to the account.",
242
+ [AgentPaymentPhase.DeliveredUnverified]: "Terminal: the merchant delivered the goods and the settlement window plus the sweep's last attribution chance have both passed with no verified on-chain evidence. The payment can no longer resolve by polling. Tell the user the goods were delivered but Haven holds no verified settlement evidence for this payment."
225
243
  };
226
244
  var AgentPaymentNextActionDescriptions = {
227
245
  [AgentPaymentNextAction.SignAndSubmitPayment]: "Sign with the delegate key and submit the payment to Haven.",
@@ -356,6 +374,24 @@ var MerchantTimeoutError = class extends HavenApiError {
356
374
  this.name = "MerchantTimeoutError";
357
375
  }
358
376
  };
377
+ var X402Erc7710AlreadySettledError = class extends HavenError {
378
+ constructor(paymentId, txHash, body) {
379
+ super(
380
+ `Payment ${paymentId} already settled on-chain (tx ${txHash}). Nothing was signed and nothing new was charged.`,
381
+ "PAYMENT_ALREADY_SETTLED",
382
+ void 0,
383
+ paymentId
384
+ );
385
+ this.paymentId = paymentId;
386
+ this.txHash = txHash;
387
+ this.body = body;
388
+ this.name = "X402Erc7710AlreadySettledError";
389
+ }
390
+ paymentId;
391
+ txHash;
392
+ body;
393
+ x402ErrorCode = "payment_already_settled";
394
+ };
359
395
  var X402UnexpectedStatusError = class extends HavenApiError {
360
396
  x402ErrorCode = "unexpected_non_402_status";
361
397
  /**
@@ -402,6 +438,19 @@ var HavenPaymentStateError = class extends HavenApiError {
402
438
  return this.state.nextAction;
403
439
  }
404
440
  };
441
+ var X402TaskBudgetMismatchError = class extends HavenError {
442
+ constructor(message, idempotencyKey, entryTaskBudgetId, requestedTaskBudgetId) {
443
+ super(message, "X402_TASK_BUDGET_MISMATCH");
444
+ this.idempotencyKey = idempotencyKey;
445
+ this.entryTaskBudgetId = entryTaskBudgetId;
446
+ this.requestedTaskBudgetId = requestedTaskBudgetId;
447
+ this.name = "X402TaskBudgetMismatchError";
448
+ }
449
+ idempotencyKey;
450
+ entryTaskBudgetId;
451
+ requestedTaskBudgetId;
452
+ x402ErrorCode = "task_budget_mismatch";
453
+ };
405
454
  var HavenSigningError = class extends HavenError {
406
455
  constructor(message) {
407
456
  super(message, "SIGNING_ERROR");
@@ -426,7 +475,7 @@ var SignerRefusalCode = {
426
475
  UnsupportedSweepBindingVersion: "UNSUPPORTED_SWEEP_BINDING_VERSION"
427
476
  };
428
477
  function signerUpdateFallback(channel = HAVEN_CONNECTOR_CHANNEL) {
429
- return `Update @haven_ai/signer by rerunning \`${connectorRerunCommand(void 0, { channel })}\`, which reinstalls the pinned MCP runtime, then retry the same signing call. Nothing was signed or spent \u2014 the quote or payment this version came from is unaffected and does not need to be re-quoted.`;
478
+ return `Update @haven_ai/signer: run \`${connectorUpgradeCommand({ channel })}\` and then the repair line it prints, which reinstalls the pinned MCP runtime, then retry the same signing call. Nothing was signed or spent \u2014 the quote or payment this version came from is unaffected and does not need to be re-quoted.`;
430
479
  }
431
480
  var SIGNER_UPDATE_FALLBACK = signerUpdateFallback();
432
481
  var HavenUnsupportedSignerVersionError = class extends HavenError {
@@ -453,6 +502,7 @@ var HavenTimeoutError = class extends HavenError {
453
502
  }
454
503
  };
455
504
  var DIRECT_SIGN_CONTEXT_VERSION = 1;
505
+ var TASK_SIGN_CONTEXT_VERSION = 1;
456
506
  var EIP712_DOMAIN_FIELDS = [
457
507
  { name: "name", type: "string" },
458
508
  { name: "version", type: "string" },
@@ -850,7 +900,7 @@ var REDEEM_DELEGATIONS_ABI = [
850
900
  var SINGLE_DEFAULT_MODE = `0x${"00".repeat(32)}`;
851
901
  function refuse3(detail) {
852
902
  throw new HavenSigningError(
853
- `Refusing to sign: this UserOperation's redeemDelegations call ${detail}. This signer only signs one of two shapes: a single grant to the agent's own account, or a self-delegated task-budget child redeemed under it (the two-link [task child, budget] chain).`
903
+ `Refusing to sign: this UserOperation's redeemDelegations call ${detail}. This signer only signs one of three shapes: a single grant to the agent's own account, a self-delegated task-budget child redeemed under it (the two-link [task child, budget] chain), or a sub-budget grant redeemed under its parent's self-narrowing (the three-link [sub grant, parent child, budget] chain, #3330).`
854
904
  );
855
905
  }
856
906
  function assertRedeemsOwnBudgetDelegation(redeemCalldata, ownAccount) {
@@ -894,9 +944,9 @@ function assertRedeemsOwnBudgetDelegation(redeemCalldata, ownAccount) {
894
944
  "carries an EMPTY delegation chain \u2014 DelegationManager treats this as self-authorised and runs the paired execution as the account, with no caveat, budget or recipient pin"
895
945
  );
896
946
  }
897
- if (delegations.length !== 1 && delegations.length !== 2) {
947
+ if (delegations.length !== 1 && delegations.length !== 2 && delegations.length !== 3) {
898
948
  refuse3(
899
- `carries a ${delegations.length}-link delegation chain, not the single budget grant or the two-link [task child, budget] chain Haven emits`
949
+ `carries a ${delegations.length}-link delegation chain, not the single budget grant, the two-link [task child, budget] chain, or the three-link [sub grant, parent child, budget] chain Haven emits`
900
950
  );
901
951
  }
902
952
  const reEncodedContext = viem.encodeAbiParameters(DELEGATION_ARRAY_PARAM, [delegations]);
@@ -928,6 +978,37 @@ function assertRedeemsOwnBudgetDelegation(redeemCalldata, ownAccount) {
928
978
  }
929
979
  return;
930
980
  }
981
+ if (delegations.length === 3) {
982
+ if (leaf.delegator.toLowerCase() === ownAccount.toLowerCase()) {
983
+ refuse3(
984
+ "carries a three-link chain whose leaf is delegated by this signer's OWN account \u2014 a sub-budget grant always comes from the delegating agent, never from the sub-agent itself"
985
+ );
986
+ }
987
+ const parentChild = delegations[1];
988
+ const parentAccount = leaf.delegator;
989
+ if (parentChild.delegate.toLowerCase() !== parentAccount.toLowerCase()) {
990
+ refuse3(
991
+ `carries a three-link chain whose middle link delegates to ${parentChild.delegate}, not the delegating agent's account the leaf names as its delegator (${parentAccount})`
992
+ );
993
+ }
994
+ if (parentChild.delegator.toLowerCase() !== parentAccount.toLowerCase()) {
995
+ refuse3(
996
+ `carries a three-link chain whose middle link is delegated by ${parentChild.delegator}, not the delegating agent's own account (${parentAccount}) \u2014 the parent link is a self-delegated narrowing`
997
+ );
998
+ }
999
+ const budget = delegations[2];
1000
+ if (budget.delegate.toLowerCase() !== parentAccount.toLowerCase()) {
1001
+ refuse3(
1002
+ `carries a three-link chain whose budget link delegates to ${budget.delegate}, not the delegating agent's account (${parentAccount})`
1003
+ );
1004
+ }
1005
+ if (budget.delegator.toLowerCase() === parentAccount.toLowerCase()) {
1006
+ refuse3(
1007
+ "carries a three-link chain whose budget link is granted by the delegating agent's OWN account \u2014 a real budget delegation always comes from elsewhere"
1008
+ );
1009
+ }
1010
+ return;
1011
+ }
931
1012
  const root = delegations[delegations.length - 1];
932
1013
  if (root.delegator.toLowerCase() === ownAccount.toLowerCase()) {
933
1014
  refuse3(
@@ -981,13 +1062,17 @@ exports.SIGNER_UPDATE_FALLBACK = SIGNER_UPDATE_FALLBACK;
981
1062
  exports.SIMPLE_FACTORY_ADDRESS = SIMPLE_FACTORY_ADDRESS;
982
1063
  exports.SINGLE_DEFAULT_MODE = SINGLE_DEFAULT_MODE;
983
1064
  exports.SignerRefusalCode = SignerRefusalCode;
1065
+ exports.TASK_SIGN_CONTEXT_VERSION = TASK_SIGN_CONTEXT_VERSION;
984
1066
  exports.X402AlreadySettledError = X402AlreadySettledError;
1067
+ exports.X402Erc7710AlreadySettledError = X402Erc7710AlreadySettledError;
1068
+ exports.X402TaskBudgetMismatchError = X402TaskBudgetMismatchError;
985
1069
  exports.X402UnexpectedStatusError = X402UnexpectedStatusError;
986
1070
  exports.assertRedeemsOwnBudgetDelegation = assertRedeemsOwnBudgetDelegation;
987
1071
  exports.assertUserOpTypedDataBinding = assertUserOpTypedDataBinding;
988
1072
  exports.chainIdForNetwork = chainIdForNetwork;
989
1073
  exports.connectorRerunCommand = connectorRerunCommand;
990
1074
  exports.connectorSpec = connectorSpec;
1075
+ exports.connectorUpgradeCommand = connectorUpgradeCommand;
991
1076
  exports.deriveDelegateAccountAddress = deriveDelegateAccountAddress;
992
1077
  exports.isConnectorChannel = isConnectorChannel;
993
1078
  exports.isPackedUserOperationTypedData = isPackedUserOperationTypedData;
@@ -996,5 +1081,5 @@ exports.packedUserOperationHash = packedUserOperationHash;
996
1081
  exports.resolveConnectorChannel = resolveConnectorChannel;
997
1082
  exports.signerUpdateFallback = signerUpdateFallback;
998
1083
  exports.verifySettlementChild = verifySettlementChild;
999
- //# sourceMappingURL=chunk-S42QSWJY.cjs.map
1000
- //# sourceMappingURL=chunk-S42QSWJY.cjs.map
1084
+ //# sourceMappingURL=chunk-HX34HOW4.cjs.map
1085
+ //# sourceMappingURL=chunk-HX34HOW4.cjs.map