@dev.sail.money/sailor 1.3.0-98 → 1.4.0-242

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.
Files changed (231) hide show
  1. package/AGENTS.md +7 -7
  2. package/LICENSE +1 -1
  3. package/README.md +64 -472
  4. package/package.json +11 -6
  5. package/packages/cli/README.md +1 -1
  6. package/packages/cli/dist/index.cjs +1469 -463
  7. package/packages/cli/dist/server.cjs +19796 -21737
  8. package/packages/sdk/README.md +1 -1
  9. package/packages/sdk/dist/abis/ConfigurablePermission.d.ts +130 -0
  10. package/packages/sdk/dist/abis/ConfigurablePermission.d.ts.map +1 -0
  11. package/packages/sdk/dist/abis/ConfigurablePermission.js +79 -0
  12. package/packages/sdk/dist/abis/ConfigurablePermission.js.map +1 -0
  13. package/packages/sdk/dist/abis/SailKernel.d.ts +42 -0
  14. package/packages/sdk/dist/abis/SailKernel.d.ts.map +1 -1
  15. package/packages/sdk/dist/abis/SailKernel.js +34 -0
  16. package/packages/sdk/dist/abis/SailKernel.js.map +1 -1
  17. package/packages/sdk/dist/abis/index.d.ts +1 -0
  18. package/packages/sdk/dist/abis/index.d.ts.map +1 -1
  19. package/packages/sdk/dist/abis/index.js +1 -0
  20. package/packages/sdk/dist/abis/index.js.map +1 -1
  21. package/packages/sdk/dist/chains.d.ts +0 -7
  22. package/packages/sdk/dist/chains.d.ts.map +1 -1
  23. package/packages/sdk/dist/chains.js +81 -32
  24. package/packages/sdk/dist/chains.js.map +1 -1
  25. package/packages/sdk/dist/client.d.ts +1 -1
  26. package/packages/sdk/dist/client.d.ts.map +1 -1
  27. package/packages/sdk/dist/client.js +137 -16
  28. package/packages/sdk/dist/client.js.map +1 -1
  29. package/packages/sdk/dist/deployments.d.ts +6 -4
  30. package/packages/sdk/dist/deployments.d.ts.map +1 -1
  31. package/packages/sdk/dist/deployments.js +120 -118
  32. package/packages/sdk/dist/deployments.js.map +1 -1
  33. package/packages/sdk/dist/eip712.d.ts +84 -0
  34. package/packages/sdk/dist/eip712.d.ts.map +1 -1
  35. package/packages/sdk/dist/eip712.js +148 -0
  36. package/packages/sdk/dist/eip712.js.map +1 -1
  37. package/packages/sdk/dist/fees.d.ts +2 -1
  38. package/packages/sdk/dist/fees.d.ts.map +1 -1
  39. package/packages/sdk/dist/fees.js +2 -1
  40. package/packages/sdk/dist/fees.js.map +1 -1
  41. package/packages/sdk/dist/index.d.ts +3 -2
  42. package/packages/sdk/dist/index.d.ts.map +1 -1
  43. package/packages/sdk/dist/index.js +3 -2
  44. package/packages/sdk/dist/index.js.map +1 -1
  45. package/packages/sdk/dist/intelligence.d.ts +1 -1
  46. package/packages/sdk/dist/intelligence.js +1 -1
  47. package/packages/sdk/dist/safe.d.ts +49 -0
  48. package/packages/sdk/dist/safe.d.ts.map +1 -1
  49. package/packages/sdk/dist/safe.js +74 -0
  50. package/packages/sdk/dist/safe.js.map +1 -1
  51. package/packages/sdk/package.json +6 -2
  52. package/packages/ui/dist/assets/{add-BX5reKtK.js → add-CBbu2pe_.js} +2 -2
  53. package/packages/ui/dist/assets/{all-wallets-IZ3PlVF-.js → all-wallets-C1oy4NUu.js} +2 -2
  54. package/packages/ui/dist/assets/{app-store-ARgRdMdF.js → app-store-DKqyf0Zv.js} +1 -1
  55. package/packages/ui/dist/assets/{apple-VCaqsI9w.js → apple-DyoIbCFy.js} +2 -2
  56. package/packages/ui/dist/assets/{arrow-bottom-circle-h5vFiZ2I.js → arrow-bottom-circle-CMS-OqZQ.js} +2 -2
  57. package/packages/ui/dist/assets/arrow-bottom-pUWeEqYu.js +8 -0
  58. package/packages/ui/dist/assets/arrow-left-B81HMJNL.js +8 -0
  59. package/packages/ui/dist/assets/arrow-right-Z5czoKlC.js +8 -0
  60. package/packages/ui/dist/assets/arrow-top-C6ym1oll.js +8 -0
  61. package/packages/ui/dist/assets/{bank-6c28yOM9.js → bank-B41nlslf.js} +2 -2
  62. package/packages/ui/dist/assets/{basic-CJnbTfSd.js → basic-CWqOb7CV.js} +177 -177
  63. package/packages/ui/dist/assets/{browser-CDKlxM3D.js → browser-DDKdqoZ9.js} +2 -2
  64. package/packages/ui/dist/assets/{card-DQdED02q.js → card-BgOmTajq.js} +2 -2
  65. package/packages/ui/dist/assets/ccip-CtJUKWRd.js +1 -0
  66. package/packages/ui/dist/assets/{checkmark-JoRNVoFV.js → checkmark-CGqQipH4.js} +2 -2
  67. package/packages/ui/dist/assets/{checkmark-bold-B6bGHVIs.js → checkmark-bold-Ci5xf90j.js} +2 -2
  68. package/packages/ui/dist/assets/chevron-bottom-D7Xert17.js +8 -0
  69. package/packages/ui/dist/assets/chevron-left-BGbUebR2.js +8 -0
  70. package/packages/ui/dist/assets/chevron-right-xVsESnHU.js +8 -0
  71. package/packages/ui/dist/assets/chevron-top-DEA9cR6v.js +8 -0
  72. package/packages/ui/dist/assets/{chrome-store-D-fiJ9qJ.js → chrome-store-BsyI-4PI.js} +2 -2
  73. package/packages/ui/dist/assets/{clock-xCPkzwjj.js → clock-Dct9oQ3M.js} +2 -2
  74. package/packages/ui/dist/assets/{close-BkqmPpWG.js → close-BvSCnI2y.js} +2 -2
  75. package/packages/ui/dist/assets/{coinPlaceholder-PIvN9oq_.js → coinPlaceholder-p7RiWkon.js} +2 -2
  76. package/packages/ui/dist/assets/{compass-CW5kWcxW.js → compass-BUeeZqX4.js} +2 -2
  77. package/packages/ui/dist/assets/{copy-DUZlAQJJ.js → copy-C5jXbxLq.js} +2 -2
  78. package/packages/ui/dist/assets/core-CiAm42Mq.js +907 -0
  79. package/packages/ui/dist/assets/cursor-C0T7JWFO.js +3 -0
  80. package/packages/ui/dist/assets/{cursor-transparent-BUAMB0G1.js → cursor-transparent-BZp3-JmA.js} +2 -2
  81. package/packages/ui/dist/assets/{desktop-BxdlwV8P.js → desktop-BIui_Lzb.js} +2 -2
  82. package/packages/ui/dist/assets/{disconnect-GelNh3mn.js → disconnect-B3Bxdchp.js} +2 -2
  83. package/packages/ui/dist/assets/{discord-N0jnxkzC.js → discord-VWI0yDyx.js} +2 -2
  84. package/packages/ui/dist/assets/{etherscan-B41u7wF4.js → etherscan-BpBvUT9i.js} +2 -2
  85. package/packages/ui/dist/assets/events-DQ172AOg.js +1 -0
  86. package/packages/ui/dist/assets/{exclamation-triangle-BWJC56FC.js → exclamation-triangle-o1TJHIUw.js} +2 -2
  87. package/packages/ui/dist/assets/{extension-G6I6oogw.js → extension-4RaLvbh5.js} +2 -2
  88. package/packages/ui/dist/assets/external-link-BHIwjDgj.js +8 -0
  89. package/packages/ui/dist/assets/{facebook-47twy32b.js → facebook-Bes5g-wN.js} +2 -2
  90. package/packages/ui/dist/assets/{farcaster-DYqnqCqs.js → farcaster-CiJ-352m.js} +2 -2
  91. package/packages/ui/dist/assets/{filters-dF6xeJnE.js → filters-DMOteumb.js} +2 -2
  92. package/packages/ui/dist/assets/{github-DbW4Ihz2.js → github-D2nDec9X.js} +2 -2
  93. package/packages/ui/dist/assets/{google-TKm7G8LF.js → google-lZZlQZPQ.js} +2 -2
  94. package/packages/ui/dist/assets/{help-circle-CY3qTmsG.js → help-circle-D4cSSziR.js} +1 -1
  95. package/packages/ui/dist/assets/{id-JpHW4q14.js → id-BmhXZq5P.js} +2 -2
  96. package/packages/ui/dist/assets/{image-Dip2fG98.js → image-Dz4FPeET.js} +2 -2
  97. package/packages/ui/dist/assets/index-B07bCKJ8.css +1 -0
  98. package/packages/ui/dist/assets/index-BV8s6ez1.js +1 -0
  99. package/packages/ui/dist/assets/index-BeUp3nOq.js +1 -0
  100. package/packages/ui/dist/assets/index-CvRylmZJ.js +16 -0
  101. package/packages/ui/dist/assets/{index-q0mGElxZ.js → index-DeoQO45V.js} +3 -3
  102. package/packages/ui/dist/assets/index-Et5S3ZaW.js +47 -0
  103. package/packages/ui/dist/assets/index-LiKeH8Cd.js +1780 -0
  104. package/packages/ui/dist/assets/index.es-dfpEui-9.js +26 -0
  105. package/packages/ui/dist/assets/{info-B1enFsqh.js → info-77RSvIMg.js} +2 -2
  106. package/packages/ui/dist/assets/{info-circle-D4j3FISs.js → info-circle-CWsII-NN.js} +2 -2
  107. package/packages/ui/dist/assets/{lightbulb-DZbKr-vS.js → lightbulb-BZXzm7XE.js} +2 -2
  108. package/packages/ui/dist/assets/{mail-D-TO_uVQ.js → mail-DMG1YqB0.js} +2 -2
  109. package/packages/ui/dist/assets/metamask-sdk-K1x_iqcc.js +542 -0
  110. package/packages/ui/dist/assets/{mobile-Bkmwzav2.js → mobile-DuJfOBSk.js} +2 -2
  111. package/packages/ui/dist/assets/{more-D1_I_jiB.js → more-Cs9ySK2F.js} +2 -2
  112. package/packages/ui/dist/assets/{network-placeholder-DUaFjoXh.js → network-placeholder-CMDPmB1E.js} +2 -2
  113. package/packages/ui/dist/assets/{nftPlaceholder-Cc0iUryh.js → nftPlaceholder-Cj0f9y2u.js} +2 -2
  114. package/packages/ui/dist/assets/{off-BvX71sse.js → off-9zSSsm-e.js} +2 -2
  115. package/packages/ui/dist/assets/{play-store-XzLbtbTd.js → play-store-CPwIb8Gj.js} +2 -2
  116. package/packages/ui/dist/assets/{plus-B77_RmYR.js → plus-BOHQri8o.js} +2 -2
  117. package/packages/ui/dist/assets/{qr-code-BNeIhB1d.js → qr-code-DqhbK276.js} +1 -1
  118. package/packages/ui/dist/assets/{recycle-horizontal-B9sX-yty.js → recycle-horizontal-BpGM56Qz.js} +2 -2
  119. package/packages/ui/dist/assets/{refresh-BWRygnjm.js → refresh-BPzZlhTP.js} +2 -2
  120. package/packages/ui/dist/assets/{reown-logo-DCAEsGFm.js → reown-logo-OCkI0xzo.js} +2 -2
  121. package/packages/ui/dist/assets/{search-ZXIqrawS.js → search-B1JEJvwq.js} +2 -2
  122. package/packages/ui/dist/assets/{secp256k1-Doz05h4g.js → secp256k1-BqUeV9Cb.js} +1 -1
  123. package/packages/ui/dist/assets/{send-BQcO0jNC.js → send-JNsDlNoq.js} +2 -2
  124. package/packages/ui/dist/assets/{swapHorizontal-4yZEzz2K.js → swapHorizontal-C3Z1FImK.js} +2 -2
  125. package/packages/ui/dist/assets/{swapHorizontalBold-DxBKu3sl.js → swapHorizontalBold-Cmdy2iAn.js} +2 -2
  126. package/packages/ui/dist/assets/{swapHorizontalMedium-DAQYJ2JK.js → swapHorizontalMedium-DFX57Nn9.js} +2 -2
  127. package/packages/ui/dist/assets/{swapHorizontalRoundedBold-CUlZzFJ6.js → swapHorizontalRoundedBold-baB389c8.js} +2 -2
  128. package/packages/ui/dist/assets/{swapVertical-CjWHAaDM.js → swapVertical-DmAYGfK1.js} +2 -2
  129. package/packages/ui/dist/assets/{telegram-JBeabiJP.js → telegram-BHbYE-nI.js} +2 -2
  130. package/packages/ui/dist/assets/{three-dots-D3R8OjSx.js → three-dots-BwRWl6qJ.js} +2 -2
  131. package/packages/ui/dist/assets/{twitch-1f9z7xVO.js → twitch-Drx0q6B6.js} +2 -2
  132. package/packages/ui/dist/assets/{twitterIcon-BW7n2xnp.js → twitterIcon-AuJ2KQ6p.js} +2 -2
  133. package/packages/ui/dist/assets/{verify-Cs5owI38.js → verify-Dkrd3q7o.js} +2 -2
  134. package/packages/ui/dist/assets/{verify-filled-Ci5sx5qS.js → verify-filled-B9e3-nz-.js} +2 -2
  135. package/packages/ui/dist/assets/{w3m-modal-DnWtss8u.js → w3m-modal-DtkEjQA7.js} +1 -1
  136. package/packages/ui/dist/assets/{wallet-MaGNqaW-.js → wallet-CqYzSiBd.js} +2 -2
  137. package/packages/ui/dist/assets/{wallet-placeholder-kTOy12_L.js → wallet-placeholder-B05kTN_K.js} +2 -2
  138. package/packages/ui/dist/assets/{walletconnect-CyuP92jg.js → walletconnect-BwoPXLaS.js} +3 -3
  139. package/packages/ui/dist/assets/{warning-circle-BImUCdpG.js → warning-circle-DK9Ai8rT.js} +2 -2
  140. package/packages/ui/dist/assets/{x-II45JHpV.js → x-BNdh5DVW.js} +2 -2
  141. package/packages/ui/dist/index.html +2 -2
  142. package/templates/default/.agents/skills/sail-mandates/SKILL.md +1 -1
  143. package/templates/default/.agents/skills/sail-mandates/references/approvals.md +3 -3
  144. package/templates/default/.agents/skills/sail-mandates/references/examples-index.md +3 -3
  145. package/templates/default/.agents/skills/sail-onboarding/SKILL.md +34 -33
  146. package/templates/default/.agents/skills/sail-servers/SKILL.md +1 -0
  147. package/templates/default/.agents/skills/sail-swap-quote/SKILL.md +76 -0
  148. package/templates/default/.agents/skills/sail-template-approve-batch/SKILL.md +98 -0
  149. package/templates/default/.agents/skills/sail-template-borrow/SKILL.md +68 -0
  150. package/templates/default/.agents/skills/sail-template-deposit/SKILL.md +61 -0
  151. package/templates/default/.agents/skills/sail-template-swap/SKILL.md +207 -0
  152. package/templates/default/.agents/skills/sail-template-swap-no-oracle/SKILL.md +100 -0
  153. package/templates/default/.agents/skills/sail-template-transfer/SKILL.md +52 -0
  154. package/templates/default/.agents/skills/sail-template-withdraw/SKILL.md +50 -0
  155. package/templates/default/.agents/skills/sail-templates/SKILL.md +142 -0
  156. package/templates/default/.agents/skills/sail-templates/catalog.mjs +200 -0
  157. package/templates/default/.agents/skills/sail-templates/deployed.json +133 -0
  158. package/templates/default/.agents/skills/sail-templates/oracles/IOracle.sol +13 -0
  159. package/templates/default/.agents/skills/sail-templates/oracles/UniV3TwapOracle.sol +114 -0
  160. package/templates/default/.agents/skills/sail-templates/oracles/libs/FullMath.sol +62 -0
  161. package/templates/default/.agents/skills/sail-templates/oracles/libs/TickMath.sol +44 -0
  162. package/templates/default/.agents/skills/sail-templates/references/config-schemas.md +139 -0
  163. package/templates/default/.agents/skills/sail-templates/references/reuse-flow.md +139 -0
  164. package/templates/default/.agents/skills/sail-token-resolve/SKILL.md +174 -0
  165. package/templates/default/.env.example +9 -0
  166. package/templates/default/AGENTS.md +107 -13
  167. package/templates/default/docs/PERMISSION_MODEL.md +2 -2
  168. package/{examples → templates/default/examples}/custom-mandate/.sail/contracts/interfaces/IPermission.sol +4 -0
  169. package/{examples → templates/default/examples}/custom-mandate/README.md +4 -1
  170. package/{examples → templates/default/examples}/permissions/interfaces/IBatchPermission.sol +2 -0
  171. package/{examples → templates/default/examples}/permissions/interfaces/IPermission.sol +4 -0
  172. package/templates/default/scripts/quote-swap.mjs +211 -0
  173. package/templates/default/scripts/resolve-token.mjs +992 -0
  174. package/templates/default/scripts/shared-template-addr.mjs +110 -0
  175. package/templates/default/test/BoundedCallPermission.t.sol +2 -1
  176. package/docs/PERMISSION_MODEL.md +0 -93
  177. package/examples/README.md +0 -24
  178. package/examples/lifi-permissions/LifiBoundedApprovePermissionCloneable.sol +0 -84
  179. package/examples/lifi-permissions/LifiDiamondSwapPermissionCloneable.sol +0 -97
  180. package/examples/lifi-permissions/README.md +0 -53
  181. package/packages/ui/dist/assets/arrow-bottom-Cwptw8fW.js +0 -8
  182. package/packages/ui/dist/assets/arrow-left-bM1TRcV9.js +0 -8
  183. package/packages/ui/dist/assets/arrow-right-BYd_N4Jr.js +0 -8
  184. package/packages/ui/dist/assets/arrow-top-CLUnwVE2.js +0 -8
  185. package/packages/ui/dist/assets/ccip-BL7RIPfY.js +0 -1
  186. package/packages/ui/dist/assets/chevron-bottom-BMCelIEu.js +0 -8
  187. package/packages/ui/dist/assets/chevron-left-ryPLhHCc.js +0 -8
  188. package/packages/ui/dist/assets/chevron-right-CdDNRv7f.js +0 -8
  189. package/packages/ui/dist/assets/chevron-top-BxWIjjGk.js +0 -8
  190. package/packages/ui/dist/assets/core-von2c1sc.js +0 -907
  191. package/packages/ui/dist/assets/cursor-BzRVY7BD.js +0 -3
  192. package/packages/ui/dist/assets/events-C9icG2YB.js +0 -1
  193. package/packages/ui/dist/assets/external-link-BPaGQf4a.js +0 -8
  194. package/packages/ui/dist/assets/fallback-BTfJeGjh.js +0 -1
  195. package/packages/ui/dist/assets/index-BGJ_8fMk.js +0 -1
  196. package/packages/ui/dist/assets/index-Bq3PAopp.js +0 -16
  197. package/packages/ui/dist/assets/index-C4_cA5XW.js +0 -1
  198. package/packages/ui/dist/assets/index-CaDN0gL4.js +0 -1
  199. package/packages/ui/dist/assets/index-DLElIcBr.js +0 -1789
  200. package/packages/ui/dist/assets/index-lhNfD4jA.css +0 -1
  201. package/packages/ui/dist/assets/index.es-BaCKS_tW.js +0 -26
  202. package/packages/ui/dist/assets/metamask-sdk-DljW3QD1.js +0 -542
  203. package/packages/ui/dist/assets/native-CJ5et6AR.js +0 -1
  204. package/packages/ui/dist/assets/parseSignature-BAS-wKoj.js +0 -1
  205. package/scripts/check-docs.mjs +0 -309
  206. package/scripts/check-init.mjs +0 -123
  207. package/scripts/check-update.mjs +0 -177
  208. package/scripts/clean.mjs +0 -17
  209. package/scripts/pack.mjs +0 -21
  210. package/templates/default/.agents/skills/sail-overview/SKILL.md +0 -100
  211. package/templates/default/.agents/skills/sail-sailor/SKILL.md +0 -190
  212. package/templates/default/.agents/skills/sail-setup/SKILL.md +0 -38
  213. package/templates/default/.gitlab-ci.yml +0 -58
  214. /package/{examples → templates/default/examples}/custom-mandate/foundry.toml +0 -0
  215. /package/{examples → templates/default/examples}/custom-mandate/mandates/BoundedCallPermission.sol +0 -0
  216. /package/{examples → templates/default/examples}/custom-mandate/mandates/README.md +0 -0
  217. /package/{examples → templates/default/examples}/custom-mandate/mandates/SailCalldata.sol +0 -0
  218. /package/{examples → templates/default/examples}/permissions/BoundedApproveAndCallBatch.sol +0 -0
  219. /package/{examples → templates/default/examples}/permissions/BoundedBorrow_AaveV3_Arbitrum.sol +0 -0
  220. /package/{examples → templates/default/examples}/permissions/BoundedLimitless_Base.sol +0 -0
  221. /package/{examples → templates/default/examples}/permissions/BoundedPerp_GMXv2_Arbitrum.sol +0 -0
  222. /package/{examples → templates/default/examples}/permissions/BoundedStake_Venice_Base.sol +0 -0
  223. /package/{examples → templates/default/examples}/permissions/BoundedSupply_AaveV3_Arbitrum.sol +0 -0
  224. /package/{examples → templates/default/examples}/permissions/BoundedSwapNative_UniswapV3_Base.sol +0 -0
  225. /package/{examples → templates/default/examples}/permissions/BoundedSwap_UniswapV3_Base.sol +0 -0
  226. /package/{examples → templates/default/examples}/permissions/BoundedSwap_UniswapV4_Unichain.sol +0 -0
  227. /package/{examples → templates/default/examples}/permissions/BoundedTransfer_ERC20_Ethereum.sol +0 -0
  228. /package/{examples → templates/default/examples}/permissions/BoundedVault_ERC4626_Base.sol +0 -0
  229. /package/{examples → templates/default/examples}/permissions/README.md +0 -0
  230. /package/{examples → templates/default/examples}/permissions/SailCalldata.sol +0 -0
  231. /package/{examples → templates/default/examples}/permissions/foundry.toml +0 -0
@@ -15767,13 +15767,13 @@ var init_getCallError = __esm({
15767
15767
 
15768
15768
  // ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/utils/promise/withResolvers.js
15769
15769
  function withResolvers() {
15770
- let resolve3 = () => void 0;
15770
+ let resolve4 = () => void 0;
15771
15771
  let reject = () => void 0;
15772
15772
  const promise = new Promise((resolve_, reject_) => {
15773
- resolve3 = resolve_;
15773
+ resolve4 = resolve_;
15774
15774
  reject = reject_;
15775
15775
  });
15776
- return { promise, resolve: resolve3, reject };
15776
+ return { promise, resolve: resolve4, reject };
15777
15777
  }
15778
15778
  var init_withResolvers = __esm({
15779
15779
  "../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/utils/promise/withResolvers.js"() {
@@ -15792,8 +15792,8 @@ function createBatchScheduler({ fn, id, shouldSplitBatch, wait: wait2 = 0, sort
15792
15792
  if (sort && Array.isArray(data))
15793
15793
  data.sort(sort);
15794
15794
  for (let i = 0; i < scheduler.length; i++) {
15795
- const { resolve: resolve3 } = scheduler[i];
15796
- resolve3?.([data[i], data]);
15795
+ const { resolve: resolve4 } = scheduler[i];
15796
+ resolve4?.([data[i], data]);
15797
15797
  }
15798
15798
  }).catch((err) => {
15799
15799
  for (let i = 0; i < scheduler.length; i++) {
@@ -15809,16 +15809,16 @@ function createBatchScheduler({ fn, id, shouldSplitBatch, wait: wait2 = 0, sort
15809
15809
  return {
15810
15810
  flush,
15811
15811
  async schedule(args) {
15812
- const { promise, resolve: resolve3, reject } = withResolvers();
15812
+ const { promise, resolve: resolve4, reject } = withResolvers();
15813
15813
  const split2 = shouldSplitBatch?.([...getBatchedArgs(), args]);
15814
15814
  if (split2)
15815
15815
  exec();
15816
15816
  const hasActiveScheduler = getScheduler().length > 0;
15817
15817
  if (hasActiveScheduler) {
15818
- setScheduler({ args, resolve: resolve3, reject });
15818
+ setScheduler({ args, resolve: resolve4, reject });
15819
15819
  return promise;
15820
15820
  }
15821
- setScheduler({ args, resolve: resolve3, reject });
15821
+ setScheduler({ args, resolve: resolve4, reject });
15822
15822
  setTimeout(exec, wait2);
15823
15823
  return promise;
15824
15824
  }
@@ -16595,7 +16595,7 @@ var init_observe = __esm({
16595
16595
 
16596
16596
  // ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/utils/wait.js
16597
16597
  async function wait(time, { signal } = {}) {
16598
- return new Promise((resolve3, reject) => {
16598
+ return new Promise((resolve4, reject) => {
16599
16599
  if (signal?.aborted) {
16600
16600
  reject(getAbortError(signal));
16601
16601
  return;
@@ -16603,7 +16603,7 @@ async function wait(time, { signal } = {}) {
16603
16603
  const cleanup = () => signal?.removeEventListener("abort", onAbort);
16604
16604
  const timeout = setTimeout(() => {
16605
16605
  cleanup();
16606
- resolve3();
16606
+ resolve4();
16607
16607
  }, time);
16608
16608
  const onAbort = () => {
16609
16609
  clearTimeout(timeout);
@@ -17419,7 +17419,7 @@ var init_calls = __esm({
17419
17419
 
17420
17420
  // ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/utils/promise/withRetry.js
17421
17421
  function withRetry(fn, { delay: delay_ = 100, retryCount = 2, shouldRetry: shouldRetry2 = () => true, signal } = {}) {
17422
- return new Promise((resolve3, reject) => {
17422
+ return new Promise((resolve4, reject) => {
17423
17423
  const attemptRetry = async ({ count = 0 } = {}) => {
17424
17424
  if (signal?.aborted) {
17425
17425
  reject(getAbortError(signal));
@@ -17439,7 +17439,7 @@ function withRetry(fn, { delay: delay_ = 100, retryCount = 2, shouldRetry: shoul
17439
17439
  };
17440
17440
  try {
17441
17441
  const data = await fn();
17442
- resolve3(data);
17442
+ resolve4(data);
17443
17443
  } catch (err) {
17444
17444
  if (signal?.aborted) {
17445
17445
  reject(getAbortError(signal));
@@ -17586,7 +17586,7 @@ async function sendCalls(client, parameters) {
17586
17586
  results.push({ reason, status: "rejected" });
17587
17587
  }
17588
17588
  if (experimental_fallbackDelay > 0)
17589
- await new Promise((resolve3) => setTimeout(resolve3, experimental_fallbackDelay));
17589
+ await new Promise((resolve4) => setTimeout(resolve4, experimental_fallbackDelay));
17590
17590
  }
17591
17591
  if (results.every((r) => r.status === "rejected"))
17592
17592
  throw results[0].reason;
@@ -17716,9 +17716,9 @@ async function waitForCallsStatus(client, parameters) {
17716
17716
  throwOnFailure = false
17717
17717
  } = parameters;
17718
17718
  const observerId = stringify(["waitForCallsStatus", client.uid, id]);
17719
- const { promise, resolve: resolve3, reject } = withResolvers();
17719
+ const { promise, resolve: resolve4, reject } = withResolvers();
17720
17720
  let timer;
17721
- const unobserve = observe(observerId, { resolve: resolve3, reject }, (emit2) => {
17721
+ const unobserve = observe(observerId, { resolve: resolve4, reject }, (emit2) => {
17722
17722
  const unpoll = poll(async () => {
17723
17723
  const done = (fn) => {
17724
17724
  clearTimeout(timer);
@@ -18123,13 +18123,13 @@ async function isImageUri(uri) {
18123
18123
  }
18124
18124
  if (!Object.hasOwn(globalThis, "Image"))
18125
18125
  return false;
18126
- return new Promise((resolve3) => {
18126
+ return new Promise((resolve4) => {
18127
18127
  const img = new Image();
18128
18128
  img.onload = () => {
18129
- resolve3(true);
18129
+ resolve4(true);
18130
18130
  };
18131
18131
  img.onerror = () => {
18132
- resolve3(false);
18132
+ resolve4(false);
18133
18133
  };
18134
18134
  img.src = uri;
18135
18135
  });
@@ -20077,7 +20077,7 @@ var init_nonceManager = __esm({
20077
20077
 
20078
20078
  // ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/utils/promise/withTimeout.js
20079
20079
  function withTimeout(fn, { errorInstance = new Error("timed out"), timeout, signal }) {
20080
- return new Promise((resolve3, reject) => {
20080
+ return new Promise((resolve4, reject) => {
20081
20081
  ;
20082
20082
  (async () => {
20083
20083
  let timeoutId;
@@ -20092,7 +20092,7 @@ function withTimeout(fn, { errorInstance = new Error("timed out"), timeout, sign
20092
20092
  }
20093
20093
  }, timeout);
20094
20094
  }
20095
- resolve3(await fn({ signal: controller?.signal || null }));
20095
+ resolve4(await fn({ signal: controller?.signal || null }));
20096
20096
  } catch (err) {
20097
20097
  if (controller?.signal.aborted && isAbortError(err)) {
20098
20098
  reject(errorInstance);
@@ -24137,10 +24137,10 @@ async function getWebSocketRpcClient(url, options = {}) {
24137
24137
  socket.addEventListener("error", onError);
24138
24138
  socket.addEventListener("open", onOpen);
24139
24139
  if (socket.readyState === WebSocket5.CONNECTING) {
24140
- await new Promise((resolve3, reject) => {
24140
+ await new Promise((resolve4, reject) => {
24141
24141
  if (!socket)
24142
24142
  return;
24143
- socket.onopen = resolve3;
24143
+ socket.onopen = resolve4;
24144
24144
  socket.onerror = reject;
24145
24145
  });
24146
24146
  }
@@ -28321,13 +28321,13 @@ async function waitForTransactionReceipt(client, parameters) {
28321
28321
  let retrying = false;
28322
28322
  let _unobserve;
28323
28323
  let _unwatch;
28324
- const { promise, resolve: resolve3, reject } = withResolvers();
28324
+ const { promise, resolve: resolve4, reject } = withResolvers();
28325
28325
  const timer = timeout ? setTimeout(() => {
28326
28326
  _unwatch?.();
28327
28327
  _unobserve?.();
28328
28328
  reject(new WaitForTransactionReceiptTimeoutError({ hash: hash3 }));
28329
28329
  }, timeout) : void 0;
28330
- _unobserve = observe(observerId, { onReplaced, resolve: resolve3, reject }, async (emit2) => {
28330
+ _unobserve = observe(observerId, { onReplaced, resolve: resolve4, reject }, async (emit2) => {
28331
28331
  receipt = await getAction(client, getTransactionReceipt, "getTransactionReceipt")({ hash: hash3 }).catch(() => void 0);
28332
28332
  if (receipt && confirmations <= 1) {
28333
28333
  clearTimeout(timer);
@@ -30586,7 +30586,7 @@ function webSocket(url, config = {}) {
30586
30586
  },
30587
30587
  async subscribe({ params, onData, onError }) {
30588
30588
  const rpcClient = await getWebSocketRpcClient(url_, wsRpcClientOpts);
30589
- const { result: subscriptionId } = await new Promise((resolve3, reject) => rpcClient.request({
30589
+ const { result: subscriptionId } = await new Promise((resolve4, reject) => rpcClient.request({
30590
30590
  body: {
30591
30591
  method: "eth_subscribe",
30592
30592
  params
@@ -30603,7 +30603,7 @@ function webSocket(url, config = {}) {
30603
30603
  return;
30604
30604
  }
30605
30605
  if (typeof response.id === "number") {
30606
- resolve3(response);
30606
+ resolve4(response);
30607
30607
  return;
30608
30608
  }
30609
30609
  if (response.method !== "eth_subscription")
@@ -30614,12 +30614,12 @@ function webSocket(url, config = {}) {
30614
30614
  return {
30615
30615
  subscriptionId,
30616
30616
  async unsubscribe() {
30617
- return new Promise((resolve3) => rpcClient.request({
30617
+ return new Promise((resolve4) => rpcClient.request({
30618
30618
  body: {
30619
30619
  method: "eth_unsubscribe",
30620
30620
  params: [subscriptionId]
30621
30621
  },
30622
- onResponse: resolve3
30622
+ onResponse: resolve4
30623
30623
  }));
30624
30624
  }
30625
30625
  };
@@ -35190,8 +35190,8 @@ var require_websocket_server2 = __commonJS({
35190
35190
  });
35191
35191
 
35192
35192
  // src/index.ts
35193
- var import_node_fs21 = require("node:fs");
35194
- var import_node_path17 = require("node:path");
35193
+ var import_node_fs22 = require("node:fs");
35194
+ var import_node_path18 = require("node:path");
35195
35195
 
35196
35196
  // ../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/esm.mjs
35197
35197
  var import_index = __toESM(require_commander(), 1);
@@ -35211,16 +35211,18 @@ var {
35211
35211
  } = import_index.default;
35212
35212
 
35213
35213
  // ../sdk/dist/chains.js
35214
+ var CREATE2_KERNEL = "0x38b508756c976e876EFF05a29E731A4d348BA6ED";
35215
+ var CREATE2_MANDATE_FACTORY = "0x6d2C802ffa0d9A8Ed69A5Bf22c1b63ccB566B8Fc";
35216
+ var CREATE2_GOVERNANCE = "0x4315B37cA4A315A7042af1Fcb37F8436f4D24356";
35214
35217
  var chains = {
35215
35218
  // Ethereum mainnet
35216
35219
  1: {
35217
35220
  chainId: 1,
35218
35221
  name: "Ethereum",
35219
35222
  rpcEnvVar: "ETH_MAINNET_RPC_URL",
35220
- // CREATE2 deterministic deploy (2026-06-09, gitCommit 1199b33).
35221
- kernel: "0x02ABC18B65A328de2e749F56ba79ACF2718a6659",
35222
- mandateFactory: "0x14EDd6c2a56EfC0d71E215ab13094B9AF90543d2",
35223
- governance: "0x7A478118715791728BDE3bc7A4D7ECfdEB89C6EC",
35223
+ kernel: CREATE2_KERNEL,
35224
+ mandateFactory: CREATE2_MANDATE_FACTORY,
35225
+ governance: CREATE2_GOVERNANCE,
35224
35226
  dispatchModel: "selective",
35225
35227
  protocols: {}
35226
35228
  },
@@ -35229,11 +35231,9 @@ var chains = {
35229
35231
  chainId: 8453,
35230
35232
  name: "Base",
35231
35233
  rpcEnvVar: "BASE_RPC_URL",
35232
- // CREATE2 deterministic deploy (2026-06-09, gitCommit 1199b33).
35233
- // Supersedes 0x6319d3dfDDe3804ba93D65752b00c52bFb05a1ab (SAIL-405).
35234
- kernel: "0x02ABC18B65A328de2e749F56ba79ACF2718a6659",
35235
- mandateFactory: "0x14EDd6c2a56EfC0d71E215ab13094B9AF90543d2",
35236
- governance: "0x7A478118715791728BDE3bc7A4D7ECfdEB89C6EC",
35234
+ kernel: CREATE2_KERNEL,
35235
+ mandateFactory: CREATE2_MANDATE_FACTORY,
35236
+ governance: CREATE2_GOVERNANCE,
35237
35237
  dispatchModel: "selective",
35238
35238
  protocols: {}
35239
35239
  },
@@ -35242,11 +35242,20 @@ var chains = {
35242
35242
  chainId: 42161,
35243
35243
  name: "Arbitrum",
35244
35244
  rpcEnvVar: "ARBITRUM_RPC_URL",
35245
- // CREATE2 deterministic deploy (2026-06-09, gitCommit 1199b33).
35246
- // Supersedes 0x2716B12832DED0EF5688519c5Fe069EFc0374E02 (SAIL-405).
35247
- kernel: "0x02ABC18B65A328de2e749F56ba79ACF2718a6659",
35248
- mandateFactory: "0x14EDd6c2a56EfC0d71E215ab13094B9AF90543d2",
35249
- governance: "0x7A478118715791728BDE3bc7A4D7ECfdEB89C6EC",
35245
+ kernel: CREATE2_KERNEL,
35246
+ mandateFactory: CREATE2_MANDATE_FACTORY,
35247
+ governance: CREATE2_GOVERNANCE,
35248
+ dispatchModel: "selective",
35249
+ protocols: {}
35250
+ },
35251
+ // Optimism mainnet
35252
+ 10: {
35253
+ chainId: 10,
35254
+ name: "Optimism",
35255
+ rpcEnvVar: "OPTIMISM_RPC_URL",
35256
+ kernel: CREATE2_KERNEL,
35257
+ mandateFactory: CREATE2_MANDATE_FACTORY,
35258
+ governance: CREATE2_GOVERNANCE,
35250
35259
  dispatchModel: "selective",
35251
35260
  protocols: {}
35252
35261
  },
@@ -35255,11 +35264,53 @@ var chains = {
35255
35264
  chainId: 130,
35256
35265
  name: "Unichain",
35257
35266
  rpcEnvVar: "UNICHAIN_RPC_URL",
35258
- // CREATE2 deterministic deploy (2026-06-09, gitCommit 1199b33).
35259
- // Supersedes 0xD985029960a9B7C2E7E38e102C448b8b8539B156 (SAIL-406).
35260
- kernel: "0x02ABC18B65A328de2e749F56ba79ACF2718a6659",
35261
- mandateFactory: "0x14EDd6c2a56EfC0d71E215ab13094B9AF90543d2",
35262
- governance: "0x7A478118715791728BDE3bc7A4D7ECfdEB89C6EC",
35267
+ kernel: CREATE2_KERNEL,
35268
+ mandateFactory: CREATE2_MANDATE_FACTORY,
35269
+ governance: CREATE2_GOVERNANCE,
35270
+ dispatchModel: "selective",
35271
+ protocols: {}
35272
+ },
35273
+ // BSC mainnet
35274
+ 56: {
35275
+ chainId: 56,
35276
+ name: "BSC",
35277
+ rpcEnvVar: "BSC_RPC_URL",
35278
+ kernel: CREATE2_KERNEL,
35279
+ mandateFactory: CREATE2_MANDATE_FACTORY,
35280
+ governance: CREATE2_GOVERNANCE,
35281
+ dispatchModel: "selective",
35282
+ protocols: {}
35283
+ },
35284
+ // World Chain mainnet
35285
+ 480: {
35286
+ chainId: 480,
35287
+ name: "World Chain",
35288
+ rpcEnvVar: "WORLD_RPC_URL",
35289
+ kernel: CREATE2_KERNEL,
35290
+ mandateFactory: CREATE2_MANDATE_FACTORY,
35291
+ governance: CREATE2_GOVERNANCE,
35292
+ dispatchModel: "selective",
35293
+ protocols: {}
35294
+ },
35295
+ // HyperEVM mainnet
35296
+ 999: {
35297
+ chainId: 999,
35298
+ name: "HyperEVM",
35299
+ rpcEnvVar: "HYPEREVM_RPC_URL",
35300
+ kernel: CREATE2_KERNEL,
35301
+ mandateFactory: CREATE2_MANDATE_FACTORY,
35302
+ governance: CREATE2_GOVERNANCE,
35303
+ dispatchModel: "selective",
35304
+ protocols: {}
35305
+ },
35306
+ // MegaETH mainnet
35307
+ 4326: {
35308
+ chainId: 4326,
35309
+ name: "MegaETH",
35310
+ rpcEnvVar: "MEGAETH_RPC_URL",
35311
+ kernel: CREATE2_KERNEL,
35312
+ mandateFactory: CREATE2_MANDATE_FACTORY,
35313
+ governance: CREATE2_GOVERNANCE,
35263
35314
  dispatchModel: "selective",
35264
35315
  protocols: {}
35265
35316
  },
@@ -35268,11 +35319,9 @@ var chains = {
35268
35319
  chainId: 84532,
35269
35320
  name: "Base Sepolia",
35270
35321
  rpcEnvVar: "BASE_SEPOLIA_RPC_URL",
35271
- // CREATE2 deterministic deploy (2026-06-09, gitCommit 1199b33).
35272
- // Supersedes 0xf1D0F4C9893612627409948BAa9d82a01a373799 (SAIL-405).
35273
- kernel: "0x02ABC18B65A328de2e749F56ba79ACF2718a6659",
35274
- mandateFactory: "0x14EDd6c2a56EfC0d71E215ab13094B9AF90543d2",
35275
- governance: "0x7A478118715791728BDE3bc7A4D7ECfdEB89C6EC",
35322
+ kernel: CREATE2_KERNEL,
35323
+ mandateFactory: CREATE2_MANDATE_FACTORY,
35324
+ governance: CREATE2_GOVERNANCE,
35276
35325
  dispatchModel: "selective",
35277
35326
  protocols: {}
35278
35327
  },
@@ -35281,10 +35330,9 @@ var chains = {
35281
35330
  chainId: 11155111,
35282
35331
  name: "Eth Sepolia",
35283
35332
  rpcEnvVar: "SEPOLIA_RPC_URL",
35284
- // CREATE2 deterministic deploy (2026-06-09, gitCommit 1199b33).
35285
- kernel: "0x02ABC18B65A328de2e749F56ba79ACF2718a6659",
35286
- mandateFactory: "0x14EDd6c2a56EfC0d71E215ab13094B9AF90543d2",
35287
- governance: "0x7A478118715791728BDE3bc7A4D7ECfdEB89C6EC",
35333
+ kernel: CREATE2_KERNEL,
35334
+ mandateFactory: CREATE2_MANDATE_FACTORY,
35335
+ governance: CREATE2_GOVERNANCE,
35288
35336
  dispatchModel: "selective",
35289
35337
  protocols: {}
35290
35338
  }
@@ -35292,7 +35340,7 @@ var chains = {
35292
35340
  function getChain(chainId) {
35293
35341
  const config = chains[chainId];
35294
35342
  if (!config) {
35295
- throw new Error(`Chain ${chainId} is not supported. Supported chains: 1 (Ethereum), 8453 (Base), 42161 (Arbitrum), 130 (Unichain), 84532 (Base Sepolia), 11155111 (Eth Sepolia).`);
35343
+ throw new Error(`Chain ${chainId} is not supported. Supported chains: 1 (Ethereum), 8453 (Base), 42161 (Arbitrum), 10 (Optimism), 130 (Unichain), 56 (BSC), 480 (World Chain), 999 (HyperEVM), 4326 (MegaETH), 84532 (Base Sepolia), 11155111 (Eth Sepolia).`);
35296
35344
  }
35297
35345
  return config;
35298
35346
  }
@@ -35319,6 +35367,10 @@ var SailKernelAbi = [
35319
35367
  ],
35320
35368
  outputs: [{ name: "account", type: "address" }]
35321
35369
  },
35370
+ // Post-#53: two-step registration. Requires msg.sender == the Safe (trusted-proxy
35371
+ // codehash + trusted-singleton pin) and a Safe owner signature over the
35372
+ // RegisterAccount EIP-712 digest (verified via checkSignatures). Must be submitted
35373
+ // through the Safe's execTransaction, not the owner EOA. See buildRegisterAccountTypedData.
35322
35374
  {
35323
35375
  type: "function",
35324
35376
  name: "registerAccount",
@@ -35326,7 +35378,10 @@ var SailKernelAbi = [
35326
35378
  inputs: [
35327
35379
  { name: "permissionSigner", type: "address" },
35328
35380
  { name: "manager", type: "address" },
35329
- { name: "feePolicy", type: "address" }
35381
+ { name: "feePolicy", type: "address" },
35382
+ { name: "feeAsset", type: "address" },
35383
+ { name: "deadline", type: "uint256" },
35384
+ { name: "ownerSig", type: "bytes" }
35330
35385
  ],
35331
35386
  outputs: []
35332
35387
  },
@@ -35377,6 +35432,32 @@ var SailKernelAbi = [
35377
35432
  ],
35378
35433
  outputs: []
35379
35434
  },
35435
+ // ── Session kill switch ───────────────────────────────────────────────────
35436
+ // Suspend/resume manager dispatch rights. Both are permissionSigner-signed
35437
+ // (RevokeSession/ActivateSession EIP-712, nonce = signerNonces[account]) and
35438
+ // rotate the manager/batch nonce epochs so any pre-signed dispatch is invalidated.
35439
+ {
35440
+ type: "function",
35441
+ name: "revokeSession",
35442
+ stateMutability: "nonpayable",
35443
+ inputs: [
35444
+ { name: "account", type: "address" },
35445
+ { name: "deadline", type: "uint256" },
35446
+ { name: "sig", type: "bytes" }
35447
+ ],
35448
+ outputs: []
35449
+ },
35450
+ {
35451
+ type: "function",
35452
+ name: "activateSession",
35453
+ stateMutability: "nonpayable",
35454
+ inputs: [
35455
+ { name: "account", type: "address" },
35456
+ { name: "deadline", type: "uint256" },
35457
+ { name: "sig", type: "bytes" }
35458
+ ],
35459
+ outputs: []
35460
+ },
35380
35461
  // ── Manager dispatch ──────────────────────────────────────────────────────
35381
35462
  {
35382
35463
  type: "function",
@@ -35516,6 +35597,7 @@ var SailKernelAbi = [
35516
35597
  { name: "permissionSigner", type: "address" },
35517
35598
  { name: "manager", type: "address" },
35518
35599
  { name: "feePolicy", type: "address" },
35600
+ { name: "feeAsset", type: "address" },
35519
35601
  { name: "sessionActive", type: "bool" }
35520
35602
  ]
35521
35603
  },
@@ -35709,148 +35791,142 @@ async function detectKernelCapabilities(publicClient, kernel, opts) {
35709
35791
  }
35710
35792
 
35711
35793
  // ../sdk/dist/deployments.js
35712
- var CREATE2_KERNEL = "0x02ABC18B65A328de2e749F56ba79ACF2718a6659";
35713
- var CREATE2_GOVERNANCE = "0x7A478118715791728BDE3bc7A4D7ECfdEB89C6EC";
35714
- var CREATE2_TIMELOCK = "0xE48Ba8DB6d748adafD13155c3590f62e58a77f56";
35794
+ var CREATE2_KERNEL2 = "0x38b508756c976e876EFF05a29E731A4d348BA6ED";
35795
+ var CREATE2_GOVERNANCE2 = "0x4315B37cA4A315A7042af1Fcb37F8436f4D24356";
35796
+ var CREATE2_TIMELOCK = "0xC1E5F9A581D4100Aa949f80204540a33aD97A7b6";
35715
35797
  var CREATE2_SAFE_MODULE_ENABLER = "0x7897Cb53a4be4a2eaAf46D60573C4Fd83b33fE1F";
35716
- var CREATE2_MANDATE_FACTORY = "0x14EDd6c2a56EfC0d71E215ab13094B9AF90543d2";
35717
- var CREATE2_STANDARD_FEE_POLICY = "0xe7B5901b839cFFDEd9D4108A22712C8BfdA1D80D";
35718
- var CREATE2_TREASURY = "0xB01dCE443d052e44b7D13726c0EC9fFB7f5815B6";
35798
+ var CREATE2_MANDATE_FACTORY2 = "0x6d2C802ffa0d9A8Ed69A5Bf22c1b63ccB566B8Fc";
35799
+ var CREATE2_STANDARD_FEE_POLICY = "0x1087312447C8a2BfA15EB9cE23590E3502DBA04b";
35800
+ var CREATE2_DEPLOYER = "0xB01dCE443d052e44b7D13726c0EC9fFB7f5815B6";
35801
+ var CREATE2_TREASURY = "0x7b37F85575F1568a37dBA342BC5FE6d393F0872f";
35802
+ var CREATE2_MAX_PERMISSION_FEE_WEI = 10000000000000000n;
35803
+ var CREATE2_TEMPLATES = {
35804
+ swap: "0x35cEEa0db96997Cc3CF3beB42FFa36A499342F7C",
35805
+ swapNoOracle: "0x34Ba96CbEd1f46c88A5265E645DC5fe41662b519",
35806
+ borrow: "0x3e2666051599223cEAb10De55C89A0842857d8AF",
35807
+ deposit: "0xBfB5e13a97b12Ee89d2F2b9B65eCf7e0E371911f",
35808
+ withdraw: "0xF5eF5dda450a130e3020d54f565E830e4a7531f8",
35809
+ transfer: "0xda909a1CC584fb7559Ce4A828b008B473Da095e1",
35810
+ approveAndCallBatch: "0x0535A4D51333484ef583103DAB1a9449756ab732"
35811
+ };
35812
+ var CREATE2_KNOWN_TEMPLATES = [
35813
+ { kind: "SwapPermission", address: CREATE2_TEMPLATES.swap, label: "Swap" },
35814
+ {
35815
+ kind: "SwapPermissionNoOracle",
35816
+ address: CREATE2_TEMPLATES.swapNoOracle,
35817
+ label: "Swap (no oracle)"
35818
+ },
35819
+ { kind: "BorrowPermission", address: CREATE2_TEMPLATES.borrow, label: "Borrow" },
35820
+ { kind: "DepositPermission", address: CREATE2_TEMPLATES.deposit, label: "Deposit" },
35821
+ { kind: "WithdrawPermission", address: CREATE2_TEMPLATES.withdraw, label: "Withdraw" },
35822
+ { kind: "TransferPermission", address: CREATE2_TEMPLATES.transfer, label: "Transfer" },
35823
+ {
35824
+ kind: "ApproveAndCallBatchPermission",
35825
+ address: CREATE2_TEMPLATES.approveAndCallBatch,
35826
+ label: "Approve + call batch"
35827
+ }
35828
+ ];
35829
+ var COMMON_DEPLOYMENT_FIELDS = {
35830
+ deployer: CREATE2_DEPLOYER,
35831
+ governance: CREATE2_GOVERNANCE2,
35832
+ timelock: CREATE2_TIMELOCK,
35833
+ kernel: CREATE2_KERNEL2,
35834
+ mandateFactory: CREATE2_MANDATE_FACTORY2,
35835
+ standardFeePolicy: CREATE2_STANDARD_FEE_POLICY,
35836
+ safeModuleEnabler: CREATE2_SAFE_MODULE_ENABLER,
35837
+ treasury: CREATE2_TREASURY,
35838
+ maxPermissionFeeWei: CREATE2_MAX_PERMISSION_FEE_WEI,
35839
+ initialBaseFee: 0n,
35840
+ initialComplexityRate: 0n,
35841
+ dispatchModel: "selective",
35842
+ // The seven launch templates are SHARED multi-tenant ConfigurablePermission instances
35843
+ // (registered by address, configured via configure()), NOT EIP-1167 clone logic. They
35844
+ // belong in knownTemplates only. standaloneTemplates is the clone-implementation registry
35845
+ // (the `impl` arg to MandateFactory.deployAndAttach) — empty until standalone clones deploy.
35846
+ // Populating it with shared templates mislabels them as unaudited community clones in
35847
+ // `sailor mandate templates` and makes capabilities advertise them as deployAndAttach-able.
35848
+ standaloneTemplates: {}
35849
+ };
35850
+ function knownTemplatesFor(chainId) {
35851
+ return CREATE2_KNOWN_TEMPLATES.map((t) => ({ ...t, chainId }));
35852
+ }
35719
35853
  var sailDeployments = {
35720
35854
  // ── Ethereum mainnet ─────────────────────────────────────────────────────────
35721
35855
  1: {
35722
- // CREATE2 deterministic deploy (2026-06-09, gitCommit 1199b33).
35723
- // allowlistBootstrapped=true (genesis bootstrap), zero fees, 48h timelock.
35856
+ ...COMMON_DEPLOYMENT_FIELDS,
35724
35857
  chainId: 1,
35725
- blockNumber: 25280925,
35726
- deployer: CREATE2_TREASURY,
35727
- governance: CREATE2_GOVERNANCE,
35728
- timelock: CREATE2_TIMELOCK,
35729
- kernel: CREATE2_KERNEL,
35730
- mandateFactory: CREATE2_MANDATE_FACTORY,
35731
- standardFeePolicy: CREATE2_STANDARD_FEE_POLICY,
35732
- safeModuleEnabler: CREATE2_SAFE_MODULE_ENABLER,
35733
- treasury: CREATE2_TREASURY,
35734
- maxPermissionFeeWei: 1000000000000000n,
35735
- initialBaseFee: 0n,
35736
- initialComplexityRate: 0n,
35737
- dispatchModel: "selective",
35738
- knownTemplates: [],
35739
- standaloneTemplates: {}
35858
+ blockNumber: 25432741,
35859
+ knownTemplates: knownTemplatesFor(1)
35740
35860
  },
35741
35861
  // ── Base mainnet ─────────────────────────────────────────────────────────────
35742
35862
  8453: {
35743
- // CREATE2 deterministic deploy (2026-06-09, gitCommit 1199b33). Supersedes
35744
- // 0x6319d3dfDDe3804ba93D65752b00c52bFb05a1ab (SAIL-405 redeploy).
35745
- // allowlistBootstrapped=true, zero fees, 48h timelock.
35863
+ ...COMMON_DEPLOYMENT_FIELDS,
35746
35864
  chainId: 8453,
35747
- blockNumber: 47115338,
35748
- deployer: CREATE2_TREASURY,
35749
- governance: CREATE2_GOVERNANCE,
35750
- timelock: CREATE2_TIMELOCK,
35751
- kernel: CREATE2_KERNEL,
35752
- mandateFactory: CREATE2_MANDATE_FACTORY,
35753
- standardFeePolicy: CREATE2_STANDARD_FEE_POLICY,
35754
- safeModuleEnabler: CREATE2_SAFE_MODULE_ENABLER,
35755
- treasury: CREATE2_TREASURY,
35756
- maxPermissionFeeWei: 1000000000000000n,
35757
- initialBaseFee: 0n,
35758
- initialComplexityRate: 0n,
35759
- dispatchModel: "selective",
35760
- knownTemplates: [],
35761
- standaloneTemplates: {}
35865
+ blockNumber: 48029413,
35866
+ knownTemplates: knownTemplatesFor(8453)
35762
35867
  },
35763
35868
  // ── Arbitrum mainnet ─────────────────────────────────────────────────────────
35764
35869
  42161: {
35765
- // CREATE2 deterministic deploy (2026-06-09, gitCommit 1199b33). Supersedes
35766
- // 0x2716B12832DED0EF5688519c5Fe069EFc0374E02 (SAIL-405 redeploy).
35767
- // allowlistBootstrapped=true, zero fees, 48h timelock.
35870
+ ...COMMON_DEPLOYMENT_FIELDS,
35768
35871
  chainId: 42161,
35769
- blockNumber: 471736462,
35770
- deployer: CREATE2_TREASURY,
35771
- governance: CREATE2_GOVERNANCE,
35772
- timelock: CREATE2_TIMELOCK,
35773
- kernel: CREATE2_KERNEL,
35774
- mandateFactory: CREATE2_MANDATE_FACTORY,
35775
- standardFeePolicy: CREATE2_STANDARD_FEE_POLICY,
35776
- safeModuleEnabler: CREATE2_SAFE_MODULE_ENABLER,
35777
- treasury: CREATE2_TREASURY,
35778
- maxPermissionFeeWei: 1000000000000000n,
35779
- initialBaseFee: 0n,
35780
- initialComplexityRate: 0n,
35781
- dispatchModel: "selective",
35782
- knownTemplates: [],
35783
- standaloneTemplates: {}
35872
+ blockNumber: 25432669,
35873
+ knownTemplates: knownTemplatesFor(42161)
35874
+ },
35875
+ // ── Optimism mainnet ─────────────────────────────────────────────────────────
35876
+ 10: {
35877
+ ...COMMON_DEPLOYMENT_FIELDS,
35878
+ chainId: 10,
35879
+ blockNumber: 153625159,
35880
+ knownTemplates: knownTemplatesFor(10)
35784
35881
  },
35785
35882
  // ── Unichain mainnet ─────────────────────────────────────────────────────────
35786
35883
  130: {
35787
- // CREATE2 deterministic deploy (2026-06-09, gitCommit 1199b33). Supersedes
35788
- // 0xD985029960a9B7C2E7E38e102C448b8b8539B156 (SAIL-406 deploy).
35789
- // NOTE: knownTemplates and standaloneTemplates from SAIL-406 were deployed
35790
- // against the old kernel 0xD985029... and are now invalid. They must be
35791
- // redeployed against the new kernel 0x02ABC1... and re-populated here.
35884
+ ...COMMON_DEPLOYMENT_FIELDS,
35792
35885
  chainId: 130,
35793
- blockNumber: 50271704,
35794
- deployer: CREATE2_TREASURY,
35795
- governance: CREATE2_GOVERNANCE,
35796
- timelock: CREATE2_TIMELOCK,
35797
- kernel: CREATE2_KERNEL,
35798
- mandateFactory: CREATE2_MANDATE_FACTORY,
35799
- standardFeePolicy: CREATE2_STANDARD_FEE_POLICY,
35800
- safeModuleEnabler: CREATE2_SAFE_MODULE_ENABLER,
35801
- treasury: CREATE2_TREASURY,
35802
- maxPermissionFeeWei: 1000000000000000n,
35803
- initialBaseFee: 0n,
35804
- initialComplexityRate: 0n,
35805
- dispatchModel: "selective",
35806
- // Templates cleared: the SAIL-406 shared + standalone templates were deployed
35807
- // against the old kernel (0xD985029...) and are invalid against the new one.
35808
- // Re-populate after redeploying templates against 0x02ABC1...
35809
- knownTemplates: [],
35810
- standaloneTemplates: {}
35886
+ blockNumber: 52100873,
35887
+ knownTemplates: knownTemplatesFor(130)
35888
+ },
35889
+ // ── BSC mainnet ──────────────────────────────────────────────────────────────
35890
+ 56: {
35891
+ ...COMMON_DEPLOYMENT_FIELDS,
35892
+ chainId: 56,
35893
+ blockNumber: 107312662,
35894
+ knownTemplates: knownTemplatesFor(56)
35895
+ },
35896
+ // ── World Chain mainnet ──────────────────────────────────────────────────────
35897
+ 480: {
35898
+ ...COMMON_DEPLOYMENT_FIELDS,
35899
+ chainId: 480,
35900
+ blockNumber: 31756901,
35901
+ knownTemplates: knownTemplatesFor(480)
35902
+ },
35903
+ // ── HyperEVM mainnet ─────────────────────────────────────────────────────────
35904
+ 999: {
35905
+ ...COMMON_DEPLOYMENT_FIELDS,
35906
+ chainId: 999,
35907
+ blockNumber: 39238629,
35908
+ knownTemplates: knownTemplatesFor(999)
35909
+ },
35910
+ // ── MegaETH mainnet ──────────────────────────────────────────────────────────
35911
+ 4326: {
35912
+ ...COMMON_DEPLOYMENT_FIELDS,
35913
+ chainId: 4326,
35914
+ blockNumber: 20056530,
35915
+ knownTemplates: knownTemplatesFor(4326)
35811
35916
  },
35812
35917
  // ── Base Sepolia (testnet) ───────────────────────────────────────────────────
35813
35918
  84532: {
35814
- // CREATE2 deterministic deploy (2026-06-09, gitCommit 1199b33). Supersedes
35815
- // 0xf1D0F4C9893612627409948BAa9d82a01a373799 (SAIL-405 redeploy).
35816
- // allowlistBootstrapped=true, zero fees, 48h timelock.
35919
+ ...COMMON_DEPLOYMENT_FIELDS,
35817
35920
  chainId: 84532,
35818
- blockNumber: 42625843,
35819
- deployer: CREATE2_TREASURY,
35820
- governance: CREATE2_GOVERNANCE,
35821
- timelock: CREATE2_TIMELOCK,
35822
- kernel: CREATE2_KERNEL,
35823
- mandateFactory: CREATE2_MANDATE_FACTORY,
35824
- standardFeePolicy: CREATE2_STANDARD_FEE_POLICY,
35825
- safeModuleEnabler: CREATE2_SAFE_MODULE_ENABLER,
35826
- treasury: CREATE2_TREASURY,
35827
- maxPermissionFeeWei: 1000000000000000n,
35828
- initialBaseFee: 0n,
35829
- initialComplexityRate: 0n,
35830
- dispatchModel: "selective",
35831
- knownTemplates: [],
35832
- standaloneTemplates: {}
35921
+ blockNumber: 43539604,
35922
+ knownTemplates: knownTemplatesFor(84532)
35833
35923
  },
35834
35924
  // ── Eth Sepolia (testnet) ────────────────────────────────────────────────────
35835
35925
  11155111: {
35836
- // CREATE2 deterministic deploy (2026-06-09, gitCommit 1199b33).
35837
- // allowlistBootstrapped=true, zero fees, 48h timelock.
35926
+ ...COMMON_DEPLOYMENT_FIELDS,
35838
35927
  chainId: 11155111,
35839
- blockNumber: 11023571,
35840
- deployer: CREATE2_TREASURY,
35841
- governance: CREATE2_GOVERNANCE,
35842
- timelock: CREATE2_TIMELOCK,
35843
- kernel: CREATE2_KERNEL,
35844
- mandateFactory: CREATE2_MANDATE_FACTORY,
35845
- standardFeePolicy: CREATE2_STANDARD_FEE_POLICY,
35846
- safeModuleEnabler: CREATE2_SAFE_MODULE_ENABLER,
35847
- treasury: CREATE2_TREASURY,
35848
- maxPermissionFeeWei: 1000000000000000n,
35849
- initialBaseFee: 0n,
35850
- initialComplexityRate: 0n,
35851
- dispatchModel: "selective",
35852
- knownTemplates: [],
35853
- standaloneTemplates: {}
35928
+ blockNumber: 11174750,
35929
+ knownTemplates: knownTemplatesFor(11155111)
35854
35930
  }
35855
35931
  };
35856
35932
  function getSailDeployment(chainId) {
@@ -35861,122 +35937,6 @@ function getSailDeployment(chainId) {
35861
35937
  return deployment;
35862
35938
  }
35863
35939
 
35864
- // ../sdk/dist/errors.js
35865
- init_esm2();
35866
- var KERNEL_ERROR_SIGNATURES = [
35867
- "error AccountAlreadyRegistered(address account)",
35868
- "error AccountNotRegistered(address account)",
35869
- "error AccountSelfTarget()",
35870
- "error ArrayLengthMismatch()",
35871
- "error BatchPermissionDenied()",
35872
- "error BatchSubcallFailed(uint256 index, address target)",
35873
- "error BatchTooLong(uint256 length)",
35874
- "error BatchZeroTarget(uint256 index)",
35875
- "error DeadlineExpired(uint256 deadline, uint256 current)",
35876
- "error DistributorBpsTooLarge(uint256 bps)",
35877
- "error EmptyBatch()",
35878
- "error FeePolicyNotSet()",
35879
- "error FeeTokenMismatch(address provided, address expected)",
35880
- "error FeeTooLarge(uint256 requested, uint256 maxAllowed)",
35881
- "error FeeTransferFailed()",
35882
- "error InsufficientFee(uint256 required, uint256 provided)",
35883
- "error InvalidInitializer()",
35884
- "error InvalidManagerSignature()",
35885
- "error InvalidSignerSignature()",
35886
- "error KernelSelfTarget(uint256 index)",
35887
- // SAIL-405: setManager rejects a no-op rotation (newManager == current).
35888
- "error ManagerUnchanged()",
35889
- "error ModuleNotEnabled()",
35890
- // Present in the deployed conjunctive kernel; dropped in the latest source.
35891
- "error NoPermissionsRegistered(address account)",
35892
- "error NotAContract(address addr)",
35893
- "error NotGovernance()",
35894
- "error NotManager(address caller, address expected)",
35895
- "error NotPermissionSigner()",
35896
- "error NotTimelock()",
35897
- "error PermissionAlreadyRegistered(address permission)",
35898
- "error PermissionDenied(address permission)",
35899
- "error PermissionNotBatchAware(address permission)",
35900
- "error PermissionNotRegistered(address permission)",
35901
- "error ProtocolPaused()",
35902
- "error SafeExecutionFailed()",
35903
- "error SessionInactive(address account)",
35904
- "error TooManyPermissions(address account, uint256 limit)",
35905
- "error UntrustedFactory(address factory)",
35906
- "error UntrustedFeePolicy(address policy)",
35907
- "error UntrustedModuleSetup(address setup)",
35908
- "error UntrustedProxyCodehash(bytes32 codehash)",
35909
- "error UntrustedSingleton(address singleton)",
35910
- "error ZeroAddress()",
35911
- "error ZeroFee()"
35912
- ];
35913
- var KERNEL_ERROR_ABI = parseAbi(KERNEL_ERROR_SIGNATURES);
35914
- var ERROR_HINTS = {
35915
- InvalidManagerSignature: "The manager's EIP-712 Dispatch signature did not recover to the registered manager. Most common cause: a stale manager nonce (the kernel's managerNonces advanced between signing and submission \u2014 e.g. a load-balanced RPC returned a lagging value, or two dispatches were signed against the same nonce). Re-read managerNonces and re-sign, or track the nonce locally and increment it across sequential dispatches. Can also mean the wrong EIP-712 Dispatch type was used for this kernel version \u2014 see detectKernelCapabilities.",
35916
- PermissionDenied: "A registered permission's evaluate() returned false (or reverted / ran out of gas) for this call. In a conjunctive kernel EVERY registered permission must approve EVERY call, so a permission that does not pass through calls outside its own domain will block unrelated dispatches. Check that each permission either matches this call or returns true for calls it doesn't govern.",
35917
- NoPermissionsRegistered: "The account has zero registered permissions, so the kernel denies by default. Register at least one permission (kernel.registerPermission / registerPermissions) before dispatching.",
35918
- PermissionNotRegistered: "The named permission is not registered for this account. Register it first, or (on a conjunctive kernel) drop the permission argument \u2014 that kernel checks all registered permissions automatically.",
35919
- SessionInactive: "The manager's session is revoked. Re-activate it (session.activate) before dispatching.",
35920
- DeadlineExpired: "The signature deadline is in the past. Use a deadline comfortably ahead of block.timestamp.",
35921
- SafeExecutionFailed: "The underlying Safe module call reverted. The permission passed, but the target call itself failed (e.g. slippage too tight, insufficient allowance/balance, or a failing swap route).",
35922
- ModuleNotEnabled: "The Sail module is not enabled on the Safe. Complete account onboarding (enable the module) first.",
35923
- ProtocolPaused: "The protocol is paused by governance. Dispatches are blocked until it is unpaused.",
35924
- NotManager: "The submitting address is not the registered manager for this account.",
35925
- TooManyPermissions: "Registering this permission would exceed the kernel's per-account permission cap. Revoke an unused permission first."
35926
- };
35927
- async function decode2(data) {
35928
- const { decodeErrorResult: decodeErrorResult2 } = await Promise.resolve().then(() => (init_esm2(), esm_exports2));
35929
- try {
35930
- const decoded = decodeErrorResult2({ abi: KERNEL_ERROR_ABI, data });
35931
- const name = decoded.errorName;
35932
- const args = decoded.args ?? [];
35933
- const selector = data.slice(0, 10);
35934
- const hint = ERROR_HINTS[name];
35935
- const argStr = args.length ? `(${args.map(String).join(", ")})` : "()";
35936
- const message = hint ? `${name}${argStr} \u2014 ${hint}` : `${name}${argStr}`;
35937
- return { name, args, selector, hint, message };
35938
- } catch {
35939
- return null;
35940
- }
35941
- }
35942
- function decodeKernelError(data) {
35943
- if (!data || data === "0x")
35944
- return Promise.resolve(null);
35945
- return decode2(data);
35946
- }
35947
- async function explainKernelRevert(err) {
35948
- const data = extractRevertData(err);
35949
- if (!data)
35950
- return null;
35951
- return decodeKernelError(data);
35952
- }
35953
- function extractRevertData(err) {
35954
- const seen = /* @__PURE__ */ new Set();
35955
- let cursor = err;
35956
- let depth = 0;
35957
- while (cursor && typeof cursor === "object" && !seen.has(cursor) && depth < 12) {
35958
- seen.add(cursor);
35959
- depth++;
35960
- const obj = cursor;
35961
- const data = obj["data"];
35962
- if (typeof data === "string" && data.startsWith("0x") && data.length >= 10) {
35963
- return data;
35964
- }
35965
- if (data && typeof data === "object") {
35966
- const inner = data["data"];
35967
- if (typeof inner === "string" && inner.startsWith("0x") && inner.length >= 10) {
35968
- return inner;
35969
- }
35970
- }
35971
- const raw = obj["raw"];
35972
- if (typeof raw === "string" && raw.startsWith("0x") && raw.length >= 10) {
35973
- return raw;
35974
- }
35975
- cursor = obj["cause"];
35976
- }
35977
- return null;
35978
- }
35979
-
35980
35940
  // ../sdk/dist/eip712.js
35981
35941
  init_esm2();
35982
35942
  function sailKernelDomain(args) {
@@ -36112,7 +36072,198 @@ function buildRegisterPermissionsBatchTypedData(args) {
36112
36072
  nonce: args.nonce.toString(),
36113
36073
  deadline: deadline.toString()
36114
36074
  }
36115
- };
36075
+ };
36076
+ }
36077
+ var TEMPLATE_EIP712_DOMAIN_ABI = [
36078
+ {
36079
+ type: "function",
36080
+ name: "eip712Domain",
36081
+ stateMutability: "view",
36082
+ inputs: [],
36083
+ outputs: [
36084
+ { name: "fields", type: "bytes1" },
36085
+ { name: "name", type: "string" },
36086
+ { name: "version", type: "string" },
36087
+ { name: "chainId", type: "uint256" },
36088
+ { name: "verifyingContract", type: "address" },
36089
+ { name: "salt", type: "bytes32" },
36090
+ { name: "extensions", type: "uint256[]" }
36091
+ ]
36092
+ }
36093
+ ];
36094
+ var REGISTRATION_EPOCH_ABI = [
36095
+ {
36096
+ type: "function",
36097
+ name: "registrationEpoch",
36098
+ stateMutability: "view",
36099
+ inputs: [
36100
+ { name: "account", type: "address" },
36101
+ { name: "permission", type: "address" }
36102
+ ],
36103
+ outputs: [{ type: "uint256" }]
36104
+ }
36105
+ ];
36106
+ var CONFIGURE_FIELDS_V1 = [
36107
+ { name: "account", type: "address" },
36108
+ { name: "paramsHash", type: "bytes32" },
36109
+ { name: "nonce", type: "uint256" },
36110
+ { name: "deadline", type: "uint256" }
36111
+ ];
36112
+ var CONFIGURE_FIELDS_V2 = [...CONFIGURE_FIELDS_V1, { name: "epoch", type: "uint256" }];
36113
+ async function buildConfigureTypedData(args) {
36114
+ const [, name, version4, chainId] = await args.publicClient.readContract({
36115
+ address: args.template,
36116
+ abi: TEMPLATE_EIP712_DOMAIN_ABI,
36117
+ functionName: "eip712Domain"
36118
+ });
36119
+ if (version4 !== "1" && version4 !== "2") {
36120
+ throw new Error(`Unsupported template EIP-712 domain version "${version4}" for ${args.template}. This SDK signs Configure schema v1 or v2; upgrade the SDK for newer templates.`);
36121
+ }
36122
+ const isV2 = version4 === "2";
36123
+ const message = {
36124
+ account: args.account,
36125
+ paramsHash: keccak256(args.params),
36126
+ nonce: args.nonce.toString(),
36127
+ deadline: args.deadline.toString()
36128
+ };
36129
+ if (isV2) {
36130
+ const epoch = await args.publicClient.readContract({
36131
+ address: args.kernel,
36132
+ abi: REGISTRATION_EPOCH_ABI,
36133
+ functionName: "registrationEpoch",
36134
+ args: [args.account, args.template]
36135
+ });
36136
+ message.epoch = epoch.toString();
36137
+ }
36138
+ return {
36139
+ domain: {
36140
+ name,
36141
+ version: version4,
36142
+ chainId: Number(chainId),
36143
+ verifyingContract: args.template
36144
+ },
36145
+ types: {
36146
+ Configure: isV2 ? CONFIGURE_FIELDS_V2 : CONFIGURE_FIELDS_V1
36147
+ },
36148
+ primaryType: "Configure",
36149
+ message
36150
+ };
36151
+ }
36152
+
36153
+ // ../sdk/dist/errors.js
36154
+ init_esm2();
36155
+ var KERNEL_ERROR_SIGNATURES = [
36156
+ "error AccountAlreadyRegistered(address account)",
36157
+ "error AccountNotRegistered(address account)",
36158
+ "error AccountSelfTarget()",
36159
+ "error ArrayLengthMismatch()",
36160
+ "error BatchPermissionDenied()",
36161
+ "error BatchSubcallFailed(uint256 index, address target)",
36162
+ "error BatchTooLong(uint256 length)",
36163
+ "error BatchZeroTarget(uint256 index)",
36164
+ "error DeadlineExpired(uint256 deadline, uint256 current)",
36165
+ "error DistributorBpsTooLarge(uint256 bps)",
36166
+ "error EmptyBatch()",
36167
+ "error FeePolicyNotSet()",
36168
+ "error FeeTokenMismatch(address provided, address expected)",
36169
+ "error FeeTooLarge(uint256 requested, uint256 maxAllowed)",
36170
+ "error FeeTransferFailed()",
36171
+ "error InsufficientFee(uint256 required, uint256 provided)",
36172
+ "error InvalidInitializer()",
36173
+ "error InvalidManagerSignature()",
36174
+ "error InvalidSignerSignature()",
36175
+ "error KernelSelfTarget(uint256 index)",
36176
+ // SAIL-405: setManager rejects a no-op rotation (newManager == current).
36177
+ "error ManagerUnchanged()",
36178
+ "error ModuleNotEnabled()",
36179
+ // Present in the deployed conjunctive kernel; dropped in the latest source.
36180
+ "error NoPermissionsRegistered(address account)",
36181
+ "error NotAContract(address addr)",
36182
+ "error NotGovernance()",
36183
+ "error NotManager(address caller, address expected)",
36184
+ "error NotPermissionSigner()",
36185
+ "error NotTimelock()",
36186
+ "error PermissionAlreadyRegistered(address permission)",
36187
+ "error PermissionDenied(address permission)",
36188
+ "error PermissionNotBatchAware(address permission)",
36189
+ "error PermissionNotRegistered(address permission)",
36190
+ "error ProtocolPaused()",
36191
+ "error SafeExecutionFailed()",
36192
+ "error SessionInactive(address account)",
36193
+ "error TooManyPermissions(address account, uint256 limit)",
36194
+ "error UntrustedFactory(address factory)",
36195
+ "error UntrustedFeePolicy(address policy)",
36196
+ "error UntrustedModuleSetup(address setup)",
36197
+ "error UntrustedProxyCodehash(bytes32 codehash)",
36198
+ "error UntrustedSingleton(address singleton)",
36199
+ "error ZeroAddress()",
36200
+ "error ZeroFee()"
36201
+ ];
36202
+ var KERNEL_ERROR_ABI = parseAbi(KERNEL_ERROR_SIGNATURES);
36203
+ var ERROR_HINTS = {
36204
+ InvalidManagerSignature: "The manager's EIP-712 Dispatch signature did not recover to the registered manager. Most common cause: a stale manager nonce (the kernel's managerNonces advanced between signing and submission \u2014 e.g. a load-balanced RPC returned a lagging value, or two dispatches were signed against the same nonce). Re-read managerNonces and re-sign, or track the nonce locally and increment it across sequential dispatches. Can also mean the wrong EIP-712 Dispatch type was used for this kernel version \u2014 see detectKernelCapabilities.",
36205
+ PermissionDenied: "A registered permission's evaluate() returned false (or reverted / ran out of gas) for this call. In a conjunctive kernel EVERY registered permission must approve EVERY call, so a permission that does not pass through calls outside its own domain will block unrelated dispatches. Check that each permission either matches this call or returns true for calls it doesn't govern.",
36206
+ NoPermissionsRegistered: "The account has zero registered permissions, so the kernel denies by default. Register at least one permission (kernel.registerPermission / registerPermissions) before dispatching.",
36207
+ PermissionNotRegistered: "The named permission is not registered for this account. Register it first, or (on a conjunctive kernel) drop the permission argument \u2014 that kernel checks all registered permissions automatically.",
36208
+ SessionInactive: "The manager's session is revoked. Re-activate it (session.activate) before dispatching.",
36209
+ DeadlineExpired: "The signature deadline is in the past. Use a deadline comfortably ahead of block.timestamp.",
36210
+ SafeExecutionFailed: "The underlying Safe module call reverted. The permission passed, but the target call itself failed (e.g. slippage too tight, insufficient allowance/balance, or a failing swap route).",
36211
+ ModuleNotEnabled: "The Sail module is not enabled on the Safe. Complete account onboarding (enable the module) first.",
36212
+ ProtocolPaused: "The protocol is paused by governance. Dispatches are blocked until it is unpaused.",
36213
+ NotManager: "The submitting address is not the registered manager for this account.",
36214
+ TooManyPermissions: "Registering this permission would exceed the kernel's per-account permission cap. Revoke an unused permission first."
36215
+ };
36216
+ async function decode2(data) {
36217
+ const { decodeErrorResult: decodeErrorResult2 } = await Promise.resolve().then(() => (init_esm2(), esm_exports2));
36218
+ try {
36219
+ const decoded = decodeErrorResult2({ abi: KERNEL_ERROR_ABI, data });
36220
+ const name = decoded.errorName;
36221
+ const args = decoded.args ?? [];
36222
+ const selector = data.slice(0, 10);
36223
+ const hint = ERROR_HINTS[name];
36224
+ const argStr = args.length ? `(${args.map(String).join(", ")})` : "()";
36225
+ const message = hint ? `${name}${argStr} \u2014 ${hint}` : `${name}${argStr}`;
36226
+ return { name, args, selector, hint, message };
36227
+ } catch {
36228
+ return null;
36229
+ }
36230
+ }
36231
+ function decodeKernelError(data) {
36232
+ if (!data || data === "0x")
36233
+ return Promise.resolve(null);
36234
+ return decode2(data);
36235
+ }
36236
+ async function explainKernelRevert(err) {
36237
+ const data = extractRevertData(err);
36238
+ if (!data)
36239
+ return null;
36240
+ return decodeKernelError(data);
36241
+ }
36242
+ function extractRevertData(err) {
36243
+ const seen = /* @__PURE__ */ new Set();
36244
+ let cursor = err;
36245
+ let depth = 0;
36246
+ while (cursor && typeof cursor === "object" && !seen.has(cursor) && depth < 12) {
36247
+ seen.add(cursor);
36248
+ depth++;
36249
+ const obj = cursor;
36250
+ const data = obj["data"];
36251
+ if (typeof data === "string" && data.startsWith("0x") && data.length >= 10) {
36252
+ return data;
36253
+ }
36254
+ if (data && typeof data === "object") {
36255
+ const inner = data["data"];
36256
+ if (typeof inner === "string" && inner.startsWith("0x") && inner.length >= 10) {
36257
+ return inner;
36258
+ }
36259
+ }
36260
+ const raw = obj["raw"];
36261
+ if (typeof raw === "string" && raw.startsWith("0x") && raw.length >= 10) {
36262
+ return raw;
36263
+ }
36264
+ cursor = obj["cause"];
36265
+ }
36266
+ return null;
36116
36267
  }
36117
36268
 
36118
36269
  // ../sdk/dist/lifi.js
@@ -36181,9 +36332,30 @@ function buildPublicClient(config) {
36181
36332
  function defaultDeadline() {
36182
36333
  return BigInt(Math.floor(Date.now() / 1e3) + 300);
36183
36334
  }
36335
+ var CONFIGURABLE_PERMISSION_ABI = [
36336
+ {
36337
+ type: "function",
36338
+ name: "configNonces",
36339
+ stateMutability: "view",
36340
+ inputs: [{ name: "account", type: "address" }],
36341
+ outputs: [{ type: "uint256" }]
36342
+ },
36343
+ {
36344
+ type: "function",
36345
+ name: "configure",
36346
+ stateMutability: "nonpayable",
36347
+ inputs: [
36348
+ { name: "account", type: "address" },
36349
+ { name: "params", type: "bytes" },
36350
+ { name: "deadline", type: "uint256" },
36351
+ { name: "sig", type: "bytes" }
36352
+ ],
36353
+ outputs: []
36354
+ }
36355
+ ];
36184
36356
  var DEFAULT_DISPATCH_GAS = 2000000n;
36185
36357
  function delay(ms) {
36186
- return new Promise((resolve3) => setTimeout(resolve3, ms));
36358
+ return new Promise((resolve4) => setTimeout(resolve4, ms));
36187
36359
  }
36188
36360
  var CALL_COMPONENTS = [
36189
36361
  { name: "target", type: "address" },
@@ -36337,8 +36509,47 @@ var MandateNamespace = class extends KernelNamespace {
36337
36509
  value: 0n
36338
36510
  });
36339
36511
  }
36340
- reconfigure(_safe, _template, _params, _signer) {
36341
- return notImplemented();
36512
+ /**
36513
+ * Re-configure the per-account bounds of an already-registered shared template.
36514
+ * The permission signer signs the template's `Configure` EIP-712 struct — built by
36515
+ * `buildConfigureTypedData`, which reads the template's live ERC-5267 domain and emits
36516
+ * the v1 or v2 (epoch-bound) schema to match whatever is deployed — and the attached
36517
+ * wallet submits `configure(account, params, deadline, sig)`.
36518
+ *
36519
+ * The config nonce is read fresh on-chain immediately before signing (the template
36520
+ * increments it only after a successful verify), so a re-config never reuses a stale nonce.
36521
+ */
36522
+ async reconfigure(safe, template, params, signer) {
36523
+ const kernel = this.requireKernel();
36524
+ const wallet = this.requireSigner();
36525
+ const encoded = template.encoder.encode(params);
36526
+ const deadline = defaultDeadline();
36527
+ const nonce = await this.publicClient.readContract({
36528
+ address: template.address,
36529
+ abi: CONFIGURABLE_PERMISSION_ABI,
36530
+ functionName: "configNonces",
36531
+ args: [safe]
36532
+ });
36533
+ const td = await buildConfigureTypedData({
36534
+ publicClient: this.publicClient,
36535
+ kernel,
36536
+ template: template.address,
36537
+ account: safe,
36538
+ params: encoded,
36539
+ nonce,
36540
+ deadline
36541
+ });
36542
+ const sig = await signer.signTyped(td.domain, { primaryType: td.primaryType, types: td.types }, td.message);
36543
+ const txHash = await wallet.writeContract({
36544
+ address: template.address,
36545
+ abi: CONFIGURABLE_PERMISSION_ABI,
36546
+ functionName: "configure",
36547
+ args: [safe, encoded, deadline, sig]
36548
+ });
36549
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash: txHash });
36550
+ if (receipt.status !== "success") {
36551
+ throw new Error(`configure reverted (tx ${txHash})`);
36552
+ }
36342
36553
  }
36343
36554
  replace(_safe, _oldTemplate, _newTemplate, _params, _signer) {
36344
36555
  return notImplemented();
@@ -36637,14 +36848,67 @@ var StrategyNamespace = class extends KernelNamespace {
36637
36848
  }
36638
36849
  };
36639
36850
  var SessionNamespace = class extends KernelNamespace {
36640
- revoke(_safe, _signer) {
36641
- return notImplemented();
36851
+ /**
36852
+ * Suspend (`revokeSession`) or resume (`activateSession`) the manager's dispatch rights.
36853
+ * Both are permissionSigner-signed over the RevokeSession/ActivateSession EIP-712 struct,
36854
+ * with `nonce` read fresh from `signerNonces[account]` immediately before signing — the
36855
+ * kernel bumps that nonce by a full epoch on revoke (#70), so it must never be cached. The
36856
+ * kernel also rotates the manager/batch nonce epochs, invalidating any pre-signed dispatch.
36857
+ */
36858
+ async revoke(safe, signer) {
36859
+ await this.#submitSessionOp(safe, signer, "RevokeSession", "revokeSession");
36642
36860
  }
36643
- activate(_safe, _signer) {
36644
- return notImplemented();
36861
+ async activate(safe, signer) {
36862
+ await this.#submitSessionOp(safe, signer, "ActivateSession", "activateSession");
36645
36863
  }
36646
- status(_safe) {
36647
- return notImplemented();
36864
+ async #submitSessionOp(safe, signer, primaryType, fn) {
36865
+ const kernel = this.requireKernel();
36866
+ const wallet = this.requireSigner();
36867
+ const deadline = defaultDeadline();
36868
+ const nonce = await this.publicClient.readContract({
36869
+ address: kernel,
36870
+ abi: SailKernelAbi,
36871
+ functionName: "signerNonces",
36872
+ args: [safe]
36873
+ });
36874
+ const sig = await signer.signTyped(sailKernelDomain({ chainId: this.config.chainId, kernel }), {
36875
+ primaryType,
36876
+ types: {
36877
+ [primaryType]: [
36878
+ { name: "account", type: "address" },
36879
+ { name: "nonce", type: "uint256" },
36880
+ { name: "deadline", type: "uint256" }
36881
+ ]
36882
+ }
36883
+ }, { account: safe, nonce, deadline });
36884
+ const txHash = await wallet.writeContract({
36885
+ address: kernel,
36886
+ abi: SailKernelAbi,
36887
+ functionName: fn,
36888
+ args: [safe, deadline, sig]
36889
+ });
36890
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash: txHash });
36891
+ if (receipt.status !== "success") {
36892
+ throw new Error(`${fn} reverted (tx ${txHash})`);
36893
+ }
36894
+ }
36895
+ async status(safe) {
36896
+ const kernel = this.requireKernel();
36897
+ const cfg = await this.publicClient.readContract({
36898
+ address: kernel,
36899
+ abi: SailKernelAbi,
36900
+ functionName: "configs",
36901
+ args: [safe]
36902
+ });
36903
+ return {
36904
+ safe,
36905
+ active: cfg[4],
36906
+ manager: cfg[1],
36907
+ // Block-level markers require an event scan; expose live active/manager state and
36908
+ // leave the historical timestamps null.
36909
+ activatedAtBlock: null,
36910
+ revokedAtBlock: null
36911
+ };
36648
36912
  }
36649
36913
  };
36650
36914
  var FeesNamespace = class extends KernelNamespace {
@@ -37613,6 +37877,60 @@ var SailGovernanceAbi = [
37613
37877
  }
37614
37878
  ];
37615
37879
 
37880
+ // ../sdk/dist/abis/ConfigurablePermission.js
37881
+ var ConfigurablePermissionAbi = [
37882
+ {
37883
+ type: "function",
37884
+ name: "configure",
37885
+ stateMutability: "nonpayable",
37886
+ inputs: [
37887
+ { name: "account", type: "address" },
37888
+ { name: "params", type: "bytes" },
37889
+ { name: "deadline", type: "uint256" },
37890
+ { name: "sig", type: "bytes" }
37891
+ ],
37892
+ outputs: []
37893
+ },
37894
+ {
37895
+ type: "function",
37896
+ name: "configureDirect",
37897
+ stateMutability: "nonpayable",
37898
+ inputs: [
37899
+ { name: "account", type: "address" },
37900
+ { name: "params", type: "bytes" }
37901
+ ],
37902
+ outputs: []
37903
+ },
37904
+ {
37905
+ type: "function",
37906
+ name: "isConfigured",
37907
+ stateMutability: "view",
37908
+ inputs: [{ name: "account", type: "address" }],
37909
+ outputs: [{ name: "", type: "bool" }]
37910
+ },
37911
+ {
37912
+ type: "function",
37913
+ name: "configNonces",
37914
+ stateMutability: "view",
37915
+ inputs: [{ name: "account", type: "address" }],
37916
+ outputs: [{ name: "", type: "uint256" }]
37917
+ },
37918
+ {
37919
+ type: "function",
37920
+ name: "configuredEpoch",
37921
+ stateMutability: "view",
37922
+ inputs: [{ name: "account", type: "address" }],
37923
+ outputs: [{ name: "", type: "uint256" }]
37924
+ },
37925
+ {
37926
+ type: "function",
37927
+ name: "hashTypedDataV4",
37928
+ stateMutability: "view",
37929
+ inputs: [{ name: "structHash", type: "bytes32" }],
37930
+ outputs: [{ name: "", type: "bytes32" }]
37931
+ }
37932
+ ];
37933
+
37616
37934
  // ../sdk/dist/safe.js
37617
37935
  init_esm2();
37618
37936
  var setManagerAbi = [
@@ -37858,6 +38176,9 @@ var SAIL_INTELLIGENCE_DOCS_URL = "https://api.sail.money/docs";
37858
38176
  // src/commands/account.ts
37859
38177
  init_esm2();
37860
38178
 
38179
+ // src/lib/chain.ts
38180
+ init_esm2();
38181
+
37861
38182
  // ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/op-stack/contracts.js
37862
38183
  var contracts = {
37863
38184
  gasPriceOracle: { address: "0x420000000000000000000000000000000000000F" },
@@ -38129,6 +38450,35 @@ var baseSepoliaPreconf = /* @__PURE__ */ defineChain({
38129
38450
  }
38130
38451
  });
38131
38452
 
38453
+ // ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/bsc.js
38454
+ init_defineChain();
38455
+ var bsc = /* @__PURE__ */ defineChain({
38456
+ id: 56,
38457
+ name: "BNB Smart Chain",
38458
+ blockTime: 750,
38459
+ nativeCurrency: {
38460
+ decimals: 18,
38461
+ name: "BNB",
38462
+ symbol: "BNB"
38463
+ },
38464
+ rpcUrls: {
38465
+ default: { http: ["https://56.rpc.thirdweb.com"] }
38466
+ },
38467
+ blockExplorers: {
38468
+ default: {
38469
+ name: "BscScan",
38470
+ url: "https://bscscan.com",
38471
+ apiUrl: "https://api.bscscan.com/api"
38472
+ }
38473
+ },
38474
+ contracts: {
38475
+ multicall3: {
38476
+ address: "0xca11bde05977b3631167028862be2a173976ca11",
38477
+ blockCreated: 15921452
38478
+ }
38479
+ }
38480
+ });
38481
+
38132
38482
  // ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/mainnet.js
38133
38483
  init_defineChain();
38134
38484
  var mainnet = /* @__PURE__ */ defineChain({
@@ -38160,6 +38510,56 @@ var mainnet = /* @__PURE__ */ defineChain({
38160
38510
  }
38161
38511
  });
38162
38512
 
38513
+ // ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/optimism.js
38514
+ init_defineChain();
38515
+ var sourceId3 = 1;
38516
+ var optimism = /* @__PURE__ */ defineChain({
38517
+ ...chainConfig,
38518
+ id: 10,
38519
+ name: "OP Mainnet",
38520
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
38521
+ rpcUrls: {
38522
+ default: {
38523
+ http: ["https://mainnet.optimism.io"]
38524
+ }
38525
+ },
38526
+ blockExplorers: {
38527
+ default: {
38528
+ name: "Optimism Explorer",
38529
+ url: "https://optimistic.etherscan.io",
38530
+ apiUrl: "https://api-optimistic.etherscan.io/api"
38531
+ }
38532
+ },
38533
+ contracts: {
38534
+ ...chainConfig.contracts,
38535
+ disputeGameFactory: {
38536
+ [sourceId3]: {
38537
+ address: "0xe5965Ab5962eDc7477C8520243A95517CD252fA9"
38538
+ }
38539
+ },
38540
+ l2OutputOracle: {
38541
+ [sourceId3]: {
38542
+ address: "0xdfe97868233d1aa22e815a266982f2cf17685a27"
38543
+ }
38544
+ },
38545
+ multicall3: {
38546
+ address: "0xca11bde05977b3631167028862be2a173976ca11",
38547
+ blockCreated: 4286263
38548
+ },
38549
+ portal: {
38550
+ [sourceId3]: {
38551
+ address: "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed"
38552
+ }
38553
+ },
38554
+ l1StandardBridge: {
38555
+ [sourceId3]: {
38556
+ address: "0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1"
38557
+ }
38558
+ }
38559
+ },
38560
+ sourceId: sourceId3
38561
+ });
38562
+
38163
38563
  // ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/sepolia.js
38164
38564
  init_defineChain();
38165
38565
  var sepolia = /* @__PURE__ */ defineChain({
@@ -38193,7 +38593,7 @@ var sepolia = /* @__PURE__ */ defineChain({
38193
38593
 
38194
38594
  // ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/unichain.js
38195
38595
  init_defineChain();
38196
- var sourceId3 = 1;
38596
+ var sourceId4 = 1;
38197
38597
  var unichain = /* @__PURE__ */ defineChain({
38198
38598
  ...chainConfig,
38199
38599
  id: 130,
@@ -38219,22 +38619,77 @@ var unichain = /* @__PURE__ */ defineChain({
38219
38619
  blockCreated: 0
38220
38620
  },
38221
38621
  disputeGameFactory: {
38222
- [sourceId3]: {
38622
+ [sourceId4]: {
38223
38623
  address: "0x2F12d621a16e2d3285929C9996f478508951dFe4"
38224
38624
  }
38225
38625
  },
38226
38626
  portal: {
38227
- [sourceId3]: {
38627
+ [sourceId4]: {
38228
38628
  address: "0x0bd48f6B86a26D3a217d0Fa6FfE2B491B956A7a2"
38229
38629
  }
38230
38630
  },
38231
38631
  l1StandardBridge: {
38232
- [sourceId3]: {
38632
+ [sourceId4]: {
38233
38633
  address: "0x81014F44b0a345033bB2b3B21C7a1A308B35fEeA"
38234
38634
  }
38235
38635
  }
38236
38636
  },
38237
- sourceId: sourceId3
38637
+ sourceId: sourceId4
38638
+ });
38639
+
38640
+ // ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/worldchain.js
38641
+ init_defineChain();
38642
+ var sourceId5 = 1;
38643
+ var worldchain = /* @__PURE__ */ defineChain({
38644
+ ...chainConfig,
38645
+ id: 480,
38646
+ name: "World Chain",
38647
+ network: "worldchain",
38648
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
38649
+ rpcUrls: {
38650
+ default: { http: ["https://worldchain-mainnet.g.alchemy.com/public"] }
38651
+ },
38652
+ blockExplorers: {
38653
+ default: {
38654
+ name: "Worldscan",
38655
+ url: "https://worldscan.org",
38656
+ apiUrl: "https://api.worldscan.org/api"
38657
+ },
38658
+ blockscout: {
38659
+ name: "Blockscout",
38660
+ url: "https://worldchain-mainnet.explorer.alchemy.com",
38661
+ apiUrl: "https://worldchain-mainnet.explorer.alchemy.com/api"
38662
+ }
38663
+ },
38664
+ contracts: {
38665
+ ...chainConfig.contracts,
38666
+ multicall3: {
38667
+ address: "0xca11bde05977b3631167028862be2a173976ca11",
38668
+ blockCreated: 0
38669
+ },
38670
+ disputeGameFactory: {
38671
+ [sourceId5]: {
38672
+ address: "0x069c4c579671f8c120b1327a73217D01Ea2EC5ea"
38673
+ }
38674
+ },
38675
+ l2OutputOracle: {
38676
+ [sourceId5]: {
38677
+ address: "0x19A6d1E9034596196295CF148509796978343c5D"
38678
+ }
38679
+ },
38680
+ portal: {
38681
+ [sourceId5]: {
38682
+ address: "0xd5ec14a83B7d95BE1E2Ac12523e2dEE12Cbeea6C"
38683
+ }
38684
+ },
38685
+ l1StandardBridge: {
38686
+ [sourceId5]: {
38687
+ address: "0x470458C91978D2d929704489Ad730DC3E3001113"
38688
+ }
38689
+ }
38690
+ },
38691
+ testnet: false,
38692
+ sourceId: sourceId5
38238
38693
  });
38239
38694
 
38240
38695
  // src/lib/io.ts
@@ -38358,14 +38813,14 @@ function getRl() {
38358
38813
  function ask(query) {
38359
38814
  getRl();
38360
38815
  process.stdout.write(query);
38361
- return new Promise((resolve3) => {
38816
+ return new Promise((resolve4) => {
38362
38817
  const buffered = lineQueue.shift();
38363
38818
  if (buffered !== void 0) {
38364
- resolve3(buffered);
38819
+ resolve4(buffered);
38365
38820
  } else if (inputClosed) {
38366
- resolve3("");
38821
+ resolve4("");
38367
38822
  } else {
38368
- waiters.push(resolve3);
38823
+ waiters.push(resolve4);
38369
38824
  }
38370
38825
  });
38371
38826
  }
@@ -38397,11 +38852,28 @@ async function promptHidden(question) {
38397
38852
  }
38398
38853
 
38399
38854
  // src/lib/chain.ts
38855
+ var hyperevm = defineChain({
38856
+ id: 999,
38857
+ name: "HyperEVM",
38858
+ nativeCurrency: { name: "HYPE", symbol: "HYPE", decimals: 18 },
38859
+ rpcUrls: { default: { http: ["https://rpc.hyperliquid.xyz/evm"] } }
38860
+ });
38861
+ var megaeth = defineChain({
38862
+ id: 4326,
38863
+ name: "MegaETH",
38864
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
38865
+ rpcUrls: { default: { http: ["https://carrot.megaeth.com/rpc"] } }
38866
+ });
38400
38867
  var CHAINS = {
38401
38868
  1: mainnet,
38402
38869
  8453: base,
38403
38870
  42161: arbitrum,
38871
+ 10: optimism,
38404
38872
  130: unichain,
38873
+ 56: bsc,
38874
+ 480: worldchain,
38875
+ 999: hyperevm,
38876
+ 4326: megaeth,
38405
38877
  84532: baseSepolia,
38406
38878
  11155111: sepolia
38407
38879
  };
@@ -38409,7 +38881,7 @@ function getChainById(chainId) {
38409
38881
  const chain2 = CHAINS[chainId];
38410
38882
  if (!chain2) {
38411
38883
  throw new Error(
38412
- `Unsupported chainId: ${chainId}. Supported: 1 (Ethereum), 8453 (Base), 42161 (Arbitrum), 130 (Unichain), 84532 (Base Sepolia), 11155111 (Eth Sepolia)`
38884
+ `Unsupported chainId: ${chainId}. Supported: 1 (Ethereum), 8453 (Base), 42161 (Arbitrum), 10 (Optimism), 130 (Unichain), 56 (BSC), 480 (World Chain), 999 (HyperEVM), 4326 (MegaETH), 84532 (Base Sepolia), 11155111 (Eth Sepolia)`
38413
38885
  );
38414
38886
  }
38415
38887
  return chain2;
@@ -38539,11 +39011,11 @@ function isProcessAlive(pid) {
38539
39011
  }
38540
39012
  }
38541
39013
  function findFreePort(from14) {
38542
- return new Promise((resolve3, reject) => {
39014
+ return new Promise((resolve4, reject) => {
38543
39015
  const server = import_node_net.default.createServer();
38544
39016
  server.unref();
38545
- server.on("error", () => findFreePort(from14 + 1).then(resolve3, reject));
38546
- server.listen(from14, "127.0.0.1", () => server.close(() => resolve3(from14)));
39017
+ server.on("error", () => findFreePort(from14 + 1).then(resolve4, reject));
39018
+ server.listen(from14, "127.0.0.1", () => server.close(() => resolve4(from14)));
38547
39019
  });
38548
39020
  }
38549
39021
 
@@ -39157,8 +39629,9 @@ var SigningServer = class {
39157
39629
  }
39158
39630
  }
39159
39631
  if (!(0, import_node_fs6.existsSync)(this.runtimeDir)) (0, import_node_fs6.mkdirSync)(this.runtimeDir, { recursive: true });
39632
+ const serverStatePath = (0, import_node_path4.join)(this.runtimeDir, SERVER_STATE_FILE);
39160
39633
  (0, import_node_fs6.writeFileSync)(
39161
- (0, import_node_path4.join)(this.runtimeDir, SERVER_STATE_FILE),
39634
+ serverStatePath,
39162
39635
  JSON.stringify(
39163
39636
  {
39164
39637
  url: this._url,
@@ -39170,8 +39643,10 @@ var SigningServer = class {
39170
39643
  },
39171
39644
  null,
39172
39645
  2
39173
- )
39646
+ ),
39647
+ { mode: 384 }
39174
39648
  );
39649
+ (0, import_node_fs6.chmodSync)(serverStatePath, 384);
39175
39650
  }
39176
39651
  removeRuntimeState() {
39177
39652
  const path11 = (0, import_node_path4.join)(this.runtimeDir, SERVER_STATE_FILE);
@@ -39300,7 +39775,7 @@ async function createSigningChannel(projectRoot = process.cwd()) {
39300
39775
  }
39301
39776
 
39302
39777
  // src/commands/account.ts
39303
- var SAIL_MAINNET_CHAINS = [1, 8453, 42161, 130];
39778
+ var SAIL_MAINNET_CHAINS = [1, 8453, 42161, 10, 130, 56, 480, 999, 4326];
39304
39779
  async function fetchProxyCreationCode(preferredChainId) {
39305
39780
  const rpcUrl = getRpcUrl(preferredChainId) ?? void 0;
39306
39781
  const publicClient = createPublicClient({
@@ -40070,15 +40545,36 @@ var IPERMISSION_ABI = [
40070
40545
  { name: "selector", type: "bytes4" },
40071
40546
  { name: "value", type: "uint256" },
40072
40547
  { name: "blockTimestamp", type: "uint256" },
40073
- { name: "blockNumber", type: "uint256" }
40548
+ { name: "blockNumber", type: "uint256" },
40549
+ { name: "configEpoch", type: "uint256" }
40074
40550
  ]
40075
40551
  }
40076
40552
  ],
40077
40553
  outputs: [{ type: "bool" }]
40078
40554
  }
40079
40555
  ];
40556
+ var REGISTRATION_EPOCH_ABI2 = [
40557
+ {
40558
+ type: "function",
40559
+ name: "registrationEpoch",
40560
+ stateMutability: "view",
40561
+ inputs: [
40562
+ { name: "account", type: "address" },
40563
+ { name: "permission", type: "address" }
40564
+ ],
40565
+ outputs: [{ type: "uint256" }]
40566
+ }
40567
+ ];
40568
+ async function readRegistrationEpoch(publicClient, kernel, account2, permission) {
40569
+ return await publicClient.readContract({
40570
+ address: kernel,
40571
+ abi: REGISTRATION_EPOCH_ABI2,
40572
+ functionName: "registrationEpoch",
40573
+ args: [account2, permission]
40574
+ });
40575
+ }
40080
40576
  function buildPermissionContext(params) {
40081
- const { account: account2, manager, call: call2, blockInfo } = params;
40577
+ const { account: account2, manager, call: call2, blockInfo, configEpoch } = params;
40082
40578
  const selector = call2.data.length >= 10 ? call2.data.slice(0, 10) : "0x00000000";
40083
40579
  return {
40084
40580
  account: account2,
@@ -40089,12 +40585,23 @@ function buildPermissionContext(params) {
40089
40585
  selector,
40090
40586
  value: call2.value,
40091
40587
  blockTimestamp: blockInfo.timestamp,
40092
- blockNumber: blockInfo.number
40588
+ blockNumber: blockInfo.number,
40589
+ configEpoch
40093
40590
  };
40094
40591
  }
40095
40592
  async function probePermissionForCall(params) {
40096
- const { publicClient, permission, account: account2, manager, call: call2, blockInfo } = params;
40097
- const ctx = buildPermissionContext({ account: account2, manager, call: call2, blockInfo });
40593
+ const { publicClient, kernel, permission, account: account2, manager, call: call2, blockInfo } = params;
40594
+ let configEpoch;
40595
+ try {
40596
+ configEpoch = await readRegistrationEpoch(publicClient, kernel, account2, permission);
40597
+ } catch (err) {
40598
+ return {
40599
+ accepted: false,
40600
+ reverted: true,
40601
+ error: `could not read registrationEpoch from kernel ${kernel} (${err.message.split("\n")[0]})`
40602
+ };
40603
+ }
40604
+ const ctx = buildPermissionContext({ account: account2, manager, call: call2, blockInfo, configEpoch });
40098
40605
  try {
40099
40606
  const accepted = await publicClient.readContract({
40100
40607
  address: permission,
@@ -40108,10 +40615,11 @@ async function probePermissionForCall(params) {
40108
40615
  }
40109
40616
  }
40110
40617
  async function resolvePermissionForCall(params) {
40111
- const { publicClient, account: account2, manager, call: call2, registeredPermissions, blockInfo } = params;
40112
- const ctx = buildPermissionContext({ account: account2, manager, call: call2, blockInfo });
40618
+ const { publicClient, kernel, account: account2, manager, call: call2, registeredPermissions, blockInfo } = params;
40113
40619
  for (const permission of registeredPermissions) {
40114
40620
  try {
40621
+ const configEpoch = await readRegistrationEpoch(publicClient, kernel, account2, permission);
40622
+ const ctx = buildPermissionContext({ account: account2, manager, call: call2, blockInfo, configEpoch });
40115
40623
  const accepted = await publicClient.readContract({
40116
40624
  address: permission,
40117
40625
  abi: IPERMISSION_ABI,
@@ -40181,7 +40689,10 @@ async function probePassThrough(pc, permission, account2) {
40181
40689
  selector: PROBE_SELECTOR,
40182
40690
  value: 0n,
40183
40691
  blockTimestamp: 0n,
40184
- blockNumber: 0n
40692
+ blockNumber: 0n,
40693
+ // Pass-through probes only run on conjunctive kernels, which predate
40694
+ // registrationEpoch — there is no live epoch to read, so probe with 0.
40695
+ configEpoch: 0n
40185
40696
  }
40186
40697
  ]
40187
40698
  });
@@ -40357,7 +40868,7 @@ async function doctor(options = {}) {
40357
40868
  console.log(`Account: ${safe}`);
40358
40869
  if (stored?.saltNonce != null) {
40359
40870
  const saltNonce = BigInt(stored.saltNonce);
40360
- const MAINNET_CHAINS = [1, 8453, 42161, 130];
40871
+ const MAINNET_CHAINS = [1, 8453, 42161, 10, 130, 56, 480, 999, 4326];
40361
40872
  try {
40362
40873
  const proxyCreationCode = await pc.readContract({
40363
40874
  address: SAFE_V141.proxyFactory,
@@ -40477,6 +40988,10 @@ struct Context {
40477
40988
  uint256 value; // native ETH forwarded (wei)
40478
40989
  uint256 blockTimestamp; // block.timestamp at dispatch
40479
40990
  uint256 blockNumber; // block.number at dispatch
40991
+ uint256 configEpoch; // kernel registrationEpoch(account, permission) at dispatch;
40992
+ // configurable permissions fail closed on a mismatch with the
40993
+ // epoch stamped at configure() time. Custom permissions that
40994
+ // take no post-deploy configuration can ignore it.
40480
40995
  }
40481
40996
 
40482
40997
  /// @title IPermission
@@ -40512,6 +41027,8 @@ struct BatchContext {
40512
41027
  bytes32 batchHash; // keccak256(abi.encode(calls)) \u2014 stable id for the exact sequence
40513
41028
  uint256 blockTimestamp; // block.timestamp at dispatch
40514
41029
  uint256 blockNumber; // block.number at dispatch
41030
+ uint256 configEpoch; // kernel registrationEpoch(account, permission) at dispatch \u2014
41031
+ // same fail-closed freshness check as Context.configEpoch
40515
41032
  }
40516
41033
 
40517
41034
  /// @title IBatchPermission
@@ -40675,21 +41192,18 @@ This folder is the local workspace for one Sailor agent deployment.
40675
41192
 
40676
41193
  AI coding agents should read the project's \`AGENTS.md\` and this folder's \`config.json\`
40677
41194
  before changing strategy code or running commands that touch funds.
40678
- `;
40679
- var CANONICAL_PKG = "@sail.money/sailor";
40680
- var DEV_PKG = "@dev.sail.money/sailor";
40681
- function cliPackageInfo() {
40682
- try {
40683
- const pkg = JSON.parse(
40684
- import_node_fs10.default.readFileSync(import_node_path8.default.join(packageRoot(), "package.json"), "utf-8")
40685
- );
40686
- return {
40687
- name: pkg.name ?? CANONICAL_PKG,
40688
- version: pkg.version ?? "0.0.0"
40689
- };
40690
- } catch {
40691
- return { name: CANONICAL_PKG, version: "0.0.0" };
41195
+ `;
41196
+ var CANONICAL_PKG = "@sail.money/sailor";
41197
+ function cliVersion() {
41198
+ const manifest = import_node_path8.default.join(packageRoot(), "package.json");
41199
+ let version4;
41200
+ try {
41201
+ version4 = JSON.parse(import_node_fs10.default.readFileSync(manifest, "utf-8")).version;
41202
+ } catch (err) {
41203
+ throw new Error(`Cannot read CLI package manifest at ${manifest}: ${err.message}`);
40692
41204
  }
41205
+ if (!version4) throw new Error(`CLI package manifest at ${manifest} has no version`);
41206
+ return version4;
40693
41207
  }
40694
41208
  function scaffoldProjectWorkspace(dest, name, options) {
40695
41209
  const chainId = options.chain ? (() => {
@@ -40816,30 +41330,12 @@ Pass --force to scaffold into it anyway (existing files with the same name are o
40816
41330
  }
40817
41331
  })() : null;
40818
41332
  copyDirSync(templateSrc, dest);
40819
- if (options.skills === false) {
40820
- import_node_fs10.default.rmSync(import_node_path8.default.join(dest, ".agents", "skills"), { recursive: true, force: true });
40821
- }
40822
- const pkgRoot = packageRoot();
40823
- const examplesPermSrc = import_node_path8.default.join(pkgRoot, "examples", "permissions");
40824
- if (import_node_fs10.default.existsSync(examplesPermSrc)) {
40825
- copyDirSync(examplesPermSrc, import_node_path8.default.join(dest, "examples", "permissions"));
40826
- }
40827
- const customMandateSrc = import_node_path8.default.join(pkgRoot, "examples", "custom-mandate");
40828
- if (import_node_fs10.default.existsSync(customMandateSrc)) {
40829
- copyDirSync(customMandateSrc, import_node_path8.default.join(dest, "examples", "custom-mandate"));
40830
- }
40831
- const permModelSrc = import_node_path8.default.join(pkgRoot, "docs", "PERMISSION_MODEL.md");
40832
- if (import_node_fs10.default.existsSync(permModelSrc)) {
40833
- import_node_fs10.default.mkdirSync(import_node_path8.default.join(dest, "docs"), { recursive: true });
40834
- writeIfMissing2(import_node_path8.default.join(dest, "docs", "PERMISSION_MODEL.md"), import_node_fs10.default.readFileSync(permModelSrc, "utf-8"));
40835
- }
40836
41333
  const pkgPath = import_node_path8.default.join(dest, "package.json");
40837
41334
  if (import_node_fs10.default.existsSync(pkgPath)) {
40838
41335
  const pkg = JSON.parse(import_node_fs10.default.readFileSync(pkgPath, "utf-8"));
40839
41336
  pkg.name = name;
40840
41337
  const devDeps = pkg.devDependencies ?? {};
40841
- const { name: cliName, version: cliVer } = cliPackageInfo();
40842
- devDeps[CANONICAL_PKG] = cliName === DEV_PKG ? `npm:${DEV_PKG}@^${cliVer}` : `^${cliVer}`;
41338
+ devDeps[CANONICAL_PKG] = `^${cliVersion()}`;
40843
41339
  pkg.devDependencies = devDeps;
40844
41340
  import_node_fs10.default.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
40845
41341
  `);
@@ -40927,7 +41423,7 @@ function printWelcome(dest, name, inPlace, _hasRpc, freshInit = false) {
40927
41423
  console.log("Next:");
40928
41424
  console.log(" sailor ui start");
40929
41425
  console.log(" Connect your wallet and deploy your SMA in the browser.\n");
40930
- console.log('Or open this folder in your AI coding assistant and say: "continue"');
41426
+ console.log('Or open this folder in your AI coding agent and say: "continue"');
40931
41427
  return;
40932
41428
  }
40933
41429
  if (state.kind === "C") {
@@ -40944,7 +41440,7 @@ function printWelcome(dest, name, inPlace, _hasRpc, freshInit = false) {
40944
41440
  console.log(" forge build");
40945
41441
  console.log(` sailor mandate deploy --contract <Name> --attach --sma ${state.sma}
40946
41442
  `);
40947
- console.log('Or open this folder in your AI coding assistant and say: "continue"');
41443
+ console.log('Or open this folder in your AI coding agent and say: "continue"');
40948
41444
  return;
40949
41445
  }
40950
41446
  if (state.kind === "D") {
@@ -40953,7 +41449,7 @@ function printWelcome(dest, name, inPlace, _hasRpc, freshInit = false) {
40953
41449
  console.log(`SMA: ${state.sma} on ${state.chain}`);
40954
41450
  console.log(`Permissions: ${state.permissionCount} registered
40955
41451
  `);
40956
- console.log('Open this folder in your AI coding assistant and say: "continue"');
41452
+ console.log('Open this folder in your AI coding agent and say: "continue"');
40957
41453
  return;
40958
41454
  }
40959
41455
  if (!inPlace) console.log(`
@@ -41099,13 +41595,13 @@ Added (new in template):`);
41099
41595
  var import_node_fs12 = __toESM(require("node:fs"), 1);
41100
41596
  var import_node_path10 = __toESM(require("node:path"), 1);
41101
41597
  function readStdin() {
41102
- return new Promise((resolve3, reject) => {
41598
+ return new Promise((resolve4, reject) => {
41103
41599
  let data = "";
41104
41600
  process.stdin.setEncoding("utf8");
41105
41601
  process.stdin.on("data", (c) => {
41106
41602
  data += c;
41107
41603
  });
41108
- process.stdin.on("end", () => resolve3(data));
41604
+ process.stdin.on("end", () => resolve4(data));
41109
41605
  process.stdin.on("error", reject);
41110
41606
  });
41111
41607
  }
@@ -41413,6 +41909,22 @@ var MandateStore = class {
41413
41909
  this.write(data);
41414
41910
  return mandate2;
41415
41911
  }
41912
+ /**
41913
+ * Track a permission only if no record at its address exists yet, returning the
41914
+ * record either way. Used by `mandate attach` for addresses that were never
41915
+ * deployed from this project — e.g. a shared permission singleton the operator
41916
+ * attaches by address. Without a store record, `recordAttachment` is a no-op and
41917
+ * the permission stays invisible to `mandate prepare`/`sign`. Unlike `add`, this
41918
+ * never overwrites an existing record (so richer deploy-time metadata such as
41919
+ * `sourcePath` is preserved). For attach-only records, `txHash`/`deployedAt`
41920
+ * reflect the registration/first-tracked moment, not an on-chain deployment.
41921
+ */
41922
+ ensureTracked(mandate2) {
41923
+ const existing = this.read().mandates.find(
41924
+ (m) => m.address.toLowerCase() === mandate2.address.toLowerCase()
41925
+ );
41926
+ return existing ?? this.add(mandate2);
41927
+ }
41416
41928
  /** Update mutable metadata fields on a tracked mandate (name, sourcePath, artifactPath). */
41417
41929
  update(addressOrName, patch) {
41418
41930
  const data = this.read();
@@ -42059,6 +42571,14 @@ function publicClientFor(project) {
42059
42571
  transport: http(getRpcUrl(project.chainId))
42060
42572
  }).extend(publicActions);
42061
42573
  }
42574
+ function knownTemplateLabel(chainId, address) {
42575
+ try {
42576
+ const known = getSailDeployment(chainId).knownTemplates ?? [];
42577
+ return known.find((t) => t.address.toLowerCase() === address.toLowerCase())?.label;
42578
+ } catch {
42579
+ return void 0;
42580
+ }
42581
+ }
42062
42582
  async function mandateDeploy(options) {
42063
42583
  const project = requireProject();
42064
42584
  const channel = await createSigningChannel(process.cwd());
@@ -42528,7 +43048,14 @@ async function runAttach(project, channel, options) {
42528
43048
  label,
42529
43049
  json
42530
43050
  );
42531
- if (tracked) store.recordAttachment(mandateAddress, { sma, txHash });
43051
+ store.ensureTracked({
43052
+ name: label,
43053
+ address: mandateAddress,
43054
+ txHash,
43055
+ chainId: project.chainId,
43056
+ deployedAt: (/* @__PURE__ */ new Date()).toISOString()
43057
+ });
43058
+ store.recordAttachment(mandateAddress, { sma, txHash });
42532
43059
  emit(json, () => {
42533
43060
  }, {
42534
43061
  status: "ok",
@@ -42542,7 +43069,14 @@ async function runAttachBatch(project, channel, options, sma, store) {
42542
43069
  announceSigningUrl(json);
42543
43070
  const txHash = await attachBatchToSma(project, channel, publicClient, sma, permissions, json);
42544
43071
  for (const permission of permissions) {
42545
- if (store.find(permission)) store.recordAttachment(permission, { sma, txHash });
43072
+ store.ensureTracked({
43073
+ name: knownTemplateLabel(project.chainId, permission) ?? permission,
43074
+ address: permission,
43075
+ txHash,
43076
+ chainId: project.chainId,
43077
+ deployedAt: (/* @__PURE__ */ new Date()).toISOString()
43078
+ });
43079
+ store.recordAttachment(permission, { sma, txHash });
42546
43080
  }
42547
43081
  emit(json, () => {
42548
43082
  }, {
@@ -43138,14 +43672,37 @@ async function trackedPermissionsFor(account2, chainId, kernel) {
43138
43672
  };
43139
43673
  });
43140
43674
  const onChain = kernel ? await fetchOnChainPermissions(account2.safe, chainId, kernel) : null;
43141
- if (onChain !== null) {
43142
- for (const p of local) {
43143
- if (p.registeredOnSma && !onChain.has(p.address.toLowerCase())) {
43144
- p.revokedOnChain = true;
43145
- }
43675
+ if (onChain === null) return local;
43676
+ return mergeOnChainPermissions(local, onChain, knownTemplateLabeler(chainId));
43677
+ }
43678
+ function mergeOnChainPermissions(local, onChain, labelFor = () => void 0) {
43679
+ for (const p of local) {
43680
+ if (p.registeredOnSma && !onChain.has(p.address.toLowerCase())) {
43681
+ p.revokedOnChain = true;
43682
+ }
43683
+ }
43684
+ const localAddrs = new Set(local.map((p) => p.address.toLowerCase()));
43685
+ const extra = [];
43686
+ for (const addr of onChain) {
43687
+ if (!localAddrs.has(addr)) {
43688
+ extra.push({
43689
+ address: addr,
43690
+ label: labelFor(addr) ?? `permission ${addr.slice(0, 10)}\u2026`,
43691
+ registeredOnSma: true
43692
+ });
43693
+ }
43694
+ }
43695
+ return [...local, ...extra];
43696
+ }
43697
+ function knownTemplateLabeler(chainId) {
43698
+ const map = /* @__PURE__ */ new Map();
43699
+ try {
43700
+ for (const t of getSailDeployment(chainId).knownTemplates ?? []) {
43701
+ map.set(t.address.toLowerCase(), t.label);
43146
43702
  }
43703
+ } catch {
43147
43704
  }
43148
- return local;
43705
+ return (addr) => map.get(addr.toLowerCase());
43149
43706
  }
43150
43707
  function printNoPermissionsGuidance() {
43151
43708
  console.log(
@@ -43267,8 +43824,451 @@ ${unregistered.length} permission(s) are not yet registered on this SMA. Initiat
43267
43824
  \u2713 Saved to .sail/mandate.json \u2014 agent is ready to run.`);
43268
43825
  }
43269
43826
 
43270
- // src/commands/mandate-simulate.ts
43827
+ // src/commands/mandate-configure.ts
43271
43828
  var import_node_fs15 = require("node:fs");
43829
+ var import_node_path13 = require("node:path");
43830
+
43831
+ // ../sdk/dist/templates/boundedSwap.js
43832
+ init_esm2();
43833
+ var ABI = [
43834
+ { name: "routers", type: "address[]" },
43835
+ { name: "tokensIn", type: "address[]" },
43836
+ { name: "tokensOut", type: "address[]" },
43837
+ { name: "maxAmountPerTx", type: "uint256" },
43838
+ { name: "maxSlippageBps", type: "uint256" },
43839
+ { name: "priceOracle", type: "address" },
43840
+ { name: "maxPriceAgeSec", type: "uint256" }
43841
+ ];
43842
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
43843
+ var boundedSwapTemplate = {
43844
+ name: "SharedBoundedSwapPermission",
43845
+ address: "0x0000000000000000000000000000000000000000",
43846
+ encoder: {
43847
+ encode(params) {
43848
+ return encodeAbiParameters(ABI, [
43849
+ params.routers,
43850
+ params.tokensIn,
43851
+ params.tokensOut,
43852
+ params.maxAmountPerTx,
43853
+ BigInt(params.maxSlippageBps),
43854
+ params.priceOracle,
43855
+ BigInt(params.maxPriceAgeSec)
43856
+ ]);
43857
+ },
43858
+ decode(data) {
43859
+ const decoded = decodeAbiParameters(ABI, data);
43860
+ return {
43861
+ routers: [...decoded[0]],
43862
+ tokensIn: [...decoded[1]],
43863
+ tokensOut: [...decoded[2]],
43864
+ maxAmountPerTx: decoded[3],
43865
+ maxSlippageBps: Number(decoded[4]),
43866
+ priceOracle: decoded[5],
43867
+ maxPriceAgeSec: Number(decoded[6])
43868
+ };
43869
+ }
43870
+ },
43871
+ explainer: {
43872
+ explain(params) {
43873
+ const warnings = [];
43874
+ if (params.maxSlippageBps > 100) {
43875
+ warnings.push(`High slippage tolerance: ${params.maxSlippageBps / 100}%`);
43876
+ }
43877
+ if (params.priceOracle === ZERO_ADDRESS) {
43878
+ warnings.push("No price oracle configured \u2014 swaps are not checked against a reference price");
43879
+ }
43880
+ return {
43881
+ templateName: "SharedBoundedSwapPermission",
43882
+ humanReadable: [
43883
+ `Maximum input per swap: ${params.maxAmountPerTx.toString()} (input-token base units)`,
43884
+ `Maximum slippage: ${params.maxSlippageBps / 100}%`,
43885
+ `Allowed routers: ${params.routers.join(", ")}`,
43886
+ `Allowed input tokens: ${params.tokensIn.join(", ")}`,
43887
+ `Allowed output tokens: ${params.tokensOut.join(", ")}`,
43888
+ params.priceOracle === ZERO_ADDRESS ? "Price oracle: none" : `Price oracle: ${params.priceOracle} (max age ${params.maxPriceAgeSec}s)`
43889
+ ],
43890
+ warnings
43891
+ };
43892
+ }
43893
+ }
43894
+ };
43895
+
43896
+ // src/commands/mandate-configure.ts
43897
+ init_esm2();
43898
+ var TEMPLATE_REGISTRY = {
43899
+ SwapPermission: {
43900
+ label: "Bounded Swap (Uniswap V3)",
43901
+ bigintFields: ["maxAmountPerTx"],
43902
+ encode: (raw) => boundedSwapTemplate.encoder.encode(coerceSwapParams(raw)),
43903
+ decode: (blob) => {
43904
+ const p = boundedSwapTemplate.encoder.decode(blob);
43905
+ return {
43906
+ routers: p.routers,
43907
+ tokensIn: p.tokensIn,
43908
+ tokensOut: p.tokensOut,
43909
+ maxAmountPerTx: p.maxAmountPerTx.toString(),
43910
+ maxSlippageBps: p.maxSlippageBps,
43911
+ priceOracle: p.priceOracle,
43912
+ maxPriceAgeSec: p.maxPriceAgeSec
43913
+ };
43914
+ }
43915
+ }
43916
+ };
43917
+ function asAddressArray(v, field) {
43918
+ if (!Array.isArray(v)) throw new Error(`${field}: expected an array of addresses`);
43919
+ return v.map((x, i) => {
43920
+ if (typeof x !== "string" || !isAddress(x, { strict: false })) {
43921
+ throw new Error(`${field}[${i}]: invalid address "${String(x)}"`);
43922
+ }
43923
+ return getAddress(x);
43924
+ });
43925
+ }
43926
+ function asAddress(v, field) {
43927
+ if (typeof v !== "string" || !isAddress(v, { strict: false })) {
43928
+ throw new Error(`${field}: invalid address "${String(v)}"`);
43929
+ }
43930
+ return getAddress(v);
43931
+ }
43932
+ function asUint(v, field) {
43933
+ if (v === void 0 || v === null) throw new Error(`${field}: missing`);
43934
+ try {
43935
+ return BigInt(typeof v === "string" || typeof v === "number" ? v : String(v));
43936
+ } catch {
43937
+ throw new Error(`${field}: expected an integer, got "${String(v)}"`);
43938
+ }
43939
+ }
43940
+ function asInt(v, field) {
43941
+ const n = asUint(v, field);
43942
+ return Number(n);
43943
+ }
43944
+ function coerceSwapParams(raw) {
43945
+ return {
43946
+ routers: asAddressArray(raw.routers, "routers"),
43947
+ tokensIn: asAddressArray(raw.tokensIn, "tokensIn"),
43948
+ tokensOut: asAddressArray(raw.tokensOut, "tokensOut"),
43949
+ maxAmountPerTx: asUint(raw.maxAmountPerTx, "maxAmountPerTx"),
43950
+ maxSlippageBps: asInt(raw.maxSlippageBps, "maxSlippageBps"),
43951
+ priceOracle: asAddress(raw.priceOracle, "priceOracle"),
43952
+ maxPriceAgeSec: asInt(raw.maxPriceAgeSec, "maxPriceAgeSec")
43953
+ };
43954
+ }
43955
+ function requireProject2() {
43956
+ if (!ProjectContext.exists()) {
43957
+ console.log('No Sailor project found. Run "sailor init" first.');
43958
+ process.exit(1);
43959
+ }
43960
+ return new ProjectContext();
43961
+ }
43962
+ function fail2(err, json = false) {
43963
+ const msg = err instanceof Error ? err.message : String(err);
43964
+ emit(json, () => console.error(`
43965
+ Mandate configure failed: ${msg}`), {
43966
+ status: "error",
43967
+ error: msg
43968
+ });
43969
+ process.exit(1);
43970
+ }
43971
+ function publicClientFor2(project) {
43972
+ return createPublicClient({
43973
+ chain: getChainById(project.chainId),
43974
+ transport: http(getRpcUrl(project.chainId))
43975
+ }).extend(publicActions);
43976
+ }
43977
+ function announceSigningUrl2(json) {
43978
+ const url = signingPageUrl(projectPort(process.cwd()));
43979
+ if (json) {
43980
+ process.stdout.write(`${JSON.stringify({ status: "waiting_for_signature", url })}
43981
+ `);
43982
+ } else {
43983
+ console.log(`
43984
+ \u2192 Open the Sailor dashboard to approve signing requests:
43985
+ ${url}
43986
+ `);
43987
+ }
43988
+ }
43989
+ function resolveBlob(options) {
43990
+ const hasParams = options.params !== void 0;
43991
+ const hasArgsFile = options.argsFile !== void 0;
43992
+ if (hasParams && hasArgsFile) {
43993
+ throw new Error("Provide EITHER --params <hex> OR --args-file <path>, not both.");
43994
+ }
43995
+ if (!hasParams && !hasArgsFile) {
43996
+ throw new Error(
43997
+ "Provide the config blob as --params <0x-hex>, or as --args-file <path> paired with --template <Name>."
43998
+ );
43999
+ }
44000
+ if (hasParams) {
44001
+ const raw2 = options.params.trim();
44002
+ if (!isHex(raw2) || raw2.length <= 2) {
44003
+ throw new Error(`--params must be 0x-prefixed hex; got "${options.params}".`);
44004
+ }
44005
+ return { blob: raw2, via: "params" };
44006
+ }
44007
+ const templateName = options.template;
44008
+ if (!templateName) {
44009
+ throw new Error("--args-file requires --template <Name> (e.g. SwapPermission).");
44010
+ }
44011
+ const entry = TEMPLATE_REGISTRY[templateName];
44012
+ if (!entry) {
44013
+ throw new Error(
44014
+ `Unknown --template "${templateName}". Known: ${Object.keys(TEMPLATE_REGISTRY).join(", ")}. Pass a pre-encoded blob with --params for any other template.`
44015
+ );
44016
+ }
44017
+ const argsFilePath = (0, import_node_path13.resolve)(options.argsFile);
44018
+ let raw;
44019
+ try {
44020
+ raw = (0, import_node_fs15.readFileSync)(argsFilePath, "utf8").trim();
44021
+ } catch {
44022
+ throw new Error(`Cannot read --args-file: ${argsFilePath}`);
44023
+ }
44024
+ let parsed;
44025
+ try {
44026
+ parsed = JSON.parse(raw);
44027
+ } catch (err) {
44028
+ throw new Error(`--args-file is not valid JSON: ${err.message}`);
44029
+ }
44030
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
44031
+ throw new Error("--args-file must contain a JSON object of template params.");
44032
+ }
44033
+ const blob = entry.encode(parsed);
44034
+ return { blob, via: `template:${templateName}` };
44035
+ }
44036
+ async function mandateConfigure(options) {
44037
+ const project = requireProject2();
44038
+ const channel = await createSigningChannel(process.cwd());
44039
+ try {
44040
+ await channel.start();
44041
+ await runConfigure(project, channel, options);
44042
+ } catch (err) {
44043
+ fail2(err, options.json);
44044
+ } finally {
44045
+ channel.stop();
44046
+ }
44047
+ }
44048
+ async function runConfigure(project, channel, options) {
44049
+ const json = !!options.json;
44050
+ const say = (fn) => {
44051
+ if (!json) fn();
44052
+ };
44053
+ if (!isAddress(options.sma, { strict: false })) {
44054
+ throw new Error(`Invalid --sma address: ${options.sma}`);
44055
+ }
44056
+ if (!isAddress(options.address, { strict: false })) {
44057
+ throw new Error(
44058
+ `--address must be a deployed shared-template singleton address: ${options.address}`
44059
+ );
44060
+ }
44061
+ const sma = getAddress(options.sma);
44062
+ const singleton = getAddress(options.address);
44063
+ const { blob, via } = resolveBlob(options);
44064
+ const publicClient = publicClientFor2(project);
44065
+ const registered = await publicClient.readContract({
44066
+ address: project.contracts.kernel,
44067
+ abi: SailKernelAbi,
44068
+ functionName: "registered",
44069
+ args: [sma]
44070
+ });
44071
+ if (!registered) {
44072
+ throw new Error(`SMA ${sma} is not registered with SailKernel; cannot configure a permission for it.`);
44073
+ }
44074
+ const kernelConfig = await publicClient.readContract({
44075
+ address: project.contracts.kernel,
44076
+ abi: SailKernelAbi,
44077
+ functionName: "configs",
44078
+ args: [sma]
44079
+ });
44080
+ const permissionSigner = kernelConfig[0];
44081
+ if (!permissionSigner || permissionSigner === getAddress("0x0000000000000000000000000000000000000000")) {
44082
+ throw new Error(`SMA ${sma} has no on-chain permissionSigner; cannot configure.`);
44083
+ }
44084
+ const alreadyConfigured = await publicClient.readContract({
44085
+ address: singleton,
44086
+ abi: ConfigurablePermissionAbi,
44087
+ functionName: "isConfigured",
44088
+ args: [sma]
44089
+ });
44090
+ if (alreadyConfigured && !options.force) {
44091
+ say(
44092
+ () => console.log(
44093
+ `
44094
+ \u2713 ${singleton} is already configured for ${sma} (isConfigured == true).
44095
+ Re-run with --force to overwrite the current bounds.`
44096
+ )
44097
+ );
44098
+ emit(
44099
+ json,
44100
+ () => {
44101
+ },
44102
+ { status: "ok", alreadyConfigured: true, singleton, sma, chainId: project.chainId }
44103
+ );
44104
+ return;
44105
+ }
44106
+ const nonce = await publicClient.readContract({
44107
+ address: singleton,
44108
+ abi: ConfigurablePermissionAbi,
44109
+ functionName: "configNonces",
44110
+ args: [sma]
44111
+ });
44112
+ say(() => {
44113
+ console.log(`
44114
+ configure ${singleton}`);
44115
+ console.log(` SMA: ${sma}`);
44116
+ console.log(` permissionSigner: ${permissionSigner} (must sign in the browser \u2014 owner tx)`);
44117
+ console.log(` current nonce: ${nonce}`);
44118
+ console.log(` already set: ${alreadyConfigured ? "yes (--force will overwrite)" : "no"}`);
44119
+ console.log(` config blob: ${blob} (via ${via}, ${Math.floor((blob.length - 2) / 2)} bytes)`);
44120
+ });
44121
+ const configureDirectData = encodeFunctionData({
44122
+ abi: ConfigurablePermissionAbi,
44123
+ functionName: "configureDirect",
44124
+ args: [sma, blob]
44125
+ });
44126
+ say(() => console.log(`
44127
+ Pre-flight (eth_call of configureDirect, no gas)\u2026`));
44128
+ try {
44129
+ await publicClient.simulateContract({
44130
+ address: singleton,
44131
+ abi: ConfigurablePermissionAbi,
44132
+ functionName: "configureDirect",
44133
+ args: [sma, blob],
44134
+ account: permissionSigner
44135
+ });
44136
+ } catch (err) {
44137
+ const ce = getContractError(err, {
44138
+ abi: ConfigurablePermissionAbi,
44139
+ address: singleton,
44140
+ args: [sma, blob],
44141
+ functionName: "configureDirect"
44142
+ });
44143
+ const reason = ce?.message ?? err?.message ?? String(err);
44144
+ throw new Error(
44145
+ `Pre-flight reverted \u2014 the config blob is invalid for ${singleton} on ${sma}.
44146
+ Revert: ${reason}
44147
+ This is the encoding gotcha (flat params vs wrapped struct) or an internal bound check. Re-encode per the template's _applyConfig tuple and retry.`
44148
+ );
44149
+ }
44150
+ say(() => console.log("\u2713 pre-flight passed (configureDirect would succeed)."));
44151
+ let decoded;
44152
+ if (options.template && TEMPLATE_REGISTRY[options.template]) {
44153
+ try {
44154
+ decoded = TEMPLATE_REGISTRY[options.template].decode(blob);
44155
+ say(() => {
44156
+ console.log("\nDecoded bounds (what the singleton will store):");
44157
+ for (const [k, v] of Object.entries(decoded)) {
44158
+ const display = Array.isArray(v) ? v.join(", ") : String(v);
44159
+ console.log(` ${k}: ${display}`);
44160
+ }
44161
+ });
44162
+ } catch {
44163
+ }
44164
+ }
44165
+ if (options.simulateOnly) {
44166
+ emit(
44167
+ json,
44168
+ () => {
44169
+ console.log("\n--simulate-only: stopping after pre-flight (no signing, no gas).");
44170
+ },
44171
+ {
44172
+ status: "ok",
44173
+ simulateOnly: true,
44174
+ singleton,
44175
+ sma,
44176
+ permissionSigner,
44177
+ nonce: nonce.toString(),
44178
+ alreadyConfigured,
44179
+ blob,
44180
+ blobBytes: Math.floor((blob.length - 2) / 2),
44181
+ decoded,
44182
+ chainId: project.chainId
44183
+ }
44184
+ );
44185
+ return;
44186
+ }
44187
+ const label = options.label ?? (options.template ?? "shared-template");
44188
+ announceSigningUrl2(json);
44189
+ say(
44190
+ () => console.log(
44191
+ `Pushing configure request \u2014 the mandate signer (${permissionSigner}) must approve in the browser\u2026`
44192
+ )
44193
+ );
44194
+ const response = await channel.requestSignature({
44195
+ type: "transaction",
44196
+ kind: "arbitrary-tx",
44197
+ title: `Configure "${label}"`,
44198
+ description: `Write per-account bounds on the shared permission ${singleton}.
44199
+ You (the mandate signer) send the transaction \u2014 configureDirect requires msg.sender to be the permissionSigner.`,
44200
+ chainId: project.chainId,
44201
+ to: singleton,
44202
+ data: configureDirectData,
44203
+ details: [
44204
+ { label: "SMA", value: sma },
44205
+ { label: "Singleton", value: singleton },
44206
+ { label: "Template", value: options.template ?? "(raw blob)" },
44207
+ { label: "Mandate signer", value: permissionSigner },
44208
+ { label: "Config blob (bytes)", value: String(Math.floor((blob.length - 2) / 2)) },
44209
+ ...decoded ? Object.entries(decoded).map(([k, v]) => ({
44210
+ label: k,
44211
+ value: Array.isArray(v) ? v.join(", ") : String(v)
44212
+ })) : []
44213
+ ]
44214
+ });
44215
+ if (response.status === "rejected") {
44216
+ throw new Error(`User rejected configure: ${response.reason ?? "no reason given"}`);
44217
+ }
44218
+ if (response.status !== "signed") {
44219
+ throw new Error(`Expected a signed transaction, got: ${response.status}`);
44220
+ }
44221
+ say(() => console.log("Waiting for confirmation\u2026"));
44222
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: response.txHash });
44223
+ if (receipt.status !== "success") {
44224
+ throw new Error(`configureDirect transaction failed (tx ${response.txHash})`);
44225
+ }
44226
+ const configuredNow = await publicClient.readContract({
44227
+ address: singleton,
44228
+ abi: ConfigurablePermissionAbi,
44229
+ functionName: "isConfigured",
44230
+ args: [sma]
44231
+ });
44232
+ if (!configuredNow) {
44233
+ throw new Error(
44234
+ `Tx ${response.txHash} mined, but isConfigured(${sma}) is still false. Verify on-chain.`
44235
+ );
44236
+ }
44237
+ say(() => console.log("\u2713", `Configured ${singleton} for ${sma} (isConfigured == true).`));
44238
+ appendActivity({
44239
+ ts: nowIso(),
44240
+ actor: "owner",
44241
+ type: "permission_configured",
44242
+ permission: singleton,
44243
+ name: label,
44244
+ sma,
44245
+ txHash: response.txHash,
44246
+ chainId: project.chainId
44247
+ });
44248
+ emit(
44249
+ json,
44250
+ () => {
44251
+ console.log(
44252
+ `
44253
+ Next: prove it accepts/rejects the right calls before dispatching:
44254
+ sailor mandate simulate --address ${singleton} --sma ${sma} --calls ./probe.json`
44255
+ );
44256
+ },
44257
+ {
44258
+ status: "ok",
44259
+ singleton,
44260
+ sma,
44261
+ template: options.template,
44262
+ permissionSigner,
44263
+ txHash: response.txHash,
44264
+ blob,
44265
+ chainId: project.chainId
44266
+ }
44267
+ );
44268
+ }
44269
+
44270
+ // src/commands/mandate-simulate.ts
44271
+ var import_node_fs16 = require("node:fs");
43272
44272
  init_esm2();
43273
44273
  function parseExpect(raw, where) {
43274
44274
  if (raw === void 0) return void 0;
@@ -43284,7 +44284,7 @@ function resolveSampleCalls(options) {
43284
44284
  if (options.calls) {
43285
44285
  let raw;
43286
44286
  try {
43287
- raw = JSON.parse((0, import_node_fs15.readFileSync)(options.calls, "utf8"));
44287
+ raw = JSON.parse((0, import_node_fs16.readFileSync)(options.calls, "utf8"));
43288
44288
  } catch (err) {
43289
44289
  throw new Error(`Could not read --calls file "${options.calls}": ${err.message}`);
43290
44290
  }
@@ -43388,6 +44388,7 @@ async function mandateSimulate(options) {
43388
44388
  const [probe, codeCheck] = await Promise.all([
43389
44389
  probePermissionForCall({
43390
44390
  publicClient: pc,
44391
+ kernel: project.contracts.kernel,
43391
44392
  permission,
43392
44393
  account: account2,
43393
44394
  manager,
@@ -43500,7 +44501,7 @@ async function mandateSimulate(options) {
43500
44501
  }
43501
44502
 
43502
44503
  // src/commands/rotate-signer.ts
43503
- var import_node_fs16 = require("node:fs");
44504
+ var import_node_fs17 = require("node:fs");
43504
44505
  init_esm2();
43505
44506
  var PENDING_REATTACH_FILE = ["state", "pending-reattach.json"];
43506
44507
  async function rotateSigner(options) {
@@ -43886,7 +44887,7 @@ ensure the agent that signs dispatches holds this key.`
43886
44887
  const keystore = await keyring.exportKeystore(password);
43887
44888
  writeJsonFile(target, keystore, 384);
43888
44889
  const perManagerPath = managerKeystorePath(keyring.address);
43889
- (0, import_node_fs16.mkdirSync)(sailPath("keys", "managers"), { recursive: true });
44890
+ (0, import_node_fs17.mkdirSync)(sailPath("keys", "managers"), { recursive: true });
43890
44891
  writeJsonFile(perManagerPath, keystore, 384);
43891
44892
  say(
43892
44893
  () => console.log(
@@ -43898,7 +44899,7 @@ ensure the agent that signs dispatches holds this key.`
43898
44899
  function promoteManagerKeystore(newManager, say) {
43899
44900
  const stored = readJsonFile(managerKeystorePath(newManager));
43900
44901
  if (!stored) return;
43901
- (0, import_node_fs16.mkdirSync)(sailPath("keys", "managers"), { recursive: true });
44902
+ (0, import_node_fs17.mkdirSync)(sailPath("keys", "managers"), { recursive: true });
43902
44903
  const activeTarget = keyPath("manager");
43903
44904
  const displaced = readJsonFile(activeTarget);
43904
44905
  if (displaced?.address) {
@@ -43950,7 +44951,7 @@ function writePending(pending) {
43950
44951
  }
43951
44952
  function clearPending() {
43952
44953
  try {
43953
- (0, import_node_fs16.rmSync)(sailPath(...PENDING_REATTACH_FILE), { force: true });
44954
+ (0, import_node_fs17.rmSync)(sailPath(...PENDING_REATTACH_FILE), { force: true });
43954
44955
  } catch {
43955
44956
  }
43956
44957
  }
@@ -44049,12 +45050,12 @@ function ownerShow(options) {
44049
45050
  }
44050
45051
 
44051
45052
  // src/commands/run.ts
44052
- var import_node_fs17 = __toESM(require("node:fs"), 1);
44053
- var import_node_path13 = __toESM(require("node:path"), 1);
45053
+ var import_node_fs18 = __toESM(require("node:fs"), 1);
45054
+ var import_node_path14 = __toESM(require("node:path"), 1);
44054
45055
  var import_node_url = require("node:url");
44055
45056
  init_esm2();
44056
45057
  var DEFAULT_INTERVAL_SEC = 60;
44057
- var sleep2 = (ms) => new Promise((resolve3) => setTimeout(resolve3, ms));
45058
+ var sleep2 = (ms) => new Promise((resolve4) => setTimeout(resolve4, ms));
44058
45059
  var ERC20_READ_ABI = [
44059
45060
  {
44060
45061
  type: "function",
@@ -44084,7 +45085,7 @@ var ERC20_READ_ABI = [
44084
45085
  function loadAgentData(filePath) {
44085
45086
  if (!filePath) return {};
44086
45087
  try {
44087
- const parsed = JSON.parse(import_node_fs17.default.readFileSync(filePath, "utf-8"));
45088
+ const parsed = JSON.parse(import_node_fs18.default.readFileSync(filePath, "utf-8"));
44088
45089
  return parsed && typeof parsed === "object" ? parsed : {};
44089
45090
  } catch {
44090
45091
  return {};
@@ -44093,8 +45094,8 @@ function loadAgentData(filePath) {
44093
45094
  async function loadAgent() {
44094
45095
  const candidates = ["src/agent.ts", "src/agent.js", "dist/agent.js", "dist/src/agent.js"];
44095
45096
  for (const rel of candidates) {
44096
- const abs = import_node_path13.default.join(process.cwd(), rel);
44097
- if (!import_node_fs17.default.existsSync(abs)) continue;
45097
+ const abs = import_node_path14.default.join(process.cwd(), rel);
45098
+ if (!import_node_fs18.default.existsSync(abs)) continue;
44098
45099
  let mod2;
44099
45100
  if (abs.endsWith(".ts")) {
44100
45101
  const { tsImport } = await import("tsx/esm/api");
@@ -44347,6 +45348,8 @@ Configure the chain in the SDK chain registry or set KERNEL_ADDRESS in .sail/.en
44347
45348
  } else {
44348
45349
  permission = await resolvePermissionForCall({
44349
45350
  publicClient,
45351
+ kernel,
45352
+ // narrowed: runCommand validates kernel before runTick runs
44350
45353
  account: accountAddr,
44351
45354
  manager: agentManager.address,
44352
45355
  call: firstCall,
@@ -44389,7 +45392,7 @@ Configure the chain in the SDK chain registry or set KERNEL_ADDRESS in .sail/.en
44389
45392
  if (isConjunctive && result.txHash) {
44390
45393
  try {
44391
45394
  await publicClient.waitForTransactionReceipt({ hash: result.txHash, timeout: 3e4 });
44392
- await new Promise((resolve3) => setTimeout(resolve3, 500));
45395
+ await new Promise((resolve4) => setTimeout(resolve4, 500));
44393
45396
  } catch {
44394
45397
  }
44395
45398
  }
@@ -44522,7 +45525,7 @@ async function scan(options) {
44522
45525
  args: [address]
44523
45526
  })
44524
45527
  ]);
44525
- const [permissionSigner, manager, , sessionActive] = config;
45528
+ const [permissionSigner, manager, , , sessionActive] = config;
44526
45529
  smas.push({ address, registered: true, manager, permissionSigner, sessionActive, mandates });
44527
45530
  } catch (err) {
44528
45531
  smas.push({
@@ -44570,9 +45573,9 @@ async function scan(options) {
44570
45573
 
44571
45574
  // src/commands/service.ts
44572
45575
  var import_node_child_process2 = require("node:child_process");
44573
- var import_node_fs18 = __toESM(require("node:fs"), 1);
45576
+ var import_node_fs19 = __toESM(require("node:fs"), 1);
44574
45577
  var import_node_os = __toESM(require("node:os"), 1);
44575
- var import_node_path14 = __toESM(require("node:path"), 1);
45578
+ var import_node_path15 = __toESM(require("node:path"), 1);
44576
45579
  function sanitizeName(raw) {
44577
45580
  const s = raw.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
44578
45581
  return s || "agent";
@@ -44691,21 +45694,21 @@ function buildWindowsTaskXml(cfg) {
44691
45694
  `;
44692
45695
  }
44693
45696
  function isTccProtected(projectDir, home = import_node_os.default.homedir()) {
44694
- const rel = import_node_path14.default.relative(home, import_node_path14.default.resolve(projectDir));
44695
- if (rel.startsWith("..") || import_node_path14.default.isAbsolute(rel)) return false;
44696
- const top = rel.split(import_node_path14.default.sep)[0];
45697
+ const rel = import_node_path15.default.relative(home, import_node_path15.default.resolve(projectDir));
45698
+ if (rel.startsWith("..") || import_node_path15.default.isAbsolute(rel)) return false;
45699
+ const top = rel.split(import_node_path15.default.sep)[0];
44697
45700
  return ["Desktop", "Documents", "Downloads"].includes(top ?? "");
44698
45701
  }
44699
45702
  function resolveCliEntry() {
44700
45703
  try {
44701
- return import_node_fs18.default.realpathSync(process.argv[1]);
45704
+ return import_node_fs19.default.realpathSync(process.argv[1]);
44702
45705
  } catch {
44703
- return import_node_path14.default.resolve(process.argv[1]);
45706
+ return import_node_path15.default.resolve(process.argv[1]);
44704
45707
  }
44705
45708
  }
44706
45709
  function resolveProjectDir(explicit) {
44707
- const dir = import_node_path14.default.resolve(explicit ?? process.cwd());
44708
- if (!import_node_fs18.default.existsSync(import_node_path14.default.join(dir, ".sail"))) {
45710
+ const dir = import_node_path15.default.resolve(explicit ?? process.cwd());
45711
+ if (!import_node_fs19.default.existsSync(import_node_path15.default.join(dir, ".sail"))) {
44709
45712
  throw new Error(
44710
45713
  `No .sail/ found in ${dir}.
44711
45714
  Run this from your Sailor project root, or pass --project <path>. (The installer does not search parent directories \u2014 that would risk targeting the wrong project.)`
@@ -44717,7 +45720,7 @@ function passphraseReadiness(projectDir) {
44717
45720
  const account2 = (() => {
44718
45721
  try {
44719
45722
  return JSON.parse(
44720
- import_node_fs18.default.readFileSync(import_node_path14.default.join(projectDir, ".sail", "account.json"), "utf-8")
45723
+ import_node_fs19.default.readFileSync(import_node_path15.default.join(projectDir, ".sail", "account.json"), "utf-8")
44721
45724
  );
44722
45725
  } catch {
44723
45726
  return null;
@@ -44733,28 +45736,28 @@ function passphraseReadiness(projectDir) {
44733
45736
  } finally {
44734
45737
  process.chdir(prevCwd);
44735
45738
  }
44736
- const env = parseEnvFile(import_node_path14.default.join(projectDir, ".sail", ".env.local"));
45739
+ const env = parseEnvFile(import_node_path15.default.join(projectDir, ".sail", ".env.local"));
44737
45740
  const passphraseInEnvFile = Boolean(env.SAIL_PASSPHRASE);
44738
45741
  return { keystorePresent, passphraseInEnvFile, ready: keystorePresent && passphraseInEnvFile };
44739
45742
  }
44740
45743
  function buildConfig(opts) {
44741
45744
  const projectDir = resolveProjectDir(opts.project);
44742
45745
  return {
44743
- projectName: sanitizeName(import_node_path14.default.basename(projectDir)),
45746
+ projectName: sanitizeName(import_node_path15.default.basename(projectDir)),
44744
45747
  projectDir,
44745
45748
  nodePath: process.execPath,
44746
45749
  cliEntry: resolveCliEntry(),
44747
- logPath: import_node_path14.default.join(projectDir, ".sail", "agent.log"),
45750
+ logPath: import_node_path15.default.join(projectDir, ".sail", "agent.log"),
44748
45751
  interval: opts.interval != null ? Number(opts.interval) : void 0,
44749
45752
  chain: opts.chain != null ? Number(opts.chain) : void 0,
44750
45753
  restartSec: 30
44751
45754
  };
44752
45755
  }
44753
45756
  function plistPath(projectName) {
44754
- return import_node_path14.default.join(import_node_os.default.homedir(), "Library", "LaunchAgents", `${launchdLabel(projectName)}.plist`);
45757
+ return import_node_path15.default.join(import_node_os.default.homedir(), "Library", "LaunchAgents", `${launchdLabel(projectName)}.plist`);
44755
45758
  }
44756
45759
  function systemdPath(projectName) {
44757
- return import_node_path14.default.join(import_node_os.default.homedir(), ".config", "systemd", "user", systemdUnitName(projectName));
45760
+ return import_node_path15.default.join(import_node_os.default.homedir(), ".config", "systemd", "user", systemdUnitName(projectName));
44758
45761
  }
44759
45762
  async function serviceInstall(opts = {}) {
44760
45763
  const cfg = buildConfig(opts);
@@ -44778,12 +45781,12 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
44778
45781
  console.warn(`\u26A0 ${msg}
44779
45782
  Proceeding because --force was given.`);
44780
45783
  }
44781
- import_node_fs18.default.mkdirSync(import_node_path14.default.dirname(cfg.logPath), { recursive: true });
45784
+ import_node_fs19.default.mkdirSync(import_node_path15.default.dirname(cfg.logPath), { recursive: true });
44782
45785
  if (platform === "darwin") {
44783
45786
  const plist = buildLaunchdPlist(cfg);
44784
45787
  const dest = plistPath(cfg.projectName);
44785
- import_node_fs18.default.mkdirSync(import_node_path14.default.dirname(dest), { recursive: true });
44786
- import_node_fs18.default.writeFileSync(dest, plist);
45788
+ import_node_fs19.default.mkdirSync(import_node_path15.default.dirname(dest), { recursive: true });
45789
+ import_node_fs19.default.writeFileSync(dest, plist);
44787
45790
  const uid2 = process.getuid?.() ?? 0;
44788
45791
  try {
44789
45792
  try {
@@ -44802,8 +45805,8 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
44802
45805
  if (platform === "linux") {
44803
45806
  const unit = buildSystemdUnit(cfg);
44804
45807
  const dest = systemdPath(cfg.projectName);
44805
- import_node_fs18.default.mkdirSync(import_node_path14.default.dirname(dest), { recursive: true });
44806
- import_node_fs18.default.writeFileSync(dest, unit);
45808
+ import_node_fs19.default.mkdirSync(import_node_path15.default.dirname(dest), { recursive: true });
45809
+ import_node_fs19.default.writeFileSync(dest, unit);
44807
45810
  try {
44808
45811
  (0, import_node_child_process2.execFileSync)("systemctl", ["--user", "daemon-reload"], { stdio: "inherit" });
44809
45812
  (0, import_node_child_process2.execFileSync)("systemctl", ["--user", "enable", "--now", systemdUnitName(cfg.projectName)], {
@@ -44817,8 +45820,8 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
44817
45820
  }
44818
45821
  if (platform === "win32") {
44819
45822
  const xml = buildWindowsTaskXml(cfg);
44820
- const dest = import_node_path14.default.join(import_node_os.default.tmpdir(), `${windowsTaskName(cfg.projectName)}.xml`);
44821
- import_node_fs18.default.writeFileSync(dest, xml, "utf-8");
45823
+ const dest = import_node_path15.default.join(import_node_os.default.tmpdir(), `${windowsTaskName(cfg.projectName)}.xml`);
45824
+ import_node_fs19.default.writeFileSync(dest, xml, "utf-8");
44822
45825
  try {
44823
45826
  (0, import_node_child_process2.execFileSync)(
44824
45827
  "schtasks",
@@ -44829,7 +45832,7 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
44829
45832
  throw new Error(`schtasks /Create failed: ${err.message}`);
44830
45833
  } finally {
44831
45834
  try {
44832
- import_node_fs18.default.rmSync(dest, { force: true });
45835
+ import_node_fs19.default.rmSync(dest, { force: true });
44833
45836
  } catch {
44834
45837
  }
44835
45838
  }
@@ -44855,14 +45858,14 @@ function okInstall(cfg, unit) {
44855
45858
  );
44856
45859
  }
44857
45860
  async function serviceStatus(opts = {}) {
44858
- const projectName = sanitizeName(import_node_path14.default.basename(resolveProjectDir(opts.project)));
45861
+ const projectName = sanitizeName(import_node_path15.default.basename(resolveProjectDir(opts.project)));
44859
45862
  const platform = process.platform;
44860
45863
  let installed = false;
44861
45864
  let running = false;
44862
45865
  let detail = "";
44863
45866
  try {
44864
45867
  if (platform === "darwin") {
44865
- installed = import_node_fs18.default.existsSync(plistPath(projectName));
45868
+ installed = import_node_fs19.default.existsSync(plistPath(projectName));
44866
45869
  const uid2 = process.getuid?.() ?? 0;
44867
45870
  try {
44868
45871
  detail = (0, import_node_child_process2.execFileSync)("launchctl", ["print", `gui/${uid2}/${launchdLabel(projectName)}`], {
@@ -44874,7 +45877,7 @@ async function serviceStatus(opts = {}) {
44874
45877
  } catch {
44875
45878
  }
44876
45879
  } else if (platform === "linux") {
44877
- installed = import_node_fs18.default.existsSync(systemdPath(projectName));
45880
+ installed = import_node_fs19.default.existsSync(systemdPath(projectName));
44878
45881
  try {
44879
45882
  detail = (0, import_node_child_process2.execFileSync)("systemctl", ["--user", "is-active", systemdUnitName(projectName)], {
44880
45883
  encoding: "utf-8",
@@ -44910,7 +45913,7 @@ async function serviceStatus(opts = {}) {
44910
45913
  );
44911
45914
  }
44912
45915
  async function serviceStop(opts = {}) {
44913
- const projectName = sanitizeName(import_node_path14.default.basename(resolveProjectDir(opts.project)));
45916
+ const projectName = sanitizeName(import_node_path15.default.basename(resolveProjectDir(opts.project)));
44914
45917
  const platform = process.platform;
44915
45918
  if (platform === "darwin") {
44916
45919
  const uid2 = process.getuid?.() ?? 0;
@@ -44929,7 +45932,7 @@ async function serviceStop(opts = {}) {
44929
45932
  });
44930
45933
  }
44931
45934
  async function serviceUninstall(opts = {}) {
44932
- const projectName = sanitizeName(import_node_path14.default.basename(resolveProjectDir(opts.project)));
45935
+ const projectName = sanitizeName(import_node_path15.default.basename(resolveProjectDir(opts.project)));
44933
45936
  const platform = process.platform;
44934
45937
  if (platform === "darwin") {
44935
45938
  const uid2 = process.getuid?.() ?? 0;
@@ -44939,7 +45942,7 @@ async function serviceUninstall(opts = {}) {
44939
45942
  });
44940
45943
  } catch {
44941
45944
  }
44942
- import_node_fs18.default.rmSync(plistPath(projectName), { force: true });
45945
+ import_node_fs19.default.rmSync(plistPath(projectName), { force: true });
44943
45946
  } else if (platform === "linux") {
44944
45947
  try {
44945
45948
  (0, import_node_child_process2.execFileSync)("systemctl", ["--user", "disable", "--now", systemdUnitName(projectName)], {
@@ -44947,7 +45950,7 @@ async function serviceUninstall(opts = {}) {
44947
45950
  });
44948
45951
  } catch {
44949
45952
  }
44950
- import_node_fs18.default.rmSync(systemdPath(projectName), { force: true });
45953
+ import_node_fs19.default.rmSync(systemdPath(projectName), { force: true });
44951
45954
  try {
44952
45955
  (0, import_node_child_process2.execFileSync)("systemctl", ["--user", "daemon-reload"], { stdio: "ignore" });
44953
45956
  } catch {
@@ -44965,21 +45968,21 @@ async function serviceUninstall(opts = {}) {
44965
45968
  }
44966
45969
  async function serviceLogs(opts = {}) {
44967
45970
  const projectDir = resolveProjectDir(opts.project);
44968
- const logPath = import_node_path14.default.join(projectDir, ".sail", "agent.log");
44969
- if (!import_node_fs18.default.existsSync(logPath)) {
45971
+ const logPath = import_node_path15.default.join(projectDir, ".sail", "agent.log");
45972
+ if (!import_node_fs19.default.existsSync(logPath)) {
44970
45973
  console.log(`No log yet at ${logPath}. The service writes here once it runs.`);
44971
45974
  return;
44972
45975
  }
44973
45976
  if (opts.follow) {
44974
45977
  if (process.platform === "win32") {
44975
- console.log(import_node_fs18.default.readFileSync(logPath, "utf-8"));
45978
+ console.log(import_node_fs19.default.readFileSync(logPath, "utf-8"));
44976
45979
  console.log("(follow mode is not supported on Windows here \u2014 re-run to refresh)");
44977
45980
  return;
44978
45981
  }
44979
45982
  (0, import_node_child_process2.execFileSync)("tail", ["-f", logPath], { stdio: "inherit" });
44980
45983
  return;
44981
45984
  }
44982
- const lines = import_node_fs18.default.readFileSync(logPath, "utf-8").split("\n");
45985
+ const lines = import_node_fs19.default.readFileSync(logPath, "utf-8").split("\n");
44983
45986
  console.log(lines.slice(-200).join("\n"));
44984
45987
  }
44985
45988
 
@@ -45135,14 +46138,14 @@ async function sessionResume(opts = {}) {
45135
46138
  }
45136
46139
 
45137
46140
  // src/commands/station.ts
45138
- var import_node_fs19 = require("node:fs");
45139
- var import_node_path15 = require("node:path");
45140
- var RUNTIME_SERVER_FILE2 = (0, import_node_path15.join)(".sail", "runtime", "server.json");
46141
+ var import_node_fs20 = require("node:fs");
46142
+ var import_node_path16 = require("node:path");
46143
+ var RUNTIME_SERVER_FILE2 = (0, import_node_path16.join)(".sail", "runtime", "server.json");
45141
46144
  function readState(projectRoot) {
45142
- const file = (0, import_node_path15.join)(projectRoot, RUNTIME_SERVER_FILE2);
45143
- if (!(0, import_node_fs19.existsSync)(file)) return null;
46145
+ const file = (0, import_node_path16.join)(projectRoot, RUNTIME_SERVER_FILE2);
46146
+ if (!(0, import_node_fs20.existsSync)(file)) return null;
45144
46147
  try {
45145
- return JSON.parse((0, import_node_fs19.readFileSync)(file, "utf8"));
46148
+ return JSON.parse((0, import_node_fs20.readFileSync)(file, "utf8"));
45146
46149
  } catch {
45147
46150
  return null;
45148
46151
  }
@@ -45214,9 +46217,9 @@ async function stationStop(options) {
45214
46217
  }
45215
46218
  const daemon = await discoverDaemon(projectRoot);
45216
46219
  if (!daemon) {
45217
- const file = (0, import_node_path15.join)(projectRoot, RUNTIME_SERVER_FILE2);
46220
+ const file = (0, import_node_path16.join)(projectRoot, RUNTIME_SERVER_FILE2);
45218
46221
  try {
45219
- if ((0, import_node_fs19.existsSync)(file)) (0, import_node_fs19.rmSync)(file);
46222
+ if ((0, import_node_fs20.existsSync)(file)) (0, import_node_fs20.rmSync)(file);
45220
46223
  } catch {
45221
46224
  }
45222
46225
  emit(options.json, () => console.log("Station process not found; cleared stale state."), {
@@ -45232,9 +46235,9 @@ async function stationStop(options) {
45232
46235
  pid: state.pid
45233
46236
  });
45234
46237
  } catch {
45235
- const file = (0, import_node_path15.join)(projectRoot, RUNTIME_SERVER_FILE2);
46238
+ const file = (0, import_node_path16.join)(projectRoot, RUNTIME_SERVER_FILE2);
45236
46239
  try {
45237
- if ((0, import_node_fs19.existsSync)(file)) (0, import_node_fs19.rmSync)(file);
46240
+ if ((0, import_node_fs20.existsSync)(file)) (0, import_node_fs20.rmSync)(file);
45238
46241
  } catch {
45239
46242
  }
45240
46243
  emit(options.json, () => console.log("Station process not found; cleared stale state."), {
@@ -45296,9 +46299,9 @@ async function status() {
45296
46299
 
45297
46300
  // src/commands/ui.ts
45298
46301
  var import_node_child_process5 = require("node:child_process");
45299
- var import_node_fs20 = __toESM(require("node:fs"), 1);
46302
+ var import_node_fs21 = __toESM(require("node:fs"), 1);
45300
46303
  var import_node_net2 = __toESM(require("node:net"), 1);
45301
- var import_node_path16 = __toESM(require("node:path"), 1);
46304
+ var import_node_path17 = __toESM(require("node:path"), 1);
45302
46305
 
45303
46306
  // src/lib/tailscale.ts
45304
46307
  var import_node_child_process4 = require("node:child_process");
@@ -45344,12 +46347,12 @@ function tailscaleServeDown() {
45344
46347
  }
45345
46348
 
45346
46349
  // src/commands/ui.ts
45347
- var UI_STATE_FILE = import_node_path16.default.join(".sail", "runtime", "ui.json");
46350
+ var UI_STATE_FILE = import_node_path17.default.join(".sail", "runtime", "ui.json");
45348
46351
  function readState2(projectRoot) {
45349
- const file = import_node_path16.default.join(projectRoot, UI_STATE_FILE);
45350
- if (!import_node_fs20.default.existsSync(file)) return null;
46352
+ const file = import_node_path17.default.join(projectRoot, UI_STATE_FILE);
46353
+ if (!import_node_fs21.default.existsSync(file)) return null;
45351
46354
  try {
45352
- return JSON.parse(import_node_fs20.default.readFileSync(file, "utf-8"));
46355
+ return JSON.parse(import_node_fs21.default.readFileSync(file, "utf-8"));
45353
46356
  } catch {
45354
46357
  return null;
45355
46358
  }
@@ -45357,7 +46360,7 @@ function readState2(projectRoot) {
45357
46360
  function installedCliVersion() {
45358
46361
  try {
45359
46362
  const pkg = JSON.parse(
45360
- import_node_fs20.default.readFileSync(import_node_path16.default.join(packageRoot(), "package.json"), "utf-8")
46363
+ import_node_fs21.default.readFileSync(import_node_path17.default.join(packageRoot(), "package.json"), "utf-8")
45361
46364
  );
45362
46365
  return pkg.version ?? null;
45363
46366
  } catch {
@@ -45384,16 +46387,16 @@ async function warnIfVersionSkew(port) {
45384
46387
  }
45385
46388
  function waitForPort(port, timeoutMs) {
45386
46389
  const deadline = Date.now() + timeoutMs;
45387
- return new Promise((resolve3) => {
46390
+ return new Promise((resolve4) => {
45388
46391
  const attempt = () => {
45389
46392
  const socket = import_node_net2.default.connect(port, "127.0.0.1");
45390
46393
  socket.once("connect", () => {
45391
46394
  socket.destroy();
45392
- resolve3(true);
46395
+ resolve4(true);
45393
46396
  });
45394
46397
  socket.once("error", () => {
45395
46398
  socket.destroy();
45396
- if (Date.now() > deadline) resolve3(false);
46399
+ if (Date.now() > deadline) resolve4(false);
45397
46400
  else setTimeout(attempt, 150);
45398
46401
  });
45399
46402
  };
@@ -45402,16 +46405,16 @@ function waitForPort(port, timeoutMs) {
45402
46405
  }
45403
46406
  async function uiCommand(opts = {}) {
45404
46407
  const distDir = cliDistDir();
45405
- const uiDistDir = import_node_path16.default.join(packageRoot(), "packages", "ui", "dist");
45406
- const serverBundle = import_node_path16.default.resolve(distDir, "server.cjs");
46408
+ const uiDistDir = import_node_path17.default.join(packageRoot(), "packages", "ui", "dist");
46409
+ const serverBundle = import_node_path17.default.resolve(distDir, "server.cjs");
45407
46410
  const projectRoot = process.cwd();
45408
- const sailDir2 = import_node_path16.default.join(projectRoot, ".sail");
46411
+ const sailDir2 = import_node_path17.default.join(projectRoot, ".sail");
45409
46412
  const envPort = Number(process.env.PORT);
45410
46413
  const port = await findFreePort(Number.isInteger(envPort) && envPort > 0 && envPort <= 65535 ? envPort : projectPort(projectRoot));
45411
- if (!import_node_fs20.default.existsSync(serverBundle)) {
46414
+ if (!import_node_fs21.default.existsSync(serverBundle)) {
45412
46415
  throw new Error(`Server bundle not found at ${serverBundle}. Re-run the sailor build.`);
45413
46416
  }
45414
- if (!import_node_fs20.default.existsSync(import_node_path16.default.join(uiDistDir, "index.html"))) {
46417
+ if (!import_node_fs21.default.existsSync(import_node_path17.default.join(uiDistDir, "index.html"))) {
45415
46418
  throw new Error(`UI dist not found at ${uiDistDir}. Re-run the sailor build.`);
45416
46419
  }
45417
46420
  let tailnetUrl = null;
@@ -45441,10 +46444,10 @@ async function uiCommand(opts = {}) {
45441
46444
  await warnIfVersionSkew(existing.port);
45442
46445
  return;
45443
46446
  }
45444
- const runtimeDir = import_node_path16.default.join(projectRoot, ".sail", "runtime");
45445
- import_node_fs20.default.mkdirSync(runtimeDir, { recursive: true });
45446
- const logFile = import_node_path16.default.join(runtimeDir, "ui.log");
45447
- const logFd = import_node_fs20.default.openSync(logFile, "a");
46447
+ const runtimeDir = import_node_path17.default.join(projectRoot, ".sail", "runtime");
46448
+ import_node_fs21.default.mkdirSync(runtimeDir, { recursive: true });
46449
+ const logFile = import_node_path17.default.join(runtimeDir, "ui.log");
46450
+ const logFd = import_node_fs21.default.openSync(logFile, "a");
45448
46451
  const corsOrigins = [process.env.SAILOR_CORS_ORIGINS, tailnetUrl].filter(Boolean).join(",");
45449
46452
  const child = (0, import_node_child_process5.spawn)(process.execPath, [serverBundle], {
45450
46453
  detached: true,
@@ -45459,7 +46462,7 @@ async function uiCommand(opts = {}) {
45459
46462
  }
45460
46463
  });
45461
46464
  child.unref();
45462
- import_node_fs20.default.closeSync(logFd);
46465
+ import_node_fs21.default.closeSync(logFd);
45463
46466
  const READY_TIMEOUT_MS = 1e4;
45464
46467
  const deadline = Date.now() + READY_TIMEOUT_MS;
45465
46468
  let ready = false;
@@ -45473,14 +46476,14 @@ async function uiCommand(opts = {}) {
45473
46476
  if (!ready) {
45474
46477
  let tail = "";
45475
46478
  try {
45476
- tail = import_node_fs20.default.readFileSync(logFile, "utf-8").split("\n").filter(Boolean).slice(-15).join("\n");
46479
+ tail = import_node_fs21.default.readFileSync(logFile, "utf-8").split("\n").filter(Boolean).slice(-15).join("\n");
45477
46480
  } catch {
45478
46481
  }
45479
46482
  throw new Error(
45480
46483
  `Sailor UI failed to start within ${READY_TIMEOUT_MS / 1e3}s on port ${port}.` + (tail ? `
45481
46484
 
45482
46485
  Server output:
45483
- ${tail}` : ` See ${import_node_path16.default.relative(projectRoot, logFile)}.`)
46486
+ ${tail}` : ` See ${import_node_path17.default.relative(projectRoot, logFile)}.`)
45484
46487
  );
45485
46488
  }
45486
46489
  let exposed = false;
@@ -45495,8 +46498,8 @@ ${tail}` : ` See ${import_node_path16.default.relative(projectRoot, logFile)}.`)
45495
46498
  );
45496
46499
  }
45497
46500
  }
45498
- import_node_fs20.default.writeFileSync(
45499
- import_node_path16.default.join(projectRoot, UI_STATE_FILE),
46501
+ import_node_fs21.default.writeFileSync(
46502
+ import_node_path17.default.join(projectRoot, UI_STATE_FILE),
45500
46503
  JSON.stringify({ pid: child.pid, port, startedAt: (/* @__PURE__ */ new Date()).toISOString(), exposed }, null, 2)
45501
46504
  );
45502
46505
  console.log(`Sailor UI started at http://localhost:${port} (pid ${child.pid})`);
@@ -45509,7 +46512,7 @@ async function uiStatus() {
45509
46512
  console.log(`\u25CF running http://localhost:${state.port} (pid ${state.pid})`);
45510
46513
  await warnIfVersionSkew(state.port);
45511
46514
  } else {
45512
- if (state) import_node_fs20.default.rmSync(import_node_path16.default.join(process.cwd(), UI_STATE_FILE), { force: true });
46515
+ if (state) import_node_fs21.default.rmSync(import_node_path17.default.join(process.cwd(), UI_STATE_FILE), { force: true });
45513
46516
  console.log("\u25CB Sailor UI is not running");
45514
46517
  }
45515
46518
  }
@@ -45521,7 +46524,7 @@ function uiStop() {
45521
46524
  return;
45522
46525
  }
45523
46526
  if (!isProcessAlive(state.pid)) {
45524
- import_node_fs20.default.rmSync(import_node_path16.default.join(projectRoot, UI_STATE_FILE), { force: true });
46527
+ import_node_fs21.default.rmSync(import_node_path17.default.join(projectRoot, UI_STATE_FILE), { force: true });
45525
46528
  console.log("Sailor UI is not running (stale state file removed).");
45526
46529
  return;
45527
46530
  }
@@ -45530,21 +46533,21 @@ function uiStop() {
45530
46533
  tailscaleServeDown();
45531
46534
  console.log("Tailnet exposure removed.");
45532
46535
  }
45533
- import_node_fs20.default.rmSync(import_node_path16.default.join(projectRoot, UI_STATE_FILE), { force: true });
46536
+ import_node_fs21.default.rmSync(import_node_path17.default.join(projectRoot, UI_STATE_FILE), { force: true });
45534
46537
  console.log(`Stopped Sailor UI (pid ${state.pid}).`);
45535
46538
  }
45536
46539
 
45537
46540
  // src/index.ts
45538
- function cliVersion() {
46541
+ function cliVersion2() {
45539
46542
  try {
45540
- const pkg = JSON.parse((0, import_node_fs21.readFileSync)((0, import_node_path17.join)(packageRoot(), "package.json"), "utf-8"));
46543
+ const pkg = JSON.parse((0, import_node_fs22.readFileSync)((0, import_node_path18.join)(packageRoot(), "package.json"), "utf-8"));
45541
46544
  return pkg.version ?? "0.0.0";
45542
46545
  } catch {
45543
46546
  return "0.0.0";
45544
46547
  }
45545
46548
  }
45546
46549
  var program2 = new Command();
45547
- program2.name("sailor").description("Operator toolkit for Sail Protocol").version(cliVersion());
46550
+ program2.name("sailor").description("Operator toolkit for Sail Protocol").version(cliVersion2());
45548
46551
  function action(fn) {
45549
46552
  return async () => {
45550
46553
  try {
@@ -45569,7 +46572,7 @@ function actionWith(fn) {
45569
46572
  closePrompts();
45570
46573
  };
45571
46574
  }
45572
- program2.command("init [dir]").description("Scaffold a new Sail agent into the current directory (or [dir] subdirectory)").option("--template <name>", "Template to scaffold from (default: default)").option("--chain <id>", "Default EVM chain id written to .sail/config.json and .env.example").option("--rpc-url <url>", "Default RPC_URL written to .sail/.env.local").option("--force", "Re-initialize even if already initialized (overwrites scaffold files; keys/ and state/ are preserved)").option("--no-skills", "Skip scaffolding the sailor skills (use under the Sailor plugin, which already provides them to the agent)").action(
46575
+ program2.command("init [dir]").description("Scaffold a new Sail agent into the current directory (or [dir] subdirectory)").option("--template <name>", "Template to scaffold from (default: default)").option("--chain <id>", "Default EVM chain id written to .sail/config.json and .env.example").option("--rpc-url <url>", "Default RPC_URL written to .sail/.env.local").option("--force", "Re-initialize even if already initialized (overwrites scaffold files; keys/ and state/ are preserved)").action(
45573
46576
  async (name, opts) => {
45574
46577
  try {
45575
46578
  await initCommand(name, opts);
@@ -45608,6 +46611,9 @@ mandate.command("attach").description("Register one or more already-deployed per
45608
46611
  "--address <mandateOrName>",
45609
46612
  "Permission address or locally-tracked name; or a comma-separated list of addresses to register together in one signature"
45610
46613
  ).requiredOption("--sma <address>", "SMA to register the permission on").option("--label <label>", "Human-readable label shown in the signing UI").option("--json", "Emit machine-readable JSON").action(actionWith(mandateAttach));
46614
+ mandate.command("configure").description(
46615
+ "Write per-account bounds on an already-deployed shared permission singleton (configureDirect; owner tx via the signing station). Pairs with `mandate attach`, which only registers \u2014 a registered-but-unconfigured singleton denies every call."
46616
+ ).requiredOption("--address <singleton>", "Shared permission singleton address (deployed on this chain)").requiredOption("--sma <address>", "SMA to configure the singleton for").option("--params <hex>", "Pre-encoded config blob (0x-prefixed hex)").option("--args-file <path>", "JSON file of typed params (paired with --template)").option("--template <name>", "Template name (e.g. SwapPermission) \u2014 resolves the encoder for --args-file").option("--label <label>", "Human-readable label shown in the signing UI").option("--simulate-only", "Stop after the off-chain pre-flight (no signing, no gas)").option("--force", "Re-configure even if isConfigured is already true").option("--json", "Emit machine-readable JSON").action(actionWith(mandateConfigure));
45611
46617
  mandate.command("deploy-clone").description("[currently unavailable \u2014 no clone templates deployed on any chain; use `mandate deploy`] Deploy + register a standalone clone permission via the signing UI").requiredOption("--template <key>", "Standalone clone template key (e.g. boundedApprove)").requiredOption("--sma <address>", "SMA to deploy the clone for and register it on").option("--tokens <csv>", "Comma-separated allowed token addresses").option("--spenders <csv>", "Comma-separated allowed spender addresses").option("--max <amount>", "Max amount per tx in base units (default: uint256 max)").option("--label <label>", "Human-readable label to track this permission under").option("--json", "Emit machine-readable JSON").action(actionWith(mandateDeployClone));
45612
46618
  mandate.command("revoke").description("Revoke permission(s) from an SMA (EIP-712 RevokePermissions, owner-authorized)").option("--address <permissionOrName>", "Permission address, or a name tracked locally").requiredOption("--sma <address>", "Safe (SMA) to revoke the permission(s) from").option("--all", "Revoke every permission currently registered on the SMA").option("--json", "Output JSON").action(actionWith(mandateRevoke));
45613
46619
  mandate.command("templates").description("Show how to author your own permission contract (and any community-deployed addresses)").option("--json", "Emit machine-readable JSON").action(actionWith(mandateTemplates));