@fangorn-network/westmarch 2026.10.29 → 2026.11.4-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.
Files changed (360) hide show
  1. package/README.md +5 -5
  2. package/docs/app-to-agent.md +61 -625
  3. package/package.json +12 -17
  4. package/site/dist/assets/__vite-browser-external-D2U8RZpp.js +1 -0
  5. package/site/dist/assets/embed.worker-CmS57Zti.js +1 -0
  6. package/site/dist/assets/index-Djs8f08m.js +8 -0
  7. package/site/dist/assets/rolldown-runtime-COiEfhsA.js +1 -0
  8. package/site/dist/assets/{transformers.web-BTyOEJ0C.js → transformers.web-CwR_IYQV.js} +1 -1
  9. package/site/dist/index.html +3 -4
  10. package/site/worker.js +115 -338
  11. package/src/agent/agent-card.js +33 -45
  12. package/src/agent/mcp.js +168 -371
  13. package/src/agent/tools.js +2 -1
  14. package/src/agent/view-tools.js +4 -56
  15. package/src/agent/x402.js +182 -369
  16. package/src/core/roles.js +6 -6
  17. package/src/core/shard.js +4 -4
  18. package/src/discover/apps.js +67 -81
  19. package/src/discover/directory.js +2 -2
  20. package/src/market/reactions.js +21 -15
  21. package/src/publish/devnet.js +69 -18
  22. package/src/publish/init.js +1 -1
  23. package/src/publish/ship.js +74 -275
  24. package/src/publish/view.js +52 -53
  25. package/template/README.md +9 -11
  26. package/template/package.json +1 -1
  27. package/plugin/scripts/fx.mjs +0 -266
  28. package/site/dist/assets/AccountNotFoundScreen-C4njXc69-DyVH4CEz.js +0 -1
  29. package/site/dist/assets/AddFundsSelectionScreen-RAoCn7ej-Dz1--SS9.js +0 -31
  30. package/site/dist/assets/Address-H8kD1d9O-BdFZmRwI.js +0 -17
  31. package/site/dist/assets/AffirmativeConsentScreen-BG0MJxku-CxaCAisL.js +0 -6
  32. package/site/dist/assets/AllowlistRejectionScreen-Cae6e1Od-JGk7vndN.js +0 -1
  33. package/site/dist/assets/ApiController-CTLbMCcH.js +0 -5
  34. package/site/dist/assets/ArrowsRightLeftIcon-B8g9adpz.js +0 -1
  35. package/site/dist/assets/AuthenticateWithWalletScreen-CU6hIcFT-CXD9_OP8.js +0 -1
  36. package/site/dist/assets/AwaitingEvmToSolBridgingScreen-D0e_sZMS-BtJCglvU.js +0 -1
  37. package/site/dist/assets/AwaitingExternalEthereumTransferScreen-ur5HL4R7-BgC2TsqH.js +0 -1
  38. package/site/dist/assets/AwaitingPasswordlessCodeScreen-DRHz76mM-B9OzLeEO.js +0 -103
  39. package/site/dist/assets/AwaitingSolToEvmBridgingScreen-CdLRrGD2-C7r5snUL.js +0 -1
  40. package/site/dist/assets/BridgeNetworkSelectionView-CFGjB2nO-BTV0NRio.js +0 -68
  41. package/site/dist/assets/CaptchaScreen-DbpvkIGx-7rSZIuM-.js +0 -1
  42. package/site/dist/assets/CheckCircleIcon-B1l17ioc.js +0 -1
  43. package/site/dist/assets/CheckCircleIcon-BGSI8nKf.js +0 -1
  44. package/site/dist/assets/Checkbox-D1EDeo41-BUfq0w99.js +0 -52
  45. package/site/dist/assets/ChevronDownIcon-B6uJvPHu.js +0 -1
  46. package/site/dist/assets/Chip-CZKIKt9K-r9Nk__0-.js +0 -26
  47. package/site/dist/assets/CoinbaseOnrampStatusScreen-BbyCJDXL-DWWNHxmR.js +0 -16
  48. package/site/dist/assets/ConnectEmailForm-B-VRE0MN-CRQwS0Xu.js +0 -3
  49. package/site/dist/assets/ConnectLedgerScreen-DWHABGot-CZcCt31O.js +0 -10
  50. package/site/dist/assets/ConnectOnlyLandingScreen-CZYx9Bmp-C5IOf-SQ.js +0 -1
  51. package/site/dist/assets/ConnectOnlyStatusScreen-DCRzjxHx-cwg74F3A.js +0 -1
  52. package/site/dist/assets/ConnectOrCreateScreen-CUUYUO07-D28oeK6b.js +0 -1
  53. package/site/dist/assets/ConnectPhoneForm-Dek5xn4C-EEdkKeTp.js +0 -95
  54. package/site/dist/assets/ConnectWalletView-DqI-PTvX-C2mEzukj.js +0 -74
  55. package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-CH_7r8iV.js +0 -7
  56. package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-Z33kis0B.js +0 -1
  57. package/site/dist/assets/ConnectorUtil-DH4NePk5.js +0 -21
  58. package/site/dist/assets/ConstantsUtil-DmLsRHAl.js +0 -198
  59. package/site/dist/assets/CopyToClipboard-i_OQSBJr-_G88JCVR.js +0 -39
  60. package/site/dist/assets/CopyableText-CQapvaMr-CGGfc_zM.js +0 -28
  61. package/site/dist/assets/CrossAppAuthScreen-CLw7ymZq-C9Okoc0V.js +0 -1
  62. package/site/dist/assets/CustomLandingScreenView-Cm_MBSyX-D2l6hdSl.js +0 -22
  63. package/site/dist/assets/DelegatedActionsConsentScreen-DYF2U4y5-Dda3KKqS.js +0 -1
  64. package/site/dist/assets/DelegatedActionsRevokeScreen-bPp6Uwyh-DG8kJPt1.js +0 -1
  65. package/site/dist/assets/DepositAddressAddressStepView-4vdkb55L-CcOUfn6f.js +0 -187
  66. package/site/dist/assets/DepositAddressScreen-DBLRs7aI-DeituDNh.js +0 -8
  67. package/site/dist/assets/DepositAddressV3Screen-CDqIEMQw-FDg6K14-.js +0 -1
  68. package/site/dist/assets/EmailInputForm-Cqo1mda8-BmbxvPHC.js +0 -124
  69. package/site/dist/assets/EmbeddedWalletConnectingScreen-D4T7DUzs-B05CQ9rx.js +0 -1
  70. package/site/dist/assets/EmbeddedWalletCreatedScreen-D7WhW5ve-Cxd1b9XH.js +0 -1
  71. package/site/dist/assets/EmbeddedWalletKeyExportScreen-CqV4NYQ3-CrJy0ViX.js +0 -23
  72. package/site/dist/assets/EmbeddedWalletOnAccountCreateScreen-BoKb3Q2S-Bakaa3zu.js +0 -1
  73. package/site/dist/assets/EmbeddedWalletPasswordUpdateScreen-D3rMlqS7-j78vKrcj.js +0 -1
  74. package/site/dist/assets/EmbeddedWalletPasswordUpdateSplashScreen-BPFkWJeE-D3dr7W9_.js +0 -1
  75. package/site/dist/assets/EnrollTotp-Dibew4dp-BXbYV8nI.js +0 -66
  76. package/site/dist/assets/EnvelopeIcon-DjPofnRI.js +0 -1
  77. package/site/dist/assets/ErrorBanner-BcpGRt0h-BhH6_V-9.js +0 -21
  78. package/site/dist/assets/ErrorMessage-D8VaAP5m-Bs7uX2a9.js +0 -8
  79. package/site/dist/assets/ErrorScreen-DipdTWzE-BgPRgnOb.js +0 -4
  80. package/site/dist/assets/ErrorScreen-DipdTWzE-CvxXC6pz.js +0 -1
  81. package/site/dist/assets/ExclamationCircleIcon-BE-WGrut.js +0 -1
  82. package/site/dist/assets/ExclamationTriangleIcon-Ca1Xlc_f.js +0 -1
  83. package/site/dist/assets/FarcasterConnectStatusScreen-51tjUxqq-De2JvZdV.js +0 -75
  84. package/site/dist/assets/FarcasterSignerStatusScreen-6x-Uh95G-bLp3hXoO.js +0 -28
  85. package/site/dist/assets/FiatOnrampScreen-BAhYeiTI-Jr6D6JiZ.js +0 -491
  86. package/site/dist/assets/FingerPrintIcon-DOCbS93y.js +0 -1
  87. package/site/dist/assets/FundSolWalletWithExternalSolanaWallet-WtLwYaOl-A_G5kfa1.js +0 -1
  88. package/site/dist/assets/FundWalletMethodHeader-BWNkokCT-LPv35wkD.js +0 -1
  89. package/site/dist/assets/FundWithBankDepositScreen-DajkHxBD-0hfGrfvf.js +0 -58
  90. package/site/dist/assets/FundingEditAmountScreen-CpvpiO4M-Dz0s_NWR.js +0 -1
  91. package/site/dist/assets/FundingMethodSelectionScreen-Db7vhRlE-ZGm-3-Io.js +0 -1
  92. package/site/dist/assets/GlobeAltIcon-BBRl2MMn.js +0 -1
  93. package/site/dist/assets/GooglePay-B53WnudL-BGiVpB8y.js +0 -1
  94. package/site/dist/assets/HCaptchaWrapper-CUi9LJsp-CHdfIeD_.js +0 -4
  95. package/site/dist/assets/InAppBrowserLoginNotPossible-BMR9br1T-Cgoiow3m.js +0 -1
  96. package/site/dist/assets/InfoBanner-Cb3p1z12-_YqQmRiu.js +0 -22
  97. package/site/dist/assets/InjectedWalletIcon-DLcYOGDj-tuIrKQHH.js +0 -1
  98. package/site/dist/assets/InstallWalletScreen-DTA8dwLv-BMU_wa61.js +0 -1
  99. package/site/dist/assets/JsonTree-BHzNC-ic-DcVr0YF0.js +0 -34
  100. package/site/dist/assets/LabelXs-oqZNqbm_-CNprGVQM.js +0 -6
  101. package/site/dist/assets/LandingScreen-CGWUoSUG-fH6rsQen.js +0 -1
  102. package/site/dist/assets/Layouts-BMRfo5hw-e-sepi6F.js +0 -77
  103. package/site/dist/assets/Link-BdDilT2T-BdwlRJch.js +0 -40
  104. package/site/dist/assets/LinkConflictScreen-C3ZEPsgl-BXKN2Qm5.js +0 -77
  105. package/site/dist/assets/LinkEmailScreen-dKo9frwc-Cyn7Q8p1.js +0 -1
  106. package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-CWiqnwLM.js +0 -117
  107. package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-YmDevJzf.js +0 -1
  108. package/site/dist/assets/LinkPhoneScreen-oIUpfj0w-h7shW-Ay.js +0 -1
  109. package/site/dist/assets/Loader-UAZqxsnw-DJEVblm1.js +0 -62
  110. package/site/dist/assets/LoadingSkeleton-BMsgO5PV-D2atjsP5.js +0 -17
  111. package/site/dist/assets/LockClosedIcon-9EFzWK1C.js +0 -1
  112. package/site/dist/assets/LoginFailedScreen-CN0dJV6U-By3Si77a.js +0 -1
  113. package/site/dist/assets/ManualTransferScreen-CHqcuqbs-BAHPY8rs.js +0 -1
  114. package/site/dist/assets/MfaAuthEnrollmentFlowScreen-Dj7gPTRC-CLjffFG1.js +0 -1
  115. package/site/dist/assets/MfaAuthVerifyFlowScreen-DbFpyWMy-BmQg1Y61.js +0 -1
  116. package/site/dist/assets/MfaEnrollmentFlowScreen-DhLnGgnr-DmBtTtlw.js +0 -1
  117. package/site/dist/assets/MfaVerifyFlowScreen-C_XPjMRP-4a683Bmf.js +0 -1
  118. package/site/dist/assets/ModalFooter-BCuEK_nz-C_71qsaz.js +0 -403
  119. package/site/dist/assets/MoonpayStatusScreen-CzTUtokc-DEHHcEf8.js +0 -16
  120. package/site/dist/assets/OAuthStatusScreen-ufbOa-da-BjAb_WsY.js +0 -1
  121. package/site/dist/assets/OpenLink-CUpJ1mOr-BLWFsPOW.js +0 -39
  122. package/site/dist/assets/PasskeySelectSignupOrLogin-xh2ScC_l-2PJTJxX-.js +0 -1
  123. package/site/dist/assets/PasskeyStatusScreen-Bla8MaOk-DCEg761l.js +0 -6
  124. package/site/dist/assets/PasswordRecoveryScreen-awGXZkQk-8nVjNc8k.js +0 -20
  125. package/site/dist/assets/PhArrowCircleDown-D97G-BOA.js +0 -14
  126. package/site/dist/assets/PhArrowClockwise-DVgyFuez.js +0 -14
  127. package/site/dist/assets/PhArrowDown-87b1BizM.js +0 -14
  128. package/site/dist/assets/PhArrowLeft-Da0MfnbK.js +0 -14
  129. package/site/dist/assets/PhArrowRight-AdrIL4DW.js +0 -14
  130. package/site/dist/assets/PhArrowSquareOut-Bk2CMG3I.js +0 -14
  131. package/site/dist/assets/PhArrowUp-4sgyKPGx.js +0 -14
  132. package/site/dist/assets/PhArrowUpRight-BNghD2zq.js +0 -14
  133. package/site/dist/assets/PhArrowsClockwise-BXRn1GEl.js +0 -14
  134. package/site/dist/assets/PhArrowsDownUp-DM09Jo_3.js +0 -14
  135. package/site/dist/assets/PhArrowsLeftRight-MuKBLUoF.js +0 -14
  136. package/site/dist/assets/PhBank-fHbgCqqZ.js +0 -14
  137. package/site/dist/assets/PhBrowser-2-9m-AkM.js +0 -14
  138. package/site/dist/assets/PhCaretDown-BDNabFuL.js +0 -14
  139. package/site/dist/assets/PhCaretLeft-CI460R-A.js +0 -14
  140. package/site/dist/assets/PhCaretRight-D7ZS3Ls8.js +0 -14
  141. package/site/dist/assets/PhCaretUp-C-iIfyvO.js +0 -14
  142. package/site/dist/assets/PhCheck-DxQXn57r.js +0 -14
  143. package/site/dist/assets/PhCircleHalf-MJZeRBGF.js +0 -14
  144. package/site/dist/assets/PhClock-x3MS3Mwi.js +0 -14
  145. package/site/dist/assets/PhCompass-hYn3HhGN.js +0 -14
  146. package/site/dist/assets/PhCopy-CWNYcABI.js +0 -14
  147. package/site/dist/assets/PhCreditCard-Fy4pzwtt.js +0 -14
  148. package/site/dist/assets/PhCurrencyDollar-BgiaenCi.js +0 -14
  149. package/site/dist/assets/PhDesktop-CxrzCSv5.js +0 -14
  150. package/site/dist/assets/PhDeviceMobile-CsyA5Goi.js +0 -14
  151. package/site/dist/assets/PhDotsThree-D-k1BiYg.js +0 -14
  152. package/site/dist/assets/PhEnvelope-D8kzeNox.js +0 -14
  153. package/site/dist/assets/PhFunnelSimple-CfQs5DAW.js +0 -14
  154. package/site/dist/assets/PhGlobe-DvmSc9_A.js +0 -14
  155. package/site/dist/assets/PhIdentificationCard-CfkZm-5K.js +0 -14
  156. package/site/dist/assets/PhImage-Cf0J2ZfJ.js +0 -14
  157. package/site/dist/assets/PhInfo-Bwi51-2X.js +0 -14
  158. package/site/dist/assets/PhLightbulb-C4FZV7Es.js +0 -14
  159. package/site/dist/assets/PhMagnifyingGlass-C9u8jSCJ.js +0 -14
  160. package/site/dist/assets/PhPaperPlaneRight-zxQVvPLX.js +0 -14
  161. package/site/dist/assets/PhPlus-C4UoW-2n.js +0 -14
  162. package/site/dist/assets/PhPower-CFyWDmgD.js +0 -14
  163. package/site/dist/assets/PhPuzzlePiece-BjoNVfST.js +0 -14
  164. package/site/dist/assets/PhQrCode-CP3tFauY.js +0 -14
  165. package/site/dist/assets/PhQuestion-wOWJBd3G.js +0 -14
  166. package/site/dist/assets/PhQuestionMark-CV0k9C0Y.js +0 -14
  167. package/site/dist/assets/PhSealCheck-vIKzREuN.js +0 -14
  168. package/site/dist/assets/PhSignOut-CxELV-i0.js +0 -14
  169. package/site/dist/assets/PhSpinner-CGDmbzUd.js +0 -14
  170. package/site/dist/assets/PhTrash-C9PD0SAt.js +0 -14
  171. package/site/dist/assets/PhUser-0sWNXQeZ.js +0 -14
  172. package/site/dist/assets/PhVault-6JTskUcC.js +0 -14
  173. package/site/dist/assets/PhWarning-CoKs3gz6.js +0 -14
  174. package/site/dist/assets/PhWarningCircle-BXHw1fCt.js +0 -14
  175. package/site/dist/assets/PhX-DX0SFIqC.js +0 -14
  176. package/site/dist/assets/PhoneIcon-CZ47md80.js +0 -1
  177. package/site/dist/assets/PinInput-DbZ0b1i1-BrTXu3Km.js +0 -247
  178. package/site/dist/assets/PrivyPluginContext-DA-yS5vO-CY60yubk.js +0 -1
  179. package/site/dist/assets/QrCode-DbnZwlkH-CcMrWV5D.js +0 -22
  180. package/site/dist/assets/RecoveryOAuthStatusScreen-CsgtTI2x-DgeDnHOK.js +0 -1
  181. package/site/dist/assets/RecoveryPasswordCreateScreen-Be-qJ-LU-CvJJwLhK.js +0 -1
  182. package/site/dist/assets/RecoverySelectionScreen-D1iGtpmi-CADtGtSV.js +0 -7
  183. package/site/dist/assets/SIWXUtil-Cpiv91-M.js +0 -1
  184. package/site/dist/assets/Screen-D30meWsY-vEusJ7KX.js +0 -175
  185. package/site/dist/assets/ScreenHeader-CHmc4-Lu-BvGTLg53.js +0 -31
  186. package/site/dist/assets/ScreenLayout-OwaQQcxH-cfOTmyl0.js +0 -1
  187. package/site/dist/assets/SelectSourceAsset-CWFog6gm-DxYklZYs.js +0 -140
  188. package/site/dist/assets/SetAutomaticRecoveryScreen-BO_OEqAZ-oeqeo05x.js +0 -14
  189. package/site/dist/assets/SetWalletPasswordForm-DwCTVtAh-BxFee9UA.js +0 -11
  190. package/site/dist/assets/ShieldCheckIcon-eFjsosCA.js +0 -1
  191. package/site/dist/assets/SignRequestScreen-BHKv32KR-z8ixfIma.js +0 -26
  192. package/site/dist/assets/SolanaWalletConnector-C7Lqk-Wz-Bc_lvdiF.js +0 -1
  193. package/site/dist/assets/StackedContainer-B2vaEl56-Do5dXB8-.js +0 -24
  194. package/site/dist/assets/StandardSignAndSendTransactionScreen-CfhIXVtd-DudetZAc.js +0 -20
  195. package/site/dist/assets/Subtitle-CV-2yKE4-DV0o1av3.js +0 -13
  196. package/site/dist/assets/TelegramAuthScreen-UL9zLfO8-Bo3sONvf.js +0 -1
  197. package/site/dist/assets/Title-BnzYV3Is-C3qOPnO_.js +0 -7
  198. package/site/dist/assets/TodoList-DnyULl18-BvxvubbF.js +0 -36
  199. package/site/dist/assets/TransactionDetails-e9nesl30-WWflkOIi.js +0 -109
  200. package/site/dist/assets/TransactionErrorView-BDBNqA_f-CotYKcgf.js +0 -178
  201. package/site/dist/assets/TransferFromWalletScreen-Qvn1Yuno-sVFlWqa8.js +0 -31
  202. package/site/dist/assets/TransferOrBridgeLoadingScreen-Dl1I_iIz-CV2-mY19.js +0 -6
  203. package/site/dist/assets/TurnstileWrapper-B7sNddys-oPbuMTQt.js +0 -1
  204. package/site/dist/assets/UpdateEmailScreen-DVOhPV0H-D_mjSpAy.js +0 -1
  205. package/site/dist/assets/UpdatePhoneScreen-CXRswTNZ-6RLG0ahv.js +0 -1
  206. package/site/dist/assets/UserLimitReachedScreen-5we2DHn8-CaVN0bti.js +0 -1
  207. package/site/dist/assets/Value-DTgR824E-Bp6WGZZm.js +0 -27
  208. package/site/dist/assets/WalletCards-DH1rqayz-D3cOTb9x.js +0 -1
  209. package/site/dist/assets/WalletIcon-DOIZhb2l.js +0 -1
  210. package/site/dist/assets/WalletInfoCard-sq_2wgFg-bOqfl5MA.js +0 -29
  211. package/site/dist/assets/WalletInterstitialScreen-Sh7LfsAh-DWaVkMCA.js +0 -1
  212. package/site/dist/assets/WalletLink-DK5LB5Ha-DjUZvqs-.js +0 -20
  213. package/site/dist/assets/WalletOverflowButton-bfCnp-9T-B6P7DQXA.js +0 -1
  214. package/site/dist/assets/WarningBanner-ZZqCEtZK-Bc2YKZb7.js +0 -21
  215. package/site/dist/assets/__vite-browser-external-NciY4Vu1.js +0 -1
  216. package/site/dist/assets/_esm-BZP3cXTv.js +0 -1
  217. package/site/dist/assets/_esm-ZmzBJpEs.js +0 -6
  218. package/site/dist/assets/accounts-D4AXF17G.js +0 -1
  219. package/site/dist/assets/accounts-IkdFx9nq.js +0 -1
  220. package/site/dist/assets/analytics-mkkvFRju-BRBcadka.js +0 -1
  221. package/site/dist/assets/baseSepolia-Bn1j1Ysw.js +0 -1
  222. package/site/dist/assets/basic-Cz1YiCSk.js +0 -1575
  223. package/site/dist/assets/capitalizeFirstLetter-DmLYqXsO-DtOXx-2n.js +0 -1
  224. package/site/dist/assets/ccip-B1J3oTZx.js +0 -7
  225. package/site/dist/assets/ccip-Bd7261zy.js +0 -1
  226. package/site/dist/assets/ccip-D6EHKpjI.js +0 -1
  227. package/site/dist/assets/chain-scefkYIH.js +0 -5
  228. package/site/dist/assets/check-DHnllI8N.js +0 -1
  229. package/site/dist/assets/chevron-down-1y-r4bGO.js +0 -1
  230. package/site/dist/assets/circle-alert-OwxamXUX.js +0 -1
  231. package/site/dist/assets/circle-check-big-3sZGVC10.js +0 -1
  232. package/site/dist/assets/circle-x-DQjNUV9J.js +0 -1
  233. package/site/dist/assets/client-B-BpRtwY.js +0 -1
  234. package/site/dist/assets/client-BfIR1FvH.js +0 -9
  235. package/site/dist/assets/coinbase-DCPC2L_R-YEuIn3jh.js +0 -3
  236. package/site/dist/assets/copy-DMOX_yn7.js +0 -1
  237. package/site/dist/assets/core-GIEmxmAa.js +0 -12
  238. package/site/dist/assets/createLucideIcon-BsERoFTA.js +0 -1
  239. package/site/dist/assets/defineChain-B-SQDLTG.js +0 -1
  240. package/site/dist/assets/dijkstra-CY95afk4.js +0 -1
  241. package/site/dist/assets/dist-CoS6E-3x.js +0 -1
  242. package/site/dist/assets/dist-Cp6IXeJd.js +0 -1
  243. package/site/dist/assets/dist-CrNxmdZj.js +0 -1
  244. package/site/dist/assets/dist-DYGtf4F0.js +0 -16
  245. package/site/dist/assets/embed.worker-Cnl4VGr3.js +0 -1
  246. package/site/dist/assets/errors-BQ3N-RVt-CZPAWCgC.js +0 -1
  247. package/site/dist/assets/esm-C3DslVJx.js +0 -1
  248. package/site/dist/assets/esm-Ci1ogKuK.js +0 -1
  249. package/site/dist/assets/esm-Co94ENUV.js +0 -37
  250. package/site/dist/assets/esm-bb8SANZh.js +0 -1
  251. package/site/dist/assets/esm-n2lWo7kz.js +0 -1
  252. package/site/dist/assets/ethers-zTjbodk5-Cs648CnD.js +0 -1
  253. package/site/dist/assets/eventemitter3-Dzc_0Uq2.js +0 -1
  254. package/site/dist/assets/external-link-BBPG3rG7.js +0 -1
  255. package/site/dist/assets/farcaster-DPlSjvF5-CzBCmgyL.js +0 -1
  256. package/site/dist/assets/features-CuiHbgEJ.js +0 -2
  257. package/site/dist/assets/fingerprint-pattern-CjLtyIxB.js +0 -1
  258. package/site/dist/assets/floating-ui.react-DmaCfayr.js +0 -1
  259. package/site/dist/assets/floating-ui.react-dom-CaoMF8mP.js +0 -1
  260. package/site/dist/assets/formatErc20TokenAmount-BuPk9xcy-BVqOKQif.js +0 -1
  261. package/site/dist/assets/formatter-CVbp4SlJ.js +0 -1
  262. package/site/dist/assets/get-entropy-details-for-user-dHRH5Gpi-BNiOFXbK.js +0 -1
  263. package/site/dist/assets/getChainName-DjpPdUSc-DUyKDrnp.js +0 -1
  264. package/site/dist/assets/getErc20Balance-jXNpFf0N-q4bV8kQq.js +0 -1
  265. package/site/dist/assets/getErc20TokenInfo-BNTrzLMP-DcnTFrXN.js +0 -1
  266. package/site/dist/assets/getFormattedUsdFromLamports-De3U9GlO-Gx4_wxON.js +0 -1
  267. package/site/dist/assets/getUsdcMintAddress-BVgm9GRo-r2UnDeEy.js +0 -1
  268. package/site/dist/assets/guards-BIW-GiMJ-D3tWTQAR.js +0 -1
  269. package/site/dist/assets/hooks.module-BYZGfwDl.js +0 -1
  270. package/site/dist/assets/hourglass-D_GfQdJr.js +0 -1
  271. package/site/dist/assets/id-UqEwL2BI-CTlvRMA5.js +0 -1
  272. package/site/dist/assets/index-BdEw5wyl-kLbhqLbv.js +0 -1
  273. package/site/dist/assets/index-C2h3EneX.js +0 -8
  274. package/site/dist/assets/index-CWARkn2w-DxuckIFn.js +0 -61
  275. package/site/dist/assets/index-DvMddJcd-CNBb4VUn.js +0 -12
  276. package/site/dist/assets/index-YiCw0Y_x-Czl0tWfF.js +0 -436
  277. package/site/dist/assets/index.browser-B-i-Lj3J.js +0 -1
  278. package/site/dist/assets/index.browser-BMmUcykv.js +0 -1
  279. package/site/dist/assets/index.es-Crd0TyUS.js +0 -2
  280. package/site/dist/assets/index.es-DQbup1WG.js +0 -3
  281. package/site/dist/assets/isPaymentRequestAvailable-Bq1cemEn-Cjf3l05I.js +0 -1
  282. package/site/dist/assets/jsx-runtime-CndCZlyt.js +0 -1
  283. package/site/dist/assets/landmark-BZPqMFEf.js +0 -1
  284. package/site/dist/assets/lib-DGtzi2DK.js +0 -1
  285. package/site/dist/assets/localBatchGatewayRequest-B71J8sQ9.js +0 -29
  286. package/site/dist/assets/lock-DyN_c-ud.js +0 -1
  287. package/site/dist/assets/logger-CsXm3oIv-B0UYpNFI.js +0 -1
  288. package/site/dist/assets/mail-V_mcPb64.js +0 -1
  289. package/site/dist/assets/modal-context-CwmSeFcv-DPWNJrfK.js +0 -1
  290. package/site/dist/assets/native-BKj27wfc.js +0 -1
  291. package/site/dist/assets/ofetch.CWycOUEr-Duby3iHT.js +0 -1
  292. package/site/dist/assets/parseAbi-Csg-8t59.js +0 -2
  293. package/site/dist/assets/parseAbiParameters-BWbIMYe4.js +0 -1
  294. package/site/dist/assets/parseEther-CHS0GNkM.js +0 -1
  295. package/site/dist/assets/pkce-DXF0yKjP-7_VY-d83.js +0 -1
  296. package/site/dist/assets/preload-helper-CRzLMJPS.js +0 -1
  297. package/site/dist/assets/privy-context-81KmsBw2-DiR6-Yq8.js +0 -2
  298. package/site/dist/assets/property-DuZ9DLP4.js +0 -3
  299. package/site/dist/assets/react-BfYA1q0G.js +0 -1
  300. package/site/dist/assets/react-CK2HRI1t.js +0 -1
  301. package/site/dist/assets/react-DxGeY8B8.js +0 -1
  302. package/site/dist/assets/react-auth-sHnipzbS.js +0 -1
  303. package/site/dist/assets/react-dom-BI2Koe4o.js +0 -1
  304. package/site/dist/assets/reservoir-x-nGuZkT-BguVFH3D.js +0 -1
  305. package/site/dist/assets/rolldown-runtime-Bjp52BOI.js +0 -1
  306. package/site/dist/assets/safe-url-D7SRPu33-CkMedGro.js +0 -1
  307. package/site/dist/assets/secp256k1-BeYL8aZl.js +0 -1
  308. package/site/dist/assets/secp256k1-Bh4MSkhz.js +0 -1
  309. package/site/dist/assets/secp256k1-Ci4cqHl0.js +0 -1
  310. package/site/dist/assets/secp256k1-DsxXqbXv.js +0 -1
  311. package/site/dist/assets/secp256k1-N9RUmafO.js +0 -1
  312. package/site/dist/assets/serializeAuthorizationList-DGMik9Wx.js +0 -1
  313. package/site/dist/assets/serializeSignature-CWKpxoab.js +0 -2
  314. package/site/dist/assets/sha2-C6s7zZmb.js +0 -1
  315. package/site/dist/assets/shared-DRZUmnL5-BewE5wK8.js +0 -193
  316. package/site/dist/assets/shared-FM0rljBt-CxLACri_.js +0 -21
  317. package/site/dist/assets/shouldProceedtoEmbeddedWalletCreationFlow-B3vyavrh-BkAKsRNi.js +0 -1
  318. package/site/dist/assets/simulateTransaction-CfuOrae4-PjA_tGjX.js +0 -1
  319. package/site/dist/assets/smartphone-3p8nFSTE.js +0 -1
  320. package/site/dist/assets/src-BBjkfi-Q.js +0 -1
  321. package/site/dist/assets/storage-Ufl800Ne-1qCR2JMO.js +0 -8
  322. package/site/dist/assets/stringify-DqUj9VzO.js +0 -20
  323. package/site/dist/assets/stripe.esm-DEi2D291.js +0 -2
  324. package/site/dist/assets/styles-BsotlekN-Aq27nZGc.js +0 -9
  325. package/site/dist/assets/styles-Cm9H63WO-p_ic_dxE.js +0 -92
  326. package/site/dist/assets/styles-DVyDvTdj-CjsWqAld.js +0 -74
  327. package/site/dist/assets/styles-hslXy6xG-D5QHIrJU.js +0 -164
  328. package/site/dist/assets/telegram-B-JqnkqZ-Dqkm4rDn.js +0 -1
  329. package/site/dist/assets/to-ui-error-DWe-qwS3-Bi1HUQI9.js +0 -4
  330. package/site/dist/assets/toViemAccount-B5iDGq1b-CdFZwv07.js +0 -2
  331. package/site/dist/assets/transaction-BNTP-bFm-M5tJx8vY.js +0 -1
  332. package/site/dist/assets/transfer-6YztDh-t-BVQkTvG-.js +0 -1
  333. package/site/dist/assets/triangle-alert-BG3Qw-Hq.js +0 -1
  334. package/site/dist/assets/twitch-5IOe4sIQ-CaXHFlAu.js +0 -1
  335. package/site/dist/assets/types-4CuOD23i.js +0 -1
  336. package/site/dist/assets/use-headless-crypto-deposit-Yn-QRLB3-CQqeyhGY.js +0 -1
  337. package/site/dist/assets/use-unlink-wallet-BKK4_5Ur-C0xQN_Lp.js +0 -1
  338. package/site/dist/assets/useActiveWallet-B-yZYGc6-BkK6rFBm.js +0 -123
  339. package/site/dist/assets/useGetSolPrice-x7gfUIHJ-CLVXqv6I.js +0 -1
  340. package/site/dist/assets/useGetTokenPrice-CaoUkb79-DAXXs3rs.js +0 -1
  341. package/site/dist/assets/useI18n-C-5n_noF-CGpkgIVy.js +0 -1
  342. package/site/dist/assets/useWalletBalance-CZnP5f_f-Cfd64m4n.js +0 -1
  343. package/site/dist/assets/useWallets-X1ndvJ_U-CAYqg7Za.js +0 -1
  344. package/site/dist/assets/utils-BkR7EQjg.js +0 -1
  345. package/site/dist/assets/utils-DJhBNOZA.js +0 -1
  346. package/site/dist/assets/utils-DdckVfQr.js +0 -1
  347. package/site/dist/assets/w3m-modal-B4H_uiPH.js +0 -1174
  348. package/site/dist/assets/wallet-BNI12IYk.js +0 -1
  349. package/site/dist/assets/wallet-CITSaPlB.js +0 -2
  350. package/site/dist/assets/wallet-connect-BvJtUsDt-CVlSNIXP.js +0 -1
  351. package/site/dist/assets/walletconnect-registry-xxG8XLCb-BpzpBq5s.js +0 -1
  352. package/site/dist/assets/walletconnect-v2-3frQFwbg-CzZ6oybX.js +0 -12
  353. package/site/dist/assets/wui-ux-by-reown-XyHdtV1O.js +0 -1147
  354. package/site/dist/assets/x-gjDrY2rk.js +0 -1
  355. package/src/discover/explore.js +0 -291
  356. package/src/market/settle.js +0 -165
  357. package/src/market/terms.js +0 -200
  358. package/src/publish/cli.js +0 -336
  359. package/src/publish/envelope.js +0 -185
  360. package/src/publish/manifest.js +0 -142
package/src/core/roles.js CHANGED
@@ -5,7 +5,7 @@
5
5
  // on the next — which is exactly what happened the first time the probe was
6
6
  // pointed at a second bundle.
7
7
  //
8
- // The answer is already baked. A quickbeam domain manifest carries `role_map`
8
+ // The answer is already baked. A view's domain manifest carries `role_map`
9
9
  // (which field is the title, the subtitle, the tags, the prose to search, the
10
10
  // measures, the location, the link) and `presentation` (an icon, an accent and a
11
11
  // singular/plural name per entity type, plus per-type external URL templates).
@@ -158,7 +158,7 @@ export function rolesFrom(manifests = [], sample = []) {
158
158
  /**
159
159
  * Which collection a row belongs to.
160
160
  *
161
- * `entityType` is quickbeam's own convention — both bundles here carry it, and
161
+ * `entityType` is the view's own convention — every row carries it, and
162
162
  * the manifest's `entity_types` counts are keyed by it — so this is the one
163
163
  * field name the format actually fixes. `kind` is the older spelling and is
164
164
  * still on-chain in sond3r's vertices, hence the fallback.
@@ -249,7 +249,7 @@ export const isLocked = (field, roles) =>
249
249
  /** Is this row part of the corpus's free sample — the deterministic slice a
250
250
  * paywalled bake hands over whole so a buyer can read before paying?
251
251
  *
252
- * The bake picks it by hashing the row's own id (quickbeam `paywall.in_sample`),
252
+ * The bake picks it by hashing the row's own id (`inSample`),
253
253
  * which is what stops a seller putting its best rows in the shop window. That
254
254
  * only holds if someone CHECKS, and the check is this function: anyone can
255
255
  * recompute which rows should be free and see whether the shard agrees. */
@@ -460,9 +460,9 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
460
460
  if (gatesOf(rolesFrom([places])).length) throw new Error("an ungated view must report no gates");
461
461
  if (isLocked("text", rolesFrom([places]))) throw new Error("nothing is locked in an ungated view");
462
462
 
463
- // The free sample, recomputed. Must agree with quickbeam's paywall.in_sample
464
- // byte for byte or the check that keeps a seller honest checks nothing —
465
- // these ids and their verdicts are pinned against that implementation.
463
+ // The free sample, recomputed. Must agree with the bake's sample byte for byte or
464
+ // the check that keeps a seller honest checks nothing — these ids and their
465
+ // verdicts are pinned.
466
466
  for (const [id, yes] of [["row-47", true], ["row-169", true], ["row-0", false], ["row-3", false], ["row-19", false]]) {
467
467
  if (await inSample(id, 0.01) !== yes) throw new Error(`inSample must match the bake: ${id}`);
468
468
  }
package/src/core/shard.js CHANGED
@@ -1,4 +1,4 @@
1
- // Reading a quickbeam VIEW's Semantic CDN shards, in the consumer's own process.
1
+ // Reading a VIEW's Semantic CDN shards (view.js's layout), in the consumer's own process.
2
2
  //
3
3
  // One view → one manifest per watched (owner, namespace) domain → N gzipped
4
4
  // NDJSON shards, downloaded once, kept in memory, ranked locally — no index
@@ -139,7 +139,7 @@ export function setDomains(only) {
139
139
  const wanted = (name) => !_only || _only.some((e) =>
140
140
  name === e || name.split("/").pop() === e || name.startsWith(e));
141
141
 
142
- const NO_VIEW = "no quickbeam view configured — pass a view base, or wire one with configure({ resolveView })";
142
+ const NO_VIEW = "no view configured — pass a view base, or wire one with configure({ resolveView })";
143
143
 
144
144
  /** Fetch + parse a view's shards. Cached PER VIEW; concurrent callers share one
145
145
  * fetch. Keyed by the resolved base, so two apps on screen in one session can't
@@ -347,7 +347,7 @@ async function load(view, onRows) {
347
347
  // A view with nothing baked yet is the normal state of a brand-new one, not an
348
348
  // error. Say which it is, or "search finds nothing" is indistinguishable from
349
349
  // a URL pointing at the wrong view.
350
- if (!domains.length) console.warn(`shard: quickbeam view ${cdn} has no baked domains yet — nothing to read until the watcher bakes one.`);
350
+ if (!domains.length) console.warn(`shard: view ${cdn} has no baked domains yet — nothing to read until its indexer bakes one.`);
351
351
 
352
352
  const byId = new Map();
353
353
  const dead = new Set();
@@ -666,7 +666,7 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
666
666
  }
667
667
 
668
668
  // ── the bake's packed vector (`v`), the form shipped today ──
669
- // Pinned against pack_vec in quickbeam/vectors.py: [0,1,-1] -> "AH+B". A
669
+ // Pinned: [0,1,-1] -> "AH+B" (packVec in embed.js writes it). A
670
670
  // drift here is not a crash, it is cosine ranking on noise.
671
671
  {
672
672
  await serveView({ d0: [[{ track_id: "p1", owner: "0xa", v: "AH+B", fields: { entityType: "file", name: "packed.md", path: "packed.md" } },
@@ -1,20 +1,15 @@
1
- // The index of apps — read off the chain.
1
+ // The index of apps, read off the chain.
2
2
  //
3
- // An app owner binds its agent card with `setAppAgentUri`, and the AppRegistry
4
- // emits `AppAgentChanged(appId, uri)`. The log IS the directory: no registry
5
- // namespace to bake, no relay to ask, nobody's server in the loop. Scan the
6
- // logs, keep each app's latest uri, and hand every uri to `discoverApp`, which
7
- // fetches the card and checks it names that app and is still the one bound on
8
- // chain. The card then says where the data is (`views`) and where it starts
9
- // (`fromBlock`).
3
+ // An app is a publisher's repo whose `@card` record points at an agent card that points back.
4
+ // So the directory is `repos()` (one scan of the update log), each repo's `@card` (one read
5
+ // per repo, cached by head), and `discoverCard` on each card found, which checks the binding.
6
+ // No registry, no relay, nobody's server in the loop.
10
7
  //
11
- // `fangorn` is an SDK client, passed in rather than imported, so this module
12
- // stays usable where the SDK is not installed, and testable without a chain.
13
- // Reads only: a reader can create one with a throwaway key.
8
+ // `fangorn` is an SDK client, passed in rather than imported, so this module stays usable
9
+ // where the SDK is not installed, and testable without a chain.
14
10
  //
15
- // ponytail: one flat list, no ranking. Every card is one fetch, all in
16
- // parallel. Past a few hundred apps, rank by the cards' own coverage instead of
17
- // fetching them all.
11
+ // ponytail: one flat list, no ranking, every card fetched. Past a few hundred apps, rank by
12
+ // the cards' own coverage instead.
18
13
 
19
14
  /**
20
15
  * A pointer someone else wrote, and following it is the one place a reader
@@ -29,9 +24,9 @@ function safeView(url) {
29
24
  } catch { return null; }
30
25
  }
31
26
 
32
- /** The SDK's FANGORN_APP_EXTENSION. Copied so this file needs no SDK;
27
+ /** The SDK's FANGORN_REPO_EXTENSION. Copied so this file needs no SDK;
33
28
  * src/agent/agent-card.js's self-check fails if the two drift. */
34
- export const APP_EXTENSION = "https://fangorn.network/a2a/app/v1";
29
+ export const APP_EXTENSION = "https://fangorn.network/a2a/repo/v1";
35
30
 
36
31
  /** The app's agent skill, `{url, sha256}`, when its card names one well-formed; else null. */
37
32
  export const skillOf = (ext) => {
@@ -47,16 +42,19 @@ export const pluginOf = (ext) => {
47
42
  return p && PLUGIN_MARKETPLACE.test(p.marketplace ?? "") && PLUGIN_NAME.test(p.name ?? "") ? { marketplace: p.marketplace, name: p.name } : null;
48
43
  };
49
44
 
50
- /** A verified card → an app entry. `views` is westmarch's param; the SDK does not read it. */
51
- export function toApp({ card, appId, fromBlock, repos }, cardUrl) {
52
- const ext = card.capabilities.extensions.find((e) => e.uri === APP_EXTENSION);
53
- const views = (Array.isArray(ext?.params?.views) ? ext.params.views : []).map(safeView).filter(Boolean);
54
- const p = ext?.params?.paid;
55
- const paid = p && /^https?:\/\//.test(p.url ?? "") && p.url.includes("{id}") && /^\d+$/.test(String(p.price)) ? p : null;
45
+ /** A verified card (`discoverCard`'s result) → an app entry. `views` etc. are westmarch's params; the SDK ignores them. */
46
+ export function toApp({ card, publisher, repo }, cardUrl) {
47
+ const p = card.capabilities.extensions.find((e) => e.uri === APP_EXTENSION)?.params ?? {};
48
+ const views = (Array.isArray(p.views) ? p.views : []).map(safeView).filter(Boolean);
49
+ const paid = p.paid && /^https?:\/\//.test(p.paid.url ?? "") && p.paid.url.includes("{id}") ? { url: p.paid.url } : null;
56
50
  return {
57
- appId, card: cardUrl, fromBlock, repos, views, paid, skill: skillOf(ext), plugin: pluginOf(ext),
58
- mcp: safeView(ext?.params?.mcp),
59
- name: card.name ?? appId,
51
+ id: `${publisher}:${repo}`, publisher, repo, card: cardUrl,
52
+ fromBlock: /^\d+$/.test(String(p.fromBlock)) ? BigInt(p.fromBlock) : null,
53
+ repos: Array.isArray(p.repos) ? p.repos.filter((r) => typeof r === "string") : [],
54
+ views, paid, skill: skillOf({ params: p }), plugin: pluginOf({ params: p }),
55
+ mcp: safeView(p.mcp),
56
+ tools: (card.skills ?? []).map((k) => k.id),
57
+ name: card.name ?? repo,
60
58
  desc: card.description ?? "",
61
59
  url: safeView(card.url),
62
60
  };
@@ -80,29 +78,23 @@ export async function cachedLogs(store, key, start, head, read) {
80
78
  }
81
79
 
82
80
  /**
83
- * Every app with a bound, verifiable card. The ones that fail are reported
84
- * with the reason, not dropped: a card that is down and a card that lies look
85
- * the same from outside, and an agent should see both.
86
- *
87
- * An app that cleared its uri (bound to "") is skipped. It is not an error.
88
- *
89
- * With a `store` (see cachedLogs) and `toBlock`, the logs read before are not
90
- * read again; the cards are still all verified.
81
+ * Every app with a bound, verifiable card. The ones that fail are reported with the reason,
82
+ * not dropped: a card that is down and a card that lies look the same from outside, and an
83
+ * agent should see both. `store` ({ get, set }) caches each repo's card URL by head.
91
84
  */
92
- export async function listApps(fangorn, { fromBlock, toBlock, store } = {}) {
93
- if (fromBlock == null) throw new Error("listApps: pass fromBlock, a block at or before the AppRegistry's deployment — from 0 is one RPC call per 1000 blocks of chain history");
94
- const read = (from, to) => fangorn.getAppRegistry().getAppAgentLogs({ fromBlock: from, toBlock: to });
95
- const logs = store && toBlock != null
96
- ? await cachedLogs(store, `AppAgentChanged:${fromBlock}`, BigInt(fromBlock), BigInt(toBlock), read)
97
- : await read(BigInt(fromBlock), toBlock);
98
- // Oldest first, so the last write wins. discoverApp re-reads the binding,
99
- // so a stale uri here is caught there, not trusted.
100
- const latest = new Map(logs.map((l) => [l.appId, l.agentUri]));
85
+ export async function listApps(fangorn, { fromBlock, store } = {}) {
86
+ const repos = await fangorn.repos(fromBlock == null ? {} : { fromBlock: BigInt(fromBlock) });
101
87
  const apps = [], rejected = [];
102
- await Promise.all([...latest].map(async ([appId, uri]) => {
103
- if (!uri) return;
104
- try { apps.push(toApp(await fangorn.discoverApp(uri), uri)); }
105
- catch (e) { rejected.push({ appId, card: uri, why: e?.message ?? String(e) }); }
88
+ await Promise.all(repos.map(async ({ owner, repo, root }) => {
89
+ const key = `card:${owner.toLowerCase()}/${repo}@${root}`;
90
+ let url = store?.get(key);
91
+ if (url === undefined) {
92
+ try { url = (await fangorn.cardOf(owner, repo)) ?? null; } catch { return; } // unreadable now: not cached, tried next time
93
+ store?.set(key, url);
94
+ }
95
+ if (!url) return;
96
+ try { apps.push(toApp(await fangorn.discoverCard(url), url)); }
97
+ catch (e) { rejected.push({ publisher: owner, repo, card: url, why: e?.message ?? String(e) }); }
106
98
  }));
107
99
  apps.sort((a, b) => a.name.localeCompare(b.name));
108
100
  return { apps, rejected };
@@ -112,52 +104,46 @@ export async function listApps(fangorn, { fromBlock, toBlock, store } = {}) {
112
104
  if (typeof process !== "undefined" && import.meta.url === `file://${process.argv[1]}` && process.argv[1].endsWith("/apps.js")) {
113
105
  const j = (x) => JSON.stringify(x, (_, v) => (typeof v === "bigint" ? `${v}n` : v));
114
106
  const eq = (a, b, m) => { if (j(a) !== j(b)) throw new Error(`${m}: ${j(a)} != ${j(b)}`); };
115
- const A = "0x" + "a".repeat(64), B = "0x" + "b".repeat(64), C = "0x" + "c".repeat(64);
116
- const card = (appId, name, views) => ({ name, description: `${name}!`, url: "https://x.test/", capabilities: { extensions: [
117
- { uri: "https://other/ext", params: { appId, views: ["https://evil.test/"] } },
118
- { uri: "https://fangorn.network/a2a/app/v1", params: { appId, views } },
107
+ const P = "0x" + "11".repeat(20), Q = "0x" + "22".repeat(20);
108
+ const card = (publisher, repo, name, views) => ({ name, description: `${name}!`, url: "https://x.test/", capabilities: { extensions: [
109
+ { uri: "https://other/ext", params: { views: ["https://evil.test/"] } },
110
+ { uri: APP_EXTENSION, params: { publisher, repo, fromBlock: "7", repos: ["n"], views } },
119
111
  ] } });
120
112
  const cards = {
121
- "https://a.test/card": card(A, "Beta", ["https://a.test/q/v1/stream", "javascript:alert(1)"]),
122
- "https://a.test/old": card(A, "Old", []),
123
- "https://b.test/card": card(B, "Alpha", []),
113
+ "https://a.test/card": card(P, "beta", "Beta", ["https://a.test/q/v1/stream", "javascript:alert(1)"]),
114
+ "https://b.test/card": card(Q, "alpha", "Alpha", []),
124
115
  };
125
- let askedFrom;
116
+ const bound = { [`${P}/beta`]: "https://a.test/card", [`${Q}/alpha`]: "https://b.test/card", [`${Q}/liar`]: "https://liar.test/card" };
117
+ let cardReads = 0;
126
118
  const fangorn = {
127
- getAppRegistry: () => ({ getAppAgentLogs: ({ fromBlock }) => (askedFrom = fromBlock, Promise.resolve([
128
- { appId: A, agentUri: "https://a.test/old" },
129
- { appId: B, agentUri: "https://b.test/card" },
130
- { appId: A, agentUri: "https://a.test/card" }, // A rebound: last wins
131
- { appId: C, agentUri: "https://c.test/card" },
132
- { appId: C, agentUri: "" }, // C unbound
133
- { appId: "0x" + "d".repeat(64), agentUri: "https://liar.test/card" },
134
- ])) }),
135
- discoverApp: async (uri) => {
136
- if (uri === "https://liar.test/card") throw new Error("not bound to app");
137
- const c = cards[uri];
138
- return { card: c, appId: c.capabilities.extensions[1].params.appId, fromBlock: 7n, repos: ["n"] };
119
+ repos: async () => [{ owner: P, repo: "beta", root: "0x1" }, { owner: Q, repo: "alpha", root: "0x2" },
120
+ { owner: Q, repo: "plain", root: "0x3" }, { owner: Q, repo: "liar", root: "0x4" }],
121
+ cardOf: async (o, r) => (cardReads++, bound[`${o}/${r}`]),
122
+ discoverCard: async (url) => {
123
+ if (url === "https://liar.test/card") throw new Error("not bound");
124
+ const c = cards[url], p = c.capabilities.extensions[1].params;
125
+ return { card: c, publisher: p.publisher, repo: p.repo };
139
126
  },
140
127
  };
141
- const { apps, rejected } = await listApps(fangorn, { fromBlock: 42 });
142
- eq(askedFrom, 42n, "fromBlock forwarded as bigint");
143
- eq(apps.map((a) => a.name), ["Alpha", "Beta"], "one entry per app, latest card, sorted, unbound skipped");
128
+ const m = new Map(), store = { get: (k) => m.get(k), set: (k, v) => m.set(k, v) };
129
+ const { apps, rejected } = await listApps(fangorn, { store });
130
+ eq(apps.map((a) => a.name), ["Alpha", "Beta"], "one entry per carded repo, sorted, repos with no card skipped");
144
131
  const beta = apps[1];
145
132
  eq(beta.views, ["https://a.test/q/v1"], "views from the fangorn extension only, trimmed, non-http dropped");
146
- eq([beta.appId, beta.card, beta.url, beta.fromBlock, beta.desc], [A, "https://a.test/card", "https://x.test", 7n, "Beta!"], "entry fields");
147
- eq(rejected.map((r) => r.why), ["not bound to app"], "a card that fails verification is reported");
148
- await listApps(fangorn).then(() => { throw new Error("missing fromBlock must throw"); }, () => {});
133
+ eq([beta.id, beta.card, beta.url, beta.fromBlock, beta.repos, beta.desc], [`${P}:beta`, "https://a.test/card", "https://x.test", 7n, ["n"], "Beta!"], "entry fields");
134
+ eq(rejected.map((r) => r.why), ["not bound"], "a card that fails verification is reported");
135
+ eq(cardReads, 4, "one @card read per repo");
136
+ await listApps(fangorn, { store });
137
+ eq(cardReads, 4, "an unchanged head is not read again");
149
138
 
150
- const m = new Map(), store = { get: (k) => m.get(k), set: (k, v) => m.set(k, v) }, asked = [];
139
+ const asked = [];
151
140
  const chain = [{ blockNumber: 10n, n: 1 }, { blockNumber: 150n, n: 2 }, { blockNumber: 190n, n: 3 }];
152
141
  const read = async (from, to) => (asked.push([from, to]), chain.filter((l) => l.blockNumber >= from && l.blockNumber <= to));
153
- eq((await cachedLogs(store, "k", 5n, 200n, read)).map((l) => l.n), [1, 2, 3], "first call reads it all");
154
- eq(m.get("k").to, 136n, "stores only what is settled");
155
- eq(m.get("k").logs.map((l) => l.n), [1], "the unsettled tail is not stored");
156
- eq((await cachedLogs(store, "k", 5n, 210n, read)).map((l) => l.n), [1, 2, 3], "second call: same logs, no duplicates");
142
+ const lm = new Map(), ls = { get: (k) => lm.get(k), set: (k, v) => lm.set(k, v) };
143
+ eq((await cachedLogs(ls, "k", 5n, 200n, read)).map((l) => l.n), [1, 2, 3], "first call reads it all");
144
+ eq(lm.get("k").to, 136n, "stores only what is settled");
145
+ eq((await cachedLogs(ls, "k", 5n, 210n, read)).map((l) => l.n), [1, 2, 3], "second call: same logs, no duplicates");
157
146
  eq(asked, [[5n, 200n], [137n, 210n]], "second call reads only from the settled point");
158
- asked.length = 0;
159
- await cachedLogs(store, "k", 5n, 146n, read);
160
- eq(asked, [], "head at the stored point: no read");
161
147
 
162
- console.log("apps.js self-check ok — latest card per app, unbound skipped, failures reported, views gated to http(s)");
148
+ console.log("apps.js self-check ok — an app is a repo whose card verifies, cards read once per head, failures reported, views gated to http(s)");
163
149
  }
@@ -62,7 +62,7 @@ export async function survey(sources = [], { timeoutMs = 8000 } = {}) {
62
62
  for (const d of cat.domains ?? []) {
63
63
  corpora.push({
64
64
  view,
65
- publisher: typeof src === "string" ? null : (src.name ?? src.appId ?? null),
65
+ publisher: typeof src === "string" ? null : (src.name ?? src.id ?? null),
66
66
  owner: typeof src === "string" ? null : (src.owner ?? null),
67
67
  domain: d.name,
68
68
  description: d.description || "",
@@ -164,7 +164,7 @@ export async function findCorpora(query, { sources = [], embed, model, limit = 1
164
164
  * modules to run a survey. Rejected cards come back beside the sources. */
165
165
  export async function sourcesFromChain(fangorn, opts) {
166
166
  const { apps, rejected } = await listApps(fangorn, opts);
167
- return { sources: apps.flatMap((a) => a.views.map((view) => ({ view, name: a.name, appId: a.appId }))), rejected };
167
+ return { sources: apps.flatMap((a) => a.views.map((view) => ({ view, name: a.name, id: a.id }))), rejected };
168
168
  }
169
169
 
170
170
  // ── self-check: `node src/discover/directory.js` ─────────────────────────────────
@@ -16,7 +16,7 @@
16
16
  // ------------------------------------------------------
17
17
  // A reaction's vector is the vector of the row reacted to, which the reader
18
18
  // already downloaded in order to react to it. So a reaction corpus needs no
19
- // model, no GPU, no bake, no quickbeam — the vectors are copied, not computed.
19
+ // model, no GPU, no bake — the vectors are copied, not computed.
20
20
  // The only thing that has to be fitted locally is `coverage`, which is eight
21
21
  // centroids and is the function below. A consumer becoming a publisher is
22
22
  // therefore not a tier you upgrade into; it is this file and a price.
@@ -51,7 +51,24 @@
51
51
  // hat, and a reader with nine reactions is exactly who most needs this to hold.
52
52
 
53
53
  import { EMBED_MODEL, packVec } from "../core/embed.js";
54
- import { lineage } from "./terms.js";
54
+
55
+ const ADDR = /^0x[0-9a-fA-F]{40}$/;
56
+ /** What a publisher owes upstream for one resource, in bps of its share. Deduped by payee:
57
+ * the same source cited twice is one debt, not two, which can't be gamed by repeating an entry. */
58
+ function lineage(entries = []) {
59
+ const by = new Map();
60
+ for (const e of entries) {
61
+ const to = String(e.to ?? "").toLowerCase();
62
+ if (!ADDR.test(to)) throw new Error(`not an address: ${e.to}`);
63
+ const b = BigInt(e.bps ?? 0);
64
+ if (b < 0n || b > 10000n) throw new Error(`lineage bps must be 0..10000, got ${e.bps}`);
65
+ by.set(to, { to, bps: (by.get(to)?.bps ?? 0n) + b, note: e.note ?? by.get(to)?.note ?? "" });
66
+ }
67
+ const out = [...by.values()];
68
+ const total = out.reduce((s, e) => s + e.bps, 0n);
69
+ if (total > 10000n) throw new Error(`lineage owes ${total} bps of the publisher's share — more than all of it`);
70
+ return out.map((e) => ({ to: e.to, bps: String(e.bps), ...(e.note ? { note: e.note } : {}) }));
71
+ }
55
72
 
56
73
  // 32, not 8: on Kingsfoil the top 3 of 23 views held 92% of the true top 10 with 32
57
74
  // centroids and 86% with 8, and 8 missed whole topics (ALS → neurology).
@@ -68,7 +85,7 @@ const dot = (a, b) => { let s = 0, n = Math.min(a.length, b.length); for (let i
68
85
  * Spherical k-means over the corpus's own vectors — the routing summary that
69
86
  * lets a buyer rank this corpus WITHOUT downloading it.
70
87
  *
71
- * Mirrors quickbeam's `cdn._coverage`: fit at full width, truncate to `dim`
88
+ * The view's coverage: fit at full width, truncate to `dim`
72
89
  * leading components (Matryoshka), then RENORMALIZE, because a truncated unit
73
90
  * vector is not unit and the client compares against a truncated query it
74
91
  * renormalizes too. Get that order wrong and routing degrades silently.
@@ -238,7 +255,6 @@ export function reactionCorpus(events = [], {
238
255
 
239
256
  // ── self-check: `node src/market/reactions.js` ────────────────────────────────
240
257
  if (typeof process !== "undefined" && import.meta.url === `file://${process.argv[1]}` && process.argv[1].endsWith("/reactions.js")) {
241
- const { splitPayment } = await import("./terms.js");
242
258
  const A = (n) => `0x${String(n).repeat(40).slice(0, 40)}`;
243
259
  const vec = (a, b) => { const v = new Float32Array(256); v[0] = a; v[1] = b; return v; };
244
260
 
@@ -321,16 +337,6 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
321
337
  if (bps["archive-films"] !== 1500 || bps.games !== 500) throw new Error(`upstream must follow contribution: ${JSON.stringify(bps)}`);
322
338
  if (up.reduce((s, e) => s + Number(e.bps), 0) !== 2000) throw new Error("the declared upstream total must be exact, not a basis point short");
323
339
 
324
- // …and it reconciles against a real sale. This is the claim: the corpora that
325
- // produced the attention are paid when the attention sells.
326
- const TERMS = { appId: "fangorn.tv", owner: A(9), appBps: 1000 };
327
- const pay = splitPayment(300000n, { terms: TERMS, publisher: A(3), lineage: up });
328
- const got = Object.fromEntries(pay.map((p) => [p.to, p.amount]));
329
- if (got[A(9)] !== 30000n) throw new Error("the app's cut comes off the top and never moves");
330
- if (got[A(1)] !== 40500n || got[A(2)] !== 13500n) throw new Error(`upstream is paid from the publisher's share: ${JSON.stringify(got, (k, v) => typeof v === "bigint" ? String(v) : v)}`);
331
- if (got[A(3)] !== 216000n) throw new Error("the reader keeps the rest");
332
- if (pay.reduce((s, p) => s + p.amount, 0n) !== 300000n) throw new Error("money is neither invented nor destroyed");
333
-
334
340
  // A reader who cites a corpus nobody registered simply owes it nothing.
335
341
  const orphan = reactionCorpus(EV, { publisher: A(3), sources: { games: A(2) } });
336
342
  if (orphan.lineage.length !== 1 || Number(orphan.lineage[0].bps) !== 2000) throw new Error("an unregistered corpus cannot be paid, and its share does not vanish");
@@ -341,5 +347,5 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
341
347
 
342
348
  console.log("reactions.js self-check ok — reactions become a corpus with no model, coverage is deterministic and renormalized after truncation, "
343
349
  + "the free index ranks on centroids alone, publishes no per-row vector to join against and no paid string anywhere including its own keys, "
344
- + "time is coarse, upstream follows contribution exactly and reconciles against a real sale");
350
+ + "time is coarse, upstream follows contribution exactly");
345
351
  }
@@ -4,23 +4,56 @@
4
4
  // scripts/e2e-worker.mjs run an app against, with nothing leaving the machine.
5
5
  //
6
6
  // Needs forge and anvil, and the contracts' source (FANGORN_CONTRACTS_DIR, default
7
- // ../contracts/solidity next to westmarch).
7
+ // ../contracts next to westmarch). USDC and Semaphore are the contracts' mocks: payments
8
+ // aren't checked and any proof is accepted.
9
+ //
10
+ // The services a deployment runs are here too, each its own Worker under `wrangler dev`, wired
11
+ // to this chain: `keyServer()` and `relay()` from the webworker checkout (FANGORN_WEBWORKER_DIR,
12
+ // default ../webworker), and `worker()` for any other, such as an app's.
8
13
 
9
14
  import { spawn, spawnSync } from "node:child_process";
10
15
  import { createServer } from "node:http";
11
- import { readFileSync } from "node:fs";
16
+ import { mkdtempSync, readFileSync } from "node:fs";
17
+ import { tmpdir } from "node:os";
12
18
  import { createRequire } from "node:module";
13
- import { dirname, resolve } from "node:path";
19
+ import { dirname, join, resolve } from "node:path";
14
20
  import { fileURLToPath } from "node:url";
15
21
  import { createTestClient, encodeFunctionData, getAddress, http, parseEther, publicActions, walletActions } from "viem";
16
22
  import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
17
- import { APP_REGISTRY_ABI, DATA_REGISTRY_ABI, Fangorn, FangornConfig } from "@fangorn-network/sdk";
23
+ import { bytesToHex } from "viem";
24
+ import { DATA_REGISTRY_ABI, SETTLEMENT_REGISTRY_ABI, Fangorn, FangornConfig } from "@fangorn-network/sdk";
18
25
 
19
26
  const HERE = dirname(fileURLToPath(import.meta.url));
20
27
  const ADMIN_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; // anvil's first account
28
+ /**
29
+ * The Worker in `dir` under `wrangler dev` with `vars`, on a free port: `{ url, kill }` once `probe`
30
+ * answers. Its own process group, so `kill` takes workerd down with wrangler. Local bindings only.
31
+ */
32
+ export async function wranglerDev(dir, vars = {}, { config, probe = "/", name = dir, log = () => {} } = {}) {
33
+ const free = () => new Promise((ok) => { const s = createServer().listen(0, "127.0.0.1", () => { const p = s.address().port; s.close(() => ok(p)); }); });
34
+ // Its own inspector port too: two workers started at once both take wrangler's default (9229), and one dies.
35
+ const [port, inspector] = await Promise.all([free(), free()]);
36
+ const w = spawn("npx", ["wrangler", "dev", ...(config ? ["--config", config] : []), "--port", String(port), "--inspector-port", String(inspector), "--ip", "127.0.0.1",
37
+ "--persist-to", mkdtempSync(join(tmpdir(), "devnet-wrangler-")), ...Object.entries(vars).flatMap(([k, v]) => ["--var", `${k}:${v}`])],
38
+ { cwd: dir, detached: true, stdio: ["ignore", "pipe", "pipe"], env: { ...process.env, NO_D1_WARNING: "true" } });
39
+ let out = "";
40
+ w.stdout.on("data", (c) => { out += c; }); w.stderr.on("data", (c) => { out += c; });
41
+ const kill = () => { try { process.kill(-w.pid); } catch { /* gone */ } };
42
+ process.on("exit", kill);
43
+ const url = `http://127.0.0.1:${port}`;
44
+ for (const t0 = Date.now(); ; await new Promise((r) => setTimeout(r, 500))) {
45
+ if (w.exitCode !== null) throw new Error(`${name}: wrangler dev exited\n${out.slice(-2000)}`);
46
+ if (Date.now() - t0 > 120_000) { kill(); throw new Error(`${name}: no answer at ${url}${probe} in 2 minutes\n${out.slice(-2000)}`); }
47
+ if (await fetch(`${url}${probe}`).then(() => true, () => false)) break;
48
+ }
49
+ log(`${name} at ${url}`);
50
+ return { url, kill };
51
+ }
52
+
21
53
  const listen = (server) => new Promise((ok) => server.listen(0, "127.0.0.1", () => ok(`http://127.0.0.1:${server.address().port}`)));
22
54
 
23
- export async function devnet({ contracts = process.env.FANGORN_CONTRACTS_DIR ?? resolve(HERE, "../../../contracts/solidity"), log = () => {} } = {}) {
55
+ export async function devnet({ contracts = process.env.FANGORN_CONTRACTS_DIR ?? resolve(HERE, "../../../contracts"),
56
+ webworker = process.env.FANGORN_WEBWORKER_DIR ?? resolve(HERE, "../../../webworker"), log = () => {} } = {}) {
24
57
  const kids = [], servers = [];
25
58
  const stop = () => { for (const k of kids) k.kill(); for (const s of servers) s.close(); };
26
59
  process.on("exit", stop);
@@ -32,17 +65,18 @@ export async function devnet({ contracts = process.env.FANGORN_CONTRACTS_DIR ??
32
65
  const rpcUrl = await new Promise((ok) => { let out = ""; anvil.stdout.on("data", (c) => { out += c; const m = /Listening on (\S+)/.exec(out); if (m) ok(`http://${m[1]}`); }); });
33
66
  const chain = createTestClient({ mode: "anvil", chain: FangornConfig.chain, transport: http(rpcUrl) }).extend(publicActions).extend(walletActions);
34
67
  const admin = privateKeyToAccount(ADMIN_KEY);
35
- const artifact = (n) => { const j = JSON.parse(readFileSync(`${contracts}/out/${n}.sol/${n}.json`, "utf8")); return { abi: j.abi, bytecode: j.bytecode.object }; };
36
- const deploy = async (n, args) => getAddress((await chain.waitForTransactionReceipt({ hash: await chain.deployContract({ account: admin, ...artifact(n), args }) })).contractAddress);
68
+ // `file`: the .sol it is in, when that isn't `n`.sol.
69
+ const artifact = (n, file = n) => { const j = JSON.parse(readFileSync(`${contracts}/out/${file}.sol/${n}.json`, "utf8")); return { abi: j.abi, bytecode: j.bytecode.object }; };
70
+ const deploy = async (n, args, file) => getAddress((await chain.waitForTransactionReceipt({ hash: await chain.deployContract({ account: admin, ...artifact(n, file), args }) })).contractAddress);
37
71
  const proxied = async (n, init) => deploy("ERC1967Proxy", [await deploy(n, []), init]);
38
- const apps = await proxied("AppRegistry", encodeFunctionData({ abi: APP_REGISTRY_ABI, functionName: "initialize",
39
- args: [admin.address, "0x000000000000000000000000000000000000dEaD", 0n, 30n * 24n * 3600n] }));
40
- const data = await proxied("DataRegistry", encodeFunctionData({ abi: DATA_REGISTRY_ABI, functionName: "initialize", args: [admin.address, apps] }));
41
- await chain.waitForTransactionReceipt({ hash: await chain.writeContract({ account: admin, address: apps, abi: APP_REGISTRY_ABI, functionName: "setDataRegistry", args: [data] }) });
72
+ const data = await proxied("DataRegistry", encodeFunctionData({ abi: DATA_REGISTRY_ABI, functionName: "initialize", args: [admin.address] }));
73
+ const usdc = await deploy("MockUSDC", [], "Mocks");
74
+ const settlement = await proxied("SettlementRegistry", encodeFunctionData({ abi: SETTLEMENT_REGISTRY_ABI, functionName: "initialize",
75
+ args: [admin.address, usdc, await deploy("MockSemaphore", [], "Mocks")] }));
42
76
  // As a Worker's CONFIG.deployment takes it: strings, no BigInt.
43
- const deployment = { appRegistryContractAddress: apps, dataRegistryContractAddress: data, appRegistryFromBlock: "0" };
44
- const config = { ...FangornConfig, ...deployment, appRegistryFromBlock: 0n, rpcUrl };
45
- log(`anvil ${rpcUrl}, AppRegistry ${apps}, DataRegistry ${data}`);
77
+ const deployment = { dataRegistryContractAddress: data, settlementRegistryContractAddress: settlement, fromBlock: "0" };
78
+ const config = { ...FangornConfig, ...deployment, fromBlock: 0n, rpcUrl };
79
+ log(`anvil ${rpcUrl}, DataRegistry ${data}, SettlementRegistry ${settlement}`);
46
80
 
47
81
  // ── storage: a content-addressed store, and the gateway that serves it ────
48
82
  // multiformats, from the SDK's own dependencies.
@@ -65,10 +99,10 @@ export async function devnet({ contracts = process.env.FANGORN_CONTRACTS_DIR ??
65
99
  servers.push(gateway);
66
100
  const gatewayUrl = await listen(gateway);
67
101
 
68
- /** A funded publisher, under `app` (or none). */
69
- const client = async (app, privateKey = generatePrivateKey()) => {
102
+ /** A funded client. */
103
+ const client = async (privateKey = generatePrivateKey()) => {
70
104
  await chain.setBalance({ address: privateKeyToAccount(privateKey).address, value: parseEther("1") });
71
- return Fangorn.create({ privateKey, config, appId: app, storage: { backend } });
105
+ return Fangorn.create({ privateKey, config, storage: { backend } });
72
106
  };
73
107
 
74
108
  /** An encoder on localhost that answers as the AI binding does: POST {text} → {data}; GET → the embedder it is. */
@@ -91,5 +125,22 @@ export async function devnet({ contracts = process.env.FANGORN_CONTRACTS_DIR ??
91
125
  return listen(server);
92
126
  };
93
127
 
94
- return { rpcUrl, deployment, config, chain, backend, gatewayUrl, client, encoder, stop, kids };
128
+ // ── Workers, wired to this chain ─────────────────────────────────────────
129
+ const worker = (dir, vars, opts) => wranglerDev(dir, vars, { log, ...opts }).then(({ url, kill }) => (kids.push({ kill }), url));
130
+
131
+ /** The key server (fangorn-access-worker), with a fresh X25519 secret. */
132
+ const keyServer = () => worker(join(webworker, "fangorn-access-worker"),
133
+ { WORKER_X25519_SECRET: bytesToHex(crypto.getRandomValues(new Uint8Array(32))), SETTLEMENT_REGISTRY: settlement, RPC_URL: rpcUrl },
134
+ { probe: "/pubkey", name: "key server" });
135
+
136
+ /** Barliman, paying gas from a funded treasury key; `treasury` is the referrer on every register. */
137
+ const relay = async (treasury = privateKeyToAccount(generatePrivateKey()).address) => {
138
+ const key = generatePrivateKey();
139
+ await chain.setBalance({ address: privateKeyToAccount(key).address, value: parseEther("10") });
140
+ const url = await worker(join(webworker, "barliman"), { TREASURY_KEY: key, TREASURY: treasury, RPC_URL: rpcUrl,
141
+ DATA_REGISTRY: data, SETTLEMENT_REGISTRY: settlement }, { probe: "/supported", name: "relay (Barliman)" });
142
+ return { url, treasury };
143
+ };
144
+
145
+ return { rpcUrl, deployment, config, chain, usdc, backend, gatewayUrl, client, encoder, worker, keyServer, relay, stop, kids };
95
146
  }
@@ -41,7 +41,7 @@ export function init(app, dir = app, { install = true, log = console.log } = {})
41
41
  }
42
42
  log(`${app} is in ${dir}. Next:
43
43
  1. app.json: the description, and the type's fields (role_map)
44
- 2. npx westmarch-ship app.json # claims ${app} if it isn't yet, deploys the Worker, registers its agent`);
44
+ 2. npx westmarch-ship app.json # creates the repo ${app}, deploys the Worker, registers its agent`);
45
45
  return dir;
46
46
  }
47
47