@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
@@ -4,8 +4,8 @@
4
4
  // westmarch-view --app my-app [--repo catalog …] --out site/view (a laptop, CI)
5
5
  // site/worker.js, on a cron (the free tier)
6
6
  //
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; the schema
7
+ // Reads the registry and storage and nothing else: every repo the app presents (any
8
+ // publisher's repo of a name it lists), at their latest heads; the schema
9
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
  //
@@ -15,21 +15,20 @@
15
15
  //
16
16
  // Stateless: the view's own files are its state, and each domain's manifest names the head
17
17
  // it was built from, so a run where no head moved reads one manifest per repo and nothing
18
- // else. A repo the app stops presenting (an exclusion) loses its domain on the next run.
18
+ // else. A repo the app stops presenting loses its domain on the next run.
19
19
  //
20
- // The layout is quickbeam's (the hosted tier), so an app moves between the two by changing
21
- // one URL in its card:
22
- // - URL layout, domain names (`domainFor`, byte-identical to quickbeam's `_domain_for`),
23
- // row shape {track_id, fields, v}, manifest and catalog keys;
20
+ // The layout is fixed, so any reader (shard.js, a tab, an agent) reads any app's view:
21
+ // - URL layout, domain names (`domainFor`: the publisher's address prefix and the repo),
22
+ // row shape {track_id, owner, fields, v}, manifest and catalog keys;
24
23
  // - a record is a row: track_id = its CID, fields = payload + entityType (its type);
25
24
  // - the schema: a declared type is embedded and shipped with exactly its role map;
26
- // - the embedded text (`composeText` mirrors quickbeam's `compose_document_text`).
25
+ // - the embedded text (`composeText`).
27
26
  // The encoder is EmbeddingGemma (embed.js). Two runtimes of it agree closely but not bit for
28
27
  // bit, so the manifest names its `embedder` and this refuses to append to a view another
29
28
  // encoder built.
30
29
  //
31
- // ponytail: flat records. quickbeam folds a record's neighbours into its text and can fuse
32
- // publishers by shared identity; that is the hosted tier's job. A reference the schema
30
+ // ponytail: flat records: a record's neighbours aren't folded into its text, and publishers
31
+ // aren't fused by shared identity. A reference the schema
33
32
  // declares is written onto its source row instead (`linkRelations`), which is all a
34
33
  // serverless reader needs.
35
34
 
@@ -49,14 +48,13 @@ const MULTI = ["tags", "measures", "relations", "text"];
49
48
  // Refit coverage once a domain has grown this many times over what it was fit on.
50
49
  const COVERAGE_REFIT = 2;
51
50
 
52
- // ── the contract shared with quickbeam ────────────────────────────────────────
51
+ // ── the view's contract ────────────────────────────────────────
53
52
 
54
53
  const slug = (s) => (String(s ?? "").replace(/[^A-Za-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase() || "x");
55
- /** quickbeam `_domain_for` / registry `domainFor`, for an app id. */
56
- export const domainFor = (appId, owner, namespace) =>
57
- `${slug(appId.slice(2, 10))}-${slug(owner.slice(2, 10))}-${slug(namespace)}`;
54
+ /** A domain's name in the view: the publisher's address prefix and the repo. */
55
+ export const domainFor = (owner, namespace) => `${slug(owner.slice(2, 10))}-${slug(namespace)}`;
58
56
 
59
- /** quickbeam `compose_document_text`, minus the `search_document: ` prefix that
57
+ /** The text a row is embedded from, minus the `search_document: ` prefix that
60
58
  * `embedDocumentDirect` adds itself. */
61
59
  export function composeText(fields, rm) {
62
60
  const tags = (rm.tags ?? []).map((t) => (typeof fields[t] === "string" ? fields[t] : "")).join(" ");
@@ -90,8 +88,8 @@ export function completeRoles(rm = {}) {
90
88
  }
91
89
 
92
90
  // ponytail: for a type the schema does not declare, a guess from field names and
93
- // value lengths — enough to show and search something, and loud about it. quickbeam's
94
- // `infer_roles` is richer; the fix either way is declaring the type.
91
+ // value lengths — enough to show and search something, and loud about it. The fix is
92
+ // declaring the type.
95
93
  export function guessRoles(rows) {
96
94
  const keys = [...new Set(rows.flatMap((r) => Object.keys(r)))].filter((k) => k !== "entityType");
97
95
  const find = (names) => keys.find((k) => names.includes(k.toLowerCase())) ?? null;
@@ -104,7 +102,7 @@ export function guessRoles(rows) {
104
102
  });
105
103
  }
106
104
 
107
- /** Merge the declared types a domain holds (most common first), like quickbeam's `domain_spec`. */
105
+ /** Merge the declared types a domain holds (most common first). */
108
106
  export function domainSpec(schema, tags) {
109
107
  const decls = tags.map((t) => schema?.types?.[t]).filter(Boolean);
110
108
  if (!decls.length) return null;
@@ -148,11 +146,10 @@ export async function network(name = process.env.FANGORN_NETWORK || "baseSepolia
148
146
  return SupportedNetworks[name];
149
147
  }
150
148
 
151
- /** The IPFS gateway to read contents through: FANGORN_IPFS_GATEWAY, else the one in
152
- * ~/.fangorn/config.json (what the fangorn CLI reads through), else none (the SDK default). */
149
+ /** The IPFS gateway to read contents through: FANGORN_IPFS_GATEWAY, else none (the SDK
150
+ * default, Fangorn's gateway). Not the deployer's CLI config: that would ship into the Worker. */
153
151
  export function ipfsGateway() {
154
- let gateway = process.env.FANGORN_IPFS_GATEWAY ?? process.env.IPFS_GATEWAY;
155
- try { gateway ??= JSON.parse(readFileSync(`${process.env.HOME}/.fangorn/config.json`, "utf8")).pinataGateway || undefined; } catch { /* no CLI config */ }
152
+ const gateway = process.env.FANGORN_IPFS_GATEWAY || process.env.IPFS_GATEWAY;
156
153
  return gateway && !/^https?:\/\//.test(gateway) ? `https://${gateway}` : gateway;
157
154
  }
158
155
 
@@ -170,7 +167,7 @@ export async function readOnlyFangorn() {
170
167
  * `<owner>/<repo>` to `{ records: [{id, cid, type, payload}] }`, every one presented.
171
168
  * A build that must not touch the chain — a candidate recipe graded before it ships —
172
169
  * runs the exact code a real one does. */
173
- export function localFangorn(chain, { appId, owner }) {
170
+ export function localFangorn(chain) {
174
171
  // Every version handed out is kept, so repoDiff can diff any two, as the SDK diffs two roots.
175
172
  const versions = new Map();
176
173
  const root = (k) => { const h = `0x${createHash("sha256").update(JSON.stringify(chain[k])).digest("hex")}`; versions.set(h, structuredClone(chain[k]?.records ?? [])); return h; };
@@ -182,9 +179,7 @@ export function localFangorn(chain, { appId, owner }) {
182
179
  };
183
180
  return {
184
181
  engine: { repoDiff }, reads: 0,
185
- setAppId() {}, getAppId: () => appId,
186
- getAppRegistry: () => ({ getAppOwner: async () => owner }),
187
- appRepos: async () => Object.keys(chain).map((k) => ({ owner: k.split("/")[0], repo: k.split("/").slice(1).join("/"), root: root(k) })),
182
+ repos: async () => Object.keys(chain).map((k) => ({ owner: k.split("/")[0], repo: k.split("/").slice(1).join("/"), root: root(k) })),
188
183
  readRepo: async function (o, repo) { this.reads++; const c = chain[`${o}/${repo}`]; return { tip: c ? root(`${o}/${repo}`) : null, contents: { records: c?.records ?? [] } }; },
189
184
  };
190
185
  }
@@ -285,26 +280,26 @@ const sha256 = (s) => createHash("sha256").update(s).digest("hex");
285
280
  /**
286
281
  * Bring the view up to date with what the app presents. `fangorn` is an SDK client (reads
287
282
  * 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
288
- * names (every publisher's); without it, every repo the app presents. `fromBlock` must be
283
+ * names (every publisher's); without it, every repo. `fromBlock` must be
289
284
  * at or before the first update to a repo the app presents, or a repo the scan misses is left out;
290
285
  * left out, the SDK's deployment start. `embedBatch(texts)` embeds many at once where the
291
286
  * encoder batches (a Worker's AI binding); `embedder` is what the manifest records.
292
- * `presented` replaces the `appRepos` scan with a list the caller keeps itself
293
- * ([{owner, repo, root}], exclusions already applied), as a Worker does across runs.
287
+ * `presented` replaces the `repos` scan with a list the caller keeps itself
288
+ * ([{owner, repo, root}]), as a Worker does across runs.
294
289
  * Returns per-domain counts of what changed.
295
290
  */
296
291
  export async function publishView({ fangorn, app, schema, repos, out, store = fsStore(out), fromBlock, presented, rebake = false,
297
292
  embed = embedDocumentDirect, embedBatch = (ts) => Promise.all(ts.map(embed)),
298
- embedder = EMBEDDER, log = console.log, shardRows = 20000, concurrency = 4, open = (p) => p }) {
299
- fangorn.setAppId(app);
300
- const appId = fangorn.getAppId();
293
+ embedder = EMBEDDER, log = console.log, shardRows = 20000, concurrency = 4 }) {
301
294
  schema = schemaOf(schema);
302
295
  const declared = Object.keys(schema.types);
303
296
  log(`schema: ${declared.length ? declared.join(", ") : "no declared types"}`);
304
297
  const schemaHash = sha256(JSON.stringify(schema));
305
298
 
306
- // Every repo the app presents, at its accepted head: one log scan, exclusions applied.
307
- const listed = (presented ?? await retry(() => fangorn.appRepos(fromBlock == null ? {} : { fromBlock: BigInt(fromBlock) })))
299
+ // Every repo the app presents, at its latest head: one log scan.
300
+ // ponytail: open: any publisher's repo of a listed name, and with no names, every repo.
301
+ // Read the app's repo of citations instead once the SDK reads citations.
302
+ const listed = (presented ?? await retry(() => fangorn.repos(fromBlock == null ? {} : { fromBlock: BigInt(fromBlock) })))
308
303
  // ponytail: "fangorn.schema" is where apps shipped before 2026-10-22 committed their schema; never data.
309
304
  .filter((t) => t.repo !== "fangorn.schema" && (!repos?.length || repos.includes(t.repo)));
310
305
  log(`${listed.length} repo(s) presented${repos?.length ? ` of ${repos.join(", ")}` : ""}`);
@@ -316,19 +311,19 @@ export async function publishView({ fangorn, app, schema, repos, out, store = fs
316
311
  const queue = [...listed];
317
312
  const worker = async () => {
318
313
  for (let t; (t = queue.shift()) !== undefined;) {
319
- const domain = domainFor(appId, t.owner, t.repo);
314
+ const domain = domainFor(t.owner, t.repo);
320
315
  live.add(domain);
321
316
  // One repo failing (unreadable, the encoder out for the day) keeps its last view and
322
317
  // does not stop the others; the next run tries it again.
323
318
  const r = await publishDomain({ fangorn, store, schema, schemaHash, publisher: t.owner, repo: t.repo, head: t.root, domain,
324
- dir: `cdn/domains/${domain}`, rebake, embedBatch, embedder, log, shardRows, open })
319
+ dir: `cdn/domains/${domain}`, rebake, embedBatch, embedder, log, shardRows })
325
320
  .catch((e) => { log(`${domain}: ✗ ${e.message}; left as it was`); return { added: 0, removed: 0, error: e.message }; });
326
321
  if (r) report[domain] = r;
327
322
  }
328
323
  };
329
324
  await Promise.all(Array.from({ length: concurrency }, worker));
330
325
 
331
- // What the app no longer presents (excluded, or its publisher banned) is not served.
326
+ // What the app no longer presents is not served.
332
327
  for (const d of await store.list("cdn/domains")) {
333
328
  if (live.has(d)) continue;
334
329
  const m = await readJson(store, `cdn/domains/${d}/manifest`, null);
@@ -353,7 +348,7 @@ async function retry(f, tries = 6) {
353
348
  }
354
349
 
355
350
  const CHECKPOINT = 2048; // rows embedded between saves; a killed run redoes at most this many
356
- async function publishDomain({ fangorn, store, schema, schemaHash, publisher, repo, head, domain, dir, rebake, embedBatch, embedder, log, shardRows, open }) {
351
+ async function publishDomain({ fangorn, store, schema, schemaHash, publisher, repo, head, domain, dir, rebake, embedBatch, embedder, log, shardRows }) {
357
352
  // The head the domain was built from, and the schema it was built under: neither moved,
358
353
  // nothing to read. This is what keeps a cron run with nothing new to one read per repo.
359
354
  const was = rebake ? null : await readJson(store, `${dir}/manifest`, null);
@@ -369,9 +364,11 @@ async function publishDomain({ fangorn, store, schema, schemaHash, publisher, re
369
364
  ? await retry(() => fangorn.engine.repoDiff(was.head, head)).catch((e) => { log(`${domain}: diff from ${was.head} failed (${e.message}); reading it whole`); return null; })
370
365
  : null;
371
366
  const got = diff?.superseded ? diff.puts : (await retry(() => fangorn.readRepo(publisher, repo))).contents.records;
372
- // `open`: a private app's rows are sealed on chain (x402.js's sealRow); the Worker opens them here.
373
- const records = new Map(await Promise.all(got.filter((r) => r.payload && typeof r.payload === "object")
374
- .map(async (r) => [r.cid, { id: r.id, fields: { ...(await open(r.payload)), entityType: r.type } }])));
367
+ // `@`-ids (`@card`, `@deposit/<generation>`) are the protocol's records, not the publisher's data.
368
+ const records = new Map(got.filter((r) => r.payload && typeof r.payload === "object" && !String(r.id).startsWith("@"))
369
+ .map((r) => [r.cid, { id: r.id, fields: { ...r.payload, entityType: r.type,
370
+ // A record its publisher sells (`fangorn commit --paid`): what a buyer quotes it by, and its price.
371
+ ...(r.payload["@terms"]?.terms ? { sale: { publisher, repo, id: r.id, price: String(r.payload["@terms"].terms.price) } } : {}) } }]));
375
372
  linkRelations(records, schema);
376
373
  const fieldsOf = (cid) => records.get(cid).fields;
377
374
 
@@ -449,7 +446,7 @@ async function publishDomain({ fangorn, store, schema, schemaHash, publisher, re
449
446
  const ids = fresh.slice(i, i + 32);
450
447
  try {
451
448
  const vs = await embedBatch(ids.map((id) => composeText(fieldsOf(id), rolesOf.get(fieldsOf(id).entityType))));
452
- ids.forEach((id, j) => lines.push(JSON.stringify({ track_id: id, fields: fieldsOf(id), v: packVec(vs[j]) })));
449
+ ids.forEach((id, j) => lines.push(JSON.stringify({ track_id: id, owner: publisher, fields: fieldsOf(id), v: packVec(vs[j]) })));
453
450
  } catch (e) {
454
451
  // The encoder gave out (Workers AI's free daily allowance, say): keep what is embedded
455
452
  // and come back for the rest. Nothing served yet, nothing to save: fail as before.
@@ -545,6 +542,8 @@ export async function writeCatalog(store) {
545
542
  generated_at: Math.floor(Date.now() / 1000), embedding_model: EMBED_MODEL,
546
543
  domains: domains.map((m) => ({
547
544
  name: m.name, description: m.description, count: m.count, dim: m.dim,
545
+ // Whose it is: a reader can list publishers without opening a manifest.
546
+ ...(m.filter?.owner?.length === 1 ? { publisher: m.filter.owner[0], repo: m.filter.repo?.[0] } : {}),
548
547
  bytes: m.shards.reduce((s, x) => s + x.bytes, 0), shard_count: m.shards.length,
549
548
  entity_types: m.entity_types.map((e) => e.type), manifest: `${m.name}/manifest.json`,
550
549
  ...(m.link_hosts?.length ? { link_hosts: m.link_hosts } : {}),
@@ -563,11 +562,11 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
563
562
  const manifestOf = (dir, d) => JSON.parse(readFileSync(`${dir}/cdn/domains/${d}/manifest`, "utf8"));
564
563
  const rec = (cid, type, payload, id = cid) => ({ id, cid, type, payload });
565
564
 
566
- // quickbeam's own outputs, pinned: the contract, not an approximation of it.
567
- eq(domainFor(`0x${"7e1497af".padEnd(64, "0")}`, "0x55cf6bd2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "media"), "7e1497af-55cf6bd2-media", "domain name = quickbeam's");
565
+ // The contract, pinned: domain names and embedded text never drift.
566
+ eq(domainFor("0x55cf6bd2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "media"), "55cf6bd2-media", "domain name: owner prefix and repo");
568
567
  eq(composeText({ name: "Oak", family: "Fagaceae", description: "big", entityType: "t" },
569
568
  completeRoles({ title: "name", tags: ["family"], text: ["description"] })),
570
- "Title: Oak. Tags: Fagaceae. big", "embedded text = quickbeam's compose_document_text");
569
+ "Title: Oak. Tags: Fagaceae. big", "embedded text is pinned");
571
570
 
572
571
  const APP = `0x${"ab".repeat(32)}`, OWNER = `0x${"11".repeat(20)}`, PUB = `0x${"22".repeat(20)}`;
573
572
  const TAG = "shop.item.v1";
@@ -580,7 +579,7 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
580
579
  rec("c3", "shop.note.v1", { title: "Note", body: "an undeclared type, with a body long enough to count as its text field" }),
581
580
  ] },
582
581
  };
583
- const fangorn = localFangorn(chain, { appId: APP, owner: OWNER });
582
+ const fangorn = localFangorn(chain);
584
583
  const embedded = [];
585
584
  const embed = async (t) => { embedded.push(t); const v = new Array(EMBED_DIM).fill(0); for (const w of t.split(/\W+/)) if (w) v[w.length % EMBED_DIM] += 1; const n = Math.hypot(...v) || 1; return v.map((x) => x / n); };
586
585
  const out = mkdtempSync(`${tmpdir()}/view-`);
@@ -594,7 +593,7 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
594
593
  embedded.length = 0; rmSync(`${out}/vectors.ndjson`);
595
594
  const run = () => publishView({ fangorn, app: APP, schema, out, embed, log: () => {} });
596
595
 
597
- const d = domainFor(APP, PUB, "shop");
596
+ const d = domainFor(PUB, "shop");
598
597
  const split = mkdtempSync(`${tmpdir()}/view-`);
599
598
  await publishView({ fangorn, app: APP, schema, out: split, embed, log: () => {}, shardRows: 2 });
600
599
  eq(manifestOf(split, d).shards.map((s) => s.count), [2, 1], "rows past shardRows go to the next shard");
@@ -640,13 +639,13 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
640
639
  const { rolesFrom } = await import("../core/roles.js");
641
640
  eq(getRow(got, "b2", rolesFrom([m]))?.id, "c2b", "get by the publisher's own id, not the CID");
642
641
 
643
- // An exclusion: the app stops presenting the repo, and its domain stops being served.
642
+ // The app stops presenting the repo, and its domain stops being served.
644
643
  const shop = chain[`${PUB}/shop`];
645
644
  delete chain[`${PUB}/shop`];
646
645
  eq((await run())[d], { added: 0, removed: 2, dropped: true }, "a repo the app no longer presents is dropped");
647
646
  eq([existsSync(`${out}/cdn/domains/${d}`), JSON.parse(readFileSync(`${out}/cdn/catalog`, "utf8")).domains], [false, []], "with its files and its catalog entry");
648
647
  chain[`${PUB}/shop`] = shop;
649
- eq((await run())[d], { added: 2, removed: 0 }, "and a restore brings it back");
648
+ eq((await run())[d], { added: 2, removed: 0 }, "and presenting it again brings it back");
650
649
 
651
650
  const setEmbedder = (e) => { const x = manifestOf(out, d); x.embedder = e; x.head = "moved"; writeFileSync(`${out}/cdn/domains/${d}/manifest`, JSON.stringify(x)); };
652
651
  setEmbedder({ ...EMBEDDER, runtime: "transformers.js cuda" });
@@ -660,7 +659,7 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
660
659
  chain[BIG] = { records: Array.from({ length: 80 }, (_, i) => ({ id: `r${i}`, cid: `big${i}`, type: "shop.item.v1", payload: { sku: `r${i}`, name: `Thing ${i}` } })) };
661
660
  let budget = 40;
662
661
  const capped = (ts) => (budget -= ts.length) < 0 ? Promise.reject(new Error("daily allowance used")) : Promise.all(ts.map(embed));
663
- const bd = domainFor(APP, PUB, "big");
662
+ const bd = domainFor(PUB, "big");
664
663
  eq((await publishView({ fangorn, app: APP, schema, out: big, repos: ["big"], embedBatch: capped, log: () => {} }))[bd],
665
664
  { added: 32, removed: 0, partial: true }, "an encoder that gives out keeps what it embedded");
666
665
  eq([manifestOf(big, bd).count, manifestOf(big, bd).head], [32, null], "served, and the head not taken");
@@ -730,8 +729,8 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
730
729
  rec("i1", T, { item_id: "a#1", heading: "Rezone, committee", part_of: { local: "m" } }),
731
730
  rec("i2", T, { item_id: "b#4", heading: "Rezone, council", cites: { local: "m" } }),
732
731
  rec("m1", M, { matter_id: "plover:7", title: "Rezone" }, "m")] } };
733
- const o = mkdtempSync(`${tmpdir()}/view-`), dr = domainFor(APP, PUB, "civic");
734
- const go = () => publishView({ fangorn: localFangorn(rel, { appId: APP, owner: OWNER }), app: APP, schema: relSchema, out: o, embed, log: () => {} });
732
+ const o = mkdtempSync(`${tmpdir()}/view-`), dr = domainFor(PUB, "civic");
733
+ const go = () => publishView({ fangorn: localFangorn(rel), app: APP, schema: relSchema, out: o, embed, log: () => {} });
735
734
  const rows = async () => Object.fromEntries([...(await loadDomain(fsStore(o), `cdn/domains/${dr}`)).rows.values()]
736
735
  .map((r) => [r.fields.heading ?? r.fields.title, r.fields.part_of ?? r.fields.cites ?? null]));
737
736
  await go();
@@ -767,5 +766,5 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
767
766
  await r2.del(`cdn/domains/${d}`);
768
767
  eq([...objs.keys()].filter((k) => k.includes(d)), [], "del removes a folder and everything under it");
769
768
  }
770
- console.log("view.js self-check ok — domain names and embedded text match quickbeam's, the schema is applied, an unmoved head reads nothing, additions ship as delta shards, removals compact the domain, an excluded repo is dropped and a restored one returns, the real reader sees exactly the live records by the publisher's id, another encoder's view is refused, declared references land on their source rows, and the view builds the same into R2");
769
+ console.log("view.js self-check ok — domain names and embedded text are stable, the schema is applied, an unmoved head reads nothing, additions ship as delta shards, removals compact the domain, an excluded repo is dropped and a restored one returns, the real reader sees exactly the live records by the publisher's id, another encoder's view is refused, declared references land on their source rows, and the view builds the same into R2");
771
770
  }
@@ -2,22 +2,20 @@
2
2
 
3
3
  This repo holds the app's recipe, not its data: what a record is (`app.json`), what a good
4
4
  answer looks like (`eval/`), and the Worker that serves it (`wrangler.json`). It can be
5
- public. The data lives on chain and IPFS, committed by the app's members; the Worker
5
+ public. The data lives on chain and IPFS, committed by its publishers; the Worker
6
6
  indexes it every 5 minutes, and serves the site, the view, `/mcp` and the agent card.
7
7
 
8
8
  ## Deploy
9
9
 
10
10
  [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/fangorn-network/westmarch/tree/main/template)
11
11
 
12
- 1. Claim the app at [fangorn.network](https://fangorn.network).
13
- 2. Press the button. Name the Worker after the app (`my-app`) and its R2 bucket
12
+ 1. Press the button. Name the Worker after the app (`my-app`) and its R2 bucket
14
13
  `my-app-view`. Cloudflare copies this repo into your GitHub, makes the bucket and
15
14
  deploys; every push to `main` deploys again.
16
- 3. Back at fangorn.network, give the app its Worker's URL. Your wallet registers the
17
- app's agent and binds its card there.
15
+ 2. At fangorn.network, give the app its Worker's URL. Your wallet creates the app's repo,
16
+ `<your wallet>:my-app`, and binds its card there.
18
17
 
19
- An app name with a dot or an underscore can't be a Worker name: set `"app"` in
20
- `app.json` to the name you claimed.
18
+ An app name with a dot or an underscore can't be a Worker name.
21
19
 
22
20
  `npm run build` (`westmarch build`) is what Cloudflare runs: it builds the site and writes
23
21
  the app's config into `wrangler.json`, without signing or deploying anything.
@@ -29,13 +27,13 @@ fields in `role_map`. Push, and the Worker follows.
29
27
 
30
28
  ## Publish data
31
29
 
32
- Any member of the app commits records of its type, from anywhere:
30
+ Any wallet commits records of its type, from anywhere:
33
31
 
34
32
  ```sh
35
33
  echo '{"records":[{"id":"first","type":"my-app.item.v1","payload":{"id":"first","title":"Hello","text":"The first item.","tags":["demo"]}}]}' > items.json
36
- fangorn --app my-app repo init items
37
- fangorn --app my-app commit items.json -m "first items"
38
- fangorn --app my-app push
34
+ fangorn repo init items
35
+ fangorn commit items.json -m "first items"
36
+ fangorn push
39
37
  ```
40
38
 
41
39
  The view picks it up within 5 minutes at `<url>/view`. A source that crawls something
@@ -6,7 +6,7 @@
6
6
  "deploy": "wrangler deploy"
7
7
  },
8
8
  "dependencies": {
9
- "@fangorn-network/westmarch": "2026.10.29",
9
+ "@fangorn-network/westmarch": "2026.11.3",
10
10
  "@huggingface/transformers": "^4.3.1",
11
11
  "wrangler": "^4.83.0"
12
12
  }
@@ -1,266 +0,0 @@
1
- #!/usr/bin/env node
2
- // The Fangorn app index, headless. One command per verb, JSON on stdout.
3
- //
4
- // WHY THERE IS NO MCP SERVER HERE
5
- // -------------------------------
6
- // An index that POINTS AT apps rather than hosting them needs no runtime of its
7
- // own. Every verb below is a function `@fangorn/westmarch` already exports, and
8
- // the agent's shell is the transport. Nobody has to stand up a server to be in
9
- // the index — a publisher bakes a view, and that is the whole obligation.
10
- //
11
- // WHY THIS IS A PLUGIN AND NOT A PAGE
12
- // -----------------------------------
13
- // One thing here is not stateless: the taste kernel. It lives in
14
- // ~/.fangorn/taste.json — on the filesystem, between the human and the agent —
15
- // because it has to outlive any one app, any one tab and any one ORIGIN.
16
- // localStorage cannot do that: a taste learned in fangorn.tv is invisible to the
17
- // next app by construction, which is the whole reason apps keep rebuilding it.
18
- // A file the agent can read is the shortest thing that carries it across.
19
- //
20
- // ponytail: a plaintext file, no wallet, no sync. `src/taste/vault.js` is the
21
- // upgrade path — same object, sealed to a signature, kept in the graph — and it
22
- // is worth doing the day the kernel needs to travel between machines, not now.
23
- // ponytail: every command re-fetches its view. Fine at 917 rows, ~seconds at
24
- // 42k; add a disk cache keyed by view URL when a big corpus makes it hurt.
25
-
26
- import { homedir } from "node:os";
27
- import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
28
- import { join } from "node:path";
29
- import { configure, domainManifests, loadShard, trimView } from "../../src/core/shard.js";
30
- import { findCorpora, sourcesFromChain } from "../../src/discover/directory.js";
31
- import { linkOf, rolesFrom, textOf, titleOf } from "../../src/core/roles.js";
32
- import { exportTaste, recommend, taste } from "../../src/taste/taste.js";
33
- import { EMBED_MODEL, embedQuery, packVec, unpackVec } from "../../src/core/embed.js";
34
- import { browse, describe, facet, getRow, neighbors, search } from "../../src/agent/tools.js";
35
-
36
- const HOME = process.env.FANGORN_HOME ?? join(homedir(), ".fangorn");
37
- const TASTE = join(HOME, "taste.json");
38
-
39
- // ── the kernel on disk ───────────────────────────────────────────────────────
40
- const store = () => { try { return JSON.parse(readFileSync(TASTE, "utf8")); } catch { return { model: EMBED_MODEL, likes: [], dislikes: [] }; } };
41
- const save = (s) => { mkdirSync(HOME, { recursive: true }); writeFileSync(TASTE, JSON.stringify(s, null, 1)); };
42
- /** Picks are stored PACKED (base64 int8, the shard encoding) and unpacked here.
43
- * Storing the picks rather than only the derived vector is what keeps the
44
- * kernel correctable: you can read what it was built from and drop one. */
45
- const picks = (l = []) => l.map((p) => ({ ...p, vector: unpackVec(p.v) })).filter((p) => p.vector);
46
- const kernel = (s = store()) => taste(picks(s.likes), picks(s.dislikes));
47
-
48
- // ── args ─────────────────────────────────────────────────────────────────────
49
- const argv = process.argv.slice(2);
50
- const [cmd, ...rest] = argv;
51
- const pos = rest.filter((a) => !a.startsWith("--"));
52
- const flag = (n, d) => { const a = rest.find((x) => x.startsWith(`--${n}=`)); return a === undefined ? d : a.slice(n.length + 3); };
53
- const num = (n, d) => { const v = flag(n); return v === undefined ? d : Number(v); };
54
- const pairs = (s) => s ? Object.fromEntries(String(s).split(",").map((p) => p.split("=").map((x) => x.trim()))) : undefined;
55
- const list = (s) => String(s ?? "").split(",").map((x) => x.trim()).filter(Boolean);
56
- const out = (o) => console.log(JSON.stringify(o, null, 1));
57
- const die = (m) => { console.error(m); process.exit(1); };
58
-
59
- // ── a view, loaded ───────────────────────────────────────────────────────────
60
- let roles = rolesFrom([], []);
61
- async function load(view) {
62
- if (!view) die("need a view URL");
63
- const base = trimView(view);
64
- configure({
65
- resolveView: () => base,
66
- // Roles must be ready BEFORE the first row is parsed: rowText runs during
67
- // parsing, so deriving them afterwards leaves every row with empty text
68
- // and lexical search silently matching nothing.
69
- onManifests: (ms) => { roles = rolesFrom(ms); },
70
- rowText: (f) => textOf(f, roles),
71
- });
72
- const rows = await loadShard(base);
73
- roles = rolesFrom(domainManifests(), rows);
74
- let model = null;
75
- try { model = (await (await fetch(`${base}/cdn/catalog`)).json()).embedding_model ?? null; } catch { /* unranked, not fatal */ }
76
- return { rows, roles, base, model };
77
- }
78
-
79
- /** A query vector, or null with the reason. Never throws: every verb here
80
- * degrades to lexical and SAYS so rather than returning confident nonsense. */
81
- const qvOf = async (q) => { try { return { qv: await embedQuery(q), why: null }; } catch (e) { return { qv: null, why: e?.message ?? String(e) }; } };
82
-
83
- /** The corpus and the kernel must share an embedding space or cosine between
84
- * them is noise that still looks like a score. */
85
- const mismatch = (model, s) => model && s.model && model !== s.model
86
- ? `taste was built with ${s.model}, this corpus is ${model} — scores would be noise` : null;
87
-
88
- const sources = async () => {
89
- const f = flag("sources"); if (f) return list(f);
90
- if (process.env.FANGORN_SOURCES) return list(process.env.FANGORN_SOURCES);
91
- try { return JSON.parse(readFileSync(join(HOME, "sources.json"), "utf8")); } catch { /* none pinned */ }
92
- return chainSources();
93
- };
94
-
95
- // Every app bound on chain, the scan fangorn-mcp's list-apps runs, on FANGORN_NETWORK
96
- // (default arbitrumSepolia). From its AppRegistry's deployment; --from-block overrides.
97
- async function chainSources() {
98
- const [{ Fangorn }, { generatePrivateKey }, { network }] = await Promise.all([
99
- import("@fangorn-network/sdk"), import("viem/accounts"), import("../../src/publish/view.js")]);
100
- const config = await network();
101
- const fangorn = Fangorn.create({ privateKey: generatePrivateKey(), config }); // reads only
102
- const { sources } = await sourcesFromChain(fangorn, { fromBlock: BigInt(flag("from-block", String(config.appRegistryFromBlock))) });
103
- return sources;
104
- }
105
-
106
- // ── verbs ────────────────────────────────────────────────────────────────────
107
- switch (cmd) {
108
-
109
- // WHICH app has this. Downloads no corpus — coverage centroids only, ~4KB each.
110
- case "find": {
111
- const src = await sources();
112
- if (!src.length) die("no apps found on chain; pass --sources=a,b or write ~/.fangorn/sources.json");
113
- out(await findCorpora(pos.join(" "), { sources: src, embed: embedQuery, model: EMBED_MODEL, limit: num("limit", 10) }));
114
- break;
115
- }
116
-
117
- case "describe": {
118
- const { rows, roles: r, model } = await load(pos[0]);
119
- out({
120
- ...describe(rows), model,
121
- shape: r.declared ? "declared" : "sniffed",
122
- title: r.title, subtitle: r.subtitle, tags: r.tags, text: r.text,
123
- entityTypes: r.entityTypes, gates: r.gates,
124
- // Where the reader goes next. The index's job ends here.
125
- launch: r.launch, externalUrl: r.externalUrl, actions: r.actions,
126
- });
127
- break;
128
- }
129
-
130
- case "browse": {
131
- const { rows, roles: r } = await load(pos[0]);
132
- out(browse(rows, r, { type: flag("type"), where: pairs(flag("where")), sort: flag("sort"),
133
- desc: flag("asc") === undefined, limit: num("limit", 20), offset: num("offset", 0), fields: list(flag("fields")) }));
134
- break;
135
- }
136
-
137
- case "search": {
138
- const { rows, roles: r } = await load(pos[0]);
139
- const q = pos.slice(1).join(" ");
140
- const { qv, why } = await qvOf(q);
141
- out({ query: q, mode: qv ? "semantic where rows have vectors" : "lexical", ...(why ? { why } : {}),
142
- hits: search(rows, q, r, { qv, limit: num("limit", 10), where: pairs(flag("where")), fields: list(flag("fields")) }) });
143
- break;
144
- }
145
-
146
- case "facet": {
147
- const { rows } = await load(pos[0]);
148
- out(facet(rows, pos[1], { limit: num("limit", 20), where: pairs(flag("where")) }));
149
- break;
150
- }
151
-
152
- case "row": {
153
- const { rows, roles: r } = await load(pos[0]);
154
- const g = getRow(rows, pos[1], r);
155
- out(g ? { ...g, url: linkOf(rows.find((x) => x.id === g.id) ?? {}, r) } : null);
156
- break;
157
- }
158
-
159
- case "similar": {
160
- const { rows, roles: r } = await load(pos[0]);
161
- out(neighbors(rows, pos[1], r, { limit: num("limit", 10), fields: list(flag("fields")) }));
162
- break;
163
- }
164
-
165
- // ── the kernel ───────────────────────────────────────────────────────────────
166
- case "like": case "dislike": {
167
- const { rows, roles: r, base, model } = await load(pos[0]);
168
- const s = store();
169
- const into = cmd === "like" ? s.likes : s.dislikes;
170
- const added = [];
171
- for (const id of pos.slice(1)) {
172
- const row = rows.find((x) => x.id === id);
173
- if (!row) { console.error(`no row ${id}`); continue; }
174
- if (!row.vector) { console.error(`${id} has no vector — nothing to learn from`); continue; }
175
- // Newest last: taste() weights by recency, so order in the file is signal.
176
- const at = into.findIndex((p) => p.id === id);
177
- if (at >= 0) into.splice(at, 1);
178
- into.push({ id, title: titleOf(row, r), view: base, at: new Date().toISOString().slice(0, 10), v: packVec(Array.from(row.vector)) });
179
- added.push(id);
180
- }
181
- s.model ??= model ?? EMBED_MODEL;
182
- save(s);
183
- const t = kernel(s);
184
- out({ added, likes: s.likes.length, dislikes: s.dislikes.length, taste: t && exportTaste(t), file: TASTE });
185
- break;
186
- }
187
-
188
- case "forget": {
189
- const s = store();
190
- const drop = new Set(pos);
191
- const before = s.likes.length + s.dislikes.length;
192
- s.likes = s.likes.filter((p) => !drop.has(p.id));
193
- s.dislikes = s.dislikes.filter((p) => !drop.has(p.id));
194
- save(s);
195
- out({ removed: before - s.likes.length - s.dislikes.length, likes: s.likes.length, dislikes: s.dislikes.length });
196
- break;
197
- }
198
-
199
- case "taste": {
200
- const s = store();
201
- const t = kernel(s);
202
- out(t ? { model: s.model, n: t.n, from: t.from, rejected: t.rejected, drift: t.drift,
203
- // Where each pick was learned. A kernel built in one publisher's
204
- // corpus is meant to be pointed at another's — this is the record
205
- // of whether it actually has been.
206
- views: [...new Set([...s.likes, ...s.dislikes].map((p) => p.view))],
207
- export: exportTaste(t), file: TASTE }
208
- : { n: 0, file: TASTE, note: "nothing liked yet — `fx like <view> <id>`" });
209
- break;
210
- }
211
-
212
- // The headline: rank a corpus by a taste learned somewhere else entirely.
213
- case "recommend": {
214
- const { rows, roles: r, model } = await load(pos[0]);
215
- const s = store();
216
- const t = kernel(s);
217
- if (!t) die("no taste yet — `fx like <view> <id>` first");
218
- const warn = mismatch(model, s);
219
- if (warn) die(warn);
220
- const seen = new Set([...s.likes, ...s.dislikes].map((p) => p.id));
221
- out({ from: t.from, against: pos[0],
222
- hits: recommend(rows, t, { limit: num("limit", 10), exclude: seen })
223
- .map(({ row, score }) => ({ id: row.id, title: titleOf(row, r), score, url: linkOf(row, r) })) });
224
- break;
225
- }
226
-
227
- // ── the handoff. The index points; the app does the work. ────────────────────
228
- case "launch": {
229
- const { rows, roles: r } = await load(pos[0]);
230
- const id = flag("row");
231
- if (id) {
232
- const row = rows.find((x) => x.id === id);
233
- if (!row) die(`no row ${id}`);
234
- out({ url: linkOf(row, r), title: titleOf(row, r) });
235
- break;
236
- }
237
- if (!r.launch) die("this corpus declares no presentation.launch — nowhere to hand off to");
238
- const t = kernel();
239
- const fill = { taste: t ? JSON.stringify(exportTaste(t)) : "", q: pos.slice(1).join(" ") };
240
- const url = String(r.launch).replace(/\{(\w+)\}/g, (_, k) => encodeURIComponent(fill[k] ?? ""));
241
- const u = new URL(url);
242
- if (u.protocol !== "https:" && u.protocol !== "http:") die(`refusing a ${u.protocol} launch URL`);
243
- // The kernel travels in the URL because that is the only channel a page on
244
- // someone else's origin can receive it on. It is the app's copy from here.
245
- out({ url: u.toString(), carries: t ? { n: t.n, from: t.from } : null });
246
- break;
247
- }
248
-
249
- default:
250
- console.log(`fx <verb>
251
-
252
- find <query> [--sources=a,b|--from-block=N] which app has this. No corpus downloaded.
253
- describe <view> rows, field coverage, roles, where it hands off
254
- browse <view> [--type= --where=k=v --sort= --asc --limit= --offset=]
255
- search <view> <query> [--where=k=v --limit=] semantic where rows have vectors, else lexical
256
- facet <view> <field> [--where=k=v --limit=] count a field's values
257
- row <view> <id> one record, whole
258
- similar <view> <id> [--limit=] nearest by vector
259
-
260
- like|dislike <view> <id...> teach the kernel. Writes ${TASTE}
261
- forget <id...> drop picks from it
262
- taste what it is, and what it was built from
263
- recommend <view> [--limit=] rank ANY corpus by it
264
-
265
- launch <view> [query] | launch <view> --row=<id> the handoff URL, carrying the kernel`);
266
- }
@@ -1 +0,0 @@
1
- import{$ as e,D as t}from"./privy-context-81KmsBw2-DiR6-Yq8.js";import{t as n}from"./jsx-runtime-CndCZlyt.js";import{t as r}from"./createLucideIcon-BsERoFTA.js";import{n as i}from"./modal-context-CwmSeFcv-DPWNJrfK.js";import{t as a}from"./ScreenLayout-OwaQQcxH-cfOTmyl0.js";var o=r(`circle-question-mark`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3`,key:`1u773s`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]]),s=n(),c=({title:e=`Account not found`,subtitle:t,appName:n=`this app`,ctaText:r=`Try logging in again`,onRetry:i})=>(0,s.jsx)(a,{title:e,subtitle:t||`Please try logging in again or go to ${n} to create an account.`,icon:o,iconVariant:`warning`,primaryCta:{label:r,onClick:i},watermark:!0}),l={component:()=>{let{navigate:n,setModalData:r,data:a}=i(),o=t(),{getAuthMeta:l,client:u}=e();return(0,s.jsx)(c,{appName:o?.name,onRetry:()=>{let e=l();r({...a,login:{...a?.login,...e?.disableSignup?{disableSignup:!0}:{}}}),u?.authFlow&&(u.authFlow=void 0),n(`LandingScreen`)}})}};export{l as AccountNotFoundScreen,l as default,c as AccountNotFoundScreenView};