@fangorn-network/westmarch 2026.10.20-dev → 2026.10.22-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/docs/app-to-agent.md +48 -46
- package/package.json +6 -5
- package/site/dist/assets/AccountNotFoundScreen-C4njXc69-DyVH4CEz.js +1 -0
- package/site/dist/assets/AddFundsSelectionScreen-RAoCn7ej-Dz1--SS9.js +31 -0
- package/site/dist/assets/Address-H8kD1d9O-BdFZmRwI.js +17 -0
- package/site/dist/assets/AffirmativeConsentScreen-BG0MJxku-CxaCAisL.js +6 -0
- package/site/dist/assets/AllowlistRejectionScreen-Cae6e1Od-JGk7vndN.js +1 -0
- package/site/dist/assets/ApiController-CTLbMCcH.js +5 -0
- package/site/dist/assets/ArrowsRightLeftIcon-B8g9adpz.js +1 -0
- package/site/dist/assets/AuthenticateWithWalletScreen-CU6hIcFT-CXD9_OP8.js +1 -0
- package/site/dist/assets/AwaitingEvmToSolBridgingScreen-D0e_sZMS-BtJCglvU.js +1 -0
- package/site/dist/assets/AwaitingExternalEthereumTransferScreen-ur5HL4R7-BgC2TsqH.js +1 -0
- package/site/dist/assets/AwaitingPasswordlessCodeScreen-DRHz76mM-B9OzLeEO.js +103 -0
- package/site/dist/assets/AwaitingSolToEvmBridgingScreen-CdLRrGD2-C7r5snUL.js +1 -0
- package/site/dist/assets/BridgeNetworkSelectionView-CFGjB2nO-BTV0NRio.js +68 -0
- package/site/dist/assets/CaptchaScreen-DbpvkIGx-7rSZIuM-.js +1 -0
- package/site/dist/assets/CheckCircleIcon-B1l17ioc.js +1 -0
- package/site/dist/assets/CheckCircleIcon-BGSI8nKf.js +1 -0
- package/site/dist/assets/Checkbox-D1EDeo41-BUfq0w99.js +52 -0
- package/site/dist/assets/ChevronDownIcon-B6uJvPHu.js +1 -0
- package/site/dist/assets/Chip-CZKIKt9K-r9Nk__0-.js +26 -0
- package/site/dist/assets/CoinbaseOnrampStatusScreen-BbyCJDXL-DWWNHxmR.js +16 -0
- package/site/dist/assets/ConnectEmailForm-B-VRE0MN-CRQwS0Xu.js +3 -0
- package/site/dist/assets/ConnectLedgerScreen-DWHABGot-CZcCt31O.js +10 -0
- package/site/dist/assets/ConnectOnlyLandingScreen-CZYx9Bmp-C5IOf-SQ.js +1 -0
- package/site/dist/assets/ConnectOnlyStatusScreen-DCRzjxHx-cwg74F3A.js +1 -0
- package/site/dist/assets/ConnectOrCreateScreen-CUUYUO07-D28oeK6b.js +1 -0
- package/site/dist/assets/ConnectPhoneForm-Dek5xn4C-EEdkKeTp.js +95 -0
- package/site/dist/assets/ConnectWalletView-DqI-PTvX-C2mEzukj.js +74 -0
- package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-CH_7r8iV.js +7 -0
- package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-Z33kis0B.js +1 -0
- package/site/dist/assets/ConnectorUtil-DH4NePk5.js +21 -0
- package/site/dist/assets/ConstantsUtil-DmLsRHAl.js +198 -0
- package/site/dist/assets/CopyToClipboard-i_OQSBJr-_G88JCVR.js +39 -0
- package/site/dist/assets/CopyableText-CQapvaMr-CGGfc_zM.js +28 -0
- package/site/dist/assets/CrossAppAuthScreen-CLw7ymZq-C9Okoc0V.js +1 -0
- package/site/dist/assets/CustomLandingScreenView-Cm_MBSyX-D2l6hdSl.js +22 -0
- package/site/dist/assets/DelegatedActionsConsentScreen-DYF2U4y5-Dda3KKqS.js +1 -0
- package/site/dist/assets/DelegatedActionsRevokeScreen-bPp6Uwyh-DG8kJPt1.js +1 -0
- package/site/dist/assets/DepositAddressAddressStepView-4vdkb55L-CcOUfn6f.js +187 -0
- package/site/dist/assets/DepositAddressScreen-DBLRs7aI-DeituDNh.js +8 -0
- package/site/dist/assets/DepositAddressV3Screen-CDqIEMQw-FDg6K14-.js +1 -0
- package/site/dist/assets/{EmailInputForm-Cqo1mda8-CZD4r5LM.js → EmailInputForm-Cqo1mda8-BmbxvPHC.js} +11 -11
- package/site/dist/assets/EmbeddedWalletConnectingScreen-D4T7DUzs-B05CQ9rx.js +1 -0
- package/site/dist/assets/EmbeddedWalletCreatedScreen-D7WhW5ve-Cxd1b9XH.js +1 -0
- package/site/dist/assets/EmbeddedWalletKeyExportScreen-CqV4NYQ3-CrJy0ViX.js +23 -0
- package/site/dist/assets/EmbeddedWalletOnAccountCreateScreen-BoKb3Q2S-Bakaa3zu.js +1 -0
- package/site/dist/assets/EmbeddedWalletPasswordUpdateScreen-D3rMlqS7-j78vKrcj.js +1 -0
- package/site/dist/assets/EmbeddedWalletPasswordUpdateSplashScreen-BPFkWJeE-D3dr7W9_.js +1 -0
- package/site/dist/assets/EnrollTotp-Dibew4dp-BXbYV8nI.js +66 -0
- package/site/dist/assets/EnvelopeIcon-DjPofnRI.js +1 -0
- package/site/dist/assets/ErrorBanner-BcpGRt0h-BhH6_V-9.js +21 -0
- package/site/dist/assets/{ErrorMessage-D8VaAP5m-oSruKN8L.js → ErrorMessage-D8VaAP5m-Bs7uX2a9.js} +2 -2
- package/site/dist/assets/ErrorScreen-DipdTWzE-BgPRgnOb.js +4 -0
- package/site/dist/assets/ErrorScreen-DipdTWzE-CvxXC6pz.js +1 -0
- package/site/dist/assets/ExclamationCircleIcon-BE-WGrut.js +1 -0
- package/site/dist/assets/ExclamationTriangleIcon-Ca1Xlc_f.js +1 -0
- package/site/dist/assets/FarcasterConnectStatusScreen-51tjUxqq-De2JvZdV.js +75 -0
- package/site/dist/assets/FarcasterSignerStatusScreen-6x-Uh95G-bLp3hXoO.js +28 -0
- package/site/dist/assets/FiatOnrampScreen-BAhYeiTI-Jr6D6JiZ.js +491 -0
- package/site/dist/assets/FingerPrintIcon-DOCbS93y.js +1 -0
- package/site/dist/assets/FundSolWalletWithExternalSolanaWallet-WtLwYaOl-A_G5kfa1.js +1 -0
- package/site/dist/assets/FundWalletMethodHeader-BWNkokCT-LPv35wkD.js +1 -0
- package/site/dist/assets/FundWithBankDepositScreen-DajkHxBD-0hfGrfvf.js +58 -0
- package/site/dist/assets/FundingEditAmountScreen-CpvpiO4M-Dz0s_NWR.js +1 -0
- package/site/dist/assets/FundingMethodSelectionScreen-Db7vhRlE-ZGm-3-Io.js +1 -0
- package/site/dist/assets/GlobeAltIcon-BBRl2MMn.js +1 -0
- package/site/dist/assets/GooglePay-B53WnudL-BGiVpB8y.js +1 -0
- package/site/dist/assets/HCaptchaWrapper-CUi9LJsp-CHdfIeD_.js +4 -0
- package/site/dist/assets/InAppBrowserLoginNotPossible-BMR9br1T-Cgoiow3m.js +1 -0
- package/site/dist/assets/InfoBanner-Cb3p1z12-_YqQmRiu.js +22 -0
- package/site/dist/assets/InjectedWalletIcon-DLcYOGDj-tuIrKQHH.js +1 -0
- package/site/dist/assets/InstallWalletScreen-DTA8dwLv-BMU_wa61.js +1 -0
- package/site/dist/assets/{JsonTree-BHzNC-ic-pAEq1bl9.js → JsonTree-BHzNC-ic-DcVr0YF0.js} +3 -3
- package/site/dist/assets/{LabelXs-oqZNqbm_-D09YjVR4.js → LabelXs-oqZNqbm_-CNprGVQM.js} +2 -2
- package/site/dist/assets/LandingScreen-CGWUoSUG-fH6rsQen.js +1 -0
- package/site/dist/assets/{Layouts-BMRfo5hw-D2u1-w8g.js → Layouts-BMRfo5hw-e-sepi6F.js} +16 -16
- package/site/dist/assets/Link-BdDilT2T-BdwlRJch.js +40 -0
- package/site/dist/assets/LinkConflictScreen-C3ZEPsgl-BXKN2Qm5.js +77 -0
- package/site/dist/assets/LinkEmailScreen-dKo9frwc-Cyn7Q8p1.js +1 -0
- package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-CWiqnwLM.js +117 -0
- package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-YmDevJzf.js +1 -0
- package/site/dist/assets/LinkPhoneScreen-oIUpfj0w-h7shW-Ay.js +1 -0
- package/site/dist/assets/Loader-UAZqxsnw-DJEVblm1.js +62 -0
- package/site/dist/assets/{LoadingSkeleton-BMsgO5PV-BRMh4Fv4.js → LoadingSkeleton-BMsgO5PV-D2atjsP5.js} +6 -6
- package/site/dist/assets/LockClosedIcon-9EFzWK1C.js +1 -0
- package/site/dist/assets/LoginFailedScreen-CN0dJV6U-By3Si77a.js +1 -0
- package/site/dist/assets/ManualTransferScreen-CHqcuqbs-BAHPY8rs.js +1 -0
- package/site/dist/assets/MfaAuthEnrollmentFlowScreen-Dj7gPTRC-CLjffFG1.js +1 -0
- package/site/dist/assets/MfaAuthVerifyFlowScreen-DbFpyWMy-BmQg1Y61.js +1 -0
- package/site/dist/assets/MfaEnrollmentFlowScreen-DhLnGgnr-DmBtTtlw.js +1 -0
- package/site/dist/assets/MfaVerifyFlowScreen-C_XPjMRP-4a683Bmf.js +1 -0
- package/site/dist/assets/ModalFooter-BCuEK_nz-C_71qsaz.js +403 -0
- package/site/dist/assets/MoonpayStatusScreen-CzTUtokc-DEHHcEf8.js +16 -0
- package/site/dist/assets/OAuthStatusScreen-ufbOa-da-BjAb_WsY.js +1 -0
- package/site/dist/assets/OpenLink-CUpJ1mOr-BLWFsPOW.js +39 -0
- package/site/dist/assets/PasskeySelectSignupOrLogin-xh2ScC_l-2PJTJxX-.js +1 -0
- package/site/dist/assets/PasskeyStatusScreen-Bla8MaOk-DCEg761l.js +6 -0
- package/site/dist/assets/PasswordRecoveryScreen-awGXZkQk-8nVjNc8k.js +20 -0
- package/site/dist/assets/{PhArrowCircleDown-BtlNV0TZ.js → PhArrowCircleDown-D97G-BOA.js} +5 -5
- package/site/dist/assets/PhArrowClockwise-DVgyFuez.js +14 -0
- package/site/dist/assets/PhArrowDown-87b1BizM.js +14 -0
- package/site/dist/assets/PhArrowLeft-Da0MfnbK.js +14 -0
- package/site/dist/assets/PhArrowRight-AdrIL4DW.js +14 -0
- package/site/dist/assets/{PhArrowSquareOut-DnQ7n_B4.js → PhArrowSquareOut-Bk2CMG3I.js} +5 -5
- package/site/dist/assets/PhArrowUp-4sgyKPGx.js +14 -0
- package/site/dist/assets/PhArrowUpRight-BNghD2zq.js +14 -0
- package/site/dist/assets/{PhArrowsClockwise-Brtx2Re-.js → PhArrowsClockwise-BXRn1GEl.js} +5 -5
- package/site/dist/assets/{PhArrowsDownUp-PZosTqZG.js → PhArrowsDownUp-DM09Jo_3.js} +5 -5
- package/site/dist/assets/PhArrowsLeftRight-MuKBLUoF.js +14 -0
- package/site/dist/assets/{PhBank-hhPAIPVb.js → PhBank-fHbgCqqZ.js} +5 -5
- package/site/dist/assets/PhBrowser-2-9m-AkM.js +14 -0
- package/site/dist/assets/PhCaretDown-BDNabFuL.js +14 -0
- package/site/dist/assets/PhCaretLeft-CI460R-A.js +14 -0
- package/site/dist/assets/PhCaretRight-D7ZS3Ls8.js +14 -0
- package/site/dist/assets/PhCaretUp-C-iIfyvO.js +14 -0
- package/site/dist/assets/PhCheck-DxQXn57r.js +14 -0
- package/site/dist/assets/{PhCircleHalf-Bk9C4DvT.js → PhCircleHalf-MJZeRBGF.js} +5 -5
- package/site/dist/assets/PhClock-x3MS3Mwi.js +14 -0
- package/site/dist/assets/{PhCompass-Df1ugFO-.js → PhCompass-hYn3HhGN.js} +5 -5
- package/site/dist/assets/PhCopy-CWNYcABI.js +14 -0
- package/site/dist/assets/{PhCreditCard-CZpdid2n.js → PhCreditCard-Fy4pzwtt.js} +5 -5
- package/site/dist/assets/{PhCurrencyDollar-B6IKKjue.js → PhCurrencyDollar-BgiaenCi.js} +5 -5
- package/site/dist/assets/{PhDesktop-BuCDXYJj.js → PhDesktop-CxrzCSv5.js} +5 -5
- package/site/dist/assets/PhDeviceMobile-CsyA5Goi.js +14 -0
- package/site/dist/assets/PhDotsThree-D-k1BiYg.js +14 -0
- package/site/dist/assets/PhEnvelope-D8kzeNox.js +14 -0
- package/site/dist/assets/PhFunnelSimple-CfQs5DAW.js +14 -0
- package/site/dist/assets/{PhGlobe-q1mqj65V.js → PhGlobe-DvmSc9_A.js} +5 -5
- package/site/dist/assets/{PhIdentificationCard-BeLXJpfZ.js → PhIdentificationCard-CfkZm-5K.js} +5 -5
- package/site/dist/assets/{PhImage-BYrKfN9k.js → PhImage-Cf0J2ZfJ.js} +5 -5
- package/site/dist/assets/{PhInfo-X33f06Ej.js → PhInfo-Bwi51-2X.js} +5 -5
- package/site/dist/assets/{PhLightbulb-DMZJsowR.js → PhLightbulb-C4FZV7Es.js} +5 -5
- package/site/dist/assets/PhMagnifyingGlass-C9u8jSCJ.js +14 -0
- package/site/dist/assets/{PhPaperPlaneRight-Dvo-nXr9.js → PhPaperPlaneRight-zxQVvPLX.js} +5 -5
- package/site/dist/assets/PhPlus-C4UoW-2n.js +14 -0
- package/site/dist/assets/{PhPower-D8-AcNM6.js → PhPower-CFyWDmgD.js} +5 -5
- package/site/dist/assets/{PhPuzzlePiece-C-7mYqGO.js → PhPuzzlePiece-BjoNVfST.js} +5 -5
- package/site/dist/assets/{PhQrCode-uIXlI5ER.js → PhQrCode-CP3tFauY.js} +5 -5
- package/site/dist/assets/{PhQuestion-rUoqC2sC.js → PhQuestion-wOWJBd3G.js} +5 -5
- package/site/dist/assets/{PhQuestionMark-W55Txvvb.js → PhQuestionMark-CV0k9C0Y.js} +5 -5
- package/site/dist/assets/{PhSealCheck-BeVLq9PH.js → PhSealCheck-vIKzREuN.js} +5 -5
- package/site/dist/assets/{PhSignOut-Cq2PivQ6.js → PhSignOut-CxELV-i0.js} +5 -5
- package/site/dist/assets/{PhSpinner-CZMtAFdX.js → PhSpinner-CGDmbzUd.js} +5 -5
- package/site/dist/assets/{PhTrash-BamrmMsN.js → PhTrash-C9PD0SAt.js} +5 -5
- package/site/dist/assets/{PhUser-A2fxqIV0.js → PhUser-0sWNXQeZ.js} +5 -5
- package/site/dist/assets/{PhVault-B8m1usHw.js → PhVault-6JTskUcC.js} +5 -5
- package/site/dist/assets/{PhWarning-CpkID9oi.js → PhWarning-CoKs3gz6.js} +5 -5
- package/site/dist/assets/PhWarningCircle-BXHw1fCt.js +14 -0
- package/site/dist/assets/PhX-DX0SFIqC.js +14 -0
- package/site/dist/assets/PhoneIcon-CZ47md80.js +1 -0
- package/site/dist/assets/PinInput-DbZ0b1i1-BrTXu3Km.js +247 -0
- package/site/dist/assets/PrivyPluginContext-DA-yS5vO-CY60yubk.js +1 -0
- package/site/dist/assets/QrCode-DbnZwlkH-CcMrWV5D.js +22 -0
- package/site/dist/assets/RecoveryOAuthStatusScreen-CsgtTI2x-DgeDnHOK.js +1 -0
- package/site/dist/assets/RecoveryPasswordCreateScreen-Be-qJ-LU-CvJJwLhK.js +1 -0
- package/site/dist/assets/RecoverySelectionScreen-D1iGtpmi-CADtGtSV.js +7 -0
- package/site/dist/assets/SIWXUtil-Cpiv91-M.js +1 -0
- package/site/dist/assets/{Screen-D30meWsY-DDum2qlY.js → Screen-D30meWsY-vEusJ7KX.js} +22 -22
- package/site/dist/assets/{ScreenHeader-CHmc4-Lu-BqrAEXbV.js → ScreenHeader-CHmc4-Lu-BvGTLg53.js} +4 -4
- package/site/dist/assets/ScreenLayout-OwaQQcxH-cfOTmyl0.js +1 -0
- package/site/dist/assets/{SelectSourceAsset-CWFog6gm-8iXuqbAs.js → SelectSourceAsset-CWFog6gm-DxYklZYs.js} +18 -18
- package/site/dist/assets/SetAutomaticRecoveryScreen-BO_OEqAZ-oeqeo05x.js +14 -0
- package/site/dist/assets/SetWalletPasswordForm-DwCTVtAh-BxFee9UA.js +11 -0
- package/site/dist/assets/ShieldCheckIcon-eFjsosCA.js +1 -0
- package/site/dist/assets/SignRequestScreen-BHKv32KR-z8ixfIma.js +26 -0
- package/site/dist/assets/SolanaWalletConnector-C7Lqk-Wz-Bc_lvdiF.js +1 -0
- package/site/dist/assets/{StackedContainer-B2vaEl56-C-ojzCoQ.js → StackedContainer-B2vaEl56-Do5dXB8-.js} +2 -2
- package/site/dist/assets/StandardSignAndSendTransactionScreen-CfhIXVtd-DudetZAc.js +20 -0
- package/site/dist/assets/{Subtitle-CV-2yKE4-o-1FQLlX.js → Subtitle-CV-2yKE4-DV0o1av3.js} +2 -2
- package/site/dist/assets/TelegramAuthScreen-UL9zLfO8-Bo3sONvf.js +1 -0
- package/site/dist/assets/{Title-BnzYV3Is-RX1f0RV-.js → Title-BnzYV3Is-C3qOPnO_.js} +2 -2
- package/site/dist/assets/TodoList-DnyULl18-BvxvubbF.js +36 -0
- package/site/dist/assets/TransactionDetails-e9nesl30-WWflkOIi.js +109 -0
- package/site/dist/assets/TransactionErrorView-BDBNqA_f-CotYKcgf.js +178 -0
- package/site/dist/assets/TransferFromWalletScreen-Qvn1Yuno-sVFlWqa8.js +31 -0
- package/site/dist/assets/TransferOrBridgeLoadingScreen-Dl1I_iIz-CV2-mY19.js +6 -0
- package/site/dist/assets/TurnstileWrapper-B7sNddys-oPbuMTQt.js +1 -0
- package/site/dist/assets/UpdateEmailScreen-DVOhPV0H-D_mjSpAy.js +1 -0
- package/site/dist/assets/UpdatePhoneScreen-CXRswTNZ-6RLG0ahv.js +1 -0
- package/site/dist/assets/UserLimitReachedScreen-5we2DHn8-CaVN0bti.js +1 -0
- package/site/dist/assets/{Value-DTgR824E-DZpvBCWi.js → Value-DTgR824E-Bp6WGZZm.js} +7 -7
- package/site/dist/assets/WalletCards-DH1rqayz-D3cOTb9x.js +1 -0
- package/site/dist/assets/WalletIcon-DOIZhb2l.js +1 -0
- package/site/dist/assets/WalletInfoCard-sq_2wgFg-bOqfl5MA.js +29 -0
- package/site/dist/assets/WalletInterstitialScreen-Sh7LfsAh-DWaVkMCA.js +1 -0
- package/site/dist/assets/WalletLink-DK5LB5Ha-DjUZvqs-.js +20 -0
- package/site/dist/assets/WalletOverflowButton-bfCnp-9T-B6P7DQXA.js +1 -0
- package/site/dist/assets/WarningBanner-ZZqCEtZK-Bc2YKZb7.js +21 -0
- package/site/dist/assets/__vite-browser-external-NciY4Vu1.js +1 -0
- package/site/dist/assets/_esm-BZP3cXTv.js +1 -0
- package/site/dist/assets/_esm-ZmzBJpEs.js +6 -0
- package/site/dist/assets/accounts-D4AXF17G.js +1 -0
- package/site/dist/assets/accounts-IkdFx9nq.js +1 -0
- package/site/dist/assets/analytics-mkkvFRju-BRBcadka.js +1 -0
- package/site/dist/assets/baseSepolia-Bn1j1Ysw.js +1 -0
- package/site/dist/assets/basic-Cz1YiCSk.js +1575 -0
- package/site/dist/assets/capitalizeFirstLetter-DmLYqXsO-DtOXx-2n.js +1 -0
- package/site/dist/assets/ccip-B1J3oTZx.js +7 -0
- package/site/dist/assets/ccip-Bd7261zy.js +1 -0
- package/site/dist/assets/ccip-D6EHKpjI.js +1 -0
- package/site/dist/assets/chain-scefkYIH.js +5 -0
- package/site/dist/assets/check-DHnllI8N.js +1 -0
- package/site/dist/assets/chevron-down-1y-r4bGO.js +1 -0
- package/site/dist/assets/circle-alert-OwxamXUX.js +1 -0
- package/site/dist/assets/circle-check-big-3sZGVC10.js +1 -0
- package/site/dist/assets/circle-x-DQjNUV9J.js +1 -0
- package/site/dist/assets/client-B-BpRtwY.js +1 -0
- package/site/dist/assets/client-BfIR1FvH.js +9 -0
- package/site/dist/assets/coinbase-DCPC2L_R-YEuIn3jh.js +3 -0
- package/site/dist/assets/copy-DMOX_yn7.js +1 -0
- package/site/dist/assets/core-GIEmxmAa.js +12 -0
- package/site/dist/assets/createLucideIcon-BsERoFTA.js +1 -0
- package/site/dist/assets/defineChain-B-SQDLTG.js +1 -0
- package/site/dist/assets/dijkstra-CY95afk4.js +1 -0
- package/site/dist/assets/dist-CoS6E-3x.js +1 -0
- package/site/dist/assets/dist-Cp6IXeJd.js +1 -0
- package/site/dist/assets/dist-CrNxmdZj.js +1 -0
- package/site/dist/assets/dist-DYGtf4F0.js +16 -0
- package/site/dist/assets/embed.worker-Cnl4VGr3.js +1 -0
- package/site/dist/assets/errors-BQ3N-RVt-CZPAWCgC.js +1 -0
- package/site/dist/assets/esm-C3DslVJx.js +1 -0
- package/site/dist/assets/esm-Ci1ogKuK.js +1 -0
- package/site/dist/assets/esm-Co94ENUV.js +37 -0
- package/site/dist/assets/esm-bb8SANZh.js +1 -0
- package/site/dist/assets/esm-n2lWo7kz.js +1 -0
- package/site/dist/assets/ethers-zTjbodk5-Cs648CnD.js +1 -0
- package/site/dist/assets/eventemitter3-Dzc_0Uq2.js +1 -0
- package/site/dist/assets/external-link-BBPG3rG7.js +1 -0
- package/site/dist/assets/farcaster-DPlSjvF5-CzBCmgyL.js +1 -0
- package/site/dist/assets/features-CuiHbgEJ.js +2 -0
- package/site/dist/assets/fingerprint-pattern-CjLtyIxB.js +1 -0
- package/site/dist/assets/floating-ui.react-DmaCfayr.js +1 -0
- package/site/dist/assets/floating-ui.react-dom-CaoMF8mP.js +1 -0
- package/site/dist/assets/formatErc20TokenAmount-BuPk9xcy-BVqOKQif.js +1 -0
- package/site/dist/assets/formatter-CVbp4SlJ.js +1 -0
- package/site/dist/assets/get-entropy-details-for-user-dHRH5Gpi-BNiOFXbK.js +1 -0
- package/site/dist/assets/getChainName-DjpPdUSc-DUyKDrnp.js +1 -0
- package/site/dist/assets/getErc20Balance-jXNpFf0N-q4bV8kQq.js +1 -0
- package/site/dist/assets/getErc20TokenInfo-BNTrzLMP-DcnTFrXN.js +1 -0
- package/site/dist/assets/getFormattedUsdFromLamports-De3U9GlO-Gx4_wxON.js +1 -0
- package/site/dist/assets/getUsdcMintAddress-BVgm9GRo-r2UnDeEy.js +1 -0
- package/site/dist/assets/guards-BIW-GiMJ-D3tWTQAR.js +1 -0
- package/site/dist/assets/hooks.module-BYZGfwDl.js +1 -0
- package/site/dist/assets/hourglass-D_GfQdJr.js +1 -0
- package/site/dist/assets/id-UqEwL2BI-CTlvRMA5.js +1 -0
- package/site/dist/assets/index-BdEw5wyl-kLbhqLbv.js +1 -0
- package/site/dist/assets/index-C2h3EneX.js +8 -0
- package/site/dist/assets/{index-CWARkn2w-D6ikWJWj.js → index-CWARkn2w-DxuckIFn.js} +7 -7
- package/site/dist/assets/index-DvMddJcd-CNBb4VUn.js +12 -0
- package/site/dist/assets/index-YiCw0Y_x-Czl0tWfF.js +436 -0
- package/site/dist/assets/index.browser-B-i-Lj3J.js +1 -0
- package/site/dist/assets/index.browser-BMmUcykv.js +1 -0
- package/site/dist/assets/index.es-Crd0TyUS.js +2 -0
- package/site/dist/assets/index.es-DQbup1WG.js +3 -0
- package/site/dist/assets/isPaymentRequestAvailable-Bq1cemEn-Cjf3l05I.js +1 -0
- package/site/dist/assets/jsx-runtime-CndCZlyt.js +1 -0
- package/site/dist/assets/landmark-BZPqMFEf.js +1 -0
- package/site/dist/assets/lib-DGtzi2DK.js +1 -0
- package/site/dist/assets/localBatchGatewayRequest-B71J8sQ9.js +29 -0
- package/site/dist/assets/lock-DyN_c-ud.js +1 -0
- package/site/dist/assets/logger-CsXm3oIv-B0UYpNFI.js +1 -0
- package/site/dist/assets/mail-V_mcPb64.js +1 -0
- package/site/dist/assets/modal-context-CwmSeFcv-DPWNJrfK.js +1 -0
- package/site/dist/assets/native-BKj27wfc.js +1 -0
- package/site/dist/assets/ofetch.CWycOUEr-Duby3iHT.js +1 -0
- package/site/dist/assets/parseAbi-Csg-8t59.js +2 -0
- package/site/dist/assets/parseAbiParameters-BWbIMYe4.js +1 -0
- package/site/dist/assets/parseEther-CHS0GNkM.js +1 -0
- package/site/dist/assets/pkce-DXF0yKjP-7_VY-d83.js +1 -0
- package/site/dist/assets/preload-helper-CRzLMJPS.js +1 -0
- package/site/dist/assets/privy-context-81KmsBw2-DiR6-Yq8.js +2 -0
- package/site/dist/assets/property-DuZ9DLP4.js +3 -0
- package/site/dist/assets/react-BfYA1q0G.js +1 -0
- package/site/dist/assets/react-CK2HRI1t.js +1 -0
- package/site/dist/assets/react-DxGeY8B8.js +1 -0
- package/site/dist/assets/react-auth-sHnipzbS.js +1 -0
- package/site/dist/assets/react-dom-BI2Koe4o.js +1 -0
- package/site/dist/assets/reservoir-x-nGuZkT-BguVFH3D.js +1 -0
- package/site/dist/assets/roles-BDPDWrwo.js +1 -0
- package/site/dist/assets/roles-DKPW79Ca.js +1 -0
- package/site/dist/assets/rolldown-runtime-Bjp52BOI.js +1 -0
- package/site/dist/assets/safe-url-D7SRPu33-CkMedGro.js +1 -0
- package/site/dist/assets/secp256k1-BeYL8aZl.js +1 -0
- package/site/dist/assets/secp256k1-Bh4MSkhz.js +1 -0
- package/site/dist/assets/secp256k1-Ci4cqHl0.js +1 -0
- package/site/dist/assets/secp256k1-DsxXqbXv.js +1 -0
- package/site/dist/assets/secp256k1-N9RUmafO.js +1 -0
- package/site/dist/assets/serializeAuthorizationList-DGMik9Wx.js +1 -0
- package/site/dist/assets/serializeSignature-CWKpxoab.js +2 -0
- package/site/dist/assets/sha2-C6s7zZmb.js +1 -0
- package/site/dist/assets/{shared-DRZUmnL5-MWD-C-pp.js → shared-DRZUmnL5-BewE5wK8.js} +33 -33
- package/site/dist/assets/{shared-FM0rljBt-c4eSjzGj.js → shared-FM0rljBt-CxLACri_.js} +6 -6
- package/site/dist/assets/shouldProceedtoEmbeddedWalletCreationFlow-B3vyavrh-BkAKsRNi.js +1 -0
- package/site/dist/assets/simulateTransaction-CfuOrae4-PjA_tGjX.js +1 -0
- package/site/dist/assets/smartphone-3p8nFSTE.js +1 -0
- package/site/dist/assets/src-BBjkfi-Q.js +1 -0
- package/site/dist/assets/storage-Ufl800Ne-1qCR2JMO.js +8 -0
- package/site/dist/assets/stringify-DqUj9VzO.js +20 -0
- package/site/dist/assets/stripe.esm-DEi2D291.js +2 -0
- package/site/dist/assets/styles-BsotlekN-Aq27nZGc.js +9 -0
- package/site/dist/assets/{styles-Cm9H63WO-Cv1TbqYi.js → styles-Cm9H63WO-p_ic_dxE.js} +17 -17
- package/site/dist/assets/{styles-DVyDvTdj-CI4xZNHp.js → styles-DVyDvTdj-CjsWqAld.js} +8 -8
- package/site/dist/assets/{styles-hslXy6xG-DeVcFoDD.js → styles-hslXy6xG-D5QHIrJU.js} +23 -23
- package/site/dist/assets/telegram-B-JqnkqZ-Dqkm4rDn.js +1 -0
- package/site/dist/assets/to-ui-error-DWe-qwS3-Bi1HUQI9.js +4 -0
- package/site/dist/assets/toViemAccount-B5iDGq1b-CdFZwv07.js +2 -0
- package/site/dist/assets/transaction-BNTP-bFm-M5tJx8vY.js +1 -0
- package/site/dist/assets/transfer-6YztDh-t-BVQkTvG-.js +1 -0
- package/site/dist/assets/transformers.web-BTyOEJ0C.js +40 -0
- package/site/dist/assets/transformers.web-CUZUFjAK.js +49 -0
- package/site/dist/assets/triangle-alert-BG3Qw-Hq.js +1 -0
- package/site/dist/assets/twitch-5IOe4sIQ-CaXHFlAu.js +1 -0
- package/site/dist/assets/types-4CuOD23i.js +1 -0
- package/site/dist/assets/use-headless-crypto-deposit-Yn-QRLB3-CQqeyhGY.js +1 -0
- package/site/dist/assets/use-unlink-wallet-BKK4_5Ur-C0xQN_Lp.js +1 -0
- package/site/dist/assets/useActiveWallet-B-yZYGc6-BkK6rFBm.js +123 -0
- package/site/dist/assets/useGetSolPrice-x7gfUIHJ-CLVXqv6I.js +1 -0
- package/site/dist/assets/useGetTokenPrice-CaoUkb79-DAXXs3rs.js +1 -0
- package/site/dist/assets/useI18n-C-5n_noF-CGpkgIVy.js +1 -0
- package/site/dist/assets/useWalletBalance-CZnP5f_f-Cfd64m4n.js +1 -0
- package/site/dist/assets/useWallets-X1ndvJ_U-CAYqg7Za.js +1 -0
- package/site/dist/assets/utils-BkR7EQjg.js +1 -0
- package/site/dist/assets/utils-DJhBNOZA.js +1 -0
- package/site/dist/assets/utils-DdckVfQr.js +1 -0
- package/site/dist/assets/w3m-modal-B4H_uiPH.js +1174 -0
- package/site/dist/assets/wallet-BNI12IYk.js +1 -0
- package/site/dist/assets/wallet-CITSaPlB.js +2 -0
- package/site/dist/assets/wallet-connect-BvJtUsDt-CVlSNIXP.js +1 -0
- package/site/dist/assets/walletconnect-registry-xxG8XLCb-BpzpBq5s.js +1 -0
- package/site/dist/assets/walletconnect-v2-3frQFwbg-CzZ6oybX.js +12 -0
- package/site/dist/assets/{index-CztIxJB6.js → wui-ux-by-reown-XyHdtV1O.js} +296 -296
- package/site/dist/assets/x-gjDrY2rk.js +1 -0
- package/site/dist/index.html +5 -117
- package/site/worker.js +6 -30
- package/src/agent/mcp.js +47 -15
- package/src/agent/view-tools.js +3 -11
- package/src/agent/x402.js +3 -42
- package/src/discover/apps.js +37 -2
- package/src/discover/explore.js +19 -13
- package/src/publish/init.js +74 -0
- package/src/publish/ship.js +36 -79
- package/src/publish/view-cli.js +6 -3
- package/src/publish/view.js +27 -43
- package/template/.github/workflows/ship.yml +33 -0
- package/template/README.md +38 -0
- package/template/app.json +27 -0
- package/template/ci/ship.sh +21 -0
- package/template/eval/goals.md +7 -0
- package/template/eval/golden.jsonl +0 -0
- package/template/gitignore +3 -0
- package/template/package.json +8 -0
- package/site/dist/assets/AccountNotFoundScreen-C4njXc69-RUyAWRzV.js +0 -1
- package/site/dist/assets/AddFundsSelectionScreen-RAoCn7ej-ZV-LlYBe.js +0 -31
- package/site/dist/assets/Address-H8kD1d9O-CGQnt7Pu.js +0 -17
- package/site/dist/assets/AffirmativeConsentScreen-BG0MJxku-CKn2JLwq.js +0 -6
- package/site/dist/assets/AllowlistRejectionScreen-Cae6e1Od-9oIP9fma.js +0 -1
- package/site/dist/assets/ArrowsRightLeftIcon-BEhBD_6N.js +0 -1
- package/site/dist/assets/AuthenticateWithWalletScreen-CU6hIcFT-D1wLlSJs.js +0 -1
- package/site/dist/assets/AwaitingEvmToSolBridgingScreen-D0e_sZMS-CSBbHTyz.js +0 -1
- package/site/dist/assets/AwaitingExternalEthereumTransferScreen-ur5HL4R7-BsRq-xBt.js +0 -1
- package/site/dist/assets/AwaitingPasswordlessCodeScreen-DRHz76mM-BPdhsKvN.js +0 -103
- package/site/dist/assets/AwaitingSolToEvmBridgingScreen-CdLRrGD2-CEGNdrkr.js +0 -1
- package/site/dist/assets/BridgeNetworkSelectionView-CFGjB2nO-Da9P7eSx.js +0 -68
- package/site/dist/assets/CaptchaScreen-DbpvkIGx-BecgMnD_.js +0 -1
- package/site/dist/assets/CheckCircleIcon-DBiWFjO6.js +0 -1
- package/site/dist/assets/CheckCircleIcon-DzG2ROJZ.js +0 -1
- package/site/dist/assets/Checkbox-D1EDeo41-DMHcj9o_.js +0 -52
- package/site/dist/assets/ChevronDownIcon-2Os56gUt.js +0 -1
- package/site/dist/assets/Chip-CZKIKt9K-BWzs9fj5.js +0 -26
- package/site/dist/assets/CoinbaseOnrampStatusScreen-BbyCJDXL-CFvcSiDs.js +0 -16
- package/site/dist/assets/ConnectEmailForm-B-VRE0MN-BozkCg8q.js +0 -3
- package/site/dist/assets/ConnectLedgerScreen-DWHABGot-DaCnbBzh.js +0 -10
- package/site/dist/assets/ConnectOnlyLandingScreen-CZYx9Bmp-DUkCLkxD.js +0 -1
- package/site/dist/assets/ConnectOnlyStatusScreen-DCRzjxHx-Dv_5nMkZ.js +0 -1
- package/site/dist/assets/ConnectOrCreateScreen-CUUYUO07-DSGEeB3Y.js +0 -1
- package/site/dist/assets/ConnectPhoneForm-Dek5xn4C-C-s4s_Lq.js +0 -95
- package/site/dist/assets/ConnectWalletView-DqI-PTvX-BKX7fdYr.js +0 -74
- package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-DSoAuMFZ.js +0 -7
- package/site/dist/assets/CopyToClipboard-i_OQSBJr-CZTXyfV0.js +0 -39
- package/site/dist/assets/CopyableText-CQapvaMr-DHO818I0.js +0 -28
- package/site/dist/assets/CrossAppAuthScreen-CLw7ymZq-DW4nRGfz.js +0 -1
- package/site/dist/assets/CustomLandingScreenView-Cm_MBSyX-DH8Nnb4Y.js +0 -22
- package/site/dist/assets/DelegatedActionsConsentScreen-DYF2U4y5-gfUS_uV5.js +0 -1
- package/site/dist/assets/DelegatedActionsRevokeScreen-bPp6Uwyh-DZj9HTHc.js +0 -1
- package/site/dist/assets/DepositAddressAddressStepView-4vdkb55L-eHYsDK9W.js +0 -187
- package/site/dist/assets/DepositAddressScreen-DBLRs7aI-DK_XVgVk.js +0 -8
- package/site/dist/assets/DepositAddressV3Screen-CDqIEMQw-6gRZzhLe.js +0 -1
- package/site/dist/assets/EmbeddedWalletConnectingScreen-D4T7DUzs-BZu2ae0k.js +0 -1
- package/site/dist/assets/EmbeddedWalletCreatedScreen-D7WhW5ve-86pviemJ.js +0 -1
- package/site/dist/assets/EmbeddedWalletKeyExportScreen-CqV4NYQ3-vDcvT53Y.js +0 -23
- package/site/dist/assets/EmbeddedWalletOnAccountCreateScreen-BoKb3Q2S-rNJAtSJc.js +0 -1
- package/site/dist/assets/EmbeddedWalletPasswordUpdateScreen-D3rMlqS7-I8Q95280.js +0 -1
- package/site/dist/assets/EmbeddedWalletPasswordUpdateSplashScreen-BPFkWJeE-Coi7OxoI.js +0 -1
- package/site/dist/assets/EnrollTotp-Dibew4dp-DC7FrDgo.js +0 -66
- package/site/dist/assets/EnvelopeIcon-DY6ERnW7.js +0 -1
- package/site/dist/assets/ErrorBanner-BcpGRt0h-BvESwN99.js +0 -21
- package/site/dist/assets/ErrorScreen-DipdTWzE-DnKGxH1Z.js +0 -4
- package/site/dist/assets/ExclamationCircleIcon-BZhlqH0r.js +0 -1
- package/site/dist/assets/ExclamationTriangleIcon-CkAOJIYV.js +0 -1
- package/site/dist/assets/FarcasterConnectStatusScreen-51tjUxqq-4pi7jooW.js +0 -75
- package/site/dist/assets/FarcasterSignerStatusScreen-6x-Uh95G-z2XCMaLL.js +0 -28
- package/site/dist/assets/FiatOnrampScreen-BAhYeiTI-CBVA9v1-.js +0 -491
- package/site/dist/assets/FingerPrintIcon-ra2dqmJO.js +0 -1
- package/site/dist/assets/FundSolWalletWithExternalSolanaWallet-WtLwYaOl-DwAwc6Ny.js +0 -1
- package/site/dist/assets/FundWalletMethodHeader-BWNkokCT-CZszQsZf.js +0 -1
- package/site/dist/assets/FundWithBankDepositScreen-DajkHxBD-DfX6nvFQ.js +0 -58
- package/site/dist/assets/FundingEditAmountScreen-CpvpiO4M-CDS_sk_t.js +0 -1
- package/site/dist/assets/FundingMethodSelectionScreen-Db7vhRlE-CPfNQemT.js +0 -1
- package/site/dist/assets/GlobeAltIcon-SEUEIe_E.js +0 -1
- package/site/dist/assets/GooglePay-B53WnudL-aap7zwag.js +0 -1
- package/site/dist/assets/HCaptchaWrapper-CUi9LJsp-DgSjCjQI.js +0 -4
- package/site/dist/assets/InAppBrowserLoginNotPossible-BMR9br1T-DO4wICml.js +0 -1
- package/site/dist/assets/InfoBanner-Cb3p1z12-CDWt2ADo.js +0 -22
- package/site/dist/assets/InjectedWalletIcon-DLcYOGDj-Ba19XoBr.js +0 -1
- package/site/dist/assets/InstallWalletScreen-DTA8dwLv-DGpewEch.js +0 -1
- package/site/dist/assets/LandingScreen-CGWUoSUG-CUOCWUXd.js +0 -1
- package/site/dist/assets/Link-BdDilT2T-BYiP1zvW.js +0 -40
- package/site/dist/assets/LinkConflictScreen-C3ZEPsgl-Tb6cAepT.js +0 -77
- package/site/dist/assets/LinkEmailScreen-dKo9frwc-pq0NF2JO.js +0 -1
- package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-D9MOmDqg.js +0 -117
- package/site/dist/assets/LinkPhoneScreen-oIUpfj0w-B80UJqAZ.js +0 -1
- package/site/dist/assets/LockClosedIcon-BqkoEL9J.js +0 -1
- package/site/dist/assets/LoginFailedScreen-CN0dJV6U-DlnOM-Kh.js +0 -1
- package/site/dist/assets/ManualTransferScreen-CHqcuqbs-DSShupq9.js +0 -1
- package/site/dist/assets/MfaAuthEnrollmentFlowScreen-Dj7gPTRC-DUPV_SLA.js +0 -1
- package/site/dist/assets/MfaAuthVerifyFlowScreen-DbFpyWMy-D96GpzXX.js +0 -1
- package/site/dist/assets/MfaEnrollmentFlowScreen-DhLnGgnr-CYQDa4ND.js +0 -1
- package/site/dist/assets/MfaVerifyFlowScreen-C_XPjMRP-CJtSAXGN.js +0 -1
- package/site/dist/assets/ModalFooter-BCuEK_nz-D2I8KWtk.js +0 -403
- package/site/dist/assets/MoonpayStatusScreen-CzTUtokc-Bx5aHy-z.js +0 -16
- package/site/dist/assets/OAuthStatusScreen-ufbOa-da-CS6988X2.js +0 -1
- package/site/dist/assets/OpenLink-CUpJ1mOr-EZWVSX2r.js +0 -39
- package/site/dist/assets/PasskeySelectSignupOrLogin-xh2ScC_l-BY4eK5Jh.js +0 -1
- package/site/dist/assets/PasskeyStatusScreen-Bla8MaOk-LXys76u9.js +0 -6
- package/site/dist/assets/PasswordRecoveryScreen-awGXZkQk-RczvLvmo.js +0 -20
- package/site/dist/assets/PhArrowClockwise-mOiWYLMV.js +0 -14
- package/site/dist/assets/PhArrowDown-CkoOD89h.js +0 -14
- package/site/dist/assets/PhArrowLeft-C0jlxVhM.js +0 -14
- package/site/dist/assets/PhArrowRight-BI-V03Xf.js +0 -14
- package/site/dist/assets/PhArrowUp-izKvURUW.js +0 -14
- package/site/dist/assets/PhArrowUpRight-Bn-JhHsY.js +0 -14
- package/site/dist/assets/PhArrowsLeftRight-CYsRQ2qh.js +0 -14
- package/site/dist/assets/PhBrowser-BjzAmrHO.js +0 -14
- package/site/dist/assets/PhCaretDown-ddSjwcwm.js +0 -14
- package/site/dist/assets/PhCaretLeft-B7YLoNEF.js +0 -14
- package/site/dist/assets/PhCaretRight-BY8D5MIg.js +0 -14
- package/site/dist/assets/PhCaretUp-BG10nSut.js +0 -14
- package/site/dist/assets/PhCheck-DrKd7pBC.js +0 -14
- package/site/dist/assets/PhClock-Sj17weCB.js +0 -14
- package/site/dist/assets/PhCopy-rgttky8E.js +0 -14
- package/site/dist/assets/PhDeviceMobile-CnybhXY-.js +0 -14
- package/site/dist/assets/PhDotsThree-CSAEcba1.js +0 -14
- package/site/dist/assets/PhEnvelope-SmaNeXoQ.js +0 -14
- package/site/dist/assets/PhFunnelSimple-DKx35ITq.js +0 -14
- package/site/dist/assets/PhMagnifyingGlass-B6D0sWFL.js +0 -14
- package/site/dist/assets/PhPlus-CBvZvLax.js +0 -14
- package/site/dist/assets/PhWarningCircle-Cm58gXb9.js +0 -14
- package/site/dist/assets/PhX-C3b4cCEy.js +0 -14
- package/site/dist/assets/PhoneIcon-CzbssTb8.js +0 -1
- package/site/dist/assets/PinInput-DbZ0b1i1-1DtLWL81.js +0 -247
- package/site/dist/assets/QrCode-DbnZwlkH-ChwcUk_h.js +0 -22
- package/site/dist/assets/RecoveryOAuthStatusScreen-CsgtTI2x-C79jd345.js +0 -1
- package/site/dist/assets/RecoveryPasswordCreateScreen-Be-qJ-LU-C9c0x-yq.js +0 -1
- package/site/dist/assets/RecoverySelectionScreen-D1iGtpmi-PNqHb6CI.js +0 -7
- package/site/dist/assets/ScreenLayout-OwaQQcxH-B4Z8FjFp.js +0 -1
- package/site/dist/assets/SetAutomaticRecoveryScreen-BO_OEqAZ-CUpQZ9wq.js +0 -14
- package/site/dist/assets/SetWalletPasswordForm-DwCTVtAh-ZzvPLj2s.js +0 -15
- package/site/dist/assets/ShieldCheckIcon-Bjwe_-PV.js +0 -1
- package/site/dist/assets/SignRequestScreen-BHKv32KR-0qGeNipB.js +0 -26
- package/site/dist/assets/StandardSignAndSendTransactionScreen-CfhIXVtd-C3lgJb68.js +0 -20
- package/site/dist/assets/TelegramAuthScreen-UL9zLfO8-l35_C2DG.js +0 -1
- package/site/dist/assets/TodoList-DnyULl18-JxWWU9KA.js +0 -36
- package/site/dist/assets/TransactionDetails-e9nesl30-C91nJPM9.js +0 -109
- package/site/dist/assets/TransactionErrorView-BDBNqA_f-Cpm-4xzm.js +0 -178
- package/site/dist/assets/TransferFromWalletScreen-Qvn1Yuno-BWCH7-Si.js +0 -31
- package/site/dist/assets/TransferOrBridgeLoadingScreen-Dl1I_iIz-BWMeJabk.js +0 -6
- package/site/dist/assets/TurnstileWrapper-B7sNddys-Dgr80Gih.js +0 -1
- package/site/dist/assets/UpdateEmailScreen-DVOhPV0H-Clk4zk-8.js +0 -1
- package/site/dist/assets/UpdatePhoneScreen-CXRswTNZ-BgRsoR3B.js +0 -1
- package/site/dist/assets/UserLimitReachedScreen-5we2DHn8-D-SU-vAz.js +0 -1
- package/site/dist/assets/WalletCards-DH1rqayz-UuZ4i_Ze.js +0 -1
- package/site/dist/assets/WalletIcon-B1i03Vqc.js +0 -1
- package/site/dist/assets/WalletInfoCard-sq_2wgFg-TXTxmb8L.js +0 -29
- package/site/dist/assets/WalletInterstitialScreen-Sh7LfsAh-CbrFb0ON.js +0 -1
- package/site/dist/assets/WalletLink-DK5LB5Ha-BYQZV7UV.js +0 -20
- package/site/dist/assets/WalletOverflowButton-bfCnp-9T-CNgSPnTS.js +0 -1
- package/site/dist/assets/WarningBanner-ZZqCEtZK-DNZUUOph.js +0 -21
- package/site/dist/assets/__vite-browser-external-BIHI7g3E.js +0 -1
- package/site/dist/assets/analytics-mkkvFRju-DOXuftJB.js +0 -1
- package/site/dist/assets/basic-C9wn6QoQ.js +0 -1575
- package/site/dist/assets/bytes-CjWw8TJh.js +0 -1
- package/site/dist/assets/capitalizeFirstLetter-DmLYqXsO-tV1Idewc.js +0 -1
- package/site/dist/assets/ccip-BhHEqVIW.js +0 -1
- package/site/dist/assets/check-C_DTyjLS.js +0 -1
- package/site/dist/assets/chevron-down-iklXXH-z.js +0 -1
- package/site/dist/assets/circle-alert-KEOUF48T.js +0 -1
- package/site/dist/assets/circle-check-big-BJ_ADwB4.js +0 -1
- package/site/dist/assets/circle-x-BSfWmhYk.js +0 -1
- package/site/dist/assets/client-BnDcP42J.js +0 -9
- package/site/dist/assets/client-DH86IrJA.js +0 -125
- package/site/dist/assets/coinbase-DCPC2L_R-2ivYfoMv.js +0 -3
- package/site/dist/assets/copy-sK00DOfH.js +0 -1
- package/site/dist/assets/core-CRE213RM.js +0 -211
- package/site/dist/assets/createLucideIcon-D9OK_uxG.js +0 -1
- package/site/dist/assets/custom-V1wex-Di.js +0 -1
- package/site/dist/assets/dijkstra-COg3n3zL.js +0 -1
- package/site/dist/assets/embed.worker-BRIYO7m8.js +0 -1
- package/site/dist/assets/encodePacked-DyXYq3Cc.js +0 -1
- package/site/dist/assets/ethers-zTjbodk5-DSYOi6tU.js +0 -1
- package/site/dist/assets/external-link-Cdp8NBio.js +0 -1
- package/site/dist/assets/fallback-DiFue5Zm.js +0 -1
- package/site/dist/assets/farcaster-DPlSjvF5-DP2DLoHZ.js +0 -1
- package/site/dist/assets/features-B6BTj_BL.js +0 -5
- package/site/dist/assets/fingerprint-pattern-gFJTz5e4.js +0 -1
- package/site/dist/assets/floating-ui.react-D9ndYqYK.js +0 -1
- package/site/dist/assets/floating-ui.react-dom-CNbOgOFt.js +0 -1
- package/site/dist/assets/formatErc20TokenAmount-BuPk9xcy-CkAr4Oc0.js +0 -1
- package/site/dist/assets/getChainName-DjpPdUSc-c2urPd0g.js +0 -1
- package/site/dist/assets/getErc20Balance-jXNpFf0N-mFQ9Iqk-.js +0 -1
- package/site/dist/assets/getErc20TokenInfo-BNTrzLMP-Dx5he_uG.js +0 -1
- package/site/dist/assets/getFormattedUsdFromLamports-De3U9GlO-C446pzMl.js +0 -1
- package/site/dist/assets/getTransactionCount-80UHlwAV.js +0 -1
- package/site/dist/assets/getUsdcMintAddress-BVgm9GRo-FDalV59C.js +0 -1
- package/site/dist/assets/hashTypedData-Beq57Ogb.js +0 -22
- package/site/dist/assets/hooks.module-ClpaQ1Tg.js +0 -1
- package/site/dist/assets/hourglass-CB7z_I9H.js +0 -1
- package/site/dist/assets/http-BocEfKYb.js +0 -19
- package/site/dist/assets/index-0knDOgU9.js +0 -1
- package/site/dist/assets/index-9jNeS_nC.js +0 -1
- package/site/dist/assets/index-B--T-Fmt.js +0 -16
- package/site/dist/assets/index-BDkarAkX.js +0 -2
- package/site/dist/assets/index-BMfMy017.js +0 -679
- package/site/dist/assets/index-BOd8jv8-.js +0 -1
- package/site/dist/assets/index-BdEw5wyl-2VGMzHIs.js +0 -1
- package/site/dist/assets/index-C8ThRelw.js +0 -9
- package/site/dist/assets/index-D4LdLFDC.js +0 -1
- package/site/dist/assets/index-D6T-s6sR.js +0 -1
- package/site/dist/assets/index-D7396TWe.js +0 -1
- package/site/dist/assets/index-DdxtHe81.js +0 -2
- package/site/dist/assets/index-DvMddJcd-D7AEQrzj.js +0 -12
- package/site/dist/assets/index-nibyPLVP.js +0 -1
- package/site/dist/assets/index.browser-B6Bt5URJ.js +0 -1
- package/site/dist/assets/isPaymentRequestAvailable-Bq1cemEn-D7xtzRqA.js +0 -1
- package/site/dist/assets/landmark-CMLKifhk.js +0 -1
- package/site/dist/assets/lock-BkyjNE8h.js +0 -1
- package/site/dist/assets/mail-B6-Tq9Ld.js +0 -1
- package/site/dist/assets/native-CJ5et6AR.js +0 -1
- package/site/dist/assets/nonceManager-zkW7cM66.js +0 -1
- package/site/dist/assets/parseEther-C7aOvuze.js +0 -1
- package/site/dist/assets/parseSignature-BIjcuWdB.js +0 -1
- package/site/dist/assets/preload-helper-PPVm8Dsz.js +0 -1
- package/site/dist/assets/privateKeyToAccount-CRvvpHWf.js +0 -1
- package/site/dist/assets/property-CnFDNXw5.js +0 -3
- package/site/dist/assets/react-auth_false-DedQs79w.js +0 -1
- package/site/dist/assets/reservoir-x-nGuZkT-DFxAFt2v.js +0 -1
- package/site/dist/assets/roles-DV_6FRBZ.js +0 -1
- package/site/dist/assets/safe-url-D7SRPu33-A8zMgOTd.js +0 -1
- package/site/dist/assets/serializeErc6492Signature-CeJeL3h6.js +0 -1
- package/site/dist/assets/serializeTransaction-L-_Ej-jW.js +0 -8
- package/site/dist/assets/shouldProceedtoEmbeddedWalletCreationFlow-B3vyavrh-CF2QteTJ.js +0 -1
- package/site/dist/assets/simulateTransaction-CfuOrae4-BHUMPf6Q.js +0 -1
- package/site/dist/assets/smartphone-DAN5rY0T.js +0 -1
- package/site/dist/assets/stripe.esm-Dv8C3q95.js +0 -2
- package/site/dist/assets/styles-BsotlekN-Cjuu2SDV.js +0 -9
- package/site/dist/assets/telegram-B-JqnkqZ-DTjJLkIF.js +0 -1
- package/site/dist/assets/to-ui-error-DWe-qwS3-Dx3yzcV0.js +0 -4
- package/site/dist/assets/toAccount-Bq6rbpbI.js +0 -1
- package/site/dist/assets/transaction-BNTP-bFm-CrebgH-D.js +0 -1
- package/site/dist/assets/transactionReceipt-BwJl-gjg.js +0 -1
- package/site/dist/assets/transfer-6YztDh-t-DU6hH7CZ.js +0 -1
- package/site/dist/assets/transformers.web-BEKVh7pD.js +0 -40
- package/site/dist/assets/transformers.web-aWa49tv1.js +0 -40
- package/site/dist/assets/triangle-alert-ndoiBs4y.js +0 -1
- package/site/dist/assets/twitch-5IOe4sIQ-BXviIywg.js +0 -1
- package/site/dist/assets/useGetSolPrice-x7gfUIHJ-C7axYJ--.js +0 -1
- package/site/dist/assets/useGetTokenPrice-CaoUkb79-CR4CrguU.js +0 -1
- package/site/dist/assets/useI18n-C-5n_noF-C_t8QqBJ.js +0 -1
- package/site/dist/assets/useWalletBalance-CZnP5f_f-BnSHLVI_.js +0 -1
- package/site/dist/assets/w3m-modal-Bz5KWTQ-.js +0 -1174
- package/site/dist/assets/wallet-DTM31trz.js +0 -2
- package/site/dist/assets/wallet-UESEqPei.js +0 -1
- package/site/dist/assets/wallet-connect-BvJtUsDt-CnvUnFbz.js +0 -1
- package/site/dist/assets/walletconnect-v2-3frQFwbg-CzQk99gS.js +0 -15
- package/site/dist/assets/x-B2_XdOVQ.js +0 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// A new app from the template: its recipe (app.json, eval/, ci/), no data.
|
|
3
|
+
// npx @fangorn-network/westmarch init <app> [dir] [--no-install]
|
|
4
|
+
// The app's data is what its members commit; the repo this makes can be public.
|
|
5
|
+
import { cpSync, existsSync, mkdtempSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { spawnSync } from "node:child_process";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
import { dirname, join, resolve } from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
|
|
11
|
+
const ROOT = join(dirname(fileURLToPath(import.meta.url)), "../..");
|
|
12
|
+
const TEMPLATE = join(ROOT, "template");
|
|
13
|
+
// What fangorn.network accepts: a name a shell and a URL need no quoting for.
|
|
14
|
+
const APP_NAME = /^[a-z0-9][a-z0-9._-]{1,62}$/;
|
|
15
|
+
|
|
16
|
+
export function init(app, dir = app, { install = true, log = console.log } = {}) {
|
|
17
|
+
if (!APP_NAME.test(app ?? "")) throw new Error(`"${app}": 2-63 characters, lowercase letters, digits, dot, dash or underscore`);
|
|
18
|
+
dir = resolve(dir);
|
|
19
|
+
if (existsSync(dir) && readdirSync(dir).length) throw new Error(`${dir} is not empty`);
|
|
20
|
+
cpSync(TEMPLATE, dir, { recursive: true });
|
|
21
|
+
renameSync(join(dir, "gitignore"), join(dir, ".gitignore")); // npm drops a published .gitignore
|
|
22
|
+
|
|
23
|
+
const cfg = JSON.parse(readFileSync(join(dir, "app.json"), "utf8"));
|
|
24
|
+
const tag = `${app}.item.v1`;
|
|
25
|
+
const type = JSON.parse(JSON.stringify(cfg.types["my-app.item.v1"]).replaceAll("my-app.item.v1", tag));
|
|
26
|
+
Object.assign(cfg, { app, name: app, types: { [tag]: type } });
|
|
27
|
+
cfg.site.project = app.replace(/[._]/g, "-"); // a Worker name: letters, digits, dashes
|
|
28
|
+
writeFileSync(join(dir, "app.json"), JSON.stringify(cfg, null, 1) + "\n");
|
|
29
|
+
writeFileSync(join(dir, "README.md"), readFileSync(join(dir, "README.md"), "utf8").replaceAll("my-app", app));
|
|
30
|
+
const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
|
|
31
|
+
pkg.dependencies["@fangorn-network/westmarch"] = `^${JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8")).version}`;
|
|
32
|
+
writeFileSync(join(dir, "package.json"), JSON.stringify(pkg, null, 2) + "\n");
|
|
33
|
+
|
|
34
|
+
if (install) {
|
|
35
|
+
const sh = (cmd, ...args) => { if (spawnSync(cmd, args, { cwd: dir, stdio: "inherit" }).status !== 0) throw new Error(`${cmd} ${args[0]} failed`); };
|
|
36
|
+
sh("npm", "install"); // the lock CI installs from
|
|
37
|
+
sh("git", "init", "-q", "-b", "main");
|
|
38
|
+
sh("git", "add", "-A");
|
|
39
|
+
sh("git", "commit", "-q", "-m", `${app}: from the westmarch template`);
|
|
40
|
+
}
|
|
41
|
+
log(`${app} is in ${dir}. Next:
|
|
42
|
+
1. app.json: the description, and the type's fields (role_map)
|
|
43
|
+
2. gh repo create ${app} --private --source ${dir} --push
|
|
44
|
+
3. gh secret set ETH_PRIVATE_KEY # the wallet that claimed ${app}; read from the prompt, never echoed
|
|
45
|
+
gh secret set PINATA_JWT
|
|
46
|
+
gh variable set PINATA_GATEWAY --body <your-gateway>.mypinata.cloud
|
|
47
|
+
gh secret set CLOUDFLARE_API_TOKEN
|
|
48
|
+
gh secret set CLOUDFLARE_ACCOUNT_ID
|
|
49
|
+
4. gh workflow run ship # deploys the Worker; then publish records (README.md)`);
|
|
50
|
+
return dir;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (process.argv[2] === "--selfcheck") {
|
|
54
|
+
const dir = join(mkdtempSync(join(tmpdir(), "init-")), "app");
|
|
55
|
+
try {
|
|
56
|
+
init("my.app_1", dir, { install: false, log: () => {} });
|
|
57
|
+
const cfg = JSON.parse(readFileSync(join(dir, "app.json"), "utf8"));
|
|
58
|
+
if (cfg.app !== "my.app_1" || cfg.site.project !== "my-app-1" || !cfg.types["my.app_1.item.v1"]?.presentation.types["my.app_1.item.v1"])
|
|
59
|
+
throw new Error(`app.json not filled: ${JSON.stringify(cfg)}`);
|
|
60
|
+
if (!existsSync(join(dir, ".gitignore")) || !existsSync(join(dir, ".github/workflows/ship.yml"))) throw new Error("template files missing");
|
|
61
|
+
if (readFileSync(join(dir, "README.md"), "utf8").includes("my-app")) throw new Error("README still names my-app");
|
|
62
|
+
let threw = false;
|
|
63
|
+
try { init("x", join(dir, "y"), { install: false, log: () => {} }); } catch { threw = true; }
|
|
64
|
+
if (!threw) throw new Error("a one-letter name must be refused");
|
|
65
|
+
console.log("init: ok");
|
|
66
|
+
} finally { rmSync(dirname(dir), { recursive: true, force: true }); }
|
|
67
|
+
} else if (process.argv[2] === "init") {
|
|
68
|
+
const [app, dir] = process.argv.slice(3).filter((a) => !a.startsWith("--"));
|
|
69
|
+
try { init(app, dir, { install: !process.argv.includes("--no-install") }); }
|
|
70
|
+
catch (e) { console.error(e.message); process.exit(1); }
|
|
71
|
+
} else {
|
|
72
|
+
console.error("usage: westmarch init <app> [dir] [--no-install]");
|
|
73
|
+
process.exit(2);
|
|
74
|
+
}
|
package/src/publish/ship.js
CHANGED
|
@@ -14,16 +14,15 @@
|
|
|
14
14
|
//
|
|
15
15
|
// 1. claim the app (first run only; the claim block becomes the card's fromBlock).
|
|
16
16
|
// The claimer is the app's first member, so its own updates are accepted.
|
|
17
|
-
// 2.
|
|
18
|
-
// 3.
|
|
19
|
-
// 4. the
|
|
20
|
-
// 5.
|
|
21
|
-
// 6. register the ERC-8004 agent and bind the card, if the chain points elsewhere
|
|
17
|
+
// 2. run each source, which crawls and publishes straight into the app
|
|
18
|
+
// 3. the stock page, the card and _headers → .ship/site
|
|
19
|
+
// 4. deploy the Worker: its R2 bucket, Workers AI, the cron, CONFIG (app.json's schema rides in it)
|
|
20
|
+
// 5. register the ERC-8004 agent and bind the card, if the chain points elsewhere
|
|
22
21
|
//
|
|
23
|
-
// The Worker picks up what 2
|
|
22
|
+
// The Worker picks up what 2 published on its next cron run (every few minutes),
|
|
24
23
|
// so the view follows the chain with nobody running anything.
|
|
25
24
|
//
|
|
26
|
-
// --register is the fast path, run before there is any data: 1,
|
|
25
|
+
// --register is the fast path, run before there is any data: 1, 3, 4 and 5 binding the card
|
|
27
26
|
// without minting. The mint copies the card's skills into its IPFS registration file and is
|
|
28
27
|
// never redone, so it waits for the first full ship, when the card lists what the app does.
|
|
29
28
|
//
|
|
@@ -38,7 +37,6 @@ import { createRequire } from "node:module";
|
|
|
38
37
|
import { dirname, join, resolve } from "node:path";
|
|
39
38
|
import { homedir } from "node:os";
|
|
40
39
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
41
|
-
import { RELATION_TAG, TYPE_TAG } from "./view.js";
|
|
42
40
|
|
|
43
41
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
44
42
|
// USDC per x402 network (CAIP-2): its address and EIP-712 domain, as each contract reports them.
|
|
@@ -151,16 +149,6 @@ export function loadConfig(path) {
|
|
|
151
149
|
return { relations: [], tags: [], types: {}, ...c };
|
|
152
150
|
}
|
|
153
151
|
|
|
154
|
-
/** The schema commit for `types` + `relations`: one fangorn.type.v1 record per type, one
|
|
155
|
-
* fangorn.relation.v1 record per allowed reference. A file for `fangorn commit --replace`. */
|
|
156
|
-
export function schemaRecords(types, relations = []) {
|
|
157
|
-
return { records: [
|
|
158
|
-
...Object.entries(types).map(([tag, t]) => ({ id: `type:${tag}`, type: TYPE_TAG, payload: {
|
|
159
|
-
tag, description: t.description ?? "", role_map: t.role_map ?? {}, presentation: t.presentation ?? {} } })),
|
|
160
|
-
...relations.map((r) => ({ id: `rel:${r.rel}:${r.from}:${r.to}`, type: RELATION_TAG, payload: { rel: r.rel, from: r.from, to: r.to } })),
|
|
161
|
-
] };
|
|
162
|
-
}
|
|
163
|
-
|
|
164
152
|
/** The Worker's wrangler config: the stock worker, the site as its assets, its bucket, the AI
|
|
165
153
|
* binding, the cron and CONFIG. `worker` is site/worker.js unless a test points elsewhere. */
|
|
166
154
|
export function wranglerConfig({ name, site, account, cron = "*/5 * * * *", config, url, ipfsGateway, worker = join(HERE, "../../site/worker.js") }) {
|
|
@@ -186,13 +174,6 @@ export function wranglerConfig({ name, site, account, cron = "*/5 * * * *", conf
|
|
|
186
174
|
const stable = (v) => Array.isArray(v) ? v.map(stable)
|
|
187
175
|
: v && typeof v === "object" ? Object.fromEntries(Object.keys(v).sort().map((k) => [k, stable(v[k])])) : v;
|
|
188
176
|
|
|
189
|
-
/** Same shape parseSchema returns, so a config and the chain compare directly. */
|
|
190
|
-
const canonical = (types, relations = []) => JSON.stringify(stable({
|
|
191
|
-
types: Object.fromEntries(Object.entries(types).sort(([a], [b]) => a.localeCompare(b))
|
|
192
|
-
.map(([tag, t]) => [tag, { description: t.description ?? "", role_map: t.role_map ?? {}, presentation: t.presentation ?? {} }])),
|
|
193
|
-
relations: [...relations].sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b))),
|
|
194
|
-
}));
|
|
195
|
-
|
|
196
177
|
// ── processes ─────────────────────────────────────────────────────────────────
|
|
197
178
|
|
|
198
179
|
/** `${VAR}` and `${VAR:-default}` from the environment, so one app.json runs on a laptop
|
|
@@ -240,8 +221,9 @@ function assertSameDeployment(cli) {
|
|
|
240
221
|
|
|
241
222
|
export async function ship(configPath, { crawl = true, deploy = true, dry = false, replace = false, only = null, register = false } = {}) {
|
|
242
223
|
const cfg = loadConfig(configPath);
|
|
243
|
-
|
|
244
|
-
|
|
224
|
+
// No sources is fine: the app then presents whatever its members commit (repos: [] = all of them).
|
|
225
|
+
if (!register && !Object.keys(cfg.types).length)
|
|
226
|
+
throw new Error(`${configPath}: no types yet, so nothing to build; --register sets up the app alone`);
|
|
245
227
|
// No default: one that changed would claim every app that leaned on it again, elsewhere.
|
|
246
228
|
if (!cfg.network) throw new Error(`${configPath}: "network" is required: "baseSepolia" for a new app, or the network the app was claimed on (before 2026-10-20 the default was "arbitrumSepolia")`);
|
|
247
229
|
CLI = cliArgv(cfg);
|
|
@@ -263,7 +245,7 @@ export async function ship(configPath, { crawl = true, deploy = true, dry = fals
|
|
|
263
245
|
|
|
264
246
|
// The SDK's network name: view.js reads with it, and the CLI and the sources spawned below sign on it.
|
|
265
247
|
process.env.FANGORN_NETWORK = process.env.CHAIN_NAME = cfg.network;
|
|
266
|
-
const [{ createPublicClient, http }, view] = await Promise.all([import("viem"), import("./view.js")]);
|
|
248
|
+
const [{ createPublicClient, http, parseAbiItem }, view] = await Promise.all([import("viem"), import("./view.js")]);
|
|
267
249
|
const FangornConfig = await view.network(cfg.network);
|
|
268
250
|
const fangorn = await view.readOnlyFangorn();
|
|
269
251
|
fangorn.setAppId(cfg.app);
|
|
@@ -276,8 +258,9 @@ export async function ship(configPath, { crawl = true, deploy = true, dry = fals
|
|
|
276
258
|
const me = (fangornCli(cfg.app, ["wallet"]).match(/Address:\s+(0x[0-9a-fA-F]{40})/) ?? [])[1]?.toLowerCase();
|
|
277
259
|
if (!me) throw new Error("`fangorn wallet` shows no address; run `fangorn init`");
|
|
278
260
|
let owner = (await registry.getAppOwner()).toLowerCase();
|
|
261
|
+
const chain = createPublicClient({ transport: http(FangornConfig.rpcUrl) });
|
|
279
262
|
if (/^0x0+$/.test(owner)) {
|
|
280
|
-
const block = await
|
|
263
|
+
const block = await chain.getBlockNumber();
|
|
281
264
|
state.fromBlock = String(block);
|
|
282
265
|
log(`${cfg.app} is unclaimed; claiming it for ${me} (fromBlock ${block})`);
|
|
283
266
|
fangornCli(cfg.app, ["app", "claim"], { dry });
|
|
@@ -286,25 +269,20 @@ export async function ship(configPath, { crawl = true, deploy = true, dry = fals
|
|
|
286
269
|
} else if (owner !== me) {
|
|
287
270
|
throw new Error(`${cfg.app} belongs to ${owner}, not this wallet (${me}); pick another name`);
|
|
288
271
|
}
|
|
272
|
+
// Claimed elsewhere (fangorn.network, the CLI): the view starts at the claim, found once.
|
|
273
|
+
if (state.fromBlock == null && cfg.fromBlock == null) {
|
|
274
|
+
const from = BigInt(FangornConfig.appRegistryFromBlock), to = await chain.getBlockNumber(), step = BigInt(FangornConfig.logWindow ?? 10000);
|
|
275
|
+
const event = parseAbiItem("event AppRegistered(bytes32 indexed app_id, address indexed owner)");
|
|
276
|
+
for (let a = from; a <= to && state.fromBlock == null; a += step) {
|
|
277
|
+
const [claimed] = await chain.getLogs({ address: FangornConfig.appRegistryContractAddress, event, args: { app_id: appId },
|
|
278
|
+
fromBlock: a, toBlock: a + step - 1n < to ? a + step - 1n : to });
|
|
279
|
+
if (claimed) state.fromBlock = String(claimed.blockNumber);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
289
282
|
state.fromBlock ??= String(cfg.fromBlock ?? FangornConfig.appRegistryFromBlock);
|
|
290
283
|
log(`app ${cfg.app} = ${appId}, owner ${owner}, fromBlock ${state.fromBlock}`);
|
|
291
284
|
|
|
292
|
-
// 2.
|
|
293
|
-
if (!register) {
|
|
294
|
-
let onChain = null;
|
|
295
|
-
try { onChain = view.parseSchema((await fangorn.readRepo(owner, view.SCHEMA_REPO)).contents); } catch { /* none yet */ }
|
|
296
|
-
if (!onChain || canonical(onChain.types, onChain.relations) !== canonical(cfg.types, cfg.relations)) {
|
|
297
|
-
const sdir = join(dir, "schema");
|
|
298
|
-
mkdirSync(sdir, { recursive: true });
|
|
299
|
-
writeFileSync(join(sdir, "schema.json"), JSON.stringify(schemaRecords(cfg.types, cfg.relations), null, 1));
|
|
300
|
-
log(`schema ${onChain ? "changed" : "is new"}: committing ${Object.keys(cfg.types).join(", ")}`);
|
|
301
|
-
fangornCli(cfg.app, ["repo", "init", view.SCHEMA_REPO], { cwd: sdir, dry });
|
|
302
|
-
fangornCli(cfg.app, ["commit", "schema.json", "-m", "schema", "--replace"], { cwd: sdir, dry });
|
|
303
|
-
fangornCli(cfg.app, ["push"], { cwd: sdir, dry });
|
|
304
|
-
} else log("schema unchanged");
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// 3. sources: crawl + publish straight into the app. One source failing (a site that
|
|
285
|
+
// 2. sources: crawl + publish straight into the app. One source failing (a site that
|
|
308
286
|
// blocks us, a feed that is down) keeps its last published data and does not stop the
|
|
309
287
|
// others; the ship still exits non-zero at the end, naming it.
|
|
310
288
|
const failed = [];
|
|
@@ -322,7 +300,7 @@ export async function ship(configPath, { crawl = true, deploy = true, dry = fals
|
|
|
322
300
|
}
|
|
323
301
|
}
|
|
324
302
|
|
|
325
|
-
//
|
|
303
|
+
// 3. the page, the card, the headers
|
|
326
304
|
const { site, writeCard } = await buildSite(cfg, base);
|
|
327
305
|
// site.url: the app's own domain, routed to the Worker. Otherwise its workers.dev URL,
|
|
328
306
|
// which is only known once it is deployed: the first deploy learns it and the card follows.
|
|
@@ -335,12 +313,8 @@ export async function ship(configPath, { crawl = true, deploy = true, dry = fals
|
|
|
335
313
|
const sale = (u) => {
|
|
336
314
|
if (!cfg.paid) return { paid: null, sale: null };
|
|
337
315
|
const T = terms(cfg.paid), price = units(cfg.paid.price, T.decimals), description = cfg.paid.description ?? "";
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
chainId: cfg.paid.membership.chainId ?? FangornConfig.caip2, appId } : null;
|
|
341
|
-
const paid = { url: `${u}/paid/{id}`, key_url: `${u}/key`, price, asset: T.asset, network: T.network, decimals: T.decimals, symbol: T.symbol,
|
|
342
|
-
description, ...(membership ? { membership } : {}) };
|
|
343
|
-
return { paid, sale: { ...T, price, description, ...(membership ? { membership } : {}) } };
|
|
316
|
+
const paid = { url: `${u}/paid/{id}`, price, asset: T.asset, network: T.network, decimals: T.decimals, symbol: T.symbol, description };
|
|
317
|
+
return { paid, sale: { ...T, price, description } };
|
|
344
318
|
};
|
|
345
319
|
const access = (u) => {
|
|
346
320
|
const X = cfg.private;
|
|
@@ -354,13 +328,13 @@ export async function ship(configPath, { crawl = true, deploy = true, dry = fals
|
|
|
354
328
|
const writeSite = (u) => writeCard(u, { fromBlock: state.fromBlock, repos, paid: sale(u).paid, access: access(u).card });
|
|
355
329
|
writeSite(url ?? `https://${cfg.site.project}.workers.dev`);
|
|
356
330
|
|
|
357
|
-
//
|
|
331
|
+
// 4. the Worker
|
|
358
332
|
const workerConfig = (u) => {
|
|
359
333
|
const path = join(dir, "wrangler.json");
|
|
360
334
|
writeFileSync(path, JSON.stringify(wranglerConfig({
|
|
361
335
|
name: cfg.site.project, site, account: cfg.site.account, cron: cfg.site.cron, url: cfg.site.url, ipfsGateway: view.ipfsGateway(),
|
|
362
336
|
config: { app: cfg.app, name: cfg.name, description: cfg.description, fromBlock: state.fromBlock, network: cfg.network,
|
|
363
|
-
repos: register ? [] : repos, paid: sale(u).sale, private: access(u).config },
|
|
337
|
+
schema: { types: cfg.types, relations: cfg.relations }, repos: register ? [] : repos, paid: sale(u).sale, private: access(u).config },
|
|
364
338
|
}), null, 1));
|
|
365
339
|
return path;
|
|
366
340
|
};
|
|
@@ -384,7 +358,7 @@ export async function ship(configPath, { crawl = true, deploy = true, dry = fals
|
|
|
384
358
|
else if (cfg.paid) log("paid: set the key secret once with `npx wrangler secret put PAID_SECRET --config .ship/wrangler.json`");
|
|
385
359
|
} else workerConfig(url ?? `https://${cfg.site.project}.workers.dev`);
|
|
386
360
|
|
|
387
|
-
//
|
|
361
|
+
// 5. ERC-8004 + the binding
|
|
388
362
|
const cardUrl = `${url}/.well-known/agent-card.json`;
|
|
389
363
|
const bound = await registry.appAgentUri(appId).catch(() => "");
|
|
390
364
|
const mint = () => {
|
|
@@ -407,7 +381,7 @@ export async function ship(configPath, { crawl = true, deploy = true, dry = fals
|
|
|
407
381
|
} else if (deploy) log("card already bound");
|
|
408
382
|
|
|
409
383
|
// A new app has no view until the cron runs, which may be hours off: build the first one now.
|
|
410
|
-
if (deploy && !dry && !register && !await fetch(`${url}/view/cdn/catalog`).then((r) => r.ok, () => false)) {
|
|
384
|
+
if (deploy && !dry && !register && cfg.sources.length && !await fetch(`${url}/view/cdn/catalog`).then((r) => r.ok, () => false)) {
|
|
411
385
|
log("no view yet: indexing it here rather than waiting for the cron");
|
|
412
386
|
await indexHere(configPath).catch((e) => log(`✗ first index: ${e.message}; the cron will build it`));
|
|
413
387
|
}
|
|
@@ -583,21 +557,18 @@ export function readStage(cfg, base, { crawl = false, only = null, log: say = lo
|
|
|
583
557
|
}
|
|
584
558
|
|
|
585
559
|
/**
|
|
586
|
-
* The whole app on this machine (devnet.js): a local chain and IPFS, the app claimed and its
|
|
587
|
-
* schema committed there, what the sources staged published into it, and its Worker under
|
|
560
|
+
* The whole app on this machine (devnet.js): a local chain and IPFS, the app claimed there, what the sources staged published into it, and its Worker under
|
|
588
561
|
* `wrangler dev` with a local R2 and an encoder on localhost (or Workers AI with ai=true).
|
|
589
562
|
* Runs the indexer once, says where everything is, and stays up until interrupted.
|
|
590
563
|
*/
|
|
591
564
|
export async function devnetShip(configPath, { crawl = false, only = null, port = 8787, ai = false } = {}) {
|
|
592
565
|
const cfg = loadConfig(configPath);
|
|
593
566
|
const base = dirname(resolve(configPath));
|
|
594
|
-
const
|
|
567
|
+
const { devnet } = await import("./devnet.js");
|
|
595
568
|
const staged = readStage(cfg, base, { crawl, only });
|
|
596
569
|
const net = await devnet({ log });
|
|
597
570
|
const owner = await net.client(cfg.app);
|
|
598
571
|
await owner.getAppRegistry().registerApp();
|
|
599
|
-
await owner.initRepo(SCHEMA_REPO);
|
|
600
|
-
await owner.uploadBatch(SCHEMA_REPO, schemaRecords(cfg.types, cfg.relations).records);
|
|
601
572
|
// The claimer publishes the sources, as `fangorn` does in a ship.
|
|
602
573
|
for (const [ns, records] of Object.entries(staged)) {
|
|
603
574
|
if (!records.length) continue;
|
|
@@ -611,7 +582,7 @@ export async function devnetShip(configPath, { crawl = false, only = null, port
|
|
|
611
582
|
const { site, writeCard } = await buildSite(cfg, base);
|
|
612
583
|
writeCard(url, { fromBlock: "0", repos });
|
|
613
584
|
const wcfg = wranglerConfig({ name: cfg.site.project, site, config: { app: cfg.app, name: cfg.name, description: cfg.description,
|
|
614
|
-
fromBlock: "0", repos, paid: null, deployment: net.deployment } });
|
|
585
|
+
fromBlock: "0", schema: { types: cfg.types, relations: cfg.relations }, repos, paid: null, deployment: net.deployment } });
|
|
615
586
|
// Its own R2 and state, apart from a deployed app's.
|
|
616
587
|
wcfg.vars.RPC_URL = net.rpcUrl;
|
|
617
588
|
wcfg.vars.IPFS_GATEWAY = net.gatewayUrl;
|
|
@@ -705,8 +676,7 @@ export async function buildLocal(configPath, out, { crawl = false, only = null,
|
|
|
705
676
|
env.cacheDir = `${homedir()}/.cache/fangorn-mcp/models`;
|
|
706
677
|
// Not the app's real id or owner: nothing here is compared with the chain.
|
|
707
678
|
const appId = `0x${createHash("sha256").update(cfg.app).digest("hex")}`, owner = `0x${"10ca1".padStart(40, "0")}`;
|
|
708
|
-
const chain = {
|
|
709
|
-
records: schemaRecords(cfg.types, cfg.relations).records.map((r) => ({ ...r, cid: r.id })) } };
|
|
679
|
+
const chain = {};
|
|
710
680
|
// Storage addresses a record by its content, and so does this.
|
|
711
681
|
for (const [ns, records] of Object.entries(readStage(cfg, base, { crawl, only, log: say })))
|
|
712
682
|
chain[`${owner}/${ns}`] = { records: records.map((r) => ({ ...r, cid: createHash("sha256").update(JSON.stringify(stable(r.payload))).digest("hex") })) };
|
|
@@ -715,7 +685,7 @@ export async function buildLocal(configPath, out, { crawl = false, only = null,
|
|
|
715
685
|
const embed = view.cachedEmbed(join(base, ".ship/vectors.ndjson"));
|
|
716
686
|
const repos = [...new Set(cfg.sources.map((s) => s.namespace))].filter((n) => !only || only.includes(n));
|
|
717
687
|
const report = await view.publishView({ fangorn: view.localFangorn(chain, { appId, owner }), app: cfg.app,
|
|
718
|
-
repos, out, embed, log: say });
|
|
688
|
+
schema: { types: cfg.types, relations: cfg.relations }, repos, out, embed, log: say });
|
|
719
689
|
const rows = Object.values(report).reduce((n, r) => n + r.added, 0);
|
|
720
690
|
say(`local view: ${out} · ${rows} records, ${embed.misses} embedded, ${rows - embed.misses} from the vector cache`);
|
|
721
691
|
return report;
|
|
@@ -724,19 +694,6 @@ export async function buildLocal(configPath, out, { crawl = false, only = null,
|
|
|
724
694
|
// ── cli ───────────────────────────────────────────────────────────────────────
|
|
725
695
|
if (process.argv[1]?.endsWith("ship.js") || process.argv[1]?.endsWith("westmarch-ship")) {
|
|
726
696
|
if (process.argv[2] === "--selfcheck") {
|
|
727
|
-
// The schema as committed, read back the way the chain returns it, must compare
|
|
728
|
-
// equal to the config, or every run re-commits an unchanged schema.
|
|
729
|
-
const { parseSchema } = await import("./view.js");
|
|
730
|
-
const types = { "t.v1": { description: "d", role_map: { title: "name", text: ["body"] }, presentation: { externalUrl: { "t.v1": "{url}" } } },
|
|
731
|
-
"u.v1": { description: "e", role_map: { title: "label" } } };
|
|
732
|
-
const relations = [{ rel: "cites", from: "t.v1", to: "u.v1" }];
|
|
733
|
-
const g = schemaRecords(types, relations);
|
|
734
|
-
// Keys reversed at every depth, as a canonical (sorted) encoding hands them back.
|
|
735
|
-
const reverse = (v) => Array.isArray(v) ? v.map(reverse)
|
|
736
|
-
: v && typeof v === "object" ? Object.fromEntries(Object.keys(v).reverse().map((k) => [k, reverse(v[k])])) : v;
|
|
737
|
-
const readBack = parseSchema({ records: g.records.map((r) => ({ ...r, cid: `cid-${r.id}`, payload: reverse(r.payload) })) });
|
|
738
|
-
if (canonical(readBack.types, readBack.relations) !== canonical(types, relations)) throw new Error("schema does not round-trip");
|
|
739
|
-
if (canonical(readBack.types, readBack.relations) === canonical({ ...types, "v.v1": {} }, relations)) throw new Error("a new type must count as a change");
|
|
740
697
|
const row = { city: "Wisconsin Rapids", state: "WI", site: "https://x", args: ["--archive-page", "/569/A"] };
|
|
741
698
|
const cmd = fill(["py", "--site", "{site}", "--city", "{city}", "{args...}", "--ns", "us-{state|lower}-{city|slug}"], row);
|
|
742
699
|
if (JSON.stringify(cmd) !== JSON.stringify(["py", "--site", "https://x", "--city", "Wisconsin Rapids", "--archive-page", "/569/A", "--ns", "us-wi-wisconsin-rapids"]))
|
|
@@ -754,7 +711,7 @@ if (process.argv[1]?.endsWith("ship.js") || process.argv[1]?.endsWith("westmarch
|
|
|
754
711
|
throw new Error(`private discovery: ${JSON.stringify(dp.x402)}`);
|
|
755
712
|
if (units("0.01") !== "10000" || units("5") !== "5000000" || units("1.5", 2) !== "150") throw new Error("units");
|
|
756
713
|
if (USDC["eip155:84532"].name !== "USDC" || USDC["eip155:8453"].name !== "USD Coin") throw new Error("USDC's EIP-712 name differs on Base Sepolia and Base");
|
|
757
|
-
console.log("ship.js self-check ok — a
|
|
714
|
+
console.log("ship.js self-check ok — a source template fills per row, the Worker config binds its bucket, AI and cron, and the paid route is priced per id in /openapi.json and named in /.well-known/x402");
|
|
758
715
|
process.exit(0);
|
|
759
716
|
}
|
|
760
717
|
const [path, ...flags] = process.argv.slice(2);
|
package/src/publish/view-cli.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// westmarch-view: publish what an app presents as a view (see view.js).
|
|
3
3
|
//
|
|
4
|
-
// westmarch-view --app my-app --out site/view [--repo catalog …] [--from-block N] [--rebake]
|
|
4
|
+
// westmarch-view --app my-app --out site/view [--config app.json] [--repo catalog …] [--from-block N] [--rebake]
|
|
5
5
|
//
|
|
6
|
+
// The schema (types, relations) is read from --config; without it every type is guessed.
|
|
6
7
|
// Reads only; needs no key. Deploy <out> with the site, and put its URL in the card's
|
|
7
8
|
// `views`. An app on the free tier needs none of this: its Worker runs the same code on a
|
|
8
9
|
// cron (site/worker.js).
|
|
9
10
|
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
10
12
|
import { homedir } from "node:os";
|
|
11
13
|
|
|
12
14
|
const flags = { repo: [] };
|
|
@@ -18,7 +20,7 @@ for (let i = 2; i < process.argv.length; i++) {
|
|
|
18
20
|
if (m[1] === "repo") flags.repo.push(v); else flags[m[1]] = v;
|
|
19
21
|
}
|
|
20
22
|
if (flags.help || !flags.app || !flags.out) {
|
|
21
|
-
console.error("usage: westmarch-view --app <name|0xid> --out <dir> [--repo <name> …] [--from-block N] [--rebake]");
|
|
23
|
+
console.error("usage: westmarch-view --app <name|0xid> --out <dir> [--config app.json] [--repo <name> …] [--from-block N] [--rebake]");
|
|
22
24
|
process.exit(flags.help ? 0 : 2);
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -31,7 +33,8 @@ const fangorn = await readOnlyFangorn();
|
|
|
31
33
|
|
|
32
34
|
const t0 = Date.now();
|
|
33
35
|
const report = await publishView({
|
|
34
|
-
fangorn, app: flags.app, repos: flags.repo,
|
|
36
|
+
fangorn, app: flags.app, repos: flags.repo,
|
|
37
|
+
schema: flags.config ? JSON.parse(readFileSync(flags.config, "utf8")) : undefined, out: flags.out,
|
|
35
38
|
fromBlock: flags["from-block"], rebake: !!flags.rebake,
|
|
36
39
|
log: (s) => console.error(s),
|
|
37
40
|
});
|
package/src/publish/view.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// site/worker.js, on a cron (the free tier)
|
|
6
6
|
//
|
|
7
7
|
// Reads the registry and storage and nothing else: every repo the app presents (its
|
|
8
|
-
// members' repos, less its exclusions, `appRepos`), at their latest heads
|
|
9
|
-
//
|
|
8
|
+
// members' repos, less its exclusions, `appRepos`), at their latest heads; the schema
|
|
9
|
+
// (app.json's `types` + `relations`) comes from the caller. Embeds only records the view does not hold
|
|
10
10
|
// yet, drops removed ones, and writes, through a store (a directory or an R2 bucket):
|
|
11
11
|
//
|
|
12
12
|
// cdn/catalog
|
|
@@ -40,15 +40,9 @@ import { dirname } from "node:path";
|
|
|
40
40
|
import { EMBED_DIM, EMBED_DTYPE, EMBED_MODEL, embedDocumentDirect, packVec, unpackVec } from "../core/embed.js";
|
|
41
41
|
import { coverage as fitCoverage } from "../market/reactions.js";
|
|
42
42
|
|
|
43
|
-
/** The app owner's repo that declares the app's types: one TYPE_TAG record per type, one
|
|
44
|
-
* RELATION_TAG record per allowed reference between two of them. */
|
|
45
|
-
export const SCHEMA_REPO = "fangorn.schema";
|
|
46
|
-
export const TYPE_TAG = "fangorn.type.v1";
|
|
47
|
-
export const RELATION_TAG = "fangorn.relation.v1";
|
|
48
43
|
export const EMBEDDER = { runtime: "transformers.js", model: EMBED_MODEL, dtype: EMBED_DTYPE };
|
|
49
44
|
const SINGULAR = ["identity", "title", "subtitle", "temporal", "spatial", "media", "thread"];
|
|
50
45
|
const MULTI = ["tags", "measures", "relations", "text"];
|
|
51
|
-
const ZERO = "0x0000000000000000000000000000000000000000";
|
|
52
46
|
// Refit coverage once a domain has grown this many times over what it was fit on.
|
|
53
47
|
const COVERAGE_REFIT = 2;
|
|
54
48
|
|
|
@@ -75,17 +69,13 @@ export function composeText(fields, rm) {
|
|
|
75
69
|
return s.slice(0, 1000 - "search_document: ".length);
|
|
76
70
|
}
|
|
77
71
|
|
|
78
|
-
/**
|
|
79
|
-
export function
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
else if (r.type === RELATION_TAG && p.rel && p.from && p.to)
|
|
86
|
-
relations.push({ rel: String(p.rel), from: String(p.from), to: String(p.to) });
|
|
87
|
-
}
|
|
88
|
-
return { types, relations };
|
|
72
|
+
/** app.json's `types` + `relations` → { types: {tag: {description, role_map, presentation}}, relations }. */
|
|
73
|
+
export function schemaOf({ types = {}, relations = [] } = {}) {
|
|
74
|
+
return {
|
|
75
|
+
types: Object.fromEntries(Object.entries(types).map(([tag, t]) =>
|
|
76
|
+
[tag, { description: String(t.description ?? ""), role_map: t.role_map ?? {}, presentation: t.presentation ?? {} }])),
|
|
77
|
+
relations: relations.filter((r) => r.rel && r.from && r.to).map((r) => ({ rel: String(r.rel), from: String(r.from), to: String(r.to) })),
|
|
78
|
+
};
|
|
89
79
|
}
|
|
90
80
|
|
|
91
81
|
/** Declared means declared: every role present, left-out ones empty. */
|
|
@@ -281,7 +271,7 @@ const sha256 = (s) => createHash("sha256").update(s).digest("hex");
|
|
|
281
271
|
|
|
282
272
|
/**
|
|
283
273
|
* Bring the view up to date with what the app presents. `fangorn` is an SDK client (reads
|
|
284
|
-
* only); the view goes to `store`, or the directory `out`. `repos` narrows it to those repo
|
|
274
|
+
* only); `schema` is app.json's { types, relations } (a type it leaves out is guessed); the view goes to `store`, or the directory `out`. `repos` narrows it to those repo
|
|
285
275
|
* names (every publisher's); without it, every repo the app presents. `fromBlock` must be
|
|
286
276
|
* at or before the first update to a repo the app presents, or a repo the scan misses is left out;
|
|
287
277
|
* left out, the SDK's deployment start. `embedBatch(texts)` embeds many at once where the
|
|
@@ -290,25 +280,20 @@ const sha256 = (s) => createHash("sha256").update(s).digest("hex");
|
|
|
290
280
|
* ([{owner, repo, root}], exclusions already applied), as a Worker does across runs.
|
|
291
281
|
* Returns per-domain counts of what changed.
|
|
292
282
|
*/
|
|
293
|
-
export async function publishView({ fangorn, app, repos, out, store = fsStore(out), fromBlock, presented, rebake = false,
|
|
283
|
+
export async function publishView({ fangorn, app, schema, repos, out, store = fsStore(out), fromBlock, presented, rebake = false,
|
|
294
284
|
embed = embedDocumentDirect, embedBatch = (ts) => Promise.all(ts.map(embed)),
|
|
295
285
|
embedder = EMBEDDER, log = console.log, shardRows = 20000, concurrency = 4, open = (p) => p }) {
|
|
296
286
|
fangorn.setAppId(app);
|
|
297
287
|
const appId = fangorn.getAppId();
|
|
298
|
-
|
|
299
|
-
let schema = { types: {}, relations: [] };
|
|
300
|
-
if (owner === ZERO) log(`app ${app} is unclaimed, so it has no schema; every type will be guessed`);
|
|
301
|
-
else {
|
|
302
|
-
try { schema = parseSchema((await retry(() => fangorn.readRepo(owner, SCHEMA_REPO))).contents); }
|
|
303
|
-
catch (e) { log(`schema: none read (${e.message}); every type will be guessed`); }
|
|
304
|
-
}
|
|
288
|
+
schema = schemaOf(schema);
|
|
305
289
|
const declared = Object.keys(schema.types);
|
|
306
290
|
log(`schema: ${declared.length ? declared.join(", ") : "no declared types"}`);
|
|
307
291
|
const schemaHash = sha256(JSON.stringify(schema));
|
|
308
292
|
|
|
309
293
|
// Every repo the app presents, at its accepted head: one log scan, exclusions applied.
|
|
310
294
|
const listed = (presented ?? await retry(() => fangorn.appRepos(fromBlock == null ? {} : { fromBlock: BigInt(fromBlock) })))
|
|
311
|
-
|
|
295
|
+
// ponytail: "fangorn.schema" is where apps shipped before 2026-10-22 committed their schema; never data.
|
|
296
|
+
.filter((t) => t.repo !== "fangorn.schema" && (!repos?.length || repos.includes(t.repo)));
|
|
312
297
|
log(`${listed.length} repo(s) presented${repos?.length ? ` of ${repos.join(", ")}` : ""}`);
|
|
313
298
|
|
|
314
299
|
const report = {};
|
|
@@ -535,10 +520,9 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
|
|
|
535
520
|
|
|
536
521
|
const APP = `0x${"ab".repeat(32)}`, OWNER = `0x${"11".repeat(20)}`, PUB = `0x${"22".repeat(20)}`;
|
|
537
522
|
const TAG = "shop.item.v1";
|
|
523
|
+
const schema = { types: { [TAG]: { description: "Things for a room.", role_map: { identity: "sku", title: "name", text: "about" },
|
|
524
|
+
presentation: { externalUrl: { [TAG]: "https://shop.example/{sku}" } } } } };
|
|
538
525
|
const chain = {
|
|
539
|
-
[`${OWNER}/${SCHEMA_REPO}`]: { records: [rec("t1", TYPE_TAG, {
|
|
540
|
-
tag: TAG, description: "Things for a room.", role_map: { identity: "sku", title: "name", text: "about" },
|
|
541
|
-
presentation: { externalUrl: { [TAG]: "https://shop.example/{sku}" } } })] },
|
|
542
526
|
[`${PUB}/shop`]: { records: [
|
|
543
527
|
rec("c1", TAG, { sku: "a1", name: "Oak table", about: "a solid oak dining table", price: 3 }),
|
|
544
528
|
rec("c2", TAG, { sku: "b2", name: "Lamp", about: "brass reading lamp", price: 1 }),
|
|
@@ -557,11 +541,11 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
|
|
|
557
541
|
appendFileSync(`${out}/vectors.ndjson`, '["cut sho');
|
|
558
542
|
eq(packVec(await cachedEmbed(`${out}/vectors.ndjson`, embed)("Title: Oak")), packVec(v1), "a line cut short by a kill is skipped, not fatal");
|
|
559
543
|
embedded.length = 0; rmSync(`${out}/vectors.ndjson`);
|
|
560
|
-
const run = () => publishView({ fangorn, app: APP, out, embed, log: () => {} });
|
|
544
|
+
const run = () => publishView({ fangorn, app: APP, schema, out, embed, log: () => {} });
|
|
561
545
|
|
|
562
546
|
const d = domainFor(APP, PUB, "shop");
|
|
563
547
|
const split = mkdtempSync(`${tmpdir()}/view-`);
|
|
564
|
-
await publishView({ fangorn, app: APP, out: split, embed, log: () => {}, shardRows: 2 });
|
|
548
|
+
await publishView({ fangorn, app: APP, schema, out: split, embed, log: () => {}, shardRows: 2 });
|
|
565
549
|
eq(manifestOf(split, d).shards.map((s) => s.count), [2, 1], "rows past shardRows go to the next shard");
|
|
566
550
|
embedded.length = 0;
|
|
567
551
|
eq((await run())[d], { added: 3, removed: 0 }, "first run embeds everything");
|
|
@@ -626,16 +610,16 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
|
|
|
626
610
|
let budget = 40;
|
|
627
611
|
const capped = (ts) => (budget -= ts.length) < 0 ? Promise.reject(new Error("daily allowance used")) : Promise.all(ts.map(embed));
|
|
628
612
|
const bd = domainFor(APP, PUB, "big");
|
|
629
|
-
eq((await publishView({ fangorn, app: APP, out: big, repos: ["big"], embedBatch: capped, log: () => {} }))[bd],
|
|
613
|
+
eq((await publishView({ fangorn, app: APP, schema, out: big, repos: ["big"], embedBatch: capped, log: () => {} }))[bd],
|
|
630
614
|
{ added: 32, removed: 0, partial: true }, "an encoder that gives out keeps what it embedded");
|
|
631
615
|
eq([manifestOf(big, bd).count, manifestOf(big, bd).head], [32, null], "served, and the head not taken");
|
|
632
616
|
budget = 1e9;
|
|
633
|
-
eq((await publishView({ fangorn, app: APP, out: big, repos: ["big"], embedBatch: capped, log: () => {} }))[bd],
|
|
617
|
+
eq((await publishView({ fangorn, app: APP, schema, out: big, repos: ["big"], embedBatch: capped, log: () => {} }))[bd],
|
|
634
618
|
{ added: 48, removed: 0 }, "the next run embeds only the rest");
|
|
635
619
|
eq(manifestOf(big, bd).count, 80, "and serves all of it");
|
|
636
620
|
delete chain[BIG];
|
|
637
621
|
rmSync(big, { recursive: true, force: true });
|
|
638
|
-
eq((await publishView({ fangorn, app: APP, out, embed, rebake: true, log: () => {} }))[d],
|
|
622
|
+
eq((await publishView({ fangorn, app: APP, schema, out, embed, rebake: true, log: () => {} }))[d],
|
|
639
623
|
{ added: 2, removed: 0 }, "--rebake starts the domain over");
|
|
640
624
|
eq(readdirSync(`${out}/cdn/domains/${d}/shards`).length, 1, "and leaves no orphaned shards");
|
|
641
625
|
rmSync(out, { recursive: true, force: true });
|
|
@@ -644,16 +628,16 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
|
|
|
644
628
|
// undeclared one is left alone; a target whose identity moves relinks the row without embedding it.
|
|
645
629
|
{
|
|
646
630
|
const T = "civic.item.v1", M = "civic.matter.v1";
|
|
647
|
-
const
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
631
|
+
const relSchema = { types: { [T]: { role_map: { identity: "item_id", title: "heading", thread: "part_of" } },
|
|
632
|
+
[M]: { role_map: { identity: "matter_id", title: "title" } } },
|
|
633
|
+
relations: [{ rel: "part_of", from: T, to: M }] };
|
|
634
|
+
const rel = {
|
|
651
635
|
[`${PUB}/civic`]: { records: [
|
|
652
636
|
rec("i1", T, { item_id: "a#1", heading: "Rezone, committee", part_of: { local: "m" } }),
|
|
653
637
|
rec("i2", T, { item_id: "b#4", heading: "Rezone, council", cites: { local: "m" } }),
|
|
654
638
|
rec("m1", M, { matter_id: "plover:7", title: "Rezone" }, "m")] } };
|
|
655
639
|
const o = mkdtempSync(`${tmpdir()}/view-`), dr = domainFor(APP, PUB, "civic");
|
|
656
|
-
const go = () => publishView({ fangorn: localFangorn(rel, { appId: APP, owner: OWNER }), app: APP, out: o, embed, log: () => {} });
|
|
640
|
+
const go = () => publishView({ fangorn: localFangorn(rel, { appId: APP, owner: OWNER }), app: APP, schema: relSchema, out: o, embed, log: () => {} });
|
|
657
641
|
const rows = async () => Object.fromEntries([...(await loadDomain(fsStore(o), `cdn/domains/${dr}`)).rows.values()]
|
|
658
642
|
.map((r) => [r.fields.heading ?? r.fields.title, r.fields.part_of ?? r.fields.cites ?? null]));
|
|
659
643
|
await go();
|
|
@@ -682,7 +666,7 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
|
|
|
682
666
|
},
|
|
683
667
|
};
|
|
684
668
|
const r2 = r2Store(bucket);
|
|
685
|
-
const via = await publishView({ fangorn, app: APP, store: r2, embed, log: () => {} });
|
|
669
|
+
const via = await publishView({ fangorn, app: APP, schema, store: r2, embed, log: () => {} });
|
|
686
670
|
eq(Object.keys(via), [d], "a view builds into a bucket");
|
|
687
671
|
eq(await r2.list("cdn/domains"), [d], "list names a folder's children");
|
|
688
672
|
eq((await liveFields(r2)).length, 2, "and reads back");
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Ship when app.json changes (or by hand); grade the live view daily. Data never comes
|
|
2
|
+
# through here: publishers commit it to the app, and the Worker indexes it every 5 minutes.
|
|
3
|
+
name: ship
|
|
4
|
+
on:
|
|
5
|
+
push: { branches: [main], paths: [app.json] }
|
|
6
|
+
schedule: [{ cron: "17 13 * * *" }]
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
concurrency: { group: ship, cancel-in-progress: false }
|
|
9
|
+
permissions: { contents: write } # to commit .ship/state.json back
|
|
10
|
+
jobs:
|
|
11
|
+
ship:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
timeout-minutes: 30
|
|
14
|
+
env:
|
|
15
|
+
ETH_PRIVATE_KEY: ${{ secrets.ETH_PRIVATE_KEY }}
|
|
16
|
+
PINATA_JWT: ${{ secrets.PINATA_JWT }}
|
|
17
|
+
PINATA_GATEWAY: ${{ vars.PINATA_GATEWAY }}
|
|
18
|
+
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
19
|
+
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: actions/setup-node@v4
|
|
23
|
+
with: { node-version: 22, cache: npm }
|
|
24
|
+
- if: github.event_name != 'schedule'
|
|
25
|
+
run: ci/ship.sh ship
|
|
26
|
+
- if: github.event_name != 'schedule'
|
|
27
|
+
name: keep the claim block, URL and agent id
|
|
28
|
+
run: |
|
|
29
|
+
git add .ship/state.json
|
|
30
|
+
git diff --cached --quiet || { git -c user.name=github-actions -c user.email=41898282+github-actions[bot]@users.noreply.github.com commit -m "ship: state" && git push; }
|
|
31
|
+
- uses: actions/cache@v4
|
|
32
|
+
with: { path: ~/.cache/fangorn-mcp/models, key: models-embeddinggemma }
|
|
33
|
+
- run: ci/ship.sh eval
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# A Fangorn app
|
|
2
|
+
|
|
3
|
+
This repo holds the app's recipe, not its data: what a record is (`app.json`), what a good
|
|
4
|
+
answer looks like (`eval/`), and how to ship it (`ci/`). It can be public. The data lives
|
|
5
|
+
on chain and IPFS, committed by the app's publishers; the Worker indexes it every 5
|
|
6
|
+
minutes, and serves the site, the view, `/mcp` and the agent card.
|
|
7
|
+
|
|
8
|
+
## Set up (testnet, your own Cloudflare)
|
|
9
|
+
|
|
10
|
+
1. Edit `app.json`: `app` (the name you claim, globally unique), `name`, `description`,
|
|
11
|
+
`site.project` (the Worker's name), and the type: rename `my-app.item.v1` and map your
|
|
12
|
+
fields in `role_map`.
|
|
13
|
+
2. Add repo secrets (Settings → Secrets and variables → Actions):
|
|
14
|
+
- `ETH_PRIVATE_KEY`: a Base Sepolia wallet with test ETH; it claims and owns the app
|
|
15
|
+
- `PINATA_JWT`, and the variable `PINATA_GATEWAY`
|
|
16
|
+
- `CLOUDFLARE_API_TOKEN` (template "Edit Cloudflare Workers", plus R2 and Workers AI) and `CLOUDFLARE_ACCOUNT_ID`
|
|
17
|
+
3. Push `app.json` to `main`. The `ship` workflow claims the app, deploys the Worker and
|
|
18
|
+
binds its agent, then commits `.ship/state.json` back. Ship again whenever `app.json` changes.
|
|
19
|
+
|
|
20
|
+
## Publish data
|
|
21
|
+
|
|
22
|
+
Any member of the app commits records of its type, from anywhere:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
echo '{"records":[{"id":"first","type":"my-app.item.v1","payload":{"id":"first","title":"Hello","text":"The first item.","tags":["demo"]}}]}' > items.json
|
|
26
|
+
fangorn --app my-app repo init items
|
|
27
|
+
fangorn --app my-app commit items.json -m "first items"
|
|
28
|
+
fangorn --app my-app push
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The view picks it up within 5 minutes at `<url>/view`. A source that crawls something
|
|
32
|
+
on a schedule goes in `app.json` `sources`; see westmarch's docs.
|
|
33
|
+
|
|
34
|
+
## Keep it good
|
|
35
|
+
|
|
36
|
+
Write `eval/goals.md` (who it serves) and `eval/golden.jsonl` (one check per line:
|
|
37
|
+
`{"id","q","expect","min","goal"}`). The workflow grades the live view daily, and the run
|
|
38
|
+
goes red when a check fails. `ci/ship.sh` runs the same steps on any CI or a laptop.
|