@dev.sail.money/sailor 1.3.0-95 → 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.
- package/AGENTS.md +10 -7
- package/LICENSE +1 -1
- package/README.md +64 -472
- package/package.json +12 -8
- package/packages/cli/README.md +1 -1
- package/packages/cli/dist/index.cjs +1633 -535
- package/packages/cli/dist/server.cjs +19791 -21738
- package/packages/sdk/README.md +1 -1
- package/packages/sdk/dist/abis/ConfigurablePermission.d.ts +130 -0
- package/packages/sdk/dist/abis/ConfigurablePermission.d.ts.map +1 -0
- package/packages/sdk/dist/abis/ConfigurablePermission.js +79 -0
- package/packages/sdk/dist/abis/ConfigurablePermission.js.map +1 -0
- package/packages/sdk/dist/abis/SailGovernance.d.ts +6 -5
- package/packages/sdk/dist/abis/SailGovernance.d.ts.map +1 -1
- package/packages/sdk/dist/abis/SailGovernance.js +6 -5
- package/packages/sdk/dist/abis/SailGovernance.js.map +1 -1
- package/packages/sdk/dist/abis/SailKernel.d.ts +42 -0
- package/packages/sdk/dist/abis/SailKernel.d.ts.map +1 -1
- package/packages/sdk/dist/abis/SailKernel.js +34 -0
- package/packages/sdk/dist/abis/SailKernel.js.map +1 -1
- package/packages/sdk/dist/abis/index.d.ts +1 -0
- package/packages/sdk/dist/abis/index.d.ts.map +1 -1
- package/packages/sdk/dist/abis/index.js +1 -0
- package/packages/sdk/dist/abis/index.js.map +1 -1
- package/packages/sdk/dist/chains.d.ts +0 -7
- package/packages/sdk/dist/chains.d.ts.map +1 -1
- package/packages/sdk/dist/chains.js +81 -32
- package/packages/sdk/dist/chains.js.map +1 -1
- package/packages/sdk/dist/client.d.ts +1 -1
- package/packages/sdk/dist/client.d.ts.map +1 -1
- package/packages/sdk/dist/client.js +137 -16
- package/packages/sdk/dist/client.js.map +1 -1
- package/packages/sdk/dist/deployments.d.ts +6 -4
- package/packages/sdk/dist/deployments.d.ts.map +1 -1
- package/packages/sdk/dist/deployments.js +120 -118
- package/packages/sdk/dist/deployments.js.map +1 -1
- package/packages/sdk/dist/eip712.d.ts +84 -0
- package/packages/sdk/dist/eip712.d.ts.map +1 -1
- package/packages/sdk/dist/eip712.js +148 -0
- package/packages/sdk/dist/eip712.js.map +1 -1
- package/packages/sdk/dist/fees.d.ts +59 -10
- package/packages/sdk/dist/fees.d.ts.map +1 -1
- package/packages/sdk/dist/fees.js +74 -41
- package/packages/sdk/dist/fees.js.map +1 -1
- package/packages/sdk/dist/index.d.ts +5 -3
- package/packages/sdk/dist/index.d.ts.map +1 -1
- package/packages/sdk/dist/index.js +4 -3
- package/packages/sdk/dist/index.js.map +1 -1
- package/packages/sdk/dist/intelligence.d.ts +7 -2
- package/packages/sdk/dist/intelligence.d.ts.map +1 -1
- package/packages/sdk/dist/intelligence.js +2 -2
- package/packages/sdk/dist/intelligence.js.map +1 -1
- package/packages/sdk/dist/safe.d.ts +49 -0
- package/packages/sdk/dist/safe.d.ts.map +1 -1
- package/packages/sdk/dist/safe.js +74 -0
- package/packages/sdk/dist/safe.js.map +1 -1
- package/packages/sdk/dist/signing.d.ts +14 -0
- package/packages/sdk/dist/signing.d.ts.map +1 -1
- package/packages/sdk/package.json +6 -2
- package/packages/ui/dist/assets/{add-CLs0-B0p.js → add-CBbu2pe_.js} +2 -2
- package/packages/ui/dist/assets/{all-wallets-CDOk28sj.js → all-wallets-C1oy4NUu.js} +2 -2
- package/packages/ui/dist/assets/{app-store-DVzpi1qN.js → app-store-DKqyf0Zv.js} +1 -1
- package/packages/ui/dist/assets/{apple-C9U9iH1l.js → apple-DyoIbCFy.js} +2 -2
- package/packages/ui/dist/assets/{arrow-bottom-circle-jxial9Si.js → arrow-bottom-circle-CMS-OqZQ.js} +2 -2
- package/packages/ui/dist/assets/arrow-bottom-pUWeEqYu.js +8 -0
- package/packages/ui/dist/assets/arrow-left-B81HMJNL.js +8 -0
- package/packages/ui/dist/assets/arrow-right-Z5czoKlC.js +8 -0
- package/packages/ui/dist/assets/arrow-top-C6ym1oll.js +8 -0
- package/packages/ui/dist/assets/{bank-B98it1qN.js → bank-B41nlslf.js} +2 -2
- package/packages/ui/dist/assets/{basic-DsgeyPNu.js → basic-CWqOb7CV.js} +177 -177
- package/packages/ui/dist/assets/{browser-j4vCeHwE.js → browser-DDKdqoZ9.js} +2 -2
- package/packages/ui/dist/assets/{card-CzxbMvEd.js → card-BgOmTajq.js} +2 -2
- package/packages/ui/dist/assets/ccip-CtJUKWRd.js +1 -0
- package/packages/ui/dist/assets/{checkmark-D5sWBbk3.js → checkmark-CGqQipH4.js} +2 -2
- package/packages/ui/dist/assets/{checkmark-bold-BW6w3KCC.js → checkmark-bold-Ci5xf90j.js} +2 -2
- package/packages/ui/dist/assets/chevron-bottom-D7Xert17.js +8 -0
- package/packages/ui/dist/assets/chevron-left-BGbUebR2.js +8 -0
- package/packages/ui/dist/assets/chevron-right-xVsESnHU.js +8 -0
- package/packages/ui/dist/assets/chevron-top-DEA9cR6v.js +8 -0
- package/packages/ui/dist/assets/{chrome-store-B1OMtzC-.js → chrome-store-BsyI-4PI.js} +2 -2
- package/packages/ui/dist/assets/{clock-e0HueehS.js → clock-Dct9oQ3M.js} +2 -2
- package/packages/ui/dist/assets/{close-Cy1ytr26.js → close-BvSCnI2y.js} +2 -2
- package/packages/ui/dist/assets/{coinPlaceholder-DqJu3ZPV.js → coinPlaceholder-p7RiWkon.js} +2 -2
- package/packages/ui/dist/assets/{compass-XDz_N2Hg.js → compass-BUeeZqX4.js} +2 -2
- package/packages/ui/dist/assets/{copy-DmDo3Nob.js → copy-C5jXbxLq.js} +2 -2
- package/packages/ui/dist/assets/core-CiAm42Mq.js +907 -0
- package/packages/ui/dist/assets/cursor-C0T7JWFO.js +3 -0
- package/packages/ui/dist/assets/{cursor-transparent-DF2aA10D.js → cursor-transparent-BZp3-JmA.js} +2 -2
- package/packages/ui/dist/assets/{desktop-CVydOWLn.js → desktop-BIui_Lzb.js} +2 -2
- package/packages/ui/dist/assets/{disconnect-BuN2Whnz.js → disconnect-B3Bxdchp.js} +2 -2
- package/packages/ui/dist/assets/{discord-DMNPvTB2.js → discord-VWI0yDyx.js} +2 -2
- package/packages/ui/dist/assets/{etherscan-CacW-93f.js → etherscan-BpBvUT9i.js} +2 -2
- package/packages/ui/dist/assets/events-DQ172AOg.js +1 -0
- package/packages/ui/dist/assets/{exclamation-triangle-B26hIvqO.js → exclamation-triangle-o1TJHIUw.js} +2 -2
- package/packages/ui/dist/assets/{extension-B7rI0gv7.js → extension-4RaLvbh5.js} +2 -2
- package/packages/ui/dist/assets/external-link-BHIwjDgj.js +8 -0
- package/packages/ui/dist/assets/{facebook-BDqbE6kl.js → facebook-Bes5g-wN.js} +2 -2
- package/packages/ui/dist/assets/{farcaster-zQ3oQzZ8.js → farcaster-CiJ-352m.js} +2 -2
- package/packages/ui/dist/assets/{filters-DCglZYsM.js → filters-DMOteumb.js} +2 -2
- package/packages/ui/dist/assets/{github-BH-BYjss.js → github-D2nDec9X.js} +2 -2
- package/packages/ui/dist/assets/{google-DYFWxZbC.js → google-lZZlQZPQ.js} +2 -2
- package/packages/ui/dist/assets/{help-circle-BXH_DtZ_.js → help-circle-D4cSSziR.js} +1 -1
- package/packages/ui/dist/assets/{id-Dr2yTeX1.js → id-BmhXZq5P.js} +2 -2
- package/packages/ui/dist/assets/{image-DeJey1Eg.js → image-Dz4FPeET.js} +2 -2
- package/packages/ui/dist/assets/index-B07bCKJ8.css +1 -0
- package/packages/ui/dist/assets/index-BV8s6ez1.js +1 -0
- package/packages/ui/dist/assets/index-BeUp3nOq.js +1 -0
- package/packages/ui/dist/assets/index-CvRylmZJ.js +16 -0
- package/packages/ui/dist/assets/{index-DVjAiPHI.js → index-DeoQO45V.js} +3 -3
- package/packages/ui/dist/assets/index-Et5S3ZaW.js +47 -0
- package/packages/ui/dist/assets/index-LiKeH8Cd.js +1780 -0
- package/packages/ui/dist/assets/index.es-dfpEui-9.js +26 -0
- package/packages/ui/dist/assets/{info-B91pD5Rw.js → info-77RSvIMg.js} +2 -2
- package/packages/ui/dist/assets/{info-circle-CySl3_on.js → info-circle-CWsII-NN.js} +2 -2
- package/packages/ui/dist/assets/{lightbulb-wwG8LQLo.js → lightbulb-BZXzm7XE.js} +2 -2
- package/packages/ui/dist/assets/{mail-D617YZ8y.js → mail-DMG1YqB0.js} +2 -2
- package/packages/ui/dist/assets/metamask-sdk-K1x_iqcc.js +542 -0
- package/packages/ui/dist/assets/{mobile-CD9KlA0m.js → mobile-DuJfOBSk.js} +2 -2
- package/packages/ui/dist/assets/{more-BQ_rpPXo.js → more-Cs9ySK2F.js} +2 -2
- package/packages/ui/dist/assets/{network-placeholder-BA7nl9e6.js → network-placeholder-CMDPmB1E.js} +2 -2
- package/packages/ui/dist/assets/{nftPlaceholder-D1EaaeDn.js → nftPlaceholder-Cj0f9y2u.js} +2 -2
- package/packages/ui/dist/assets/{off-DnGG35_w.js → off-9zSSsm-e.js} +2 -2
- package/packages/ui/dist/assets/{play-store-C5u2FvYB.js → play-store-CPwIb8Gj.js} +2 -2
- package/packages/ui/dist/assets/{plus-CM4xJkvI.js → plus-BOHQri8o.js} +2 -2
- package/packages/ui/dist/assets/{qr-code-kM3FUIdR.js → qr-code-DqhbK276.js} +1 -1
- package/packages/ui/dist/assets/{recycle-horizontal-DWrRWIBM.js → recycle-horizontal-BpGM56Qz.js} +2 -2
- package/packages/ui/dist/assets/{refresh-CztbjK2d.js → refresh-BPzZlhTP.js} +2 -2
- package/packages/ui/dist/assets/{reown-logo-DUHEIodF.js → reown-logo-OCkI0xzo.js} +2 -2
- package/packages/ui/dist/assets/{search-BJtb4mn1.js → search-B1JEJvwq.js} +2 -2
- package/packages/ui/dist/assets/{secp256k1-BjrTZpQx.js → secp256k1-BqUeV9Cb.js} +1 -1
- package/packages/ui/dist/assets/{send-B3_kavG1.js → send-JNsDlNoq.js} +2 -2
- package/packages/ui/dist/assets/{swapHorizontal-BrF9POiv.js → swapHorizontal-C3Z1FImK.js} +2 -2
- package/packages/ui/dist/assets/{swapHorizontalBold-Dgf8OjXj.js → swapHorizontalBold-Cmdy2iAn.js} +2 -2
- package/packages/ui/dist/assets/{swapHorizontalMedium-C6wX0JZj.js → swapHorizontalMedium-DFX57Nn9.js} +2 -2
- package/packages/ui/dist/assets/{swapHorizontalRoundedBold-DTAVw6oF.js → swapHorizontalRoundedBold-baB389c8.js} +2 -2
- package/packages/ui/dist/assets/{swapVertical-KGlTFNoi.js → swapVertical-DmAYGfK1.js} +2 -2
- package/packages/ui/dist/assets/{telegram-DnLrK-4y.js → telegram-BHbYE-nI.js} +2 -2
- package/packages/ui/dist/assets/{three-dots-C6_oMJfw.js → three-dots-BwRWl6qJ.js} +2 -2
- package/packages/ui/dist/assets/{twitch-DvPqPD4f.js → twitch-Drx0q6B6.js} +2 -2
- package/packages/ui/dist/assets/{twitterIcon-BZdk82Am.js → twitterIcon-AuJ2KQ6p.js} +2 -2
- package/packages/ui/dist/assets/{verify-CbESD5G0.js → verify-Dkrd3q7o.js} +2 -2
- package/packages/ui/dist/assets/{verify-filled-BRjTrLxw.js → verify-filled-B9e3-nz-.js} +2 -2
- package/packages/ui/dist/assets/{w3m-modal-D9b2TGHc.js → w3m-modal-DtkEjQA7.js} +1 -1
- package/packages/ui/dist/assets/{wallet-B87E5UId.js → wallet-CqYzSiBd.js} +2 -2
- package/packages/ui/dist/assets/{wallet-placeholder-DmssSbYf.js → wallet-placeholder-B05kTN_K.js} +2 -2
- package/packages/ui/dist/assets/{walletconnect-CZkLKWMZ.js → walletconnect-BwoPXLaS.js} +3 -3
- package/packages/ui/dist/assets/{warning-circle-BPTpHB1P.js → warning-circle-DK9Ai8rT.js} +2 -2
- package/packages/ui/dist/assets/{x-D_dEtEDU.js → x-BNdh5DVW.js} +2 -2
- package/packages/ui/dist/index.html +2 -2
- package/templates/default/.agents/skills/sail-mandates/SKILL.md +13 -1
- package/templates/default/.agents/skills/sail-mandates/references/approvals.md +3 -3
- package/templates/default/.agents/skills/sail-mandates/references/examples-index.md +3 -3
- package/templates/default/.agents/skills/sail-onboarding/SKILL.md +2 -2
- package/templates/default/.agents/skills/sail-project-info/SKILL.md +2 -0
- package/templates/default/.agents/skills/sail-servers/SKILL.md +1 -0
- package/templates/default/.agents/skills/sail-swap-quote/SKILL.md +76 -0
- package/templates/default/.agents/skills/sail-template-approve-batch/SKILL.md +98 -0
- package/templates/default/.agents/skills/sail-template-borrow/SKILL.md +68 -0
- package/templates/default/.agents/skills/sail-template-deposit/SKILL.md +61 -0
- package/templates/default/.agents/skills/sail-template-swap/SKILL.md +207 -0
- package/templates/default/.agents/skills/sail-template-swap-no-oracle/SKILL.md +100 -0
- package/templates/default/.agents/skills/sail-template-transfer/SKILL.md +52 -0
- package/templates/default/.agents/skills/sail-template-withdraw/SKILL.md +50 -0
- package/templates/default/.agents/skills/sail-templates/SKILL.md +142 -0
- package/templates/default/.agents/skills/sail-templates/catalog.mjs +200 -0
- package/templates/default/.agents/skills/sail-templates/deployed.json +133 -0
- package/templates/default/.agents/skills/sail-templates/oracles/IOracle.sol +13 -0
- package/templates/default/.agents/skills/sail-templates/oracles/UniV3TwapOracle.sol +114 -0
- package/templates/default/.agents/skills/sail-templates/oracles/libs/FullMath.sol +62 -0
- package/templates/default/.agents/skills/sail-templates/oracles/libs/TickMath.sol +44 -0
- package/templates/default/.agents/skills/sail-templates/references/config-schemas.md +139 -0
- package/templates/default/.agents/skills/sail-templates/references/reuse-flow.md +139 -0
- package/templates/default/.agents/skills/sail-token-resolve/SKILL.md +174 -0
- package/templates/default/.env.example +9 -0
- package/templates/default/AGENTS.md +21 -2
- package/templates/default/docs/PERMISSION_MODEL.md +2 -2
- package/{examples → templates/default/examples}/custom-mandate/.sail/contracts/interfaces/IPermission.sol +4 -0
- package/{examples → templates/default/examples}/custom-mandate/README.md +4 -1
- package/{examples → templates/default/examples}/permissions/interfaces/IBatchPermission.sol +2 -0
- package/{examples → templates/default/examples}/permissions/interfaces/IPermission.sol +4 -0
- package/templates/default/scripts/quote-swap.mjs +211 -0
- package/templates/default/scripts/resolve-token.mjs +992 -0
- package/templates/default/scripts/shared-template-addr.mjs +110 -0
- package/templates/default/test/BoundedCallPermission.t.sol +2 -1
- package/docs/PERMISSION_MODEL.md +0 -93
- package/examples/README.md +0 -24
- package/examples/lifi-permissions/LifiBoundedApprovePermissionCloneable.sol +0 -84
- package/examples/lifi-permissions/LifiDiamondSwapPermissionCloneable.sol +0 -97
- package/examples/lifi-permissions/README.md +0 -53
- package/packages/cli/dist/mcp.cjs +0 -15534
- package/packages/ui/dist/assets/arrow-bottom-DjQ4jGMe.js +0 -8
- package/packages/ui/dist/assets/arrow-left-BjAyI8D1.js +0 -8
- package/packages/ui/dist/assets/arrow-right-BlFO4Tcx.js +0 -8
- package/packages/ui/dist/assets/arrow-top-DJ3oh3DH.js +0 -8
- package/packages/ui/dist/assets/ccip-U9yiu_EK.js +0 -1
- package/packages/ui/dist/assets/chevron-bottom-BbHhmTQq.js +0 -8
- package/packages/ui/dist/assets/chevron-left-D8BDH4Wo.js +0 -8
- package/packages/ui/dist/assets/chevron-right-BQuQk5zc.js +0 -8
- package/packages/ui/dist/assets/chevron-top-1oeSXkx4.js +0 -8
- package/packages/ui/dist/assets/core-DbkMGSYW.js +0 -907
- package/packages/ui/dist/assets/cursor-DRFqL8nZ.js +0 -3
- package/packages/ui/dist/assets/events-CZkVDFih.js +0 -1
- package/packages/ui/dist/assets/external-link-CX8skCbH.js +0 -8
- package/packages/ui/dist/assets/fallback-DWQYKf3l.js +0 -1
- package/packages/ui/dist/assets/index-BP-UuQ8g.js +0 -1
- package/packages/ui/dist/assets/index-BksbyFjf.js +0 -1
- package/packages/ui/dist/assets/index-C55-Ne92.js +0 -16
- package/packages/ui/dist/assets/index-D6_Zei-R.js +0 -1790
- package/packages/ui/dist/assets/index-DZ2C2rHq.css +0 -1
- package/packages/ui/dist/assets/index-uSdXE5b_.js +0 -1
- package/packages/ui/dist/assets/index.es-dZlNPpfR.js +0 -26
- package/packages/ui/dist/assets/metamask-sdk-RbLbxUgF.js +0 -542
- package/packages/ui/dist/assets/native-CJ5et6AR.js +0 -1
- package/packages/ui/dist/assets/parseSignature-E29x8poM.js +0 -1
- package/scripts/check-docs.mjs +0 -309
- package/scripts/check-init.mjs +0 -123
- package/scripts/check-update.mjs +0 -177
- package/scripts/clean.mjs +0 -17
- package/scripts/pack.mjs +0 -21
- /package/{examples → templates/default/examples}/custom-mandate/foundry.toml +0 -0
- /package/{examples → templates/default/examples}/custom-mandate/mandates/BoundedCallPermission.sol +0 -0
- /package/{examples → templates/default/examples}/custom-mandate/mandates/README.md +0 -0
- /package/{examples → templates/default/examples}/custom-mandate/mandates/SailCalldata.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedApproveAndCallBatch.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedBorrow_AaveV3_Arbitrum.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedLimitless_Base.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedPerp_GMXv2_Arbitrum.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedStake_Venice_Base.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedSupply_AaveV3_Arbitrum.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedSwapNative_UniswapV3_Base.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedSwap_UniswapV3_Base.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedSwap_UniswapV4_Unichain.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedTransfer_ERC20_Ethereum.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedVault_ERC4626_Base.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/README.md +0 -0
- /package/{examples → templates/default/examples}/permissions/SailCalldata.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/foundry.toml +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
function e(){if(typeof WebSocket<"u")return WebSocket;if(typeof global.WebSocket<"u")return global.WebSocket;if(typeof window.WebSocket<"u")return window.WebSocket;if(typeof self.WebSocket<"u")return self.WebSocket;throw new Error("`WebSocket` is not supported in this environment")}const t=e();export{t as WebSocket};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{aD as A,cU as k,bU as B,cd as P,d5 as _,eY as b,ch as F,bR as E,bc as O,B as v,u as L,fs as R,d3 as x,cV as q,f5 as S,fi as j,d7 as N,f$ as $,fL as I,q as D,cK as T,cO as U,de as V,fP as W,g8 as H,eZ as K,fa as G,g9 as Y,bV as Z,ff as J,fp as Q}from"./index-D6_Zei-R.js";function X(a){const{source:t}=a,o=new Map,r=new A(8192),d=new Map,i=({address:n,chainId:c})=>`${n}.${c}`,y=n=>{o.delete(n),d.delete(n)};return{async consume({address:n,chainId:c,client:u}){const e=i({address:n,chainId:c}),w=this.get({address:n,chainId:c,client:u});this.increment({address:n,chainId:c});const m=await w;return await t.set({address:n,chainId:c},m),r.set(e,m),m},async increment({address:n,chainId:c}){const u=i({address:n,chainId:c}),e=o.get(u)??0;o.set(u,e+1)},async get({address:n,chainId:c,client:u}){const e=i({address:n,chainId:c});let w=d.get(e);return w||(w=(async()=>{try{const f=await t.get({address:n,chainId:c,client:u}),s=r.get(e)??0;return s>0&&f<=s?s+1:(r.delete(e),f)}finally{y(e)}})(),d.set(e,w)),(o.get(e)??0)+await w},reset({address:n,chainId:c}){const u=i({address:n,chainId:c});r.delete(u),y(u)}}}function ee(){return{async get(a){const{address:t,client:o}=a;return k(o,{address:t,blockTag:"pending"})},set(){}}}const re=X({source:ee()}),te="0x6492649264926492649264926492649264926492649264926492649264926492",ie="0x0000000000000000000000000000000000000000000000000000000000000000";function ce(a){const{address:t,data:o,signature:r,to:d="hex"}=a,i=B([P([{type:"address"},{type:"bytes"},{type:"bytes"}],[t,o,r]),te]);return d==="hex"?i:_(i)}const M="0x5792579257925792579257925792579257925792579257925792579257925792",z=b(0,{size:32});async function ue(a,t){var m;const{account:o=a.account,chain:r=a.chain,experimental_fallback:d,experimental_fallbackDelay:i=32,forceAtomic:y=!1,id:n,version:c="2.0.0"}=t,u=o?S(o):null;let e=t.capabilities;a.dataSuffix&&!((m=t.capabilities)!=null&&m.dataSuffix)&&(typeof a.dataSuffix=="string"?e={...t.capabilities,dataSuffix:{value:a.dataSuffix,optional:!0}}:e={...t.capabilities,dataSuffix:{value:a.dataSuffix.value,...a.dataSuffix.required?{}:{optional:!0}}});const w=t.calls.map(f=>{const s=f,l=s.abi?F({abi:s.abi,functionName:s.functionName,args:s.args}):s.data;return{data:s.dataSuffix&&l?E([l,s.dataSuffix]):l,to:s.to,value:s.value?b(s.value):void 0}});try{const f=await a.request({method:"wallet_sendCalls",params:[{atomicRequired:y,calls:w,capabilities:e,chainId:b(r.id),from:u==null?void 0:u.address,id:n,version:c}]},{retryCount:0});return typeof f=="string"?{id:f}:f}catch(f){const s=f;if(d&&(s.name==="MethodNotFoundRpcError"||s.name==="MethodNotSupportedRpcError"||s.name==="UnknownRpcError"||s.details.toLowerCase().includes("does not exist / is not available")||s.details.toLowerCase().includes("missing or invalid. request()")||s.details.toLowerCase().includes("did not match any variant of untagged enum")||s.details.toLowerCase().includes("account upgraded to unsupported contract")||s.details.toLowerCase().includes("eip-7702 not supported")||s.details.toLowerCase().includes("unsupported wc_ method")||s.details.toLowerCase().includes("feature toggled misconfigured")||s.details.toLowerCase().includes("jsonrpcengine: response has no error or result for request"))){if(e&&Object.values(e).some(g=>!g.optional)){const g="non-optional `capabilities` are not supported on fallback to `eth_sendTransaction`.";throw new O(new v(g,{details:g}))}if(y&&w.length>1){const h="`forceAtomic` is not supported on fallback to `eth_sendTransaction`.";throw new L(new v(h,{details:h}))}const l=[];for(const h of w){try{const g=await R(a,{account:u,chain:r,data:h.data,to:h.to,value:h.value?x(h.value):void 0});l.push({status:"fulfilled",value:g})}catch(g){l.push({reason:g,status:"rejected"})}i>0&&await new Promise(g=>setTimeout(g,i))}if(l.every(h=>h.status==="rejected"))throw l[0].reason;const p=l.map(h=>h.status==="fulfilled"?h.value:z);return{id:E([...p,b(r.id,{size:32}),M])}}throw q(f,{...t,account:u,chain:t.chain})}}async function ae(a,t){async function o(e){if(e.endsWith(M.slice(2))){const m=$(I(e,-64,-32)),f=I(e,0,-64).slice(2).match(/.{1,64}/g),s=await Promise.all(f.map(p=>z.slice(2)!==p?a.request({method:"eth_getTransactionReceipt",params:[`0x${p}`]},{dedupe:!0}):void 0)),l=s.some(p=>p===null)?100:s.every(p=>(p==null?void 0:p.status)==="0x1")?200:s.every(p=>(p==null?void 0:p.status)==="0x0")?500:600;return{atomic:!1,chainId:N(m),receipts:s.filter(Boolean),status:l,version:"2.0.0"}}return a.request({method:"wallet_getCallsStatus",params:[e]})}const{atomic:r=!1,chainId:d,receipts:i,version:y="2.0.0",...n}=await o(t.id),[c,u]=(()=>{const e=n.status;return e>=100&&e<200?["pending",e]:e>=200&&e<300?["success",e]:e>=300&&e<700?["failure",e]:e==="CONFIRMED"?["success",200]:e==="PENDING"?["pending",100]:[void 0,e]})();return{...n,atomic:r,chainId:d?N(d):void 0,receipts:(i==null?void 0:i.map(e=>({...e,blockNumber:x(e.blockNumber),gasUsed:x(e.gasUsed),status:j[e.status]})))??[],statusCode:u,status:c,version:y}}async function le(a,t){var c;const{account:o=a.account,chainId:r,nonce:d}=t;if(!o)throw new D({docsPath:"/docs/eip7702/prepareAuthorization"});const i=S(o),y=(()=>{if(t.executor)return t.executor==="self"?t.executor:S(t.executor)})(),n={address:t.contractAddress??t.address,chainId:r,nonce:d};return typeof n.chainId>"u"&&(n.chainId=((c=a.chain)==null?void 0:c.id)??await T(a,U,"getChainId")({})),typeof n.nonce>"u"&&(n.nonce=await T(a,k,"getTransactionCount")({address:i.address,blockTag:"pending"}),(y==="self"||y!=null&&y.address&&V(y.address,i.address))&&(n.nonce+=1)),n}class se extends v{constructor(t){super(`Call bundle failed with status: ${t.statusCode}`,{name:"BundleFailedError"}),Object.defineProperty(this,"result",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.result=t}}async function de(a,t){const{id:o,pollingInterval:r=a.pollingInterval,status:d=({statusCode:l})=>l===200||l>=300,retryCount:i=4,retryDelay:y=({count:l})=>~~(1<<l)*200,timeout:n=6e4,throwOnFailure:c=!1}=t,u=W(["waitForCallsStatus",a.uid,o]),{promise:e,resolve:w,reject:m}=H();let f;const s=K(u,{resolve:w,reject:m},l=>{const p=G(async()=>{const h=g=>{clearTimeout(f),p(),g(),s()};try{const g=await Y(async()=>{const C=await T(a,ae,"getCallsStatus")({id:o});if(c&&C.status==="failure")throw new se(C);return C},{retryCount:i,delay:y});if(!d(g))return;h(()=>l.resolve(g))}catch(g){h(()=>l.reject(g))}},{interval:r,emitOnBegin:!0});return p});return f=n?setTimeout(()=>{s(),clearTimeout(f),m(new ne({id:o}))},n):void 0,await e}class ne extends v{constructor({id:t}){super(`Timed out while waiting for call bundle with id "${t}" to be confirmed.`,{name:"WaitForCallsStatusTimeoutError"})}}function fe(a){const{key:t="public",name:o="Public Client"}=a;return Z({...a,key:t,name:o,type:"publicClient"}).extend(J)}function pe(a){const{r:t,s:o}=Q.Signature.fromCompact(a.slice(2,130)),r=+`0x${a.slice(130)}`,[d,i]=(()=>{if(r===0||r===1)return[void 0,r];if(r===27)return[BigInt(r),0];if(r===28)return[BigInt(r),1];throw new Error("Invalid yParityOrV value")})();return typeof d<"u"?{r:b(t,{size:32}),s:b(o,{size:32}),v:d,yParity:i}:{r:b(t,{size:32}),s:b(o,{size:32}),yParity:i}}export{se as B,ne as W,fe as a,le as b,X as c,ce as d,te as e,ae as g,re as n,pe as p,ue as s,de as w,ie as z};
|
package/scripts/check-docs.mjs
DELETED
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Doc-drift gate.
|
|
4
|
-
*
|
|
5
|
-
* The agent-facing docs (CLAUDE.md, AGENTS.md, AGENT_PLAYBOOK.md, the scaffolded
|
|
6
|
-
* template, package READMEs) tell an LLM agent which `sailor` commands and which
|
|
7
|
-
* `client.<ns>.<method>(...)` SDK calls to use. If a doc names a command or method
|
|
8
|
-
* that no longer exists, the agent confidently does the wrong thing. This script
|
|
9
|
-
* is the regression net: it derives the *real* surface from source and fails if a
|
|
10
|
-
* doc references something that isn't there.
|
|
11
|
-
*
|
|
12
|
-
* - CLI commands ← parsed from packages/cli/src/index.ts (commander tree)
|
|
13
|
-
* - SDK methods ← parsed from packages/sdk/src/client.ts (namespace classes)
|
|
14
|
-
*
|
|
15
|
-
* Only `sailor …` is validated, never the SailFramework `sail …` binary that some
|
|
16
|
-
* docs reference. Only references inside `inline code` or ```fenced``` blocks are
|
|
17
|
-
* checked, so prose ("the sailor CLI") never trips it.
|
|
18
|
-
*
|
|
19
|
-
* Run: `node scripts/check-docs.mjs` (or `pnpm docs:check`). Exit 1 on any miss.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
23
|
-
import { dirname, join, relative } from "node:path";
|
|
24
|
-
import { fileURLToPath } from "node:url";
|
|
25
|
-
|
|
26
|
-
const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
27
|
-
const rel = (p) => relative(ROOT, p);
|
|
28
|
-
|
|
29
|
-
// ── 1. Derive the real CLI command surface ──────────────────────────────────
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Parse the commander tree from index.ts into:
|
|
33
|
-
* leaves — Set of full top-level invocations ("init", "doctor", "dispatch preview")
|
|
34
|
-
* groups — Map<groupName, Set<subcommand>> (e.g. "mandate" → {prepare, sign, …})
|
|
35
|
-
*/
|
|
36
|
-
function parseCliSurface() {
|
|
37
|
-
const src = readFileSync(join(ROOT, "packages/cli/src/index.ts"), "utf-8");
|
|
38
|
-
const leaves = new Set();
|
|
39
|
-
const groups = new Map();
|
|
40
|
-
const varToGroup = new Map(); // commander variable name → group command name
|
|
41
|
-
|
|
42
|
-
// `const ui = program.command("ui")` — a group declared on a variable.
|
|
43
|
-
for (const m of src.matchAll(/const\s+(\w+)\s*=\s*program\s*\.command\(\s*"([^"]+)"/g)) {
|
|
44
|
-
const groupName = m[2].split(/\s+/)[0];
|
|
45
|
-
varToGroup.set(m[1], groupName);
|
|
46
|
-
if (!groups.has(groupName)) groups.set(groupName, new Set());
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// `program.command("init [dir]")` — a top-level leaf (not assigned to a var).
|
|
50
|
-
for (const m of src.matchAll(/program\s*\.command\(\s*"([^"]+)"/g)) {
|
|
51
|
-
const name = m[1].split(/\s+/)[0];
|
|
52
|
-
// Multi-word leaf names (e.g. the "dispatch preview" stub) keep their full form too.
|
|
53
|
-
const full = m[1]
|
|
54
|
-
.replace(/\s*\[.*$/, "")
|
|
55
|
-
.replace(/\s*<.*$/, "")
|
|
56
|
-
.trim();
|
|
57
|
-
if (!groups.has(name)) {
|
|
58
|
-
leaves.add(name);
|
|
59
|
-
if (full.includes(" ")) leaves.add(full);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// `stub("setup", …)` / `stub("dispatch preview", …)` — registered top-level commands.
|
|
64
|
-
for (const m of src.matchAll(/\bstub\(\s*"([^"]+)"/g)) {
|
|
65
|
-
leaves.add(m[1]);
|
|
66
|
-
leaves.add(m[1].split(/\s+/)[0]);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// `ui.command("start")` / `mandate.command("prepare")` — subcommands of a group.
|
|
70
|
-
for (const m of src.matchAll(/(\w+)\s*\.command\(\s*"([^"]+)"/g)) {
|
|
71
|
-
const groupName = varToGroup.get(m[1]);
|
|
72
|
-
if (!groupName) continue; // not a known group variable (e.g. program.command handled above)
|
|
73
|
-
const sub = m[2].split(/\s+/)[0];
|
|
74
|
-
groups.get(groupName).add(sub);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return { leaves, groups };
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// ── 2. Derive the real SDK surface ───────────────────────────────────────────
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Parse client.ts into:
|
|
84
|
-
* namespaces — Map<propertyName, Set<methodName>> (account → {create, get, …})
|
|
85
|
-
* clientMethods — Set of direct SailorClient methods (capabilities, withSigner, …)
|
|
86
|
-
*/
|
|
87
|
-
function parseSdkSurface() {
|
|
88
|
-
const src = readFileSync(join(ROOT, "packages/sdk/src/client.ts"), "utf-8");
|
|
89
|
-
const lines = src.split("\n");
|
|
90
|
-
|
|
91
|
-
// Map namespace *class* → set of method names, by slicing each class body.
|
|
92
|
-
const classMethods = new Map();
|
|
93
|
-
let current = null;
|
|
94
|
-
let depth = 0;
|
|
95
|
-
const reserved = new Set([
|
|
96
|
-
"if",
|
|
97
|
-
"for",
|
|
98
|
-
"while",
|
|
99
|
-
"switch",
|
|
100
|
-
"catch",
|
|
101
|
-
"return",
|
|
102
|
-
"super",
|
|
103
|
-
"constructor",
|
|
104
|
-
"function",
|
|
105
|
-
"await",
|
|
106
|
-
"typeof",
|
|
107
|
-
"new",
|
|
108
|
-
]);
|
|
109
|
-
for (const line of lines) {
|
|
110
|
-
const classMatch = line.match(/^\s*(?:export\s+)?(?:abstract\s+)?class\s+(\w+)/);
|
|
111
|
-
if (classMatch) {
|
|
112
|
-
current = classMatch[1];
|
|
113
|
-
classMethods.set(current, new Set());
|
|
114
|
-
depth = 0;
|
|
115
|
-
}
|
|
116
|
-
if (current) {
|
|
117
|
-
// Method declarations live at class-body depth 1.
|
|
118
|
-
const methodMatch = line.match(
|
|
119
|
-
/^\s{2}(?:public\s+|private\s+|protected\s+)?(?:async\s+)?(?:get\s+)?(\w+)\s*[(<]/,
|
|
120
|
-
);
|
|
121
|
-
if (methodMatch && !reserved.has(methodMatch[1])) {
|
|
122
|
-
classMethods.get(current).add(methodMatch[1]);
|
|
123
|
-
}
|
|
124
|
-
depth += (line.match(/{/g)?.length ?? 0) - (line.match(/}/g)?.length ?? 0);
|
|
125
|
-
if (depth <= 0 && line.includes("}")) current = null;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Map runtime property name → class: `this.account = new AccountNamespace(`
|
|
130
|
-
const namespaces = new Map();
|
|
131
|
-
for (const m of src.matchAll(/this\.(\w+)\s*=\s*new\s+(\w+)\s*\(/g)) {
|
|
132
|
-
const [, prop, cls] = m;
|
|
133
|
-
if (classMethods.has(cls)) namespaces.set(prop, classMethods.get(cls));
|
|
134
|
-
}
|
|
135
|
-
// `this.dispatch = dispatch;` — assigned from a local built earlier in the ctor.
|
|
136
|
-
for (const m of src.matchAll(/this\.(\w+)\s*=\s*(\w+);/g)) {
|
|
137
|
-
const [, prop, localVar] = m;
|
|
138
|
-
if (namespaces.has(prop)) continue;
|
|
139
|
-
// Resolve the local: `const dispatch = new DispatchNamespace(`
|
|
140
|
-
const localDecl = new RegExp(`(?:const|let)\\s+${localVar}\\s*=\\s*new\\s+(\\w+)\\s*\\(`);
|
|
141
|
-
const lm = src.match(localDecl);
|
|
142
|
-
if (lm && classMethods.has(lm[1])) namespaces.set(prop, classMethods.get(lm[1]));
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Direct methods on the SailorClient class itself.
|
|
146
|
-
const clientMethods = classMethods.get("SailorClient") ?? new Set();
|
|
147
|
-
|
|
148
|
-
return { namespaces, clientMethods };
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// ── 3. Collect doc files + extract code references ───────────────────────────
|
|
152
|
-
|
|
153
|
-
const DOC_GLOBS = [
|
|
154
|
-
"CLAUDE.md",
|
|
155
|
-
"AGENTS.md",
|
|
156
|
-
"AGENT_PLAYBOOK.md",
|
|
157
|
-
"README.md",
|
|
158
|
-
"docs",
|
|
159
|
-
"templates",
|
|
160
|
-
"packages/cli/README.md",
|
|
161
|
-
"packages/sdk/README.md",
|
|
162
|
-
];
|
|
163
|
-
|
|
164
|
-
function collectDocs() {
|
|
165
|
-
const files = [];
|
|
166
|
-
const walk = (p) => {
|
|
167
|
-
const st = statSync(p, { throwIfNoEntry: false });
|
|
168
|
-
if (!st) return;
|
|
169
|
-
if (st.isDirectory()) {
|
|
170
|
-
for (const e of readdirSync(p)) {
|
|
171
|
-
if (e === "node_modules" || e === "dist" || e.startsWith(".git")) continue;
|
|
172
|
-
walk(join(p, e));
|
|
173
|
-
}
|
|
174
|
-
} else if (p.endsWith(".md")) {
|
|
175
|
-
files.push(p);
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
for (const g of DOC_GLOBS) walk(join(ROOT, g));
|
|
179
|
-
return [...new Set(files)];
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/** Pull the text of every `inline` and ```fenced``` code region from markdown. */
|
|
183
|
-
function codeRegions(md) {
|
|
184
|
-
const regions = [];
|
|
185
|
-
// Fenced blocks first, then strip them so inline matching doesn't double-count.
|
|
186
|
-
const rest = md.replace(/```[\s\S]*?```/g, (block) => {
|
|
187
|
-
regions.push(block.replace(/```/g, ""));
|
|
188
|
-
return "\n";
|
|
189
|
-
});
|
|
190
|
-
for (const m of rest.matchAll(/`([^`\n]+)`/g)) regions.push(m[1]);
|
|
191
|
-
return regions;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// ── 4. Skills consistency ─────────────────────────────────────────────────────
|
|
195
|
-
//
|
|
196
|
-
// The scaffolded template ships agent skills under .agents/skills/. AGENTS.md is
|
|
197
|
-
// the routing layer: it must point at every skill that exists, and every skill it
|
|
198
|
-
// points at must exist with valid frontmatter — otherwise an agent either never
|
|
199
|
-
// discovers a workflow or follows a dangling pointer.
|
|
200
|
-
|
|
201
|
-
function checkSkills(errors) {
|
|
202
|
-
const skillsRoot = join(ROOT, "templates/default/.agents/skills");
|
|
203
|
-
const agentsPath = join(ROOT, "templates/default/AGENTS.md");
|
|
204
|
-
if (!existsSync(skillsRoot)) {
|
|
205
|
-
errors.push("templates/default/.agents/skills: directory missing");
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
const agentsMd = readFileSync(agentsPath, "utf-8");
|
|
209
|
-
const dirs = readdirSync(skillsRoot).filter((d) =>
|
|
210
|
-
statSync(join(skillsRoot, d)).isDirectory(),
|
|
211
|
-
);
|
|
212
|
-
if (dirs.length === 0) errors.push("templates/default/.agents/skills: no skills found");
|
|
213
|
-
|
|
214
|
-
for (const d of dirs) {
|
|
215
|
-
const skillFile = join(skillsRoot, d, "SKILL.md");
|
|
216
|
-
if (!existsSync(skillFile)) {
|
|
217
|
-
errors.push(`templates/default/.agents/skills/${d}: missing SKILL.md`);
|
|
218
|
-
continue;
|
|
219
|
-
}
|
|
220
|
-
const fm = readFileSync(skillFile, "utf-8").match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
221
|
-
if (!fm) {
|
|
222
|
-
errors.push(`${rel(skillFile)}: missing YAML frontmatter`);
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
const name = fm[1].match(/^name:\s*(\S+)\s*$/m)?.[1];
|
|
226
|
-
const description = fm[1].match(/^description:\s*(.+)$/m)?.[1]?.trim();
|
|
227
|
-
if (name !== d) errors.push(`${rel(skillFile)}: frontmatter name "${name}" ≠ directory "${d}"`);
|
|
228
|
-
if (!description) errors.push(`${rel(skillFile)}: frontmatter description missing or empty`);
|
|
229
|
-
if (!agentsMd.includes(`.agents/skills/${d}/SKILL.md`)) {
|
|
230
|
-
errors.push(`templates/default/AGENTS.md: routing table does not reference .agents/skills/${d}/SKILL.md`);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
for (const m of agentsMd.matchAll(/\.agents\/skills\/([\w-]+)\/SKILL\.md/g)) {
|
|
235
|
-
if (!dirs.includes(m[1])) {
|
|
236
|
-
errors.push(`templates/default/AGENTS.md: references .agents/skills/${m[1]}/SKILL.md which does not exist`);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// ── 5. Validate ──────────────────────────────────────────────────────────────
|
|
242
|
-
|
|
243
|
-
function main() {
|
|
244
|
-
const cli = parseCliSurface();
|
|
245
|
-
const sdk = parseSdkSurface();
|
|
246
|
-
const docs = collectDocs();
|
|
247
|
-
const errors = [];
|
|
248
|
-
|
|
249
|
-
for (const file of docs) {
|
|
250
|
-
const md = readFileSync(file, "utf-8");
|
|
251
|
-
for (const code of codeRegions(md)) {
|
|
252
|
-
for (const lineRaw of code.split("\n")) {
|
|
253
|
-
const line = lineRaw.trim();
|
|
254
|
-
|
|
255
|
-
// ── CLI: `sailor <word1> [<word2>]` ──────────────────────────────────
|
|
256
|
-
for (const m of line.matchAll(/\bsailor\s+([a-z][\w-]*)(?:\s+([a-z][\w-]*))?/g)) {
|
|
257
|
-
const [, w1, w2] = m;
|
|
258
|
-
const two = w2 ? `${w1} ${w2}` : null;
|
|
259
|
-
if (cli.leaves.has(w1) || (two && cli.leaves.has(two))) continue; // top-level leaf
|
|
260
|
-
if (cli.groups.has(w1)) {
|
|
261
|
-
// Group: if a subcommand word follows (and isn't a flag), it must exist.
|
|
262
|
-
if (!w2 || w2.startsWith("-")) continue; // bare group invocation, or a flag
|
|
263
|
-
if (cli.groups.get(w1).has(w2)) continue;
|
|
264
|
-
errors.push(
|
|
265
|
-
`${rel(file)}: \`sailor ${w1} ${w2}\` — "${w2}" is not a subcommand of "${w1}" (have: ${[...cli.groups.get(w1)].join(", ")})`,
|
|
266
|
-
);
|
|
267
|
-
continue;
|
|
268
|
-
}
|
|
269
|
-
errors.push(`${rel(file)}: \`sailor ${w1}\` — unknown command`);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// ── SDK: `client.<ns>[.<method>]` ────────────────────────────────────
|
|
273
|
-
for (const m of line.matchAll(/\bclient\.(\w+)(?:\.(\w+))?/g)) {
|
|
274
|
-
const [, ns, method] = m;
|
|
275
|
-
if (sdk.namespaces.has(ns)) {
|
|
276
|
-
if (!method) continue;
|
|
277
|
-
if (sdk.namespaces.get(ns).has(method)) continue;
|
|
278
|
-
errors.push(
|
|
279
|
-
`${rel(file)}: \`client.${ns}.${method}\` — "${method}" is not a method of the "${ns}" namespace (have: ${[...sdk.namespaces.get(ns)].join(", ")})`,
|
|
280
|
-
);
|
|
281
|
-
continue;
|
|
282
|
-
}
|
|
283
|
-
if (sdk.clientMethods.has(ns)) continue; // direct client method, e.g. capabilities/withSigner
|
|
284
|
-
errors.push(`${rel(file)}: \`client.${ns}\` — unknown SDK namespace or method`);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
checkSkills(errors);
|
|
291
|
-
|
|
292
|
-
// ── Report ───────────────────────────────────────────────────────────────
|
|
293
|
-
const cliCount = cli.leaves.size + [...cli.groups.values()].reduce((n, s) => n + s.size, 0);
|
|
294
|
-
const sdkCount =
|
|
295
|
-
[...sdk.namespaces.values()].reduce((n, s) => n + s.size, 0) + sdk.clientMethods.size;
|
|
296
|
-
console.log(
|
|
297
|
-
`Doc-drift check: ${docs.length} docs vs ${cliCount} CLI commands, ${sdkCount} SDK methods`,
|
|
298
|
-
);
|
|
299
|
-
|
|
300
|
-
if (errors.length > 0) {
|
|
301
|
-
console.error(`\n✗ ${errors.length} stale reference(s):\n`);
|
|
302
|
-
for (const e of [...new Set(errors)].sort()) console.error(` ${e}`);
|
|
303
|
-
console.error("\nFix the doc, or update the CLI/SDK so the referenced surface exists.");
|
|
304
|
-
process.exit(1);
|
|
305
|
-
}
|
|
306
|
-
console.log("✓ Every sailor command and client.* method referenced in docs exists.");
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
main();
|
package/scripts/check-init.mjs
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* `sailor init` smoke test.
|
|
4
|
-
*
|
|
5
|
-
* PASS 1 — fresh init: scaffolds a new project and asserts expected files exist.
|
|
6
|
-
*
|
|
7
|
-
* Template files are read live from disk (not bundled), so no rebuild is needed
|
|
8
|
-
* between runs — the in-tree templates/default/ IS the "latest version".
|
|
9
|
-
*
|
|
10
|
-
* Run: node scripts/check-init.mjs (CI builds the CLI first)
|
|
11
|
-
* Exit: 0 = all passes OK, 1 = failure (prints what went wrong).
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { execFileSync } from "node:child_process";
|
|
15
|
-
import fs from "node:fs";
|
|
16
|
-
import os from "node:os";
|
|
17
|
-
import path from "node:path";
|
|
18
|
-
import { fileURLToPath } from "node:url";
|
|
19
|
-
|
|
20
|
-
const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
21
|
-
const BUNDLE = path.join(ROOT, "packages/cli/dist/index.cjs");
|
|
22
|
-
const PROJECT = "smoke-agent";
|
|
23
|
-
|
|
24
|
-
function fail(msg) {
|
|
25
|
-
console.error(`✗ init smoke test FAILED: ${msg}`);
|
|
26
|
-
process.exit(1);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (!fs.existsSync(BUNDLE)) {
|
|
30
|
-
fail(`CLI bundle not found at ${BUNDLE}.\n Build it first: pnpm --filter sailor build`);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Scaffold into a temp dir. `init` requires the destination to live inside the
|
|
34
|
-
// process cwd, so we run the bundle with cwd set to a fresh temp root.
|
|
35
|
-
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "sailor-init-smoke-"));
|
|
36
|
-
const dest = path.join(tmpRoot, PROJECT);
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
let stdout = "";
|
|
40
|
-
try {
|
|
41
|
-
stdout = execFileSync(process.execPath, [BUNDLE, "init", PROJECT], {
|
|
42
|
-
cwd: tmpRoot,
|
|
43
|
-
encoding: "utf-8",
|
|
44
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
45
|
-
});
|
|
46
|
-
} catch (err) {
|
|
47
|
-
const out = `${err.stdout ?? ""}${err.stderr ?? ""}`.trim();
|
|
48
|
-
fail(`\`sailor init ${PROJECT}\` exited non-zero.\n ${out || err.message}`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// A successful fresh init prints the AGENTS.md onboarding banner.
|
|
52
|
-
if (!/AGENTS\.md/i.test(stdout)) {
|
|
53
|
-
fail(`init did not report success.\n stdout: ${stdout.trim()}`);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Assert the scaffold landed.
|
|
57
|
-
const mustExist = [
|
|
58
|
-
".sail/config.json",
|
|
59
|
-
"package.json",
|
|
60
|
-
"foundry.toml",
|
|
61
|
-
"mandates",
|
|
62
|
-
"AGENTS.md",
|
|
63
|
-
"CLAUDE.md",
|
|
64
|
-
"Dockerfile",
|
|
65
|
-
".dockerignore",
|
|
66
|
-
".sail/contracts/interfaces/IPermission.sol",
|
|
67
|
-
".sail/contracts/interfaces/IBatchPermission.sol",
|
|
68
|
-
"test/BoundedCallPermission.t.sol",
|
|
69
|
-
"examples/custom-mandate/README.md",
|
|
70
|
-
".agents/skills/sail-onboarding/SKILL.md",
|
|
71
|
-
".agents/skills/sail-project-info/SKILL.md",
|
|
72
|
-
".agents/skills/sail-servers/SKILL.md",
|
|
73
|
-
".agents/skills/sail-transactions/SKILL.md",
|
|
74
|
-
".agents/skills/sail-mandates/SKILL.md",
|
|
75
|
-
".agents/skills/sail-mandates/references/approvals.md",
|
|
76
|
-
".agents/skills/sail-automation/SKILL.md",
|
|
77
|
-
".agents/skills/sail-automation/references/docker-vm.md",
|
|
78
|
-
".agents/skills/sail-automation/references/github-actions.md",
|
|
79
|
-
".agents/skills/sail-automation/references/local-daemon.md",
|
|
80
|
-
".agents/skills/sail-automation/references/self-hosted-runner.md",
|
|
81
|
-
".agents/skills/sail-extend/SKILL.md",
|
|
82
|
-
];
|
|
83
|
-
for (const rel of mustExist) {
|
|
84
|
-
if (!fs.existsSync(path.join(dest, rel))) fail(`expected scaffolded "${rel}" — not found`);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// config.json is valid JSON named after the project.
|
|
88
|
-
const config = JSON.parse(fs.readFileSync(path.join(dest, ".sail/config.json"), "utf-8"));
|
|
89
|
-
if (config.name !== PROJECT) fail(`config.json name is "${config.name}", expected "${PROJECT}"`);
|
|
90
|
-
|
|
91
|
-
// package.json is valid, renamed, and the workspace protocol was resolved away
|
|
92
|
-
// (a leftover "workspace:*" would make the scaffold un-installable for users).
|
|
93
|
-
const pkg = JSON.parse(fs.readFileSync(path.join(dest, "package.json"), "utf-8"));
|
|
94
|
-
if (pkg.name !== PROJECT) fail(`package.json name is "${pkg.name}", expected "${PROJECT}"`);
|
|
95
|
-
if (pkg.dependencies?.["@sail/sdk"] === "workspace:*") {
|
|
96
|
-
fail(`package.json still has "@sail/sdk": "workspace:*" — init did not resolve it`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// ── Regression guard: absolute path outside cwd ───────────────────────────
|
|
100
|
-
// An absolute path outside the cwd must be REJECTED, not silently nested into
|
|
101
|
-
// `<cwd>/<abs path>`. (Pre-fix, `path.join` swallowed the leading slash and
|
|
102
|
-
// scaffolded a bogus nested tree while printing success.)
|
|
103
|
-
const outside = path.join(os.tmpdir(), "sailor-init-outside", "agent");
|
|
104
|
-
let rejected = false;
|
|
105
|
-
try {
|
|
106
|
-
execFileSync(process.execPath, [BUNDLE, "init", outside], {
|
|
107
|
-
cwd: tmpRoot,
|
|
108
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
109
|
-
});
|
|
110
|
-
} catch {
|
|
111
|
-
rejected = true; // non-zero exit = correctly refused
|
|
112
|
-
}
|
|
113
|
-
if (!rejected) fail(`an absolute path outside cwd ("${outside}") was accepted — should be rejected`);
|
|
114
|
-
if (fs.existsSync(path.join(outside, ".sail/config.json"))) {
|
|
115
|
-
fail(`init scaffolded into an out-of-cwd absolute path "${outside}"`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
console.log(`✓ init smoke test passed — scaffolded ${PROJECT}/ from the in-tree bundle`);
|
|
119
|
-
console.log("✓ init guard passed — absolute path outside cwd rejected, not silently nested");
|
|
120
|
-
} finally {
|
|
121
|
-
fs.rmSync(path.join(os.tmpdir(), "sailor-init-outside"), { recursive: true, force: true });
|
|
122
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
123
|
-
}
|
package/scripts/check-update.mjs
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* `sailor update` smoke tests.
|
|
4
|
-
*
|
|
5
|
-
* PASS 1 — standard update:
|
|
6
|
-
* Deletes a template-owned file and a user skill, runs `sailor update`,
|
|
7
|
-
* asserts the template file is restored and the user skill is untouched.
|
|
8
|
-
*
|
|
9
|
-
* PASS 2 — seeds missing user-space files:
|
|
10
|
-
* Deletes a user-space file (package.json) and dir (src/), runs update,
|
|
11
|
-
* asserts they are re-added. Asserts AGENTS.md / CLAUDE.md / Dockerfile
|
|
12
|
-
* are NOT overwritten when they already exist.
|
|
13
|
-
*
|
|
14
|
-
* PASS 3 — stale path pruning:
|
|
15
|
-
* Manually creates .agents/skills/sail-ci/ (orphan from old template version),
|
|
16
|
-
* runs update, asserts it is deleted and sail-automation is present.
|
|
17
|
-
*
|
|
18
|
-
* PASS 4 — init-on-existing errors:
|
|
19
|
-
* Runs `sailor init` inside the already-initialized project;
|
|
20
|
-
* asserts it exits non-zero with an "already initialized" message.
|
|
21
|
-
*
|
|
22
|
-
* Run: node scripts/check-update.mjs (CI builds the CLI first)
|
|
23
|
-
* Exit: 0 = all passes OK, 1 = failure (prints what went wrong).
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
import { execFileSync } from "node:child_process";
|
|
27
|
-
import fs from "node:fs";
|
|
28
|
-
import os from "node:os";
|
|
29
|
-
import path from "node:path";
|
|
30
|
-
import { fileURLToPath } from "node:url";
|
|
31
|
-
|
|
32
|
-
const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
33
|
-
const BUNDLE = path.join(ROOT, "packages/cli/dist/index.cjs");
|
|
34
|
-
const PROJECT = "smoke-update";
|
|
35
|
-
|
|
36
|
-
function fail(msg) {
|
|
37
|
-
console.error(`✗ update smoke test FAILED: ${msg}`);
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (!fs.existsSync(BUNDLE)) {
|
|
42
|
-
fail(`CLI bundle not found at ${BUNDLE}.\n Build it first: pnpm --filter sailor build`);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "sailor-update-smoke-"));
|
|
46
|
-
const dest = path.join(tmpRoot, PROJECT);
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
// Bootstrap: fresh init so we have a valid project to update.
|
|
50
|
-
try {
|
|
51
|
-
execFileSync(process.execPath, [BUNDLE, "init", PROJECT], {
|
|
52
|
-
cwd: tmpRoot,
|
|
53
|
-
encoding: "utf-8",
|
|
54
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
55
|
-
});
|
|
56
|
-
} catch (err) {
|
|
57
|
-
const out = `${err.stdout ?? ""}${err.stderr ?? ""}`.trim();
|
|
58
|
-
fail(`bootstrap \`sailor init ${PROJECT}\` exited non-zero.\n ${out || err.message}`);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// ── PASS 1 — standard update ───────────────────────────────────────────────
|
|
62
|
-
// Delete a template-owned file and add a user skill that must survive update.
|
|
63
|
-
const templateOwned = path.join(dest, ".agents/skills/sail-automation/SKILL.md");
|
|
64
|
-
const cursorRules = path.join(dest, ".cursor/rules");
|
|
65
|
-
const userSkill = path.join(dest, ".agents/skills/my-custom-skill/SKILL.md");
|
|
66
|
-
|
|
67
|
-
fs.rmSync(templateOwned);
|
|
68
|
-
fs.rmSync(cursorRules);
|
|
69
|
-
fs.mkdirSync(path.dirname(userSkill), { recursive: true });
|
|
70
|
-
fs.writeFileSync(userSkill, "# custom skill\n", "utf-8");
|
|
71
|
-
|
|
72
|
-
try {
|
|
73
|
-
execFileSync(process.execPath, [BUNDLE, "update"], {
|
|
74
|
-
cwd: dest,
|
|
75
|
-
encoding: "utf-8",
|
|
76
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
77
|
-
});
|
|
78
|
-
} catch (err) {
|
|
79
|
-
const out = `${err.stdout ?? ""}${err.stderr ?? ""}`.trim();
|
|
80
|
-
fail(`Pass 1: \`sailor update\` exited non-zero.\n ${out || err.message}`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (!fs.existsSync(templateOwned))
|
|
84
|
-
fail(`Pass 1: update did not restore "${path.relative(dest, templateOwned)}"`);
|
|
85
|
-
if (!fs.existsSync(cursorRules))
|
|
86
|
-
fail(`Pass 1: update did not restore "${path.relative(dest, cursorRules)}"`);
|
|
87
|
-
if (!fs.existsSync(userSkill))
|
|
88
|
-
fail(`Pass 1: update removed user file "${path.relative(dest, userSkill)}" — must be preserved`);
|
|
89
|
-
|
|
90
|
-
console.log("✓ Pass 1 passed — template files restored, user skill preserved");
|
|
91
|
-
|
|
92
|
-
// ── PASS 2 — seeds missing user-space files ───────────────────────────────
|
|
93
|
-
const agentsMd = path.join(dest, "AGENTS.md");
|
|
94
|
-
const claudeMd = path.join(dest, "CLAUDE.md");
|
|
95
|
-
const dockerfile = path.join(dest, "Dockerfile");
|
|
96
|
-
const packageJson = path.join(dest, "package.json");
|
|
97
|
-
const srcDir = path.join(dest, "src");
|
|
98
|
-
|
|
99
|
-
// Record AGENTS.md content before update — it must not change.
|
|
100
|
-
const agentsContentBefore = fs.readFileSync(agentsMd, "utf-8");
|
|
101
|
-
|
|
102
|
-
fs.rmSync(packageJson);
|
|
103
|
-
fs.rmSync(srcDir, { recursive: true });
|
|
104
|
-
|
|
105
|
-
try {
|
|
106
|
-
execFileSync(process.execPath, [BUNDLE, "update"], {
|
|
107
|
-
cwd: dest,
|
|
108
|
-
encoding: "utf-8",
|
|
109
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
110
|
-
});
|
|
111
|
-
} catch (err) {
|
|
112
|
-
const out = `${err.stdout ?? ""}${err.stderr ?? ""}`.trim();
|
|
113
|
-
fail(`Pass 2: \`sailor update\` exited non-zero.\n ${out || err.message}`);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (!fs.existsSync(packageJson))
|
|
117
|
-
fail(`Pass 2: update did not re-add missing "package.json"`);
|
|
118
|
-
if (!fs.existsSync(srcDir))
|
|
119
|
-
fail(`Pass 2: update did not re-add missing "src/" directory`);
|
|
120
|
-
|
|
121
|
-
// AGENTS.md, CLAUDE.md, Dockerfile must not be overwritten.
|
|
122
|
-
const agentsContentAfter = fs.readFileSync(agentsMd, "utf-8");
|
|
123
|
-
if (agentsContentAfter !== agentsContentBefore)
|
|
124
|
-
fail(`Pass 2: update overwrote "AGENTS.md" — user-space files must never be overwritten`);
|
|
125
|
-
if (!fs.existsSync(claudeMd))
|
|
126
|
-
fail(`Pass 2: "CLAUDE.md" is missing after update`);
|
|
127
|
-
if (!fs.existsSync(dockerfile))
|
|
128
|
-
fail(`Pass 2: "Dockerfile" is missing after update`);
|
|
129
|
-
|
|
130
|
-
console.log("✓ Pass 2 passed — missing user-space files seeded, existing ones untouched");
|
|
131
|
-
|
|
132
|
-
// ── PASS 3 — stale path pruning ───────────────────────────────────────────
|
|
133
|
-
const staleSkill = path.join(dest, ".agents/skills/sail-ci/SKILL.md");
|
|
134
|
-
fs.mkdirSync(path.dirname(staleSkill), { recursive: true });
|
|
135
|
-
fs.writeFileSync(staleSkill, "# old sail-ci skill\n", "utf-8");
|
|
136
|
-
|
|
137
|
-
try {
|
|
138
|
-
execFileSync(process.execPath, [BUNDLE, "update"], {
|
|
139
|
-
cwd: dest,
|
|
140
|
-
encoding: "utf-8",
|
|
141
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
142
|
-
});
|
|
143
|
-
} catch (err) {
|
|
144
|
-
const out = `${err.stdout ?? ""}${err.stderr ?? ""}`.trim();
|
|
145
|
-
fail(`Pass 3: \`sailor update\` exited non-zero.\n ${out || err.message}`);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (fs.existsSync(path.join(dest, ".agents/skills/sail-ci")))
|
|
149
|
-
fail(`Pass 3: stale ".agents/skills/sail-ci" was not removed`);
|
|
150
|
-
if (!fs.existsSync(path.join(dest, ".agents/skills/sail-automation/SKILL.md")))
|
|
151
|
-
fail(`Pass 3: ".agents/skills/sail-automation/SKILL.md" missing after update`);
|
|
152
|
-
|
|
153
|
-
console.log("✓ Pass 3 passed — stale sail-ci skill pruned, sail-automation present");
|
|
154
|
-
|
|
155
|
-
// ── PASS 4 — init-on-existing errors ──────────────────────────────────────
|
|
156
|
-
let initRejected = false;
|
|
157
|
-
let initOutput = "";
|
|
158
|
-
try {
|
|
159
|
-
initOutput = execFileSync(process.execPath, [BUNDLE, "init"], {
|
|
160
|
-
cwd: dest,
|
|
161
|
-
encoding: "utf-8",
|
|
162
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
163
|
-
});
|
|
164
|
-
} catch (err) {
|
|
165
|
-
initRejected = true;
|
|
166
|
-
initOutput = `${err.stdout ?? ""}${err.stderr ?? ""}`.trim();
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (!initRejected)
|
|
170
|
-
fail(`Pass 4: \`sailor init\` on existing project did not exit non-zero — should refuse`);
|
|
171
|
-
if (!/already initialized/i.test(initOutput))
|
|
172
|
-
fail(`Pass 4: error message did not mention "already initialized".\n output: ${initOutput}`);
|
|
173
|
-
|
|
174
|
-
console.log("✓ Pass 4 passed — init on existing project correctly refused");
|
|
175
|
-
} finally {
|
|
176
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
177
|
-
}
|
package/scripts/clean.mjs
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { rmSync } from "node:fs";
|
|
2
|
-
|
|
3
|
-
const targets = [
|
|
4
|
-
"node_modules",
|
|
5
|
-
"packages/sdk/node_modules",
|
|
6
|
-
"packages/sdk/dist",
|
|
7
|
-
"packages/sdk/tsconfig.tsbuildinfo",
|
|
8
|
-
"packages/cli/node_modules",
|
|
9
|
-
"packages/cli/dist",
|
|
10
|
-
"packages/ui/node_modules",
|
|
11
|
-
"packages/ui/dist",
|
|
12
|
-
];
|
|
13
|
-
|
|
14
|
-
for (const p of targets) {
|
|
15
|
-
rmSync(p, { recursive: true, force: true });
|
|
16
|
-
console.log(` removed ${p}`);
|
|
17
|
-
}
|
package/scripts/pack.mjs
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// Build the publishable npm package as a .tgz archive — the npm analog of `docker build`.
|
|
2
|
-
// Packs under the canonical published name (@sail.money/sailor) so the artifact installs and
|
|
3
|
-
// resolves exactly like the registry package; CI applies the same rename at publish time.
|
|
4
|
-
// ponytail: .tgz is npm's native archive (install offline with `npm i ./<file>.tgz`). For a
|
|
5
|
-
// literal .zip, unpack the tgz and re-zip — not added until something actually needs it.
|
|
6
|
-
import { execSync } from "node:child_process";
|
|
7
|
-
import { readFileSync, writeFileSync } from "node:fs";
|
|
8
|
-
|
|
9
|
-
const PKG = "package.json";
|
|
10
|
-
const CANONICAL = "@sail.money/sailor";
|
|
11
|
-
|
|
12
|
-
const original = readFileSync(PKG, "utf8");
|
|
13
|
-
try {
|
|
14
|
-
const manifest = JSON.parse(original);
|
|
15
|
-
if (manifest.name !== CANONICAL) {
|
|
16
|
-
writeFileSync(PKG, `${JSON.stringify({ ...manifest, name: CANONICAL }, null, 2)}\n`);
|
|
17
|
-
}
|
|
18
|
-
execSync("npm pack", { stdio: "inherit" }); // emits sail.money-sailor-<version>.tgz
|
|
19
|
-
} finally {
|
|
20
|
-
writeFileSync(PKG, original); // restore the working manifest verbatim
|
|
21
|
-
}
|
|
File without changes
|
/package/{examples → templates/default/examples}/custom-mandate/mandates/BoundedCallPermission.sol
RENAMED
|
File without changes
|