@fangorn-network/westmarch 0.0.14-dev → 0.0.16-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/site/agent.js +7 -1
- package/site/dist/assets/{AddFundsSelectionScreen-RAoCn7ej-D_EsIeJu.js → AddFundsSelectionScreen-RAoCn7ej-B6uvYyqa.js} +1 -1
- package/site/dist/assets/{Address-H8kD1d9O-C85sJ79B.js → Address-H8kD1d9O-DcHv7A8C.js} +1 -1
- package/site/dist/assets/{AffirmativeConsentScreen-BG0MJxku-DdEPFOww.js → AffirmativeConsentScreen-BG0MJxku-v2wz-N-s.js} +1 -1
- package/site/dist/assets/{ApiController-CYdiyu9B.js → ApiController-BbhXeqTV.js} +3 -3
- package/site/dist/assets/{AuthenticateWithWalletScreen-CU6hIcFT-8rbYiYYE.js → AuthenticateWithWalletScreen-CU6hIcFT-B0eT1zE6.js} +1 -1
- package/site/dist/assets/{AwaitingEvmToSolBridgingScreen-D0e_sZMS-2pkNfCno.js → AwaitingEvmToSolBridgingScreen-D0e_sZMS-DL5PH-v_.js} +1 -1
- package/site/dist/assets/{AwaitingExternalEthereumTransferScreen-ur5HL4R7-7AQt25_k.js → AwaitingExternalEthereumTransferScreen-ur5HL4R7-n1BsRPqc.js} +1 -1
- package/site/dist/assets/{AwaitingPasswordlessCodeScreen-DRHz76mM-BZY30TGs.js → AwaitingPasswordlessCodeScreen-DRHz76mM-BVl2BJDY.js} +1 -1
- package/site/dist/assets/{AwaitingSolToEvmBridgingScreen-CdLRrGD2-BILOOLi_.js → AwaitingSolToEvmBridgingScreen-CdLRrGD2-BD-OZUQb.js} +1 -1
- package/site/dist/assets/{BridgeNetworkSelectionView-CFGjB2nO-CvsbQcFv.js → BridgeNetworkSelectionView-CFGjB2nO-CaYrzRje.js} +1 -1
- package/site/dist/assets/{CaptchaScreen-DbpvkIGx-D8eDcAkc.js → CaptchaScreen-DbpvkIGx-BQJ7inx1.js} +1 -1
- package/site/dist/assets/{CoinbaseOnrampStatusScreen-BbyCJDXL-DLs9zX-Q.js → CoinbaseOnrampStatusScreen-BbyCJDXL-DDaMC7cl.js} +1 -1
- package/site/dist/assets/{ConnectEmailForm-B-VRE0MN-N9J6T_YL.js → ConnectEmailForm-B-VRE0MN-DVSf4tFJ.js} +1 -1
- package/site/dist/assets/{ConnectOnlyLandingScreen-CZYx9Bmp-LeuDMN1E.js → ConnectOnlyLandingScreen-CZYx9Bmp-DP19hJq5.js} +1 -1
- package/site/dist/assets/{ConnectOnlyStatusScreen-DCRzjxHx-DaRa59tZ.js → ConnectOnlyStatusScreen-DCRzjxHx-DHvijlTx.js} +1 -1
- package/site/dist/assets/{ConnectOrCreateScreen-CUUYUO07-crHzh-TL.js → ConnectOrCreateScreen-CUUYUO07-ewmXYPTQ.js} +1 -1
- package/site/dist/assets/{ConnectPhoneForm-Dek5xn4C-BEA4FmhI.js → ConnectPhoneForm-Dek5xn4C-DUYdmVtr.js} +1 -1
- package/site/dist/assets/{ConnectWalletView-DqI-PTvX-CMQIad63.js → ConnectWalletView-DqI-PTvX-RobGErVW.js} +1 -1
- package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-Bbiq3hY6.js +1 -0
- package/site/dist/assets/{ConnectionStatusScreen-fUfROm9m-BeWLchcf.js → ConnectionStatusScreen-fUfROm9m-DPkOGNWl.js} +1 -1
- package/site/dist/assets/{ConnectorUtil-Cq4lWnfe.js → ConnectorUtil-BO1L6VvV.js} +1 -1
- package/site/dist/assets/{CrossAppAuthScreen-CLw7ymZq-Csju14vF.js → CrossAppAuthScreen-CLw7ymZq-DbGy4QyA.js} +1 -1
- package/site/dist/assets/{CustomLandingScreenView-Cm_MBSyX-CBOrbNLo.js → CustomLandingScreenView-Cm_MBSyX-B3WqJZBh.js} +1 -1
- package/site/dist/assets/{DelegatedActionsConsentScreen-DYF2U4y5-BL5hzNUI.js → DelegatedActionsConsentScreen-DYF2U4y5-CmUDoS0C.js} +1 -1
- package/site/dist/assets/{DepositAddressAddressStepView-4vdkb55L-B3vY888G.js → DepositAddressAddressStepView-4vdkb55L-ClAb_j1B.js} +1 -1
- package/site/dist/assets/{DepositAddressScreen-DBLRs7aI-DmdQaFI2.js → DepositAddressScreen-DBLRs7aI-CN1P_KY9.js} +1 -1
- package/site/dist/assets/{DepositAddressV3Screen-CDqIEMQw-BoupRyfV.js → DepositAddressV3Screen-CDqIEMQw-BtDZmuEN.js} +1 -1
- package/site/dist/assets/{EmbeddedWalletConnectingScreen-D4T7DUzs-D_AVgO4s.js → EmbeddedWalletConnectingScreen-D4T7DUzs-D3pExuaW.js} +1 -1
- package/site/dist/assets/{EmbeddedWalletKeyExportScreen-CqV4NYQ3-C9sAExzE.js → EmbeddedWalletKeyExportScreen-CqV4NYQ3-DI6bu-oi.js} +1 -1
- package/site/dist/assets/{EmbeddedWalletOnAccountCreateScreen-BoKb3Q2S-DxaWAAKa.js → EmbeddedWalletOnAccountCreateScreen-BoKb3Q2S-BQ9Ygr0P.js} +1 -1
- package/site/dist/assets/{EnrollTotp-Dibew4dp-SA2pvNEc.js → EnrollTotp-Dibew4dp-7gVtJ1Jt.js} +1 -1
- package/site/dist/assets/{ErrorScreen-DipdTWzE-c8g8En21.js → ErrorScreen-DipdTWzE-BT8TtRTx.js} +1 -1
- package/site/dist/assets/ErrorScreen-DipdTWzE-DAam41Xl.js +1 -0
- package/site/dist/assets/{FarcasterConnectStatusScreen-51tjUxqq-s_s5M2CZ.js → FarcasterConnectStatusScreen-51tjUxqq-BPCBi37Q.js} +1 -1
- package/site/dist/assets/{FarcasterSignerStatusScreen-6x-Uh95G-BHBR4k8H.js → FarcasterSignerStatusScreen-6x-Uh95G-XCmWpnUd.js} +1 -1
- package/site/dist/assets/{FiatOnrampScreen-BAhYeiTI-BH_sU6EV.js → FiatOnrampScreen-BAhYeiTI-DJRcUh2N.js} +1 -1
- package/site/dist/assets/{FundSolWalletWithExternalSolanaWallet-WtLwYaOl-B8TRV36j.js → FundSolWalletWithExternalSolanaWallet-WtLwYaOl-BfNVSTb1.js} +1 -1
- package/site/dist/assets/{FundWithBankDepositScreen-DajkHxBD-9rPtyA3d.js → FundWithBankDepositScreen-DajkHxBD-BfvMcHb6.js} +1 -1
- package/site/dist/assets/{FundingEditAmountScreen-CpvpiO4M-GaXigGI9.js → FundingEditAmountScreen-CpvpiO4M-VBfbahnA.js} +1 -1
- package/site/dist/assets/{FundingMethodSelectionScreen-Db7vhRlE-UsmtTqv4.js → FundingMethodSelectionScreen-Db7vhRlE-CMuBYf64.js} +1 -1
- package/site/dist/assets/{LandingScreen-CGWUoSUG-DK1EY-6v.js → LandingScreen-CGWUoSUG-Q7hgXKvM.js} +1 -1
- package/site/dist/assets/{LinkConflictScreen-C3ZEPsgl-ClWoqvEL.js → LinkConflictScreen-C3ZEPsgl-DK1z_v7y.js} +1 -1
- package/site/dist/assets/{LinkEmailScreen-dKo9frwc-C3v7glH0.js → LinkEmailScreen-dKo9frwc-BYYpJ5-6.js} +1 -1
- package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-uhub9C26.js +1 -0
- package/site/dist/assets/{LinkPasskeyScreen-zbrl_AI_-D72Gb0LW.js → LinkPasskeyScreen-zbrl_AI_-uid22VTN.js} +1 -1
- package/site/dist/assets/{LinkPhoneScreen-oIUpfj0w-C0DuD14j.js → LinkPhoneScreen-oIUpfj0w-CVQibNi9.js} +1 -1
- package/site/dist/assets/{ManualTransferScreen-CHqcuqbs-tXiZDHmN.js → ManualTransferScreen-CHqcuqbs-DMygAXMU.js} +1 -1
- package/site/dist/assets/{MfaAuthEnrollmentFlowScreen-Dj7gPTRC-CaW7xeCC.js → MfaAuthEnrollmentFlowScreen-Dj7gPTRC-_1GFUSIg.js} +1 -1
- package/site/dist/assets/{MfaAuthVerifyFlowScreen-DbFpyWMy-CeRqvx8k.js → MfaAuthVerifyFlowScreen-DbFpyWMy-DLnBJ5b8.js} +1 -1
- package/site/dist/assets/{MfaEnrollmentFlowScreen-DhLnGgnr-BkN1k4lh.js → MfaEnrollmentFlowScreen-DhLnGgnr-BUJY1lzs.js} +1 -1
- package/site/dist/assets/{MfaVerifyFlowScreen-C_XPjMRP-CXSqLVbE.js → MfaVerifyFlowScreen-C_XPjMRP-25l5fVun.js} +1 -1
- package/site/dist/assets/{OAuthStatusScreen-ufbOa-da-CeiGcSia.js → OAuthStatusScreen-ufbOa-da-DL30vu07.js} +1 -1
- package/site/dist/assets/{PasskeySelectSignupOrLogin-xh2ScC_l-CIf5I7wU.js → PasskeySelectSignupOrLogin-xh2ScC_l-DtxhRQyw.js} +1 -1
- package/site/dist/assets/{PasskeyStatusScreen-Bla8MaOk-CLoL7QC-.js → PasskeyStatusScreen-Bla8MaOk-CNfu8ujT.js} +1 -1
- package/site/dist/assets/{PasswordRecoveryScreen-awGXZkQk-B9F67IYV.js → PasswordRecoveryScreen-awGXZkQk-BR6z6xE8.js} +1 -1
- package/site/dist/assets/{QrCode-DbnZwlkH-h6Bhoe5U.js → QrCode-DbnZwlkH-BymHrKY7.js} +1 -1
- package/site/dist/assets/{RecoveryOAuthStatusScreen-CsgtTI2x-D-A5P3PX.js → RecoveryOAuthStatusScreen-CsgtTI2x-Dro1btv5.js} +1 -1
- package/site/dist/assets/{RecoveryPasswordCreateScreen-Be-qJ-LU-C8lTSeSr.js → RecoveryPasswordCreateScreen-Be-qJ-LU-C1q1hiaN.js} +1 -1
- package/site/dist/assets/{RecoverySelectionScreen-D1iGtpmi-P5P3plkH.js → RecoverySelectionScreen-D1iGtpmi-C21D20gD.js} +1 -1
- package/site/dist/assets/{SIWXUtil-TUCxa7aA.js → SIWXUtil-CHZVugix.js} +1 -1
- package/site/dist/assets/{SelectSourceAsset-CWFog6gm-D7yTw87h.js → SelectSourceAsset-CWFog6gm-RKjBsB6m.js} +1 -1
- package/site/dist/assets/{SetAutomaticRecoveryScreen-BO_OEqAZ-f0iDIGmw.js → SetAutomaticRecoveryScreen-BO_OEqAZ-BcWHJoEG.js} +1 -1
- package/site/dist/assets/{SignRequestScreen-BHKv32KR-DDpMYyJ1.js → SignRequestScreen-BHKv32KR-iQCaBkcz.js} +1 -1
- package/site/dist/assets/{SolanaWalletConnector-C7Lqk-Wz-DPwhuzcI.js → SolanaWalletConnector-C7Lqk-Wz-BUdJJ0ep.js} +1 -1
- package/site/dist/assets/{StandardSignAndSendTransactionScreen-CfhIXVtd-BJ-onCjv.js → StandardSignAndSendTransactionScreen-CfhIXVtd-nART-xUU.js} +1 -1
- package/site/dist/assets/{TelegramAuthScreen-UL9zLfO8-NWlMgNRX.js → TelegramAuthScreen-UL9zLfO8-Dw9geyK3.js} +1 -1
- package/site/dist/assets/{TransactionDetails-e9nesl30-C4MpIHR-.js → TransactionDetails-e9nesl30-DeEL1JQS.js} +1 -1
- package/site/dist/assets/{TransactionErrorView-BDBNqA_f-p1T9WVMx.js → TransactionErrorView-BDBNqA_f-Dffuo7I4.js} +1 -1
- package/site/dist/assets/{TransferFromWalletScreen-Qvn1Yuno-88IQcRnY.js → TransferFromWalletScreen-Qvn1Yuno-CWLWUiHy.js} +1 -1
- package/site/dist/assets/{TransferOrBridgeLoadingScreen-Dl1I_iIz-1fDAIxAf.js → TransferOrBridgeLoadingScreen-Dl1I_iIz-Bo-tm6wr.js} +1 -1
- package/site/dist/assets/{UpdateEmailScreen-DVOhPV0H-Jj2DQW8D.js → UpdateEmailScreen-DVOhPV0H-gFbSIUhh.js} +1 -1
- package/site/dist/assets/{UpdatePhoneScreen-CXRswTNZ-DwYIUBqi.js → UpdatePhoneScreen-CXRswTNZ-Coy4E1NQ.js} +1 -1
- package/site/dist/assets/{WalletInfoCard-sq_2wgFg-DpNSAGte.js → WalletInfoCard-sq_2wgFg-ISBsQt8p.js} +1 -1
- package/site/dist/assets/{WalletLink-DK5LB5Ha-DHaL350n.js → WalletLink-DK5LB5Ha-CXBqCHf3.js} +1 -1
- package/site/dist/assets/{WalletOverflowButton-bfCnp-9T-CUyIJFzt.js → WalletOverflowButton-bfCnp-9T-DP0-PoZL.js} +1 -1
- package/site/dist/assets/{_esm-B26FZg5Y.js → _esm-CJe2F7LL.js} +1 -1
- package/site/dist/assets/{_esm-BdeM6pxJ.js → _esm-zhBBffjV.js} +1 -1
- package/site/dist/assets/{accounts-DiZ-0VmN.js → accounts-Bq8t1wAD.js} +1 -1
- package/site/dist/assets/{basic-oIwwSyu4.js → basic-MlZ7f4s9.js} +1 -1
- package/site/dist/assets/ccip-BI9LWBBg.js +1 -0
- package/site/dist/assets/{ccip-BZvRTL6g.js → ccip-C-59SNEF.js} +2 -2
- package/site/dist/assets/{ccip-65sIfSPR.js → ccip-y08wK9du.js} +1 -1
- package/site/dist/assets/{client-CZG0ndth.js → client-D0IV9lV9.js} +1 -1
- package/site/dist/assets/{coinbase-DCPC2L_R-D3aIgpyd.js → coinbase-DCPC2L_R-Rs9nVCfm.js} +1 -1
- package/site/dist/assets/{core-snws5xwv.js → core-zQ1tZtVZ.js} +3 -3
- package/site/dist/assets/{dist-DnGANz51.js → dist-BxQqwnue.js} +1 -1
- package/site/dist/assets/{esm-ByALO6mA.js → esm-DXsETz3H.js} +1 -1
- package/site/dist/assets/{esm-B5cbIQaz.js → esm-vs5jNx_Y.js} +2 -2
- package/site/dist/assets/{ethers-zTjbodk5-wHhL_BQ1.js → ethers-zTjbodk5-B7BBFFKf.js} +1 -1
- package/site/dist/assets/{features-DQ0UYy6K.js → features-CYXRa3_m.js} +1 -1
- package/site/dist/assets/{getErc20Balance-jXNpFf0N-Bb9WM31M.js → getErc20Balance-jXNpFf0N-V2btxzrJ.js} +1 -1
- package/site/dist/assets/{getErc20TokenInfo-BNTrzLMP-KPrdn04K.js → getErc20TokenInfo-BNTrzLMP-CtCwQuGA.js} +1 -1
- package/site/dist/assets/{id-UqEwL2BI-BkKm533U.js → id-UqEwL2BI-CdKXapd-.js} +1 -1
- package/site/dist/assets/index-DPuRQJG2.js +8 -0
- package/site/dist/assets/{index-DvMddJcd-BatvgC-S.js → index-DvMddJcd-D-4mRLKK.js} +1 -1
- package/site/dist/assets/{index-YiCw0Y_x-CX5i3Z87.js → index-YiCw0Y_x-BX1zsiqG.js} +4 -4
- package/site/dist/assets/{localBatchGatewayRequest-3kLrX_c7.js → localBatchGatewayRequest-5YxrERBj.js} +2 -2
- package/site/dist/assets/parseEther-CGP3gnf2.js +1 -0
- package/site/dist/assets/{pkce-DXF0yKjP-ChQhE0st.js → pkce-DXF0yKjP-Bqz4wAsq.js} +1 -1
- package/site/dist/assets/preload-helper-BaNbYf_w.js +1 -0
- package/site/dist/assets/roles-32M1l9jI.js +1 -0
- package/site/dist/assets/roles-DKPW79Ca.js +1 -0
- package/site/dist/assets/shouldProceedtoEmbeddedWalletCreationFlow-B3vyavrh-ByFOTrQK.js +1 -0
- package/site/dist/assets/{simulateTransaction-CfuOrae4-64lWYJAL.js → simulateTransaction-CfuOrae4-CMFGDgT_.js} +1 -1
- package/site/dist/assets/{storage-Ufl800Ne-D0bZBw-H.js → storage-Ufl800Ne-EalZTH9q.js} +1 -1
- package/site/dist/assets/{styles-Cm9H63WO-Br4QtzUL.js → styles-Cm9H63WO-D90SsXOs.js} +1 -1
- package/site/dist/assets/{to-ui-error-DWe-qwS3-Cx2bk1kZ.js → to-ui-error-DWe-qwS3-DgCO-Y70.js} +1 -1
- package/site/dist/assets/{toViemAccount-B5iDGq1b-Ba8L7zed.js → toViemAccount-B5iDGq1b-DZ1MBqUW.js} +2 -2
- package/site/dist/assets/{transformers.web-CVP3pJOS.js → transformers.web-D4RvOP4-.js} +1 -1
- package/site/dist/assets/{use-headless-crypto-deposit-Yn-QRLB3-LUIVFBSd.js → use-headless-crypto-deposit-Yn-QRLB3-Dn6_8w-Y.js} +1 -1
- package/site/dist/assets/{use-unlink-wallet-BKK4_5Ur-CC2pq27z.js → use-unlink-wallet-BKK4_5Ur-DgsQ75lh.js} +1 -1
- package/site/dist/assets/{useActiveWallet-B-yZYGc6-D7Ik-LxJ.js → useActiveWallet-B-yZYGc6-B6JWREbk.js} +1 -1
- package/site/dist/assets/{useWalletBalance-CZnP5f_f-Dw2GIJ4g.js → useWalletBalance-CZnP5f_f-L3V0jDjL.js} +1 -1
- package/site/dist/assets/{useWallets-X1ndvJ_U-DRjz7uYD.js → useWallets-X1ndvJ_U-CLwUcevw.js} +1 -1
- package/site/dist/assets/{w3m-modal-BeVrBOIf.js → w3m-modal-BMubXAoG.js} +1 -1
- package/site/dist/assets/{wallet-DMLc-ukR.js → wallet-Bmjp2WfA.js} +2 -2
- package/site/dist/assets/{walletconnect-v2-3frQFwbg-CrtLXofr.js → walletconnect-v2-3frQFwbg-Dv6JY_ko.js} +3 -3
- package/site/dist/assets/{wui-ux-by-reown-D34ILNLS.js → wui-ux-by-reown-fVu0QkI4.js} +1 -1
- package/site/dist/index.html +4 -4
- package/src/agent/tools.js +69 -2
- package/src/agent/view-tools.js +7 -1
- package/src/core/roles.js +7 -2
- package/src/publish/ship.js +11 -4
- package/src/publish/view.js +101 -22
- package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-wu3a3kw4.js +0 -1
- package/site/dist/assets/ErrorScreen-DipdTWzE-DcxVjMO4.js +0 -1
- package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-DYIl5Kr2.js +0 -1
- package/site/dist/assets/ccip-DA_zG341.js +0 -1
- package/site/dist/assets/index-B5YmgwLH.js +0 -8
- package/site/dist/assets/ort-wasm-simd-threaded.asyncify-CxOG5pUO.wasm +0 -0
- package/site/dist/assets/parseEther-VjhVo3dd.js +0 -1
- package/site/dist/assets/preload-helper-uBIymjUX.js +0 -1
- package/site/dist/assets/roles-C9V_uDr_.js +0 -1
- package/site/dist/assets/roles-YDRjv_PY.js +0 -1
- package/site/dist/assets/shouldProceedtoEmbeddedWalletCreationFlow-B3vyavrh-BK_FBkaE.js +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./PhArrowCircleDown-D97G-BOA.js","./property-DuZ9DLP4.js","./PhArrowClockwise-DVgyFuez.js","./PhArrowDown-87b1BizM.js","./PhArrowLeft-Da0MfnbK.js","./PhArrowRight-AdrIL4DW.js","./PhArrowSquareOut-Bk2CMG3I.js","./PhArrowsDownUp-DM09Jo_3.js","./PhArrowsLeftRight-MuKBLUoF.js","./PhArrowUp-4sgyKPGx.js","./PhArrowUpRight-BNghD2zq.js","./PhArrowsClockwise-BXRn1GEl.js","./PhBank-fHbgCqqZ.js","./PhBrowser-2-9m-AkM.js","./PhCaretDown-BDNabFuL.js","./PhCaretLeft-CI460R-A.js","./PhCaretRight-D7ZS3Ls8.js","./PhCaretUp-C-iIfyvO.js","./PhCheck-DxQXn57r.js","./PhCircleHalf-MJZeRBGF.js","./PhClock-x3MS3Mwi.js","./PhCompass-hYn3HhGN.js","./PhCopy-CWNYcABI.js","./PhCreditCard-Fy4pzwtt.js","./PhCurrencyDollar-BgiaenCi.js","./PhDesktop-CxrzCSv5.js","./PhDeviceMobile-CsyA5Goi.js","./PhDotsThree-D-k1BiYg.js","./PhVault-6JTskUcC.js","./PhEnvelope-D8kzeNox.js","./PhFunnelSimple-CfQs5DAW.js","./PhGlobe-DvmSc9_A.js","./PhIdentificationCard-CfkZm-5K.js","./PhImage-Cf0J2ZfJ.js","./PhInfo-Bwi51-2X.js","./PhLightbulb-C4FZV7Es.js","./PhMagnifyingGlass-C9u8jSCJ.js","./PhPaperPlaneRight-zxQVvPLX.js","./PhPlus-C4UoW-2n.js","./PhPower-CFyWDmgD.js","./PhPuzzlePiece-BjoNVfST.js","./PhQrCode-CP3tFauY.js","./PhQuestion-wOWJBd3G.js","./PhQuestionMark-CV0k9C0Y.js","./PhSealCheck-vIKzREuN.js","./PhSignOut-CxELV-i0.js","./PhSpinner-CGDmbzUd.js","./PhTrash-C9PD0SAt.js","./PhUser-0sWNXQeZ.js","./PhWarning-CoKs3gz6.js","./PhWarningCircle-BXHw1fCt.js","./PhX-DX0SFIqC.js"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{t as e}from"./preload-helper-
|
|
2
|
+
import{t as e}from"./preload-helper-BaNbYf_w.js";import{_ as t,c as n,d as r,g as i,h as a,i as o,l as s,n as c,p as l,s as u,u as ee,v as d}from"./ConstantsUtil-DmLsRHAl.js";var te={attribute:!0,type:String,converter:t,reflect:!1,hasChanged:i},ne=(e=te,t,n)=>{let{kind:r,metadata:i}=n,a=globalThis.litPropertyMetadata.get(i);if(a===void 0&&globalThis.litPropertyMetadata.set(i,a=new Map),r===`setter`&&((e=Object.create(e)).wrapped=!0),a.set(n.name,e),r===`accessor`){let{name:r}=n;return{set(n){let i=t.get.call(this);t.set.call(this,n),this.requestUpdate(r,i,e,!0,n)},init(t){return t!==void 0&&this.C(r,void 0,e,t),t}}}if(r===`setter`){let{name:r}=n;return function(n){let i=this[r];t.call(this,n),this.requestUpdate(r,i,e,!0,n)}}throw Error(`Unsupported decorator location: `+r)};function f(e){return(t,n)=>typeof n==`object`?ne(e,t,n):((e,t,n)=>{let r=t.hasOwnProperty(n);return t.constructor.createProperty(n,e),r?Object.getOwnPropertyDescriptor(t,n):void 0})(e,t,n)}function re(e){return f({...e,state:!0,attribute:!1})}var p=`.`,m={getSpacingStyles(e,t){if(Array.isArray(e))return e[t]?`var(--apkt-spacing-${e[t]})`:void 0;if(typeof e==`string`)return`var(--apkt-spacing-${e})`},getFormattedDate(e){return new Intl.DateTimeFormat(`en-US`,{month:`short`,day:`numeric`}).format(e)},formatCurrency(e=0,t={}){let n=Number(e);return isNaN(n)?`$0.00`:new Intl.NumberFormat(`en-US`,{style:`currency`,currency:`USD`,minimumFractionDigits:2,maximumFractionDigits:2,...t}).format(n)},getHostName(e){try{return new URL(e).hostname}catch{return``}},getTruncateString({string:e,charsStart:t,charsEnd:n,truncate:r}){return e.length<=t+n?e:r===`end`?`${e.substring(0,t)}...`:r===`start`?`...${e.substring(e.length-n)}`:`${e.substring(0,Math.floor(t))}...${e.substring(e.length-Math.floor(n))}`},generateAvatarColors(e){let t=e.toLowerCase().replace(/^0x/iu,``).replace(/[^a-f0-9]/gu,``).substring(0,6).padEnd(6,`0`),n=this.hexToRgb(t),r=getComputedStyle(document.documentElement).getPropertyValue(`--w3m-border-radius-master`),i=100-3*Number(r?.replace(`px`,``)),a=`${i}% ${i}% at 65% 40%`,o=[];for(let e=0;e<5;e+=1){let t=this.tintColor(n,.15*e);o.push(`rgb(${t[0]}, ${t[1]}, ${t[2]})`)}return`
|
|
3
3
|
--local-color-1: ${o[0]};
|
|
4
4
|
--local-color-2: ${o[1]};
|
|
5
5
|
--local-color-3: ${o[2]};
|
package/site/dist/index.html
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
<script type="module" crossorigin src="./assets/index-
|
|
3
|
+
<script type="module" crossorigin src="./assets/index-DPuRQJG2.js"></script>
|
|
4
4
|
<link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-BcKkbAw3.js">
|
|
5
|
-
<link rel="modulepreload" crossorigin href="./assets/preload-helper-
|
|
6
|
-
<link rel="modulepreload" crossorigin href="./assets/roles-
|
|
5
|
+
<link rel="modulepreload" crossorigin href="./assets/preload-helper-BaNbYf_w.js">
|
|
6
|
+
<link rel="modulepreload" crossorigin href="./assets/roles-DKPW79Ca.js">
|
|
7
7
|
|
|
8
8
|
<meta charset="utf-8">
|
|
9
9
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
10
10
|
<title>Fangorn app</title>
|
|
11
|
-
<style>:root{--bg:#fbfbf8;--fg:#1a1c19;--muted:#6a6f68;--line:#dfe1db;--accent:#2f5d45;--mark:#e6eedb;--hot:#b4432f;--edge:#b7bab2;--font:system-ui, sans-serif;--font-display:var(--font);--radius:3px;--gutter:16px;--measure:760px;--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light}@media (prefers-color-scheme:dark){:root:not([data-theme=light]){--bg:#121412;--fg:#e4e6e0;--muted:#959a92;--line:#2a2e29;--accent:#8fbf9f;--mark:#2d3b2a;--hot:#d9674f;--edge:#4b5049;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}}*{box-sizing:border-box}body{background:var(--bg);color:var(--fg);font:16px/1.5 var(--font);margin:0}a{color:var(--accent)}button,input{font:inherit;color:inherit}button{cursor:pointer;border:1px solid var(--line);border-radius:var(--radius);background:0 0;padding:4px 10px}button:disabled{opacity:.45;cursor:default}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}ul{margin:0;padding:0;list-style:none}h2{text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin:28px 0 8px;font-size:.75rem;font-weight:600}h2.page,.record h2{font:600 1.3rem/1.3 var(--font-display);text-transform:none;letter-spacing:0;color:var(--fg);margin:4px 0 12px}h3{margin:0;font-size:1rem}small,time,.hint,.empty,.about,#status,.resultsbar,.detail{color:var(--muted)}small,time,.hint{font-size:.8rem}.paid{border:1px solid var(--line);border-radius:var(--radius);gap:6px;margin:12px 0;padding:10px 14px;display:grid}.paid h3{margin:0;font-size:1rem}.paid ul{margin:0;padding-left:18px}.detail{margin:0;font-size:.9rem}mark{background:var(--mark);color:inherit}.bar{z-index:2;background:var(--bg);border-bottom:1px solid var(--line);position:sticky;top:0}.bar>div,main,footer{max-width:var(--measure);padding-inline:var(--gutter);margin:0 auto}.bar>div{flex-wrap:wrap;align-items:center;gap:12px;padding-block:10px;display:flex}#home{color:var(--fg);font:600 1.1rem var(--font-display);white-space:nowrap;text-decoration:none}#q{flex:240px}#q input{border:1px solid var(--line);border-radius:var(--radius);background:0 0;width:100%;padding:8px 10px}nav{gap:14px;font-size:.9rem;display:flex}nav a{color:var(--muted);text-decoration:none}nav a.on,nav a:hover{color:var(--fg)}main{padding-block:16px 48px}.list,article{border-top:1px solid var(--line)}.row{border-bottom:1px solid var(--line);align-items:flex-start;gap:10px;padding:10px 0;display:flex}.main{overflow-wrap:anywhere;flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.title{color:var(--fg);font-weight:500;text-decoration:none}.title:hover{color:var(--accent)}.resultsbar{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;margin-bottom:8px;font-size:.9rem;display:flex}.sort,.chips,.acts,.votes{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.chips{margin:4px 0 16px}.picker{color:var(--muted);flex-direction:column;gap:4px;margin:4px 0 16px;font-size:.85rem;display:inline-flex}.picker select{font:inherit;color:var(--fg);background:var(--bg);border:1px solid var(--edge);border-radius:var(--radius);min-width:min(320px,100%);padding:6px 10px;font-size:1rem}details.about summary{cursor:pointer;color:var(--fg);font-size:1.05rem}details.about p{color:var(--muted);margin:6px 0 0}.chip{padding:2px 10px;font-size:.85rem}.chip.on,.vote[aria-pressed=true]{border-color:var(--accent);background:var(--mark)}.vote{padding:2px 7px;line-height:1.3}.star{color:var(--muted);border:0;padding:4px 6px;font-size:1.25rem;line-height:1}.star[aria-pressed=true]{color:var(--accent);background:0 0}.more,.linkish{color:var(--accent);border:0;padding:8px 0 0;font-size:.9rem}.act{color:var(--fg);border:1px solid var(--line);border-radius:var(--radius);padding:4px 10px;font-size:.88rem;text-decoration:none}article{padding:12px 0 4px}article header{flex-direction:column;margin-bottom:4px;display:flex}article .list{border-top:0}article .row:last-child{border-bottom:0}.record{border-top:0}.record dl{grid-template-columns:max-content 1fr;gap:2px 14px;margin:12px 0;font-size:.88rem;display:grid}.record dt{color:var(--muted);text-transform:capitalize}.record dd{margin:0}.acts{margin:12px 0 4px}.doc iframe{border:1px solid var(--line);background:#fff;width:100%;height:80vh;margin-top:12px}.taste{margin-bottom:20px}.pills{flex-wrap:wrap;gap:6px;margin:6px 0;display:flex}.pills li{border:1px solid var(--line);border-radius:var(--radius);align-items:center;gap:2px;padding:0 0 0 8px;font-size:.85rem;display:inline-flex}.pills li.no{color:var(--muted);text-decoration:line-through}.pills button{color:var(--muted);border:0;padding:0 8px}.knobs{grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin:12px 0;display:grid}.knob{gap:2px;font-size:.85rem;display:grid}.knob span{justify-content:space-between;font-weight:600;display:flex}.knob input{width:100%;accent-color:var(--accent)}body.wide{--measure:1200px}.mapbar input{border:1px solid var(--line);border-radius:var(--radius);background:0 0;width:100%;margin-bottom:8px;padding:8px 10px}.mapwrap{grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:start;gap:16px;display:grid}@media (width<=760px){.mapwrap{grid-template-columns:1fr}}svg.map{width:100%;height:auto;display:block;position:sticky;top:70px}svg.map path{stroke:var(--edge);stroke-width:.8px;cursor:pointer}svg.map path:hover,svg.map path:focus{stroke:var(--accent);stroke-width:2px;outline:none}svg.map path.near{stroke:var(--accent);stroke-width:2px;stroke-dasharray:4 3}svg.map path.on{stroke:var(--fg);stroke-width:2.6px}.h0{fill:var(--bg);background:var(--bg)}.h1{fill:color-mix(in srgb, var(--hot) 18%, var(--bg));background:color-mix(in srgb, var(--hot) 18%, var(--bg))}.h2{fill:color-mix(in srgb, var(--hot) 36%, var(--bg));background:color-mix(in srgb, var(--hot) 36%, var(--bg))}.h3{fill:color-mix(in srgb, var(--hot) 56%, var(--bg));background:color-mix(in srgb, var(--hot) 56%, var(--bg))}.h4{fill:color-mix(in srgb, var(--hot) 78%, var(--bg));background:color-mix(in srgb, var(--hot) 78%, var(--bg))}.h5{fill:var(--hot);background:var(--hot)}.sw{border:1px solid var(--edge);vertical-align:-1px;width:14px;height:12px;display:inline-block}.panel h3{margin:4px 0}.panel .chips{margin:6px 0}.panel .list{margin-top:8px}footer{color:var(--muted);padding-block:0 32px;font-size:.8rem}</style>
|
|
11
|
+
<style>:root{--bg:#fbfbf8;--fg:#1a1c19;--muted:#6a6f68;--line:#dfe1db;--accent:#2f5d45;--mark:#e6eedb;--hot:#b4432f;--edge:#b7bab2;--font:system-ui, sans-serif;--font-display:var(--font);--radius:3px;--gutter:16px;--measure:760px;--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light}@media (prefers-color-scheme:dark){:root:not([data-theme=light]){--bg:#121412;--fg:#e4e6e0;--muted:#959a92;--line:#2a2e29;--accent:#8fbf9f;--mark:#2d3b2a;--hot:#d9674f;--edge:#4b5049;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}}*{box-sizing:border-box}body{background:var(--bg);color:var(--fg);font:16px/1.5 var(--font);margin:0}a{color:var(--accent)}button,input{font:inherit;color:inherit}button{cursor:pointer;border:1px solid var(--line);border-radius:var(--radius);background:0 0;padding:4px 10px}button:disabled{opacity:.45;cursor:default}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}ul{margin:0;padding:0;list-style:none}h2{text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin:28px 0 8px;font-size:.75rem;font-weight:600}h2.page,.record h2{font:600 1.3rem/1.3 var(--font-display);text-transform:none;letter-spacing:0;color:var(--fg);margin:4px 0 12px}h3{margin:0;font-size:1rem}small,time,.hint,.empty,.about,#status,.resultsbar,.detail{color:var(--muted)}small,time,.hint{font-size:.8rem}.paid{border:1px solid var(--line);border-radius:var(--radius);gap:6px;margin:12px 0;padding:10px 14px;display:grid}.paid h3{margin:0;font-size:1rem}.paid ul{margin:0;padding-left:18px}.detail{margin:0;font-size:.9rem}mark{background:var(--mark);color:inherit}.bar{z-index:2;background:var(--bg);border-bottom:1px solid var(--line);position:sticky;top:0}.bar>div,main,footer{max-width:var(--measure);padding-inline:var(--gutter);margin:0 auto}.bar>div{flex-wrap:wrap;align-items:center;gap:12px;padding-block:10px;display:flex}#home{color:var(--fg);font:600 1.1rem var(--font-display);white-space:nowrap;text-decoration:none}#q{flex:240px}#q input{border:1px solid var(--line);border-radius:var(--radius);background:0 0;width:100%;padding:8px 10px}nav{gap:14px;font-size:.9rem;display:flex}nav a{color:var(--muted);text-decoration:none}nav a.on,nav a:hover{color:var(--fg)}main{padding-block:16px 48px}.list,article{border-top:1px solid var(--line)}.row{border-bottom:1px solid var(--line);align-items:flex-start;gap:10px;padding:10px 0;display:flex}.main{overflow-wrap:anywhere;flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.title{color:var(--fg);font-weight:500;text-decoration:none}.title:hover{color:var(--accent)}.resultsbar{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;margin-bottom:8px;font-size:.9rem;display:flex}.sort,.chips,.acts,.votes{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.chips{margin:4px 0 16px}.picker{color:var(--muted);flex-direction:column;gap:4px;margin:4px 0 16px;font-size:.85rem;display:inline-flex}.picker select{font:inherit;color:var(--fg);background:var(--bg);border:1px solid var(--edge);border-radius:var(--radius);min-width:min(320px,100%);padding:6px 10px;font-size:1rem}details.about summary{cursor:pointer;color:var(--fg);font-size:1.05rem}details.about p{color:var(--muted);margin:6px 0 0}.chip{padding:2px 10px;font-size:.85rem}.chip.on,.vote[aria-pressed=true]{border-color:var(--accent);background:var(--mark)}.vote{padding:2px 7px;line-height:1.3}.star{color:var(--muted);border:0;padding:4px 6px;font-size:1.25rem;line-height:1}.star[aria-pressed=true]{color:var(--accent);background:0 0}.more,.linkish{color:var(--accent);border:0;padding:8px 0 0;font-size:.9rem}.act{color:var(--fg);border:1px solid var(--line);border-radius:var(--radius);padding:4px 10px;font-size:.88rem;text-decoration:none}article{padding:12px 0 4px}article header{flex-direction:column;margin-bottom:4px;display:flex}article .list{border-top:0}article .row:last-child{border-bottom:0}.record{border-top:0}.record dl{grid-template-columns:max-content 1fr;gap:2px 14px;margin:12px 0;font-size:.88rem;display:grid}.record dt{color:var(--muted);text-transform:capitalize}.record dd{margin:0}.acts{margin:12px 0 4px}.signal{padding:14px 0 6px}.signal h3{font:600 1.15rem/1.3 var(--font-display);margin:4px 0 6px}.signal .meta{color:var(--muted);text-transform:uppercase;letter-spacing:.04em;flex-wrap:wrap;align-items:center;gap:4px 10px;font-size:.78rem;display:flex}.stage{border:1px solid var(--accent);color:var(--accent);text-transform:none;letter-spacing:0;border-radius:999px;padding:0 8px}.steps{margin:8px 0 0;padding:0;list-style:none}.steps li{border-top:1px solid var(--line);grid-template-columns:7.5em 1fr;gap:10px;padding:5px 0;font-size:.9rem;display:grid}.steps time{color:var(--muted);font-variant-numeric:tabular-nums}.doc iframe{border:1px solid var(--line);background:#fff;width:100%;height:80vh;margin-top:12px}.taste{margin-bottom:20px}.pills{flex-wrap:wrap;gap:6px;margin:6px 0;display:flex}.pills li{border:1px solid var(--line);border-radius:var(--radius);align-items:center;gap:2px;padding:0 0 0 8px;font-size:.85rem;display:inline-flex}.pills li.no{color:var(--muted);text-decoration:line-through}.pills button{color:var(--muted);border:0;padding:0 8px}.knobs{grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin:12px 0;display:grid}.knob{gap:2px;font-size:.85rem;display:grid}.knob span{justify-content:space-between;font-weight:600;display:flex}.knob input{width:100%;accent-color:var(--accent)}body.wide{--measure:1200px}.mapbar input{border:1px solid var(--line);border-radius:var(--radius);background:0 0;width:100%;margin-bottom:8px;padding:8px 10px}.mapwrap{grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:start;gap:16px;display:grid}@media (width<=760px){.mapwrap{grid-template-columns:1fr}}svg.map{width:100%;height:auto;display:block;position:sticky;top:70px}svg.map path{stroke:var(--edge);stroke-width:.8px;cursor:pointer}svg.map path:hover,svg.map path:focus{stroke:var(--accent);stroke-width:2px;outline:none}svg.map path.near{stroke:var(--accent);stroke-width:2px;stroke-dasharray:4 3}svg.map path.on{stroke:var(--fg);stroke-width:2.6px}.h0{fill:var(--bg);background:var(--bg)}.h1{fill:color-mix(in srgb, var(--hot) 18%, var(--bg));background:color-mix(in srgb, var(--hot) 18%, var(--bg))}.h2{fill:color-mix(in srgb, var(--hot) 36%, var(--bg));background:color-mix(in srgb, var(--hot) 36%, var(--bg))}.h3{fill:color-mix(in srgb, var(--hot) 56%, var(--bg));background:color-mix(in srgb, var(--hot) 56%, var(--bg))}.h4{fill:color-mix(in srgb, var(--hot) 78%, var(--bg));background:color-mix(in srgb, var(--hot) 78%, var(--bg))}.h5{fill:var(--hot);background:var(--hot)}.sw{border:1px solid var(--edge);vertical-align:-1px;width:14px;height:12px;display:inline-block}.panel h3{margin:4px 0}.panel .chips{margin:6px 0}.panel .list{margin-top:8px}footer{color:var(--muted);padding-block:0 32px;font-size:.8rem}</style>
|
|
12
12
|
<link rel="stylesheet" href="./theme.css">
|
|
13
13
|
<header class="bar"><div>
|
|
14
14
|
<a id="home" href="#/"><span id="name">Fangorn app</span></a>
|
package/src/agent/tools.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// Pure functions, so `node tools.js` checks them with no browser and no network.
|
|
13
13
|
|
|
14
14
|
import { bestPassage, cosine, lexScore, norm, zFloor } from "../core/rank.js";
|
|
15
|
-
import { briefOf, collections, linkOf, subtitleOf, titleOf, typeOf, values } from "../core/roles.js";
|
|
15
|
+
import { briefOf, collections, linkOf, pick, subtitleOf, titleOf, typeOf, values } from "../core/roles.js";
|
|
16
16
|
|
|
17
17
|
/** Fields that are plumbing rather than content — never worth faceting or
|
|
18
18
|
* showing as "what this corpus holds". */
|
|
@@ -214,6 +214,50 @@ export function neighbors(rows, id, roles, { limit = 10, fields } = {}) {
|
|
|
214
214
|
};
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
/**
|
|
218
|
+
* One thing followed across rows: a matter a committee took up and then the council, as a
|
|
219
|
+
* thread whose steps are in order. Rows group by the declared `thread` role (view.js wrote
|
|
220
|
+
* each row's target onto it); the thread's head is the target row itself, when this corpus
|
|
221
|
+
* holds it. The thread that moved last comes first.
|
|
222
|
+
*
|
|
223
|
+
* A step is one occasion: rows sharing a date and a subtitle (an agenda and its minutes)
|
|
224
|
+
* count once, keeping the one that says the most. `where` narrows the steps, `id` asks for
|
|
225
|
+
* one thread, and `min` (default 2) is how many steps make a thread: a matter taken up once
|
|
226
|
+
* so far is a record, not news.
|
|
227
|
+
*
|
|
228
|
+
* ponytail: the head is found by value (any field of a row that is not itself a step), since
|
|
229
|
+
* a fused view's identity role names one type's field. Index it if corpora get huge.
|
|
230
|
+
*/
|
|
231
|
+
export function threads(rows, roles, { id, where, min = 2, limit = 20, offset = 0, fields = [] } = {}) {
|
|
232
|
+
const f = roles.thread;
|
|
233
|
+
if (!f) return { total: 0, offset, threads: [], error: "this corpus declares no thread relation" };
|
|
234
|
+
const dateOf = (r) => String(pick(r, roles.temporal) ?? "").slice(0, 10);
|
|
235
|
+
const groups = new Map();
|
|
236
|
+
for (const r of rows) {
|
|
237
|
+
const k = r[f] == null ? "" : String(r[f]);
|
|
238
|
+
if (!k || (id != null && k !== String(id)) || !matches(r, where)) continue;
|
|
239
|
+
const occ = `${dateOf(r)}|${subtitleOf(r, roles) ?? ""}`;
|
|
240
|
+
const g = groups.get(k) ?? groups.set(k, new Map()).get(k);
|
|
241
|
+
const had = g.get(occ);
|
|
242
|
+
if (!had || String(r.text ?? "").length > String(had.text ?? "").length) g.set(occ, r);
|
|
243
|
+
}
|
|
244
|
+
const heads = new Map();
|
|
245
|
+
for (const r of rows) {
|
|
246
|
+
if (r[f] != null) continue;
|
|
247
|
+
for (const v of Object.values(r)) if (typeof v === "string" && groups.has(v) && !heads.has(v)) heads.set(v, r);
|
|
248
|
+
}
|
|
249
|
+
const all = [...groups].map(([k, g]) => {
|
|
250
|
+
const steps = [...g.values()].sort((a, b) => dateOf(a).localeCompare(dateOf(b)));
|
|
251
|
+
const head = heads.get(k), last = steps.at(-1);
|
|
252
|
+
return {
|
|
253
|
+
id: k, title: titleOf(head ?? last, roles), url: linkOf(head ?? last, roles), first: dateOf(steps[0]), date: dateOf(last),
|
|
254
|
+
head: head ? brief(head, roles, fields) : null,
|
|
255
|
+
steps: steps.map((r) => ({ ...brief(r, roles, fields), date: dateOf(r) })),
|
|
256
|
+
};
|
|
257
|
+
}).filter((t) => t.steps.length >= min || id != null).sort((a, b) => b.date.localeCompare(a.date) || a.id.localeCompare(b.id));
|
|
258
|
+
return { total: all.length, offset, threads: all.slice(offset, offset + limit) };
|
|
259
|
+
}
|
|
260
|
+
|
|
217
261
|
/** One row, whole. Deliberately the only verb that returns everything — the
|
|
218
262
|
* others preview, so an agent chooses when to spend its context. */
|
|
219
263
|
export function getRow(rows, id, roles) {
|
|
@@ -377,5 +421,28 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
|
|
|
377
421
|
}
|
|
378
422
|
}
|
|
379
423
|
|
|
380
|
-
|
|
424
|
+
// threads: one matter across meetings, an agenda and its minutes as one step, headed by
|
|
425
|
+
// the matter's own row, the latest-moving first.
|
|
426
|
+
{
|
|
427
|
+
const rl = { title: ["heading", "title"], subtitle: ["meeting"], temporal: ["date"], tags: [], measures: [], thread: "part_of", externalUrl: {} };
|
|
428
|
+
const pool = [
|
|
429
|
+
{ id: "1", heading: "Rezone Oak St", meeting: "Plan Commission", date: "2026-01-05", part_of: "p:7", text: "on the agenda" },
|
|
430
|
+
{ id: "2", heading: "Rezone Oak St", meeting: "Plan Commission", date: "2026-01-05", part_of: "p:7", text: "recommended for approval 5-0" },
|
|
431
|
+
{ id: "3", heading: "Rezone Oak St", meeting: "Village Board", date: "2026-01-20", part_of: "p:7", text: "adopted" },
|
|
432
|
+
{ id: "4", heading: "Pool bid", meeting: "Village Board", date: "2026-03-01", part_of: "p:9" },
|
|
433
|
+
{ id: "5", heading: "Pool bid", meeting: "Finance", date: "2026-02-20", part_of: "p:9", place: "A" },
|
|
434
|
+
{ id: "6", heading: "Once", meeting: "Village Board", date: "2026-04-01", part_of: "p:11" },
|
|
435
|
+
{ id: "m7", title: "Rezoning of Oak Street", matter_id: "p:7" },
|
|
436
|
+
];
|
|
437
|
+
const t = threads(pool, rl);
|
|
438
|
+
if (t.threads.map((x) => x.id).join() !== "p:9,p:7") throw new Error(`latest-moving first, one step is not a thread: ${t.threads.map((x) => x.id)}`);
|
|
439
|
+
const oak = t.threads[1];
|
|
440
|
+
if (oak.steps.map((s) => s.id).join() !== "2,3" || oak.title !== "Rezoning of Oak Street" || oak.head?.id !== "m7")
|
|
441
|
+
throw new Error(`an agenda and its minutes are one step, the head titles the thread: ${JSON.stringify(oak)}`);
|
|
442
|
+
if (threads(pool, rl, { id: "p:11" }).threads[0]?.steps.length !== 1) throw new Error("asked for by id, any thread comes back");
|
|
443
|
+
if (threads(pool, rl, { where: { place: "A" }, min: 1 }).total !== 1) throw new Error("where narrows the steps");
|
|
444
|
+
if (!threads(pool, { ...rl, thread: null }).error) throw new Error("no thread role must say so");
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
console.log("tools.js self-check ok — coverage not schema, semantic/lexical modes + z-floor, list-ish facets + where, neighbours, whole-row fetch, previews truncate, threads");
|
|
381
448
|
}
|
package/src/agent/view-tools.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
import { configure, loadShard, trimView } from "../core/shard.js";
|
|
20
20
|
import { rolesFrom, textOf } from "../core/roles.js";
|
|
21
|
-
import { browse, facet, getRow, neighbors, search } from "./tools.js";
|
|
21
|
+
import { browse, facet, getRow, neighbors, search, threads } from "./tools.js";
|
|
22
22
|
import { lexScore, rankDomains } from "../core/rank.js";
|
|
23
23
|
import { existsSync } from "node:fs";
|
|
24
24
|
import { EMBED_MODEL, embedQueryDirect, warmDirect } from "../core/embed.js";
|
|
@@ -150,6 +150,10 @@ export function viewTools(app, { fetchCatalog = fetch } = {}) {
|
|
|
150
150
|
const [v] = await pick([view]);
|
|
151
151
|
return { view: v.name, ...browse(await load(v), rolesOf(v.view), { limit, offset, sort, where: w }) };
|
|
152
152
|
},
|
|
153
|
+
threads: async ({ view, id, limit = 20, offset = 0, where: w }) => {
|
|
154
|
+
const [v] = await pick([view]);
|
|
155
|
+
return { view: v.name, ...threads(await load(v), rolesOf(v.view), { id, limit, offset, where: w }) };
|
|
156
|
+
},
|
|
153
157
|
};
|
|
154
158
|
|
|
155
159
|
const n = app.name;
|
|
@@ -166,6 +170,8 @@ export function viewTools(app, { fetchCatalog = fetch } = {}) {
|
|
|
166
170
|
inputSchema: { type: "object", properties: { field: str("Field name, e.g. from get"), views: VIEWS, limit: num("Max values (default 20)"), where: WHERE }, required: ["field"] } },
|
|
167
171
|
{ name: "browse", description: `List one view of ${n} without a query, with filters, sorting and paging.`,
|
|
168
172
|
inputSchema: { type: "object", properties: { view: str("View name from describe"), limit: num("default 20"), offset: num("default 0"), sort: str("Field to sort by"), where: WHERE }, required: ["view"] } },
|
|
173
|
+
{ name: "threads", description: `One thing followed across records of a ${n} view (a matter from committee to council): steps in date order, the latest-moving first. Views that declare no thread say so.`,
|
|
174
|
+
inputSchema: { type: "object", properties: { view: str("View name from describe"), id: str("One thread, by a step's thread field"), limit: num("default 20"), offset: num("default 0"), where: WHERE }, required: ["view"] } },
|
|
169
175
|
];
|
|
170
176
|
// Records the app sells over x402 (its card's `paid`). Paid from this server's wallet,
|
|
171
177
|
// never above FANGORN_MCP_MAX_PRICE, and checked against the sha256 the app published
|
package/src/core/roles.js
CHANGED
|
@@ -71,7 +71,7 @@ export function rolesFrom(manifests = [], sample = []) {
|
|
|
71
71
|
let launch = null, refers = null;
|
|
72
72
|
const entityTypes = [];
|
|
73
73
|
const gates = [];
|
|
74
|
-
let identity = null;
|
|
74
|
+
let identity = null, thread = null;
|
|
75
75
|
|
|
76
76
|
const push = (into, v) => { for (const x of arr(v)) if (x && !into.includes(x)) into.push(x); };
|
|
77
77
|
|
|
@@ -80,6 +80,10 @@ export function rolesFrom(manifests = [], sample = []) {
|
|
|
80
80
|
push(title, rm.title); push(subtitle, rm.subtitle); push(tags, rm.tags);
|
|
81
81
|
push(text, rm.text); push(measures, rm.measures); push(spatial, rm.spatial); push(media, rm.media); push(temporal, rm.temporal);
|
|
82
82
|
identity ??= rm.identity ?? null;
|
|
83
|
+
// The relation that follows one thing across rows: an agenda item's `part_of` names
|
|
84
|
+
// its matter, so the items taken up at a committee and then the council are one thread.
|
|
85
|
+
// view.js writes the target's identity onto the row; a reader groups by it.
|
|
86
|
+
thread ??= rm.thread ?? null;
|
|
83
87
|
// Where a row in THIS corpus points, in someone else's.
|
|
84
88
|
//
|
|
85
89
|
// The 21,131 subtitle rows in the archive bundle each carry the `path`
|
|
@@ -137,7 +141,7 @@ export function rolesFrom(manifests = [], sample = []) {
|
|
|
137
141
|
guess(text, GUESS.text);
|
|
138
142
|
|
|
139
143
|
return {
|
|
140
|
-
title, subtitle, tags, text, measures, spatial, media, temporal, facets, identity,
|
|
144
|
+
title, subtitle, tags, text, measures, spatial, media, temporal, facets, identity, thread,
|
|
141
145
|
labels, types, fieldLabels, externalUrl, actions, launch, refers, entityTypes,
|
|
142
146
|
// What this view sells, if anything. A list because a fused view can pull
|
|
143
147
|
// domains from several publishers and they price independently.
|
|
@@ -393,6 +397,7 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
|
|
|
393
397
|
if (!r.declared) throw new Error("a manifest with a role_map is declared, not sniffed");
|
|
394
398
|
if (titleOf(row, r) !== "Cira's Red, White & Brew Bar") throw new Error("declared title lost");
|
|
395
399
|
if (subtitleOf(row, r) !== "Bar & Grill") throw new Error("declared subtitle lost");
|
|
400
|
+
if (r.thread !== null || rolesFrom([{ role_map: { thread: "part_of" } }, places]).thread !== "part_of") throw new Error("thread is declared, never guessed");
|
|
396
401
|
if (textOf(row, r) !== "Bar & Grill in Saint Germain, WI.") throw new Error("empty declared text fields must be skipped, not joined as blanks");
|
|
397
402
|
// A declared reference into another publisher's corpus. All three parts or
|
|
398
403
|
// none: a half-written join would silently point at nothing, and the caller
|
package/src/publish/ship.js
CHANGED
|
@@ -363,7 +363,7 @@ export async function ship(configPath, { crawl = true, deploy = true, dry = fals
|
|
|
363
363
|
* `.ship/vectors.ndjson` keeps it cheap, so two recipes over the same data embed only the
|
|
364
364
|
* text that differs.
|
|
365
365
|
*
|
|
366
|
-
* ponytail: reads every `volume_<n>_*.json`
|
|
366
|
+
* ponytail: reads every `volume_<n>_*.json` in a source's --output-dir; the
|
|
367
367
|
* harness publishes only the stems its source declares, so a stale file left by an older
|
|
368
368
|
* shape of a source is built here and not on chain. Clear the stage dir if that bites.
|
|
369
369
|
*/
|
|
@@ -386,15 +386,22 @@ export async function buildLocal(configPath, out, { crawl = false, only = null,
|
|
|
386
386
|
const dir = resolve(cwd, expandEnv(s.command[at + 1]));
|
|
387
387
|
const volume = s.command.includes("--volume") ? s.command[s.command.indexOf("--volume") + 1] : "1";
|
|
388
388
|
const ns = (chain[`${owner}/${s.namespace}`] ??= { vertices: [], edges: [] });
|
|
389
|
+
const cidOf = new Map();
|
|
389
390
|
for (const f of existsSync(dir) ? readdirSync(dir).sort() : []) {
|
|
390
391
|
const m = new RegExp(`^volume_${volume}_(.+)\\.json$`).exec(f);
|
|
391
392
|
if (!m || m[1] === "edges") continue;
|
|
392
393
|
// The harness publishes {id: name, tag: entity, payload: fields}; the chain
|
|
393
394
|
// addresses it by the payload's hash, and so does this.
|
|
394
|
-
for (const n of JSON.parse(readFileSync(join(dir, f), "utf8")))
|
|
395
|
-
cid
|
|
396
|
-
|
|
395
|
+
for (const n of JSON.parse(readFileSync(join(dir, f), "utf8"))) {
|
|
396
|
+
const cid = createHash("sha256").update(JSON.stringify(stable(n.fields))).digest("hex");
|
|
397
|
+
cidOf.set(n.name, cid);
|
|
398
|
+
ns.vertices.push({ cid, schemaId: n.fields?.entityType ?? m[1][0].toUpperCase() + m[1].slice(1), payload: n.fields });
|
|
399
|
+
}
|
|
397
400
|
}
|
|
401
|
+
// Edges name vertices by the harness's local ids; the chain returns them by CID.
|
|
402
|
+
const edges = join(dir, `volume_${volume}_edges.json`);
|
|
403
|
+
for (const e of existsSync(edges) ? JSON.parse(readFileSync(edges, "utf8")) : [])
|
|
404
|
+
if (cidOf.has(e.from) && cidOf.has(e.to)) ns.edges.push({ relation: e.rel, sourceCid: cidOf.get(e.from), targetCid: cidOf.get(e.to) });
|
|
398
405
|
}
|
|
399
406
|
// An empty stage is a crawl that did not happen (or a cache that was not restored), not
|
|
400
407
|
// an app with no records; a view of it would grade as a failure for the wrong reason.
|
package/src/publish/view.js
CHANGED
|
@@ -26,8 +26,9 @@
|
|
|
26
26
|
// its `embedder` and this refuses to append to a view another encoder built.
|
|
27
27
|
//
|
|
28
28
|
// ponytail: flat records. quickbeam folds a record's graph neighbours into its text
|
|
29
|
-
// and can fuse publishers by shared identity; that is the hosted tier's job. Edges
|
|
30
|
-
//
|
|
29
|
+
// and can fuse publishers by shared identity; that is the hosted tier's job. Edges are
|
|
30
|
+
// not shipped as edges (quickbeam's edges.json): a relation the schema declares is written
|
|
31
|
+
// onto its source row instead (`linkRelations`), which is all a serverless reader needs.
|
|
31
32
|
|
|
32
33
|
import { gunzipSync, gzipSync } from "node:zlib";
|
|
33
34
|
import { createHash } from "node:crypto";
|
|
@@ -38,7 +39,7 @@ import { coverage as fitCoverage } from "../market/reactions.js";
|
|
|
38
39
|
export const SCHEMA_NAMESPACE = "fangorn.schema";
|
|
39
40
|
export const TYPE_TAG = "fangorn.type.v1";
|
|
40
41
|
export const EMBEDDER = { runtime: "transformers.js", model: EMBED_MODEL, dtype: EMBED_DTYPE };
|
|
41
|
-
const SINGULAR = ["identity", "title", "subtitle", "temporal", "spatial", "media"];
|
|
42
|
+
const SINGULAR = ["identity", "title", "subtitle", "temporal", "spatial", "media", "thread"];
|
|
42
43
|
const MULTI = ["tags", "measures", "relations", "text"];
|
|
43
44
|
const ZERO = "0x0000000000000000000000000000000000000000";
|
|
44
45
|
// Refit coverage once a domain has grown this many times over what it was fit on.
|
|
@@ -120,6 +121,23 @@ export function domainSpec(schema, tags) {
|
|
|
120
121
|
return { description: decls.map((d) => d.description).filter(Boolean).join(" "), role_map, presentation };
|
|
121
122
|
}
|
|
122
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Each declared relation, onto the row it starts from: an agenda item with a `part_of` edge
|
|
126
|
+
* to a matter carries `part_of: <the matter's identity>`, so a reader groups rows by it
|
|
127
|
+
* without walking the graph. Undeclared edges are left alone (the schema is the contract).
|
|
128
|
+
* `records` maps CID → fields and is changed in place.
|
|
129
|
+
* ponytail: one target per relation and row (the last edge wins); a list when a relation
|
|
130
|
+
* needs many.
|
|
131
|
+
*/
|
|
132
|
+
export function linkRelations(records, edges, schema) {
|
|
133
|
+
for (const e of edges ?? []) {
|
|
134
|
+
const from = records.get(e.sourceCid), to = records.get(e.targetCid);
|
|
135
|
+
if (!from || !to || !schema.relations.some((r) => r.rel === e.relation && r.from === from.entityType && r.to === to.entityType)) continue;
|
|
136
|
+
const id = schema.types[to.entityType]?.role_map?.identity;
|
|
137
|
+
from[e.relation] = String((id && to[id]) ?? e.targetCid);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
123
141
|
// ── a client that only reads ──────────────────────────────────────────────────
|
|
124
142
|
|
|
125
143
|
/** An SDK client for reading commits: a throwaway key (nothing signs) and no upload
|
|
@@ -201,7 +219,7 @@ export function liveFields(out) {
|
|
|
201
219
|
* Returns per-domain counts of what changed.
|
|
202
220
|
*/
|
|
203
221
|
export async function publishView({ fangorn, app, namespaces, out, fromBlock = 0n, rebake = false,
|
|
204
|
-
embed = embedDocumentDirect, log = console.log, shardRows = 20000 }) {
|
|
222
|
+
embed = embedDocumentDirect, log = console.log, shardRows = 20000, concurrency = 4 }) {
|
|
205
223
|
if (!namespaces?.length) throw new Error("publishView: name the data namespace(s) to publish");
|
|
206
224
|
fangorn.setAppId(app);
|
|
207
225
|
const appId = fangorn.getAppId();
|
|
@@ -216,24 +234,54 @@ export async function publishView({ fangorn, app, namespaces, out, fromBlock = 0
|
|
|
216
234
|
log(`schema: ${declared.length ? declared.join(", ") : "no declared types"}`);
|
|
217
235
|
|
|
218
236
|
const report = {};
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
237
|
+
// Several namespaces at once: reading one back through an IPFS gateway is block by block and
|
|
238
|
+
// takes minutes, while its embedding takes seconds. Each domain writes only its own folder.
|
|
239
|
+
const queue = namespaces.filter((n) => n !== SCHEMA_NAMESPACE);
|
|
240
|
+
// Who published into each namespace, from ONE scan of the app's commit logs. The chain filters
|
|
241
|
+
// them by app only, so a scan per namespace re-reads every log of the app each time: 376 s a
|
|
242
|
+
// namespace through a public RPC, against 3 s to read the namespace itself.
|
|
243
|
+
const reg = fangorn.getDataRegistry?.();
|
|
244
|
+
let committed = null;
|
|
245
|
+
if (reg?.getStateCommittedLogs && reg.namespaceKey) {
|
|
246
|
+
const logs = await retry(() => reg.getStateCommittedLogs({}, BigInt(fromBlock)));
|
|
247
|
+
committed = { keys: new Set(logs.map((l) => l.namespaceKey)), publishers: [...new Set(logs.map((l) => l.publisher))] };
|
|
248
|
+
log(`commit logs since block ${fromBlock}: ${logs.length} from ${committed.publishers.length} publisher(s)`);
|
|
228
249
|
}
|
|
250
|
+
const publishersOf = (ns) => (committed
|
|
251
|
+
? committed.publishers.filter((p) => committed.keys.has(reg.namespaceKey(p, ns))).map((owner) => ({ owner }))
|
|
252
|
+
: retry(() => fangorn.appNamespaces({ namespace: ns, fromBlock: BigInt(fromBlock) })));
|
|
253
|
+
const worker = async () => {
|
|
254
|
+
for (let ns; (ns = queue.shift()) !== undefined;) {
|
|
255
|
+
const timelines = await publishersOf(ns);
|
|
256
|
+
log(`${ns}: ${timelines.length} publisher(s) since block ${fromBlock}`);
|
|
257
|
+
for (const { owner: publisher } of timelines) {
|
|
258
|
+
const domain = domainFor(appId, publisher, ns);
|
|
259
|
+
report[domain] = await publishDomain({
|
|
260
|
+
fangorn, schema, publisher, ns, domain, dir: `${out}/cdn/domains/${domain}`, rebake, embed, log, shardRows,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
await Promise.all(Array.from({ length: concurrency }, worker));
|
|
229
266
|
writeCatalog(out);
|
|
230
267
|
return report;
|
|
231
268
|
}
|
|
232
269
|
|
|
270
|
+
/** A public RPC answers a burst with 429s: back off and try again, a few times. */
|
|
271
|
+
async function retry(f, tries = 6) {
|
|
272
|
+
for (let i = 0; ; i++) {
|
|
273
|
+
try { return await f(); } catch (e) {
|
|
274
|
+
if (i >= tries - 1 || !/429|Too Many Requests|rate limit|timeout|ECONNRESET|fetch failed/i.test(String(e?.message ?? e))) throw e;
|
|
275
|
+
await new Promise((ok) => setTimeout(ok, 2000 * 2 ** i));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
233
280
|
async function publishDomain({ fangorn, schema, publisher, ns, domain, dir, rebake, embed, log, shardRows }) {
|
|
234
|
-
const { contents } = await fangorn.readNamespace(publisher, ns);
|
|
281
|
+
const { contents } = await retry(() => fangorn.readNamespace(publisher, ns));
|
|
235
282
|
const records = new Map((contents.vertices ?? []).filter((v) => v.payload && typeof v.payload === "object")
|
|
236
283
|
.map((v) => [v.cid, { ...v.payload, entityType: v.schemaId }]));
|
|
284
|
+
linkRelations(records, contents.edges, schema);
|
|
237
285
|
|
|
238
286
|
if (rebake) rmSync(dir, { recursive: true, force: true }); // old shards would stay reachable
|
|
239
287
|
const had = loadDomain(dir);
|
|
@@ -248,6 +296,11 @@ async function publishDomain({ fangorn, schema, publisher, ns, domain, dir, reba
|
|
|
248
296
|
const live = (id) => had.rows.has(id) && !dead.has(id);
|
|
249
297
|
const fresh = [...records.keys()].filter((id) => !live(id));
|
|
250
298
|
const gone = [...had.rows.keys()].filter((id) => live(id) && !records.has(id));
|
|
299
|
+
// A row already served whose links changed (its matter came later, or moved): new fields,
|
|
300
|
+
// the same vector, so no embedding, only a rewrite.
|
|
301
|
+
const relinked = [...had.rows.keys()].filter((id) => live(id) && records.has(id)
|
|
302
|
+
&& JSON.stringify(had.rows.get(id).fields) !== JSON.stringify(records.get(id)));
|
|
303
|
+
for (const id of relinked) had.rows.get(id).fields = records.get(id);
|
|
251
304
|
|
|
252
305
|
// Roles per type: declared exactly, else guessed (and said so).
|
|
253
306
|
const byType = new Map();
|
|
@@ -271,7 +324,7 @@ async function publishDomain({ fangorn, schema, publisher, ns, domain, dir, reba
|
|
|
271
324
|
if (Math.floor((n + ids.length) / 1000) > Math.floor(n / 1000)) log(`${domain}: embedded ${n + ids.length}/${fresh.length}`);
|
|
272
325
|
n += ids.length;
|
|
273
326
|
}
|
|
274
|
-
if (!fresh.length && !gone.length && had.manifest && !rebake) {
|
|
327
|
+
if (!fresh.length && !gone.length && !relinked.length && had.manifest && !rebake) {
|
|
275
328
|
applySpec(dir, had.manifest, schema, had.rows, dead); // a schema change alone still lands
|
|
276
329
|
return { added: 0, removed: 0 };
|
|
277
330
|
}
|
|
@@ -297,11 +350,11 @@ async function publishDomain({ fangorn, schema, publisher, ns, domain, dir, reba
|
|
|
297
350
|
}
|
|
298
351
|
for (const id of gone) dead.add(id);
|
|
299
352
|
// A tombstone hides a row from readers, but its shard still serves the bytes. A record
|
|
300
|
-
// retracted for what it said (a name, an address) has to be gone, so any removal
|
|
301
|
-
// rewrites the live rows into one shard and the old
|
|
302
|
-
// the vectors are already in the rows.
|
|
353
|
+
// retracted for what it said (a name, an address) has to be gone, so any removal (or a
|
|
354
|
+
// relink, whose rows' fields changed) rewrites the live rows into one shard and the old
|
|
355
|
+
// files are deleted. No re-embedding: the vectors are already in the rows.
|
|
303
356
|
// ponytail: rewrites the whole domain on every removal; compact past a threshold if domains get big.
|
|
304
|
-
if (dead.size) {
|
|
357
|
+
if (dead.size || relinked.length) {
|
|
305
358
|
for (const s of manifest.shards) rmSync(`${dir}/shards/${s.file}`, { force: true });
|
|
306
359
|
manifest.shards = [];
|
|
307
360
|
for (const id of dead) had.rows.delete(id);
|
|
@@ -311,8 +364,8 @@ async function publishDomain({ fangorn, schema, publisher, ns, domain, dir, reba
|
|
|
311
364
|
manifest.tombstones = [...dead].sort();
|
|
312
365
|
manifest.created_at = Math.floor(Date.now() / 1000);
|
|
313
366
|
applySpec(dir, manifest, schema, had.rows, dead, rolesOf);
|
|
314
|
-
log(`${domain}: +${fresh.length} embedded, -${gone.length} removed, ${manifest.count} live`);
|
|
315
|
-
return { added: fresh.length, removed: gone.length };
|
|
367
|
+
log(`${domain}: +${fresh.length} embedded, -${gone.length} removed, ${relinked.length} relinked, ${manifest.count} live`);
|
|
368
|
+
return { added: fresh.length, removed: gone.length, ...(relinked.length ? { relinked: relinked.length } : {}) };
|
|
316
369
|
}
|
|
317
370
|
|
|
318
371
|
/** Counts, types, roles, description, presentation and coverage from what the domain now holds. */
|
|
@@ -457,5 +510,31 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
|
|
|
457
510
|
{ added: 2, removed: 0 }, "--rebake starts the domain over");
|
|
458
511
|
eq(readdirSync(`${out}/cdn/domains/${d}/shards`).length, 1, "and leaves no orphaned shards");
|
|
459
512
|
rmSync(out, { recursive: true, force: true });
|
|
460
|
-
|
|
513
|
+
|
|
514
|
+
// Relations: a declared edge lands on its source row as the target's identity; an
|
|
515
|
+
// undeclared one does not; a link that arrives later rewrites the row without embedding it.
|
|
516
|
+
{
|
|
517
|
+
const T = { tag: "civic.item.v1" }, M = { tag: "civic.matter.v1" };
|
|
518
|
+
const rel = { [`${OWNER}/${SCHEMA_NAMESPACE}`]: { vertices: [
|
|
519
|
+
{ cid: "ti", schemaId: TYPE_TAG, payload: { ...T, role_map: { identity: "item_id", title: "heading", thread: "part_of" } } },
|
|
520
|
+
{ cid: "tm", schemaId: TYPE_TAG, payload: { ...M, role_map: { identity: "matter_id", title: "title" } } }],
|
|
521
|
+
edges: [{ relation: "part_of", sourceCid: "ti", targetCid: "tm" }] },
|
|
522
|
+
[`${PUB}/civic`]: { vertices: [
|
|
523
|
+
{ cid: "i1", schemaId: T.tag, payload: { item_id: "a#1", heading: "Rezone, committee" } },
|
|
524
|
+
{ cid: "i2", schemaId: T.tag, payload: { item_id: "b#4", heading: "Rezone, council" } },
|
|
525
|
+
{ cid: "m1", schemaId: M.tag, payload: { matter_id: "plover:7", title: "Rezone" } }],
|
|
526
|
+
edges: [{ relation: "part_of", sourceCid: "i1", targetCid: "m1" }, { relation: "cites", sourceCid: "i2", targetCid: "m1" }] } };
|
|
527
|
+
const o = mkdtempSync(`${tmpdir()}/view-`), dr = domainFor(APP, PUB, "civic");
|
|
528
|
+
const go = () => publishView({ fangorn: localFangorn(rel, { appId: APP, owner: OWNER }), app: APP, namespaces: ["civic"], out: o, embed, log: () => {} });
|
|
529
|
+
const parts = () => Object.fromEntries([...loadDomain(`${o}/cdn/domains/${dr}`).rows.values()].map((r) => [r.fields.heading ?? r.fields.title, r.fields.part_of ?? r.fields.cites ?? null]));
|
|
530
|
+
await go();
|
|
531
|
+
eq(parts(), { "Rezone, committee": "plover:7", "Rezone, council": null, Rezone: null }, "a declared relation carries the target's identity; an undeclared one is not written");
|
|
532
|
+
eq(readJson(`${o}/cdn/domains/${dr}/manifest`).role_map.thread, "part_of", "the thread role reaches the manifest");
|
|
533
|
+
rel[`${PUB}/civic`].edges.push({ relation: "part_of", sourceCid: "i2", targetCid: "m1" });
|
|
534
|
+
const before = embedded.length;
|
|
535
|
+
eq((await go())[dr], { added: 0, removed: 0, relinked: 1 }, "a link that comes later relinks the row");
|
|
536
|
+
eq([parts()["Rezone, council"], embedded.length - before], ["plover:7", 0], "without embedding it again");
|
|
537
|
+
rmSync(o, { recursive: true, force: true });
|
|
538
|
+
}
|
|
539
|
+
console.log("view.js self-check ok — domain names and embedded text match quickbeam's, the schema is applied, a second run embeds nothing, additions ship as delta shards, removals compact the domain, the real reader sees exactly the live records by the publisher's id, and another encoder's view is refused, and declared relations land on their source rows");
|
|
461
540
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e,r as t,t as n}from"./ConnectionStatusScreen-fUfROm9m-BeWLchcf.js";export{n as ConnectionStatusScreen,n as default,e as ConnectionStatusView,t as getErrorDetails};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e,t}from"./ErrorScreen-DipdTWzE-c8g8En21.js";export{t as ErrorScreen,t as default,e as ErrorScreenView};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{i as e,n as t,r as n,t as r}from"./LinkPasskeyScreen-zbrl_AI_-D72Gb0LW.js";export{n as DoubleIconWrapper,t as LinkButton,r as LinkPasskeyScreen,r as default,e as LinkPasskeyView};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{i as e,n as t}from"./ccip-BZvRTL6g.js";export{t as offchainLookup,e as offchainLookupSignature};
|