excaliagent 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +90 -2
- package/bin/excaliagent.js +2 -0
- package/dist/server/args.js +51 -0
- package/dist/server/cli.js +99 -0
- package/dist/server/desktop/desktop.js +108 -0
- package/dist/server/http.js +240 -0
- package/dist/server/hub.js +101 -0
- package/dist/server/panes/herdr-client.js +220 -0
- package/dist/server/panes/herdr-clients.js +58 -0
- package/dist/server/panes/herdr.js +246 -0
- package/dist/server/panes/none.js +10 -0
- package/dist/server/panes/types.js +1 -0
- package/dist/server/scene-store.js +61 -0
- package/dist/server/sources/claude.js +292 -0
- package/dist/server/sources/git.js +65 -0
- package/dist/server/sources/log.js +10 -0
- package/dist/server/sources/registry.js +79 -0
- package/dist/server/sources/transcript.js +204 -0
- package/dist/server/sources/types.js +1 -0
- package/dist/shared/types.js +9 -0
- package/dist/web/assets/Assistant-Bold-gm-uSS1B.woff2 +0 -0
- package/dist/web/assets/Assistant-Medium-DrcxCXg3.woff2 +0 -0
- package/dist/web/assets/Assistant-Regular-DVxZuzxb.woff2 +0 -0
- package/dist/web/assets/Assistant-SemiBold-SCI4bEL9.woff2 +0 -0
- package/dist/web/assets/abnfDiagram-VCTEODGH-lVjPevGa.js +1 -0
- package/dist/web/assets/ar-SA-G6X2FPQ2-CD5aVmDx.js +10 -0
- package/dist/web/assets/arc-Y1ARJVZ4.js +1 -0
- package/dist/web/assets/architecture-7GRP2DOG-9pDjotLm.js +1 -0
- package/dist/web/assets/architectureDiagram-5GKGNRK7-D0Yl-_Yc.js +36 -0
- package/dist/web/assets/array-BifhSqXX.js +1 -0
- package/dist/web/assets/az-AZ-76LH7QW2-D4vT9Alz.js +1 -0
- package/dist/web/assets/bg-BG-XCXSNQG7-MMTI5wg3.js +5 -0
- package/dist/web/assets/blockDiagram-I7D4REHJ-DhrilPMV.js +129 -0
- package/dist/web/assets/bn-BD-2XOGV67Q-CCHqTpZW.js +5 -0
- package/dist/web/assets/c4Diagram-7LVT6UL2-DGXbRPw_.js +38 -0
- package/dist/web/assets/ca-ES-6MX7JW3Y-ChGGIAut.js +8 -0
- package/dist/web/assets/channel-fspI7jZI.js +1 -0
- package/dist/web/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/dist/web/assets/chunk-4HAMMTFA-Cw9s83q8.js +62 -0
- package/dist/web/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/dist/web/assets/chunk-75Z2AOVW-BC0CaRUB.js +2 -0
- package/dist/web/assets/chunk-DU6HZSFF-W9nFVr4b.js +127 -0
- package/dist/web/assets/chunk-EIO257PC-DG_y2xQ1.js +22 -0
- package/dist/web/assets/chunk-F27PBJKO-yfVK-Hr6.js +1 -0
- package/dist/web/assets/chunk-FOHPRMQF-DD4dKubD.js +161 -0
- package/dist/web/assets/chunk-GMAD6QVW-C2Qn052r.js +72 -0
- package/dist/web/assets/chunk-GVQU2GXP-IFaX5U4g.js +1 -0
- package/dist/web/assets/chunk-IMKFNOWR-M1ZEBqas.js +231 -0
- package/dist/web/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/dist/web/assets/chunk-L3NEJ4N5-oLQiZ5i-.js +1 -0
- package/dist/web/assets/chunk-OSK3NFVY-D-OfNZzS.js +10 -0
- package/dist/web/assets/chunk-P2QGCYS3-DJerQdnp.js +1 -0
- package/dist/web/assets/chunk-POPQ4Y6H-BC0OyYJc.js +1 -0
- package/dist/web/assets/chunk-PWAF6VOD-CjU6T4Vk.js +1 -0
- package/dist/web/assets/chunk-SHT3W25Y-DBMa5yhK.js +168 -0
- package/dist/web/assets/chunk-SVP7TREG-Bbvoxr5d.js +88 -0
- package/dist/web/assets/chunk-TICWLB2K-DIPq7Qti.js +206 -0
- package/dist/web/assets/chunk-XXDRQBXY-CnbRkih_.js +1 -0
- package/dist/web/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/dist/web/assets/classDiagram-ZZMXUADV-Dr-7S1cu.js +1 -0
- package/dist/web/assets/classDiagram-v2-VYDZK3BY-Dr-7S1cu.js +1 -0
- package/dist/web/assets/cose-bilkent-JH36ORCC-lWVj4msc.js +1 -0
- package/dist/web/assets/cs-CZ-2BRQDIVT-Bax3wFiz.js +11 -0
- package/dist/web/assets/cynefin-OW5HDTMX-y_XDTnaT.js +1 -0
- package/dist/web/assets/cynefinDiagram-5FMLGOSQ-BeJtQvjE.js +62 -0
- package/dist/web/assets/cytoscape.esm-BegBNzOV.js +321 -0
- package/dist/web/assets/da-DK-5WZEPLOC-i66Qepbp.js +5 -0
- package/dist/web/assets/dagre-D7JM2Yhv.js +1 -0
- package/dist/web/assets/dagre-GXQ25YYZ-CzBP3X6H.js +4 -0
- package/dist/web/assets/de-DE-XR44H4JA-yjhmbrBK.js +8 -0
- package/dist/web/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/dist/web/assets/diagram-S7CK7UJ4-CL5OmME1.js +30 -0
- package/dist/web/assets/diagram-UQ7AKVKN-6_lscQb4.js +41 -0
- package/dist/web/assets/diagram-VSXAHHWV-C3E4-nJG.js +3 -0
- package/dist/web/assets/diagram-VX7I27RA-51lQ_NN2.js +24 -0
- package/dist/web/assets/diagram-Z3DM3KII-D86k1y9Z.js +24 -0
- package/dist/web/assets/directory-open-01563666-D4xXyWb_.js +1 -0
- package/dist/web/assets/directory-open-4ed118d0-1i309Asm.js +1 -0
- package/dist/web/assets/dist-BPnbDAwD.js +62 -0
- package/dist/web/assets/dist-CumnGVmJ.js +1 -0
- package/dist/web/assets/ebnfDiagram-PWID7BFC-DDjKtPWY.js +1 -0
- package/dist/web/assets/el-GR-BZB4AONW-Deizd0yM.js +10 -0
- package/dist/web/assets/en-B4ZKOASM-Dvqqxrua.js +1 -0
- package/dist/web/assets/erDiagram-RLTQ6QDP-Dju3XIzd.js +99 -0
- package/dist/web/assets/es-ES-U4NZUMDT-Bz7tNFv9.js +9 -0
- package/dist/web/assets/eu-ES-A7QVB2H4-B3BHiHTa.js +11 -0
- package/dist/web/assets/eventmodeling-NTZA5JFV-MeBWwPID.js +1 -0
- package/dist/web/assets/fa-IR-HGAKTJCU-B9t2EOWw.js +8 -0
- package/dist/web/assets/fi-FI-Z5N7JZ37-BRW-fC7d.js +6 -0
- package/dist/web/assets/file-open-002ab408-BHUWm0Sh.js +1 -0
- package/dist/web/assets/file-open-7c801643-DZtJT5zp.js +1 -0
- package/dist/web/assets/file-save-3189631c-CO9S4HFW.js +1 -0
- package/dist/web/assets/file-save-745eba88-Bwdfz6OZ.js +1 -0
- package/dist/web/assets/flowDiagram-HODETNUW-kdP64-E7.js +1 -0
- package/dist/web/assets/fr-FR-RHASNOE6-C1x7RIuS.js +9 -0
- package/dist/web/assets/ganttDiagram-EL5Y4UJY-CUQyfHZV.js +292 -0
- package/dist/web/assets/gitGraph-4MIJSDKK-77imLp1D.js +1 -0
- package/dist/web/assets/gitGraphDiagram-WWUBYQGX-CC4ZOu_u.js +106 -0
- package/dist/web/assets/gl-ES-HMX3MZ6V-DSChLEXM.js +10 -0
- package/dist/web/assets/graphlib-DS17s2tU.js +1 -0
- package/dist/web/assets/he-IL-6SHJWFNN-DqrJHras.js +10 -0
- package/dist/web/assets/hi-IN-IWLTKZ5I-scDn95Bz.js +4 -0
- package/dist/web/assets/hu-HU-A5ZG7DT2-2BB7ywaE.js +7 -0
- package/dist/web/assets/id-ID-SAP4L64H-BCD-rITt.js +10 -0
- package/dist/web/assets/image-GAAHSSAO-BHEttEFL.js +1 -0
- package/dist/web/assets/image-blob-reduce.esm-Fj7y_Tzy.js +2 -0
- package/dist/web/assets/index-C6RFmwp_.js +212 -0
- package/dist/web/assets/index-DtRVLazd.css +1 -0
- package/dist/web/assets/info-A6RAGUB7-Ee6NHVyn.js +1 -0
- package/dist/web/assets/infoDiagram-27XIBGKW-bwB50WOT.js +2 -0
- package/dist/web/assets/init-C-OQMol4.js +1 -0
- package/dist/web/assets/ishikawaDiagram-5VMMS53U-6CilUSFW.js +70 -0
- package/dist/web/assets/it-IT-JPQ66NNP-D4MSuNp_.js +11 -0
- package/dist/web/assets/ja-JP-DBVTYXUO-BkR3NP86.js +8 -0
- package/dist/web/assets/journeyDiagram-3NMN7TZE-C-woTmG9.js +139 -0
- package/dist/web/assets/kaa-6HZHGXH3-C_EQTf78.js +1 -0
- package/dist/web/assets/kab-KAB-ZGHBKWFO-P-qeHBkl.js +8 -0
- package/dist/web/assets/kanban-definition-UXKFOSKX-CL-EUtyf.js +89 -0
- package/dist/web/assets/katex-DJhrJSbw.js +257 -0
- package/dist/web/assets/kk-KZ-P5N5QNE5-DwZmyItd.js +1 -0
- package/dist/web/assets/km-KH-HSX4SM5Z-3SN2ksDz.js +11 -0
- package/dist/web/assets/ko-KR-MTYHY66A--YzrPq0D.js +9 -0
- package/dist/web/assets/ku-TR-6OUDTVRD-BV1o1ulU.js +9 -0
- package/dist/web/assets/line-DGLpHp6u.js +1 -0
- package/dist/web/assets/linear-C9iwaMOi.js +1 -0
- package/dist/web/assets/lt-LT-XHIRWOB4-BuU5cssW.js +3 -0
- package/dist/web/assets/lv-LV-5QDEKY6T-Z9bSAiFr.js +7 -0
- package/dist/web/assets/mermaid-parser.core-DA_7CZUN.js +7 -0
- package/dist/web/assets/mindmap-definition-YA3MSWOX-B58mvQws.js +96 -0
- package/dist/web/assets/mr-IN-CRQNXWMA-Cz6h_4fN.js +13 -0
- package/dist/web/assets/my-MM-5M5IBNSE-n2l8bHxH.js +1 -0
- package/dist/web/assets/nb-NO-T6EIAALU-r9C_Vo0N.js +10 -0
- package/dist/web/assets/nl-NL-IS3SIHDZ-z43DJLFx.js +8 -0
- package/dist/web/assets/nn-NO-6E72VCQL-Dc6CXJ79.js +8 -0
- package/dist/web/assets/oc-FR-POXYY2M6-BgJXbWuu.js +8 -0
- package/dist/web/assets/ordinal-BDEzSJ7C.js +1 -0
- package/dist/web/assets/pa-IN-N4M65BXN-CNGXNDOU.js +4 -0
- package/dist/web/assets/packet-AYTQ26CC-DBS9PBUE.js +1 -0
- package/dist/web/assets/path-fybaL0A-.js +1 -0
- package/dist/web/assets/pegDiagram-XKGWAZYB-DA7TGmky.js +1 -0
- package/dist/web/assets/percentages-BXMCSKIN-btxXaPp4.js +1 -0
- package/dist/web/assets/pica-CXv_OHDX.js +2 -0
- package/dist/web/assets/pie-WAS4IAKB-Cx2pnjZr.js +1 -0
- package/dist/web/assets/pieDiagram-E7YTZNPT-q7SgBOc3.js +39 -0
- package/dist/web/assets/pl-PL-T2D74RX3-NeLUNwLZ.js +9 -0
- package/dist/web/assets/pt-BR-5N22H2LF-D5X0RFzx.js +9 -0
- package/dist/web/assets/pt-PT-UZXXM6DQ-_ZsKyBBN.js +9 -0
- package/dist/web/assets/quadrantDiagram-AXDQQJYC-CqjGVnZh.js +7 -0
- package/dist/web/assets/radar-RG4KPBEZ-BWJANoHa.js +1 -0
- package/dist/web/assets/railroad-74A4TZTK-BTAfdSvV.js +1 -0
- package/dist/web/assets/railroad-abnf-HS5TGJTU-NfS3EnaM.js +1 -0
- package/dist/web/assets/railroad-ebnf-LZEXJU2U-Ce5m2P1B.js +1 -0
- package/dist/web/assets/railroad-peg-WCYAUIDC-CyXkeDDy.js +1 -0
- package/dist/web/assets/railroadDiagram-O6MQD6OU-C4wOSBs0.js +1 -0
- package/dist/web/assets/requirementDiagram-BXWQKSXE-dC2Q9_dM.js +84 -0
- package/dist/web/assets/ro-RO-JPDTUUEW-B0TUgaSO.js +11 -0
- package/dist/web/assets/rolldown-runtime-COiEfhsA.js +1 -0
- package/dist/web/assets/rough.esm-Dy-Kn_BL.js +1 -0
- package/dist/web/assets/roundRect-D01gJrlt.js +1 -0
- package/dist/web/assets/ru-RU-B4JR7IUQ-FyI4SBb1.js +9 -0
- package/dist/web/assets/sankeyDiagram-P5KCCOFB-czlewm_g.js +40 -0
- package/dist/web/assets/sequenceDiagram-WJ2MYXX4-rtSwZGtV.js +162 -0
- package/dist/web/assets/si-LK-N5RQ5JYF-q-KyMvoF.js +1 -0
- package/dist/web/assets/sizeCapture-INFHLROL-3uHXrFqA.js +1 -0
- package/dist/web/assets/sk-SK-C5VTKIMK-tX-HO0L6.js +6 -0
- package/dist/web/assets/sl-SI-NN7IZMDC-Dy8vWC0s.js +6 -0
- package/dist/web/assets/src-BWF7jMDv.js +1 -0
- package/dist/web/assets/stateDiagram-D77RDMKH-CWDH4s-t.js +1 -0
- package/dist/web/assets/stateDiagram-v2-MP3YSRHH-DdSAvpNH.js +1 -0
- package/dist/web/assets/subset-shared.chunk-D1bYkpAa.js +1 -0
- package/dist/web/assets/subset-worker.chunk-CBZq9OSE.js +1 -0
- package/dist/web/assets/sv-SE-XGPEYMSR-D1ErsBn-.js +10 -0
- package/dist/web/assets/swimlanes-42K2YHIH-CM2OkOmc.js +1 -0
- package/dist/web/assets/swimlanesDiagram-VR7AAH4N-CVzVUDpQ.js +8 -0
- package/dist/web/assets/ta-IN-2NMHFXQM-PSu4eqYe.js +9 -0
- package/dist/web/assets/th-TH-HPSO5L25-BVu-PlXo.js +2 -0
- package/dist/web/assets/timeline-definition-24CTP7MA-Bo6sYnPJ.js +120 -0
- package/dist/web/assets/tr-TR-DEFEU3FU-BtC_O7fA.js +7 -0
- package/dist/web/assets/treeView-Q6P3EWNA-B3NS1SBg.js +1 -0
- package/dist/web/assets/treemap-WGGIJYW6-Du_VkW6s.js +1 -0
- package/dist/web/assets/uk-UA-QMV73CPH-RwWQcIwP.js +6 -0
- package/dist/web/assets/vennDiagram-4TSXK5OY-R1EH0pXq.js +34 -0
- package/dist/web/assets/vi-VN-M7AON7JQ-CUEI6eHH.js +5 -0
- package/dist/web/assets/wardley-WFR3VGLG-9B3cKl8K.js +1 -0
- package/dist/web/assets/wardleyDiagram-VM6X3IG4-XZ18gIOz.js +78 -0
- package/dist/web/assets/xychartDiagram-S5SC5T6Z-BLzXnvba.js +7 -0
- package/dist/web/assets/zh-CN-LNUGB5OW-C3asHvVp.js +10 -0
- package/dist/web/assets/zh-HK-E62DVLB3-BO6FsJfO.js +1 -0
- package/dist/web/assets/zh-TW-RAJ6MFWO-DGtaI2hh.js +9 -0
- package/dist/web/fonts/Assistant/Assistant-Bold.woff2 +0 -0
- package/dist/web/fonts/Assistant/Assistant-Medium.woff2 +0 -0
- package/dist/web/fonts/Assistant/Assistant-Regular.woff2 +0 -0
- package/dist/web/fonts/Assistant/Assistant-SemiBold.woff2 +0 -0
- package/dist/web/fonts/Cascadia/CascadiaCode-Regular.woff2 +0 -0
- package/dist/web/fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2 +0 -0
- package/dist/web/fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2 +0 -0
- package/dist/web/fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2 +0 -0
- package/dist/web/fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2 +0 -0
- package/dist/web/fonts/Excalifont/Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2 +0 -0
- package/dist/web/fonts/Excalifont/Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2 +0 -0
- package/dist/web/fonts/Excalifont/Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2 +0 -0
- package/dist/web/fonts/Excalifont/Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2 +0 -0
- package/dist/web/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2 +0 -0
- package/dist/web/fonts/Excalifont/Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2 +0 -0
- package/dist/web/fonts/Excalifont/Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2 +0 -0
- package/dist/web/fonts/Liberation/LiberationSans-Regular.woff2 +0 -0
- package/dist/web/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2 +0 -0
- package/dist/web/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2 +0 -0
- package/dist/web/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2 +0 -0
- package/dist/web/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2 +0 -0
- package/dist/web/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2 +0 -0
- package/dist/web/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2 +0 -0
- package/dist/web/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2 +0 -0
- package/dist/web/fonts/Virgil/Virgil-Regular.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-019d66dcad46dc156b162d267f981c20.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-04b718e5623574919c8b0dea5f301444.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-069e77aac84590e2e991d0a0176d34f2.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-06c77b8c66e51ed6c63ccb502dd8b8af.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-08e0dc436ad0ad61ba5558db0674d762.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-093b9ef39a46ceae95a1df18a0a3a326.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-095c169f3314805276f603a362766abd.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-09850c4077f3fffe707905872e0e2460.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-0986d134c05864f5025962eef9f994a0.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-0b5d723fdc4e249c140f0909e87d03b4.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-0f626226ba1272e832aea87bafd9720e.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-0f7fb1e0d5015bb1371343153ecf7ce3.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-0fa55a080fcd0f9dc2e0b0058b793df8.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-0facdf1ea213ba40261022f5d5ed4493.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-10a7ae9a371830a80c3d844acf1c02d7.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-112c051027b2d766c19a519f6ee1f4f7.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-11c345711937f0ba4b8f7b6b919c8440.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-12b52b58eb3df36804b9a654ec9ee194.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-13ae07ed2e272d26d59bc0691cd7117a.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-13d2887ec8ee73c43acdabc52a05af7b.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-145aa02cdd91946e67dc934e1acffe75.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-15dc6d811c9cd078f9086a740d5a1038.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-173945821411c09f70c95f98d590e697.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-1b611157cd46bb184d4fa4dae2d6a2b8.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-1e6fd68f1f3902ce48ce8c69df385622.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-1ee544f0f1dac422545c505baa788992.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-1fdc0c67ed57263a80fd108c1f6ccf24.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-203b0e569e3b14aac86a003dc3fa523e.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-20cc1bbf50e7efb442756cb605672c1f.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-20e7bf72fa05de9adf7dbcc7bf51dde6.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-21430ee05a1248901da8d0de08744d47.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-23686f7f29da6e8008c36dd3a80c83d6.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-23ad2d71b280f00b1363b95b7bea94eb.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-23f228f3999c01983860012330e4be08.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-24476a126f129212beb33f66853ea151.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-24a21c1e4449222e8d1898d69ff3a404.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-25b7f38e18f035f96cb5e547bd2bd08c.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-29cec36cd205b211da97acabaa62f055.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2a26d20a23b00898ce82f09d2ee47c3f.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2adbc89c11e65905393d3dfc468b9d5b.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2b7441d46298788ac94e610ffcc709b6.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2b77e8ebfb2367ab2662396a60e7d320.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2cf96d082d35ea3d8106851223ad0d16.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2d43040e86ff03ba677f6f9c04cd0805.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2e33e8dc771ef5e1d9127d60a6b73679.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-33432927cd87d40cfe393c7482bf221f.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-353f33792a8f60dc69323ddf635a269e.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-36925dfe329a45086cbb7fc5c20d45ac.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3717077e38f98d89eae729b6c14e56dc.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3756e81d3e149cf6099163ee79944fec.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-395c35dd584b56b0789f58a0559beaf1.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3c9de2ae0ea4bc91a510942dfa4be8d2.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3cc70dbb64df5b21f1326cc24dee2195.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3e1f8f654357353bf0e04ba5c34b5f7f.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3e63ed8162808a9e425ed80a8bc79114.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3eaa538115d76932653c21d8dc28f207.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4095eb84ef3874e2600247bee0b04026.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-41521fade99856108931b4768b1b2648.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-450da755d5bcb70906e1295e559b9602.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-452225341522a7942f0f6aab1a5c91a3.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4535823663ad81405188a528d8f2b1a2.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4806e761d750087c2d734fc64596eaff.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4a0fdb40036e87b40aa08dd30584cb85.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4a38cc3e9cf104e69ba246d37f8cf135.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4aca6a43e59aceee2166b0c7e4e85ef1.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4bfaa8ffa64c5ee560aa2daba7c9cbd3.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4dc6d5f188d5c96d44815cd1e81aa885.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4ddc14ed3eb0c3e46364317dfc0144a3.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4ee10ae43505e2e0bc62656ced49c0fa.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4f50e5136e136527280bc902c5817561.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-51502f1206be09c565f1547c406e9558.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-51a0e808bbc8361236ac521a119758a3.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-52a84a22fd1369bffeaf21da2d6158dc.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5330a2119a716e4e7224ed108b085dac.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-543fa46ace099a7099dad69123399400.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-544fc28abe2c5c30e62383fd4dac255f.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-54acdfc2166ad7fcbd074f75fd4a56ba.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5572b3513ba8df57a3d5d7303ee6b11b.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-56467a5c8840c4d23a60b2f935114848.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-56a32a7689abd0326e57c10c6c069bb4.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-57862b464a55b18c7bf234ce22907d73.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-583d166e56ba0de4b77eabb47ef67839.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5882ffa04f32584d26109137e2da4352.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-58fd02350d0bc52cf1ca3bb32ce9766e.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5935a5775af3d5c6307ac667bd9ae74e.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-59e9ff77b0efaf684bc09274fb6908c9.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5a1ce3117cfe90c48e8fb4a9a00f694d.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5a45d991244d4c7140217e1e5f5ca4f4.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5a7fac4b8b23a6e4e5ba0c9bf1756c91.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5b0ed6971aaab9c8ad563230bd5471a7.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5d2898fbc097a7e24c6f38d80587621e.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-603aefd23e350ba7eb124273e3c9bcf1.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-60a3089806700d379f11827ee9843b6b.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-60a41c7e1c68f22424e6d22df544bc82.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-642b26e2e5f5fb780b51b593dbc8c851.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-66493ba5a8367f2928812f446f47b56a.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-670ba603758d94268e8606f240a42e12.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-671a2c20b1eb9e4ef8a192833940e319.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-684d65f1793cac449dde5d59cb3c47fb.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-69c09cc5fa3e55c74fc4821f76909cc3.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-6ae5b42180ad70b971c91e7eefb8eba2.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-6e092f71c1e634059ada0e52abadce67.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-6f3256af8454371776bc46670d33cc65.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-6fe5c5973cc06f74b2387a631ea36b88.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-70c2eb8d64e71a42a834eb857ea9df51.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-70e811fd7994e61f408c923de6ddd078.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7197d6fda6cba7c3874c53d6381ca239.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-72252d73220fa3cd856677888cee1635.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-72536a3d71b694a0d53dd90ddceae41e.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-726303e0774b4e678bff8c2deb6ca603.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-733171b4ffcd17ea1fe1c0ba627173bf.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-739bc1a567439c7cffcd1614644593d2.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-73e309718fd16cea44b4d54a33581811.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7494dc504ae00ee9cd0505f990f88c5d.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-74e2263a91439c25b91d5132ce9f4d62.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-761d05e3cd968cf574166867998ef06a.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7718fe60986d8b42b1be9c5ace5ccf25.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-774d4f764a1299da5d28ec2f2ffe0d69.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-79d494361ae093b69e74ee9dbe65bfd4.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-79f007c1c6d07557120982951ea67998.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7a07ddc0f0c0f5f4a9bad6ee3dda66b5.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7ab2bed91166a9dca83a5ebfbe2a7f38.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7ccce86603f80a099ddb0cb21d4ae3e3.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7e4bde7e9c7f84cd34d8a845e384c746.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7e929f262f30c8ee78bf398150b1a7cd.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7eb9fffd1aa890d07d0f88cc82e6cfe4.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7f855356ab893b0d2b9c1c83b8116f0e.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-829615148e6357d826b9242eb7fbbd1e.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-866fa7613df6b3fd272bcfd4530c0bb9.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-87599f94b6cc129d505b375798d0d751.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-8c2f33cee3993174f7e87c28e4bf42ee.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-8d3bcabb847b56243b16afe62adaaf21.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-8de5b863cb50dfefdd07cb11c774d579.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-8e9f97f01034820170065b2921b4fb5e.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-8f476c4c99813d57cbe6eca4727388ad.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-903bb6865f3452e2fda42e3a25547bc5.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-91ddb2969bf2d31ba02ad82998d1314c.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-938d90c10ff8c20386af7f242c05d6b0.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-93fc8f28a33234bcadf1527cafabd502.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-95429962233afd82db1c27df1500a28c.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-9544732d2e62d1a429674f8ee41b5d3a.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-9592bfc861f07bcb8d75c196b370e548.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-95bfd249da4902577b4b7d76ebdd0b44.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-968cffdc8ee679da094e77ebf50f58ef.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-97f7f48ce90c9429bf32ae51469db74d.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-982b630266d87db93d2539affb1275c6.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-98f2ad84457de7f3740d9920b8fa8667.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-99a16ef6a64934d5781933dbd9c46b2e.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-9cfb2a77a4e45025105ad29a1748b90d.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-9d81066dd2b337c938df6e90380a00dc.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-9eb5a99df4e76ac3363453ac9ca288b1.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a004ddfcb26e67bd6e678c8ed19e25ce.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a0ca5df4258213d7fc9fce80f65ce760.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a1f916d6039285c4ffb900cd654e418f.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a203b91dad570bf05a58c3c3ddb529bf.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a365e82ed54697a52f27adcea1315fe8.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a4c34be6d42152e64b0df90bc4607f64.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a7accba310e821da5505f71c03b76bdb.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-aa0d470430e6391eca720c7cfa44446f.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-aa5c9ca6cf4fba00433b7aa3fa10671a.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-ac9ceb44437becc3e9c4dbfebab7fc2d.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b1220a3c61f85cc0408deedb4c5f57a2.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b358f7a51ece39a3247942b1feabdb29.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b57aaedfd8ebdf3931f25119dc6a5eb2.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b5c1596551c256e0e9cf02028595b092.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b6d128682ee29e471486354d486a1b90.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b6fd38ca30869792244804b04bc058da.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b7d203b051eff504ff59ddca7576b6a9.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b96d9226ce77ec94ceca043d712182e6.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-ba3de316d63c7e339987b16f41a0b879.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-bafff7a14c27403dcc6cf1432e8ea836.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-bd77e3c7f9e0b072d96af37f73d1aa32.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-be549ab72f0719d606a5c01e2c0219b6.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c16ed9740b85badf16e86ea782a3062f.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c1f94158256bb1f3bf665b053d895af9.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c40533fdf4cc57177b12803598af7e59.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c4a687ac4f0c2766eefc9f77ed99cddf.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c69f61a4ab18d0488c8d1fc12e7028e8.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c8b71798409ccc126ee264a00aadcf21.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c99eda15fc26a2941579560f76c3a5cf.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cb17fc3db95f6d139afc9d31a8e93293.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cbaaefaaf326668277aa24dfa93c4d28.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cd145ce4a0ea18469358df53c207bc1b.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cdbce89e82cc1ab53a2decbf5819278f.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-ce4884f96f11589608b76b726a755803.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cf2cc71752631e579e35b0e423bf2638.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cf6ff4e0f491ca0cf3038187a997b9b4.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cfb211578629b7e8153b37240de6a9d5.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-d0cf73942fea1c74edbdf0b3011f4656.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-d2666cbed13462c5dc36fa2f15c202ca.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-d3716376641d615e2995605b29bca7b6.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-dac48066b5883d8b4551fc584f0c2a3e.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-dbea1af6dcd9860be40c3d18254338f5.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e11567fd2accf9957cd0d3c2be937d87.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e2ead7ea7da0437f085f42ffc05f8d13.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e3fcf5180fd466c8915c4e8069491054.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e480d9c614742d05f0e78f274f1e69e6.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e4bca6cfa53e499cae0a6be4894a90e9.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e51ef413167c6e14e0c0fdcc585f2fc9.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e5f453bb04da18eed01675eeebd88bf8.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e656f091b9dc4709722c9f4b84d3c797.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-ec181b795ac1fb5a50d700b6e996d745.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-ee8bae97908d5147b423f77ad0d3c1bb.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-f0f13b5c60e0af5553bd359f5513be1b.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-f2b54d4e7be0eaefe1c2c56836fa5368.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-f56414bf9bced67990def8660e306759.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-f5d079153c99a25b9be5b8583c4cc8a7.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-f6032fc06eb20480f096199713f70885.woff2 +0 -0
- package/dist/web/fonts/Xiaolai/Xiaolai-Regular-f8ee5d36068a42b51d0e4a1116cfcec1.woff2 +0 -0
- package/dist/web/index.html +15 -0
- package/package.json +67 -4
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/** Claude session ids are UUIDs; anything else is never put into a command. */
|
|
2
|
+
export const SESSION_ID = /^[0-9a-f-]{36}$/i;
|
|
3
|
+
const LABEL_MAX = 40;
|
|
4
|
+
function resumeLabel(s) {
|
|
5
|
+
const title = s.title?.trim();
|
|
6
|
+
if (!title)
|
|
7
|
+
return s.repo;
|
|
8
|
+
const chars = [...title];
|
|
9
|
+
return chars.length <= LABEL_MAX ? title : chars.slice(0, LABEL_MAX - 1).join("") + "…";
|
|
10
|
+
}
|
|
11
|
+
/** Joins a Source with a PaneLink and fans the result out to subscribers. */
|
|
12
|
+
export function createHub({ source, panes }) {
|
|
13
|
+
let raw = [];
|
|
14
|
+
let current = [];
|
|
15
|
+
let serialized = "[]";
|
|
16
|
+
const listeners = new Set();
|
|
17
|
+
const cleanups = [];
|
|
18
|
+
const withPane = (s) => {
|
|
19
|
+
const pane = s.pid !== undefined ? panes.match(s.pid) : undefined;
|
|
20
|
+
const { pane: _old, ...rest } = s;
|
|
21
|
+
return pane ? { ...rest, pane } : rest;
|
|
22
|
+
};
|
|
23
|
+
function recompute() {
|
|
24
|
+
const next = raw.map(withPane);
|
|
25
|
+
const json = JSON.stringify(next);
|
|
26
|
+
if (json === serialized)
|
|
27
|
+
return;
|
|
28
|
+
current = next;
|
|
29
|
+
serialized = json;
|
|
30
|
+
for (const cb of listeners)
|
|
31
|
+
cb(current);
|
|
32
|
+
}
|
|
33
|
+
function setRaw(next) {
|
|
34
|
+
const ids = (l) => l.map((s) => `${s.id}:${s.pid}`).join(",");
|
|
35
|
+
const membershipChanged = ids(next) !== ids(raw);
|
|
36
|
+
raw = next;
|
|
37
|
+
recompute();
|
|
38
|
+
if (membershipChanged)
|
|
39
|
+
void panes.refresh?.().catch(() => { });
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
async start() {
|
|
43
|
+
raw = await source.list();
|
|
44
|
+
current = raw.map(withPane);
|
|
45
|
+
serialized = JSON.stringify(current);
|
|
46
|
+
cleanups.push(source.watch(setRaw));
|
|
47
|
+
cleanups.push(panes.onChange(recompute));
|
|
48
|
+
},
|
|
49
|
+
stop() {
|
|
50
|
+
for (const c of cleanups.splice(0))
|
|
51
|
+
c();
|
|
52
|
+
listeners.clear();
|
|
53
|
+
},
|
|
54
|
+
sessions: () => current,
|
|
55
|
+
subscribe(cb) {
|
|
56
|
+
listeners.add(cb);
|
|
57
|
+
return () => listeners.delete(cb);
|
|
58
|
+
},
|
|
59
|
+
async lookup(ids) {
|
|
60
|
+
const out = [];
|
|
61
|
+
for (const id of ids) {
|
|
62
|
+
const live = current.find((s) => s.id === id);
|
|
63
|
+
const found = live ?? (await source.get(id));
|
|
64
|
+
if (found)
|
|
65
|
+
out.push(live ? found : withPane(found));
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
},
|
|
69
|
+
async picker() {
|
|
70
|
+
const live = new Set(current.map((s) => s.id));
|
|
71
|
+
return (await source.listDormant()).filter((s) => !s.live && !live.has(s.id));
|
|
72
|
+
},
|
|
73
|
+
async resume(sessionId) {
|
|
74
|
+
if (!SESSION_ID.test(sessionId))
|
|
75
|
+
return "unknown";
|
|
76
|
+
if (current.some((s) => s.id === sessionId))
|
|
77
|
+
return "live";
|
|
78
|
+
const s = await source.get(sessionId);
|
|
79
|
+
if (!s)
|
|
80
|
+
return "unknown";
|
|
81
|
+
if (s.live)
|
|
82
|
+
return "live";
|
|
83
|
+
if (!panes.resume || !panes.available())
|
|
84
|
+
return "no-herdr";
|
|
85
|
+
await panes.resume({
|
|
86
|
+
cwd: s.cwd,
|
|
87
|
+
...(s.repoRoot !== undefined ? { repoRoot: s.repoRoot } : {}),
|
|
88
|
+
command: `claude --resume ${s.id}`,
|
|
89
|
+
label: resumeLabel(s),
|
|
90
|
+
});
|
|
91
|
+
return "resumed";
|
|
92
|
+
},
|
|
93
|
+
async focus(sessionId) {
|
|
94
|
+
const pane = current.find((s) => s.id === sessionId)?.pane;
|
|
95
|
+
if (!pane)
|
|
96
|
+
return false;
|
|
97
|
+
await panes.focus(pane.paneId);
|
|
98
|
+
return true;
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal herdr socket client (verified against herdr 0.9.0, protocol 22).
|
|
3
|
+
*
|
|
4
|
+
* Wire: newline-delimited JSON over a Unix stream socket.
|
|
5
|
+
* request {"id","method","params"}
|
|
6
|
+
* response {"id","result":{"type",...}} | {"id","error":{"code","message"}}
|
|
7
|
+
* event {"event":"pane_created","data":{"type":"pane_created",...}} (no id)
|
|
8
|
+
*
|
|
9
|
+
* herdr serves ONE request per connection: a second line on the same
|
|
10
|
+
* connection resets it, including on an events.subscribe connection. So this
|
|
11
|
+
* client keeps one long-lived subscription connection (events, reconnect with
|
|
12
|
+
* backoff, `connected()`), and opens a short connection per request.
|
|
13
|
+
* Malformed requests get an error with id "" — on a one-shot connection any
|
|
14
|
+
* reply is ours, so it is accepted.
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync } from "node:fs";
|
|
17
|
+
import net from "node:net";
|
|
18
|
+
export class HerdrError extends Error {
|
|
19
|
+
code;
|
|
20
|
+
constructor(code, message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = "HerdrError";
|
|
23
|
+
this.code = code;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Parse one wire line; undefined for blank or unrecognised lines. */
|
|
27
|
+
export function parseLine(line) {
|
|
28
|
+
let msg;
|
|
29
|
+
try {
|
|
30
|
+
msg = JSON.parse(line);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
if (!msg || typeof msg !== "object")
|
|
36
|
+
return undefined;
|
|
37
|
+
const m = msg;
|
|
38
|
+
if (m.error && typeof m.error === "object") {
|
|
39
|
+
const e = m.error;
|
|
40
|
+
return { kind: "error", id: String(m.id ?? ""), code: String(e.code ?? "unknown"), message: String(e.message ?? "") };
|
|
41
|
+
}
|
|
42
|
+
if ("result" in m)
|
|
43
|
+
return { kind: "response", id: String(m.id ?? ""), result: m.result };
|
|
44
|
+
if (typeof m.event === "string") {
|
|
45
|
+
const data = m.data && typeof m.data === "object" ? m.data : {};
|
|
46
|
+
return { kind: "event", event: { event: m.event, data } };
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
const defaultConnect = (p) => net.createConnection(p);
|
|
51
|
+
function onLines(sock, cb) {
|
|
52
|
+
let buf = "";
|
|
53
|
+
sock.setEncoding("utf8");
|
|
54
|
+
sock.on("data", (chunk) => {
|
|
55
|
+
buf += chunk;
|
|
56
|
+
let i;
|
|
57
|
+
while ((i = buf.indexOf("\n")) >= 0) {
|
|
58
|
+
const line = buf.slice(0, i);
|
|
59
|
+
buf = buf.slice(i + 1);
|
|
60
|
+
if (line.trim())
|
|
61
|
+
cb(line);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
let seq = 0;
|
|
66
|
+
const nextId = (prefix) => `${prefix}-${process.pid}-${++seq}`;
|
|
67
|
+
/** One request on its own connection. Never throws synchronously. */
|
|
68
|
+
export function herdrRequest(socketPath, method, params = {}, opts = {}) {
|
|
69
|
+
const { timeoutMs = 5000, connect = defaultConnect } = opts;
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
if (!existsSync(socketPath)) {
|
|
72
|
+
reject(new HerdrError("unavailable", `herdr socket not found: ${socketPath}`));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const id = nextId("ea");
|
|
76
|
+
let sock;
|
|
77
|
+
try {
|
|
78
|
+
sock = connect(socketPath);
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
reject(new HerdrError("unavailable", String(e)));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const untrack = opts.track?.(sock);
|
|
85
|
+
let done = false;
|
|
86
|
+
const finish = (err, value) => {
|
|
87
|
+
if (done)
|
|
88
|
+
return;
|
|
89
|
+
done = true;
|
|
90
|
+
clearTimeout(timer);
|
|
91
|
+
untrack?.();
|
|
92
|
+
sock.destroy();
|
|
93
|
+
if (err)
|
|
94
|
+
reject(err);
|
|
95
|
+
else
|
|
96
|
+
resolve(value);
|
|
97
|
+
};
|
|
98
|
+
const timer = setTimeout(() => finish(new HerdrError("timeout", `${method} timed out after ${timeoutMs} ms`)), timeoutMs);
|
|
99
|
+
sock.on("error", (e) => finish(new HerdrError("unavailable", `${method}: ${e.code ?? e.message}`)));
|
|
100
|
+
sock.on("close", () => finish(new HerdrError("closed", `${method}: connection closed without a reply`)));
|
|
101
|
+
onLines(sock, (line) => {
|
|
102
|
+
const msg = parseLine(line);
|
|
103
|
+
if (!msg || msg.kind === "event")
|
|
104
|
+
return;
|
|
105
|
+
if (msg.id !== id && msg.id !== "")
|
|
106
|
+
return;
|
|
107
|
+
if (msg.kind === "error")
|
|
108
|
+
finish(new HerdrError(msg.code, msg.message));
|
|
109
|
+
else
|
|
110
|
+
finish(undefined, msg.result);
|
|
111
|
+
});
|
|
112
|
+
sock.write(JSON.stringify({ id, method, params }) + "\n");
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
export function createHerdrClient(opts) {
|
|
116
|
+
const { socketPath, requestTimeoutMs = 5000, retryMinMs = 250, retryMaxMs = 5000 } = opts;
|
|
117
|
+
const connect = opts.connect ?? defaultConnect;
|
|
118
|
+
let closed = false;
|
|
119
|
+
let isConnected = false;
|
|
120
|
+
let sub;
|
|
121
|
+
let retryTimer;
|
|
122
|
+
let delay = retryMinMs;
|
|
123
|
+
const inflight = new Set();
|
|
124
|
+
const scheduleRetry = () => {
|
|
125
|
+
if (closed || retryTimer)
|
|
126
|
+
return;
|
|
127
|
+
retryTimer = setTimeout(() => {
|
|
128
|
+
retryTimer = undefined;
|
|
129
|
+
start();
|
|
130
|
+
}, delay);
|
|
131
|
+
retryTimer.unref?.();
|
|
132
|
+
delay = Math.min(delay * 2, retryMaxMs);
|
|
133
|
+
};
|
|
134
|
+
const start = () => {
|
|
135
|
+
if (closed)
|
|
136
|
+
return;
|
|
137
|
+
if (!existsSync(socketPath)) {
|
|
138
|
+
scheduleRetry();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
let sock;
|
|
142
|
+
try {
|
|
143
|
+
sock = connect(socketPath);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
scheduleRetry();
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
sub = sock;
|
|
150
|
+
const subId = nextId("ea-sub");
|
|
151
|
+
let acked = false;
|
|
152
|
+
sock.on("error", () => { });
|
|
153
|
+
sock.on("close", () => {
|
|
154
|
+
if (sub === sock)
|
|
155
|
+
sub = undefined;
|
|
156
|
+
const was = isConnected && acked;
|
|
157
|
+
if (acked)
|
|
158
|
+
isConnected = false;
|
|
159
|
+
if (was)
|
|
160
|
+
opts.onDisconnect?.();
|
|
161
|
+
scheduleRetry();
|
|
162
|
+
});
|
|
163
|
+
onLines(sock, (line) => {
|
|
164
|
+
const msg = parseLine(line);
|
|
165
|
+
if (!msg)
|
|
166
|
+
return;
|
|
167
|
+
if (msg.kind === "event") {
|
|
168
|
+
if (msg.event.event === "events_lost")
|
|
169
|
+
opts.onEventsLost?.();
|
|
170
|
+
else
|
|
171
|
+
opts.onEvent?.(msg.event);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (msg.kind === "error") {
|
|
175
|
+
if (msg.code === "events_lost")
|
|
176
|
+
opts.onEventsLost?.();
|
|
177
|
+
else if (!acked)
|
|
178
|
+
sock.destroy(); // subscribe rejected: retry later
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (!acked && (msg.id === subId || msg.id === "")) {
|
|
182
|
+
acked = true;
|
|
183
|
+
isConnected = true;
|
|
184
|
+
delay = retryMinMs;
|
|
185
|
+
opts.onConnect?.();
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
sock.write(JSON.stringify({ id: subId, method: "events.subscribe", params: { subscriptions: opts.subscriptions } }) + "\n");
|
|
189
|
+
};
|
|
190
|
+
start();
|
|
191
|
+
return {
|
|
192
|
+
request(method, params = {}) {
|
|
193
|
+
if (closed)
|
|
194
|
+
return Promise.reject(new HerdrError("closed", "herdr client closed"));
|
|
195
|
+
return herdrRequest(socketPath, method, params, {
|
|
196
|
+
timeoutMs: requestTimeoutMs,
|
|
197
|
+
connect,
|
|
198
|
+
track: (s) => {
|
|
199
|
+
inflight.add(s);
|
|
200
|
+
return () => inflight.delete(s);
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
},
|
|
204
|
+
connected: () => isConnected && !closed,
|
|
205
|
+
close() {
|
|
206
|
+
if (closed)
|
|
207
|
+
return;
|
|
208
|
+
closed = true;
|
|
209
|
+
isConnected = false;
|
|
210
|
+
if (retryTimer)
|
|
211
|
+
clearTimeout(retryTimer);
|
|
212
|
+
retryTimer = undefined;
|
|
213
|
+
sub?.destroy();
|
|
214
|
+
sub = undefined;
|
|
215
|
+
for (const s of inflight)
|
|
216
|
+
s.destroy();
|
|
217
|
+
inflight.clear();
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find herdr client processes (the TUI attached to a herdr server) by
|
|
3
|
+
* scanning /proc: comm "herdr" and no "server" argument. Clients whose socket
|
|
4
|
+
* (HERDR_SOCKET_PATH, else ~/.config/herdr/herdr.sock under their HOME) is
|
|
5
|
+
* ours are returned. Clients whose socket cannot be read are a fallback only
|
|
6
|
+
* when none match; a client known to be on another server is never returned.
|
|
7
|
+
*/
|
|
8
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
async function read(path) {
|
|
11
|
+
try {
|
|
12
|
+
return await readFile(path, "utf8");
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export async function findHerdrClientPids(opts) {
|
|
19
|
+
const procRoot = opts.procRoot ?? "/proc";
|
|
20
|
+
let entries;
|
|
21
|
+
try {
|
|
22
|
+
entries = await readdir(procRoot);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
const unknown = [];
|
|
28
|
+
const ours = [];
|
|
29
|
+
await Promise.all(entries
|
|
30
|
+
.filter((e) => /^\d+$/.test(e))
|
|
31
|
+
.map(async (e) => {
|
|
32
|
+
const dir = join(procRoot, e);
|
|
33
|
+
if ((await read(join(dir, "comm")))?.trim() !== "herdr")
|
|
34
|
+
return;
|
|
35
|
+
const argv = (await read(join(dir, "cmdline")))?.split("\0").filter(Boolean) ?? [];
|
|
36
|
+
if (argv.slice(1).includes("server"))
|
|
37
|
+
return;
|
|
38
|
+
const pid = Number(e);
|
|
39
|
+
const environ = await read(join(dir, "environ"));
|
|
40
|
+
if (environ === undefined) {
|
|
41
|
+
unknown.push(pid);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const env = new Map();
|
|
45
|
+
for (const kv of environ.split("\0")) {
|
|
46
|
+
const i = kv.indexOf("=");
|
|
47
|
+
if (i > 0)
|
|
48
|
+
env.set(kv.slice(0, i), kv.slice(i + 1));
|
|
49
|
+
}
|
|
50
|
+
const home = env.get("HOME");
|
|
51
|
+
const sock = env.get("HERDR_SOCKET_PATH") || (home ? join(home, ".config/herdr/herdr.sock") : undefined);
|
|
52
|
+
if (sock === undefined)
|
|
53
|
+
unknown.push(pid);
|
|
54
|
+
else if (sock === opts.socketPath)
|
|
55
|
+
ours.push(pid);
|
|
56
|
+
}));
|
|
57
|
+
return (ours.length > 0 ? ours : unknown).sort((a, b) => a - b);
|
|
58
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* herdr pane link: pid → pane map built from pane.list + pane.process_info.
|
|
3
|
+
* Rebuilt on pane events, on (re)connect, on events_lost (herdr 0.9.2+), every
|
|
4
|
+
* `resyncMs` (0.9.0 has no events_lost), and on refresh(). Never throws when
|
|
5
|
+
* herdr is absent: available() is false and the socket is retried.
|
|
6
|
+
*/
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import { basename, join } from "node:path";
|
|
9
|
+
import { createHerdrClient, HerdrError } from "./herdr-client.js";
|
|
10
|
+
import { findHerdrClientPids } from "./herdr-clients.js";
|
|
11
|
+
export { createNoPaneLink } from "./none.js";
|
|
12
|
+
export const HERDR_SUBSCRIPTIONS = [
|
|
13
|
+
{ type: "pane.created" },
|
|
14
|
+
{ type: "pane.closed" },
|
|
15
|
+
{ type: "pane.exited" },
|
|
16
|
+
{ type: "pane.agent_detected" },
|
|
17
|
+
// Labels shown on cards: rebuild when they appear, change or go away.
|
|
18
|
+
{ type: "workspace.created" },
|
|
19
|
+
{ type: "workspace.renamed" },
|
|
20
|
+
{ type: "workspace.closed" },
|
|
21
|
+
{ type: "tab.created" },
|
|
22
|
+
{ type: "tab.renamed" },
|
|
23
|
+
{ type: "tab.closed" },
|
|
24
|
+
];
|
|
25
|
+
/** Every method this link sends (tests check them against the schema). */
|
|
26
|
+
export const HERDR_METHODS = [
|
|
27
|
+
"events.subscribe",
|
|
28
|
+
"pane.list",
|
|
29
|
+
"pane.process_info",
|
|
30
|
+
"pane.focus",
|
|
31
|
+
"workspace.list",
|
|
32
|
+
"tab.list",
|
|
33
|
+
"tab.create",
|
|
34
|
+
"workspace.create",
|
|
35
|
+
"pane.send_text",
|
|
36
|
+
];
|
|
37
|
+
/** True when path is dir or inside it (separator boundary: /a/b is not inside /a/bc). */
|
|
38
|
+
export function isInside(path, dir) {
|
|
39
|
+
const d = dir.length > 1 ? dir.replace(/\/+$/, "") : dir;
|
|
40
|
+
return path === d || path.startsWith(d === "/" ? "/" : d + "/");
|
|
41
|
+
}
|
|
42
|
+
/** Workspace showing root: the focused pane's workspace if it matches, else the first match. */
|
|
43
|
+
export function pickWorkspace(panes, root) {
|
|
44
|
+
const matches = panes.filter((p) => [p.cwd, p.foreground_cwd].some((c) => typeof c === "string" && isInside(c, root)));
|
|
45
|
+
const pick = matches.find((p) => p.focused) ?? matches[0];
|
|
46
|
+
return pick ? (pick.workspace_id ?? workspaceOf(pick.pane_id)) : undefined;
|
|
47
|
+
}
|
|
48
|
+
export function defaultHerdrSocketPath() {
|
|
49
|
+
return process.env.HERDR_SOCKET_PATH || join(homedir(), ".config/herdr/herdr.sock");
|
|
50
|
+
}
|
|
51
|
+
const workspaceOf = (paneId) => paneId.split(":")[0] ?? paneId;
|
|
52
|
+
/** pid → pane for every foreground process of every pane; `panes` supplies ids and labels. */
|
|
53
|
+
export function parsePaneMap(infos, panes = new Map()) {
|
|
54
|
+
const map = new Map();
|
|
55
|
+
for (const info of infos) {
|
|
56
|
+
const pane = panes.get(info.pane_id) ?? { paneId: info.pane_id, workspaceId: workspaceOf(info.pane_id) };
|
|
57
|
+
for (const p of info.foreground_processes ?? []) {
|
|
58
|
+
if (typeof p.pid === "number")
|
|
59
|
+
map.set(p.pid, pane);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return map;
|
|
63
|
+
}
|
|
64
|
+
function sameMap(a, b) {
|
|
65
|
+
if (a.size !== b.size)
|
|
66
|
+
return false;
|
|
67
|
+
for (const [pid, pane] of a) {
|
|
68
|
+
const other = b.get(pid);
|
|
69
|
+
if (!other ||
|
|
70
|
+
other.paneId !== pane.paneId ||
|
|
71
|
+
other.workspaceId !== pane.workspaceId ||
|
|
72
|
+
other.workspaceLabel !== pane.workspaceLabel ||
|
|
73
|
+
other.tabLabel !== pane.tabLabel) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
export function createHerdrLink(opts = {}) {
|
|
80
|
+
const { resyncMs = 30_000 } = opts;
|
|
81
|
+
const socketPath = opts.socketPath ?? defaultHerdrSocketPath();
|
|
82
|
+
const clientPids = () => findHerdrClientPids({ socketPath, procRoot: opts.procRoot });
|
|
83
|
+
let map = new Map();
|
|
84
|
+
const listeners = new Set();
|
|
85
|
+
let closed = false;
|
|
86
|
+
const setMap = (next) => {
|
|
87
|
+
if (sameMap(map, next))
|
|
88
|
+
return;
|
|
89
|
+
map = next;
|
|
90
|
+
for (const cb of [...listeners]) {
|
|
91
|
+
try {
|
|
92
|
+
cb();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// a listener's failure must not break the link
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const client = createHerdrClient({
|
|
100
|
+
socketPath,
|
|
101
|
+
subscriptions: HERDR_SUBSCRIPTIONS,
|
|
102
|
+
requestTimeoutMs: opts.requestTimeoutMs,
|
|
103
|
+
retryMinMs: opts.retryMinMs,
|
|
104
|
+
retryMaxMs: opts.retryMaxMs,
|
|
105
|
+
connect: opts.connect,
|
|
106
|
+
onConnect: () => void rebuild(),
|
|
107
|
+
onEvent: () => void rebuild(),
|
|
108
|
+
onEventsLost: () => void rebuild(),
|
|
109
|
+
onDisconnect: () => setMap(new Map()),
|
|
110
|
+
});
|
|
111
|
+
/** id → label from workspace.list / tab.list; empty when the call fails (labels are optional). */
|
|
112
|
+
async function labels(method, key, id) {
|
|
113
|
+
try {
|
|
114
|
+
const res = (await client.request(method, {}));
|
|
115
|
+
const out = new Map();
|
|
116
|
+
for (const item of res[key] ?? []) {
|
|
117
|
+
const k = item[id];
|
|
118
|
+
if (typeof k === "string" && typeof item.label === "string")
|
|
119
|
+
out.set(k, item.label);
|
|
120
|
+
}
|
|
121
|
+
return out;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return new Map();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async function build() {
|
|
128
|
+
let list;
|
|
129
|
+
const wsLabels = labels("workspace.list", "workspaces", "workspace_id");
|
|
130
|
+
const tabLabels = labels("tab.list", "tabs", "tab_id");
|
|
131
|
+
try {
|
|
132
|
+
const res = (await client.request("pane.list", {}));
|
|
133
|
+
list = res.panes ?? [];
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return; // keep the current map; the next event/timer/reconnect retries
|
|
137
|
+
}
|
|
138
|
+
const [ws, tabs] = await Promise.all([wsLabels, tabLabels]);
|
|
139
|
+
const panes = new Map();
|
|
140
|
+
for (const p of list) {
|
|
141
|
+
const pane = { paneId: p.pane_id, workspaceId: p.workspace_id ?? workspaceOf(p.pane_id) };
|
|
142
|
+
const wl = ws.get(pane.workspaceId);
|
|
143
|
+
const tl = p.tab_id !== undefined ? tabs.get(p.tab_id) : undefined;
|
|
144
|
+
if (wl !== undefined)
|
|
145
|
+
pane.workspaceLabel = wl;
|
|
146
|
+
if (tl !== undefined)
|
|
147
|
+
pane.tabLabel = tl;
|
|
148
|
+
panes.set(p.pane_id, pane);
|
|
149
|
+
}
|
|
150
|
+
const panesList = list;
|
|
151
|
+
const infos = await Promise.all(panesList.map(async (p) => {
|
|
152
|
+
try {
|
|
153
|
+
const res = (await client.request("pane.process_info", { pane_id: p.pane_id }));
|
|
154
|
+
return res.process_info;
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return undefined; // pane vanished or herdr hiccuped: skip it
|
|
158
|
+
}
|
|
159
|
+
}));
|
|
160
|
+
if (closed || !client.connected())
|
|
161
|
+
return;
|
|
162
|
+
setMap(parsePaneMap(infos.filter((i) => !!i), panes));
|
|
163
|
+
}
|
|
164
|
+
// Coalesce: at most one build running, plus one queued behind it.
|
|
165
|
+
let running;
|
|
166
|
+
let queued;
|
|
167
|
+
function rebuild() {
|
|
168
|
+
if (closed || !client.connected())
|
|
169
|
+
return Promise.resolve();
|
|
170
|
+
if (!running) {
|
|
171
|
+
running = build().finally(() => {
|
|
172
|
+
running = undefined;
|
|
173
|
+
});
|
|
174
|
+
return running;
|
|
175
|
+
}
|
|
176
|
+
queued ??= running.then(() => {
|
|
177
|
+
queued = undefined;
|
|
178
|
+
return rebuild();
|
|
179
|
+
});
|
|
180
|
+
return queued;
|
|
181
|
+
}
|
|
182
|
+
const timer = setInterval(() => void rebuild(), resyncMs);
|
|
183
|
+
timer.unref?.();
|
|
184
|
+
const pending = new Set();
|
|
185
|
+
async function raise() {
|
|
186
|
+
if (!opts.desktop)
|
|
187
|
+
return;
|
|
188
|
+
try {
|
|
189
|
+
await opts.desktop.raise(await clientPids());
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// raising the window is best effort
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
available: () => !closed && client.connected(),
|
|
197
|
+
match: (pid) => map.get(pid),
|
|
198
|
+
async focus(paneId) {
|
|
199
|
+
if (closed || !client.connected())
|
|
200
|
+
return;
|
|
201
|
+
await client.request("pane.focus", { pane_id: paneId });
|
|
202
|
+
await raise();
|
|
203
|
+
},
|
|
204
|
+
async resume(req) {
|
|
205
|
+
if (closed || !client.connected())
|
|
206
|
+
throw new HerdrError("unavailable", "herdr is not connected");
|
|
207
|
+
const root = req.repoRoot ?? req.cwd;
|
|
208
|
+
const { panes = [] } = (await client.request("pane.list", {}));
|
|
209
|
+
const workspaceId = pickWorkspace(panes, root);
|
|
210
|
+
const created = (workspaceId !== undefined
|
|
211
|
+
? await client.request("tab.create", { workspace_id: workspaceId, cwd: req.cwd, label: req.label, focus: true })
|
|
212
|
+
: await client.request("workspace.create", { cwd: req.cwd, label: basename(root) || root, focus: true }));
|
|
213
|
+
const paneId = created.root_pane?.pane_id;
|
|
214
|
+
if (typeof paneId !== "string")
|
|
215
|
+
throw new HerdrError("bad_response", "herdr did not return the new pane");
|
|
216
|
+
// A fresh shell buffers typed input until it is ready (checked on herdr 0.9.0 with sh and a slow zsh).
|
|
217
|
+
await client.request("pane.send_text", { pane_id: paneId, text: req.command + "\n" });
|
|
218
|
+
await raise();
|
|
219
|
+
const t = setTimeout(() => {
|
|
220
|
+
pending.delete(t);
|
|
221
|
+
void rebuild();
|
|
222
|
+
}, opts.resumeRefreshMs ?? 1500);
|
|
223
|
+
t.unref?.();
|
|
224
|
+
pending.add(t);
|
|
225
|
+
return { paneId };
|
|
226
|
+
},
|
|
227
|
+
clientPids,
|
|
228
|
+
onChange(cb) {
|
|
229
|
+
listeners.add(cb);
|
|
230
|
+
return () => listeners.delete(cb);
|
|
231
|
+
},
|
|
232
|
+
refresh: rebuild,
|
|
233
|
+
close() {
|
|
234
|
+
if (closed)
|
|
235
|
+
return;
|
|
236
|
+
closed = true;
|
|
237
|
+
clearInterval(timer);
|
|
238
|
+
for (const t of pending)
|
|
239
|
+
clearTimeout(t);
|
|
240
|
+
pending.clear();
|
|
241
|
+
client.close();
|
|
242
|
+
listeners.clear();
|
|
243
|
+
map = new Map();
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** PaneLink for when herdr is disabled: never available, does nothing. */
|
|
2
|
+
export function createNoPaneLink() {
|
|
3
|
+
return {
|
|
4
|
+
available: () => false,
|
|
5
|
+
match: () => undefined,
|
|
6
|
+
focus: async () => { },
|
|
7
|
+
onChange: () => () => { },
|
|
8
|
+
close: () => { },
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|