excaliagent 0.1.0 → 0.2.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.
Files changed (359) hide show
  1. package/README.md +18 -2
  2. package/dist/server/args.js +1 -0
  3. package/dist/server/cli.js +4 -3
  4. package/dist/server/desktop/desktop.js +106 -64
  5. package/dist/server/desktop/exec.js +27 -0
  6. package/dist/server/desktop/process-table.js +167 -0
  7. package/dist/server/panes/herdr-clients.js +28 -49
  8. package/dist/server/panes/herdr.js +5 -3
  9. package/dist/web/assets/{abnfDiagram-VCTEODGH-lVjPevGa.js → abnfDiagram-VCTEODGH-tmjYj3VY.js} +1 -1
  10. package/dist/web/assets/{ar-SA-G6X2FPQ2-CD5aVmDx.js → ar-SA-G6X2FPQ2-8ZGGBDRT.js} +1 -1
  11. package/dist/web/assets/{architecture-7GRP2DOG-9pDjotLm.js → architecture-7GRP2DOG-CsvDkWt3.js} +1 -1
  12. package/dist/web/assets/{architectureDiagram-5GKGNRK7-D0Yl-_Yc.js → architectureDiagram-5GKGNRK7-Bq-1CDhU.js} +1 -1
  13. package/dist/web/assets/{az-AZ-76LH7QW2-D4vT9Alz.js → az-AZ-76LH7QW2-DbdS_q-w.js} +1 -1
  14. package/dist/web/assets/{bg-BG-XCXSNQG7-MMTI5wg3.js → bg-BG-XCXSNQG7-CANqXhG1.js} +1 -1
  15. package/dist/web/assets/{blockDiagram-I7D4REHJ-DhrilPMV.js → blockDiagram-I7D4REHJ-DtYn-xOl.js} +1 -1
  16. package/dist/web/assets/{bn-BD-2XOGV67Q-CCHqTpZW.js → bn-BD-2XOGV67Q-DJdq0B1R.js} +1 -1
  17. package/dist/web/assets/{c4Diagram-7LVT6UL2-DGXbRPw_.js → c4Diagram-7LVT6UL2-DW6Pzj1e.js} +1 -1
  18. package/dist/web/assets/{ca-ES-6MX7JW3Y-ChGGIAut.js → ca-ES-6MX7JW3Y-B7pUqerV.js} +1 -1
  19. package/dist/web/assets/channel-gFr9jEgP.js +1 -0
  20. package/dist/web/assets/{chunk-4HAMMTFA-Cw9s83q8.js → chunk-4HAMMTFA-_AKNu1--.js} +1 -1
  21. package/dist/web/assets/{chunk-75Z2AOVW-BC0CaRUB.js → chunk-75Z2AOVW-BoMl8Mqw.js} +1 -1
  22. package/dist/web/assets/{chunk-DU6HZSFF-W9nFVr4b.js → chunk-DU6HZSFF-DYHa8ENH.js} +1 -1
  23. package/dist/web/assets/{chunk-EIO257PC-DG_y2xQ1.js → chunk-EIO257PC--adgQBo2.js} +1 -1
  24. package/dist/web/assets/{chunk-F27PBJKO-yfVK-Hr6.js → chunk-F27PBJKO-CvQi01qZ.js} +1 -1
  25. package/dist/web/assets/{chunk-GMAD6QVW-C2Qn052r.js → chunk-GMAD6QVW-ojaxPuMG.js} +1 -1
  26. package/dist/web/assets/{chunk-GVQU2GXP-IFaX5U4g.js → chunk-GVQU2GXP-DYAeD1IL.js} +1 -1
  27. package/dist/web/assets/{chunk-IMKFNOWR-M1ZEBqas.js → chunk-IMKFNOWR-oVPWqbpV.js} +1 -1
  28. package/dist/web/assets/{chunk-L3NEJ4N5-oLQiZ5i-.js → chunk-L3NEJ4N5-BelAXiIN.js} +1 -1
  29. package/dist/web/assets/{chunk-OSK3NFVY-D-OfNZzS.js → chunk-OSK3NFVY-CATtjN8l.js} +1 -1
  30. package/dist/web/assets/{chunk-P2QGCYS3-DJerQdnp.js → chunk-P2QGCYS3-CbKPCENJ.js} +1 -1
  31. package/dist/web/assets/{chunk-POPQ4Y6H-BC0OyYJc.js → chunk-POPQ4Y6H-BfOCSezn.js} +1 -1
  32. package/dist/web/assets/{chunk-PWAF6VOD-CjU6T4Vk.js → chunk-PWAF6VOD-C7O-JWJt.js} +1 -1
  33. package/dist/web/assets/{chunk-SHT3W25Y-DBMa5yhK.js → chunk-SHT3W25Y-BfEpPCTX.js} +1 -1
  34. package/dist/web/assets/{chunk-SVP7TREG-Bbvoxr5d.js → chunk-SVP7TREG-CaeKcCSu.js} +1 -1
  35. package/dist/web/assets/{chunk-TICWLB2K-DIPq7Qti.js → chunk-TICWLB2K-Bx6AcLB_.js} +1 -1
  36. package/dist/web/assets/classDiagram-ZZMXUADV-9J2CNLBI.js +1 -0
  37. package/dist/web/assets/classDiagram-v2-VYDZK3BY-9J2CNLBI.js +1 -0
  38. package/dist/web/assets/{cs-CZ-2BRQDIVT-Bax3wFiz.js → cs-CZ-2BRQDIVT-DF8hZ2mh.js} +1 -1
  39. package/dist/web/assets/{cynefin-OW5HDTMX-y_XDTnaT.js → cynefin-OW5HDTMX-Dol6Weuo.js} +1 -1
  40. package/dist/web/assets/{cynefinDiagram-5FMLGOSQ-BeJtQvjE.js → cynefinDiagram-5FMLGOSQ-CbOJ2lks.js} +1 -1
  41. package/dist/web/assets/{da-DK-5WZEPLOC-i66Qepbp.js → da-DK-5WZEPLOC-CgPdNz6E.js} +1 -1
  42. package/dist/web/assets/{dagre-GXQ25YYZ-CzBP3X6H.js → dagre-GXQ25YYZ-CcuaBID7.js} +1 -1
  43. package/dist/web/assets/{de-DE-XR44H4JA-yjhmbrBK.js → de-DE-XR44H4JA-DaVeYWRc.js} +1 -1
  44. package/dist/web/assets/{diagram-S7CK7UJ4-CL5OmME1.js → diagram-S7CK7UJ4-BR2gIsNx.js} +1 -1
  45. package/dist/web/assets/{diagram-UQ7AKVKN-6_lscQb4.js → diagram-UQ7AKVKN-DwSZsV-Z.js} +1 -1
  46. package/dist/web/assets/{diagram-VSXAHHWV-C3E4-nJG.js → diagram-VSXAHHWV-BcJpQHbj.js} +1 -1
  47. package/dist/web/assets/{diagram-VX7I27RA-51lQ_NN2.js → diagram-VX7I27RA-CvjRTkwu.js} +1 -1
  48. package/dist/web/assets/{diagram-Z3DM3KII-D86k1y9Z.js → diagram-Z3DM3KII-vg0-r_P4.js} +1 -1
  49. package/dist/web/assets/{dist-BPnbDAwD.js → dist-D-3cz42D.js} +4 -4
  50. package/dist/web/assets/{ebnfDiagram-PWID7BFC-DDjKtPWY.js → ebnfDiagram-PWID7BFC-DZCaMmMd.js} +1 -1
  51. package/dist/web/assets/{el-GR-BZB4AONW-Deizd0yM.js → el-GR-BZB4AONW-nYncjO-L.js} +1 -1
  52. package/dist/web/assets/{en-B4ZKOASM-Dvqqxrua.js → en-B4ZKOASM-DqIz0rJz.js} +1 -1
  53. package/dist/web/assets/{erDiagram-RLTQ6QDP-Dju3XIzd.js → erDiagram-RLTQ6QDP-DgyrjoaZ.js} +1 -1
  54. package/dist/web/assets/{es-ES-U4NZUMDT-Bz7tNFv9.js → es-ES-U4NZUMDT-e3WeRDLl.js} +1 -1
  55. package/dist/web/assets/{eu-ES-A7QVB2H4-B3BHiHTa.js → eu-ES-A7QVB2H4-CwXv1t13.js} +1 -1
  56. package/dist/web/assets/{eventmodeling-NTZA5JFV-MeBWwPID.js → eventmodeling-NTZA5JFV-DCTWpAwP.js} +1 -1
  57. package/dist/web/assets/{fa-IR-HGAKTJCU-B9t2EOWw.js → fa-IR-HGAKTJCU-D-9plwKu.js} +1 -1
  58. package/dist/web/assets/{fi-FI-Z5N7JZ37-BRW-fC7d.js → fi-FI-Z5N7JZ37-BTK1rs8G.js} +1 -1
  59. package/dist/web/assets/flowDiagram-HODETNUW--2QUGuZ7.js +1 -0
  60. package/dist/web/assets/{fr-FR-RHASNOE6-C1x7RIuS.js → fr-FR-RHASNOE6-CAuUMPtN.js} +1 -1
  61. package/dist/web/assets/{ganttDiagram-EL5Y4UJY-CUQyfHZV.js → ganttDiagram-EL5Y4UJY-bFfu4BMj.js} +1 -1
  62. package/dist/web/assets/{gitGraph-4MIJSDKK-77imLp1D.js → gitGraph-4MIJSDKK-DIl4-oqK.js} +1 -1
  63. package/dist/web/assets/{gitGraphDiagram-WWUBYQGX-CC4ZOu_u.js → gitGraphDiagram-WWUBYQGX-ho3FT8XP.js} +1 -1
  64. package/dist/web/assets/{gl-ES-HMX3MZ6V-DSChLEXM.js → gl-ES-HMX3MZ6V-DlKPdjtk.js} +1 -1
  65. package/dist/web/assets/{he-IL-6SHJWFNN-DqrJHras.js → he-IL-6SHJWFNN-CLyP0zBo.js} +1 -1
  66. package/dist/web/assets/{hi-IN-IWLTKZ5I-scDn95Bz.js → hi-IN-IWLTKZ5I-kvhBHNzH.js} +1 -1
  67. package/dist/web/assets/{hu-HU-A5ZG7DT2-2BB7ywaE.js → hu-HU-A5ZG7DT2-Dtd-o-RJ.js} +1 -1
  68. package/dist/web/assets/{id-ID-SAP4L64H-BCD-rITt.js → id-ID-SAP4L64H-VZ3IV-8B.js} +1 -1
  69. package/dist/web/assets/{image-GAAHSSAO-BHEttEFL.js → image-GAAHSSAO-DWvjHHd3.js} +1 -1
  70. package/dist/web/assets/{index-C6RFmwp_.js → index-B2hGCC2V.js} +13 -13
  71. package/dist/web/assets/{info-A6RAGUB7-Ee6NHVyn.js → info-A6RAGUB7-DN8pwhKt.js} +1 -1
  72. package/dist/web/assets/{infoDiagram-27XIBGKW-bwB50WOT.js → infoDiagram-27XIBGKW-i2JHBJKe.js} +1 -1
  73. package/dist/web/assets/{ishikawaDiagram-5VMMS53U-6CilUSFW.js → ishikawaDiagram-5VMMS53U-DLLdu9-W.js} +1 -1
  74. package/dist/web/assets/{it-IT-JPQ66NNP-D4MSuNp_.js → it-IT-JPQ66NNP-6SULWnRA.js} +1 -1
  75. package/dist/web/assets/{ja-JP-DBVTYXUO-BkR3NP86.js → ja-JP-DBVTYXUO-BbgutQYO.js} +1 -1
  76. package/dist/web/assets/{journeyDiagram-3NMN7TZE-C-woTmG9.js → journeyDiagram-3NMN7TZE-DsysKJxX.js} +1 -1
  77. package/dist/web/assets/{kaa-6HZHGXH3-C_EQTf78.js → kaa-6HZHGXH3-Bc6yhZWQ.js} +1 -1
  78. package/dist/web/assets/{kab-KAB-ZGHBKWFO-P-qeHBkl.js → kab-KAB-ZGHBKWFO-BaICxis-.js} +1 -1
  79. package/dist/web/assets/{kanban-definition-UXKFOSKX-CL-EUtyf.js → kanban-definition-UXKFOSKX-w3k_6RhT.js} +1 -1
  80. package/dist/web/assets/{kk-KZ-P5N5QNE5-DwZmyItd.js → kk-KZ-P5N5QNE5-BVsfmPoG.js} +1 -1
  81. package/dist/web/assets/{km-KH-HSX4SM5Z-3SN2ksDz.js → km-KH-HSX4SM5Z-BS1M1bUx.js} +1 -1
  82. package/dist/web/assets/{ko-KR-MTYHY66A--YzrPq0D.js → ko-KR-MTYHY66A-C0x16zQm.js} +1 -1
  83. package/dist/web/assets/{ku-TR-6OUDTVRD-BV1o1ulU.js → ku-TR-6OUDTVRD-BWI9z5E8.js} +1 -1
  84. package/dist/web/assets/{line-DGLpHp6u.js → line-BRXlgUrO.js} +1 -1
  85. package/dist/web/assets/{lt-LT-XHIRWOB4-BuU5cssW.js → lt-LT-XHIRWOB4-CTDq1zFR.js} +1 -1
  86. package/dist/web/assets/{lv-LV-5QDEKY6T-Z9bSAiFr.js → lv-LV-5QDEKY6T-h8b-E15B.js} +1 -1
  87. package/dist/web/assets/{mermaid-parser.core-DA_7CZUN.js → mermaid-parser.core-Da_XEVmR.js} +3 -3
  88. package/dist/web/assets/{mindmap-definition-YA3MSWOX-B58mvQws.js → mindmap-definition-YA3MSWOX-DUBdgu2g.js} +1 -1
  89. package/dist/web/assets/{mr-IN-CRQNXWMA-Cz6h_4fN.js → mr-IN-CRQNXWMA-dTdkz007.js} +1 -1
  90. package/dist/web/assets/{my-MM-5M5IBNSE-n2l8bHxH.js → my-MM-5M5IBNSE-CmYwTRil.js} +1 -1
  91. package/dist/web/assets/{nb-NO-T6EIAALU-r9C_Vo0N.js → nb-NO-T6EIAALU-DLLYcK-s.js} +1 -1
  92. package/dist/web/assets/{nl-NL-IS3SIHDZ-z43DJLFx.js → nl-NL-IS3SIHDZ-mtv15Mmm.js} +1 -1
  93. package/dist/web/assets/{nn-NO-6E72VCQL-Dc6CXJ79.js → nn-NO-6E72VCQL-CJDTT3kB.js} +1 -1
  94. package/dist/web/assets/{oc-FR-POXYY2M6-BgJXbWuu.js → oc-FR-POXYY2M6-DdHJTqH4.js} +1 -1
  95. package/dist/web/assets/{pa-IN-N4M65BXN-CNGXNDOU.js → pa-IN-N4M65BXN-DxzzhbLu.js} +1 -1
  96. package/dist/web/assets/{packet-AYTQ26CC-DBS9PBUE.js → packet-AYTQ26CC-CzX42SOE.js} +1 -1
  97. package/dist/web/assets/{pegDiagram-XKGWAZYB-DA7TGmky.js → pegDiagram-XKGWAZYB-1R2Hd3Th.js} +1 -1
  98. package/dist/web/assets/percentages-BXMCSKIN-Br7824d3.js +1 -0
  99. package/dist/web/assets/{pie-WAS4IAKB-Cx2pnjZr.js → pie-WAS4IAKB-DEI2uslz.js} +1 -1
  100. package/dist/web/assets/{pieDiagram-E7YTZNPT-q7SgBOc3.js → pieDiagram-E7YTZNPT-DOQnFSrs.js} +1 -1
  101. package/dist/web/assets/{pl-PL-T2D74RX3-NeLUNwLZ.js → pl-PL-T2D74RX3-Dpyab0lI.js} +1 -1
  102. package/dist/web/assets/{pt-BR-5N22H2LF-D5X0RFzx.js → pt-BR-5N22H2LF-DOGrUA6Y.js} +1 -1
  103. package/dist/web/assets/{pt-PT-UZXXM6DQ-_ZsKyBBN.js → pt-PT-UZXXM6DQ-DAoNiiOg.js} +1 -1
  104. package/dist/web/assets/{quadrantDiagram-AXDQQJYC-CqjGVnZh.js → quadrantDiagram-AXDQQJYC-CQE1OxRJ.js} +1 -1
  105. package/dist/web/assets/{radar-RG4KPBEZ-BWJANoHa.js → radar-RG4KPBEZ-B-er2ORT.js} +1 -1
  106. package/dist/web/assets/{railroad-74A4TZTK-BTAfdSvV.js → railroad-74A4TZTK-D1Veuu81.js} +1 -1
  107. package/dist/web/assets/{railroad-abnf-HS5TGJTU-NfS3EnaM.js → railroad-abnf-HS5TGJTU-DTxLo5az.js} +1 -1
  108. package/dist/web/assets/{railroad-ebnf-LZEXJU2U-Ce5m2P1B.js → railroad-ebnf-LZEXJU2U-BmP2IZGe.js} +1 -1
  109. package/dist/web/assets/{railroad-peg-WCYAUIDC-CyXkeDDy.js → railroad-peg-WCYAUIDC-Do60gMTC.js} +1 -1
  110. package/dist/web/assets/{railroadDiagram-O6MQD6OU-C4wOSBs0.js → railroadDiagram-O6MQD6OU-5I8Qk1dI.js} +1 -1
  111. package/dist/web/assets/{requirementDiagram-BXWQKSXE-dC2Q9_dM.js → requirementDiagram-BXWQKSXE-CIIM8YmC.js} +1 -1
  112. package/dist/web/assets/{ro-RO-JPDTUUEW-B0TUgaSO.js → ro-RO-JPDTUUEW-DR9yu2MV.js} +1 -1
  113. package/dist/web/assets/{ru-RU-B4JR7IUQ-FyI4SBb1.js → ru-RU-B4JR7IUQ-B9uIhZUd.js} +1 -1
  114. package/dist/web/assets/{sankeyDiagram-P5KCCOFB-czlewm_g.js → sankeyDiagram-P5KCCOFB-BdGmiiCQ.js} +1 -1
  115. package/dist/web/assets/{sequenceDiagram-WJ2MYXX4-rtSwZGtV.js → sequenceDiagram-WJ2MYXX4-BeCmgCpG.js} +1 -1
  116. package/dist/web/assets/{si-LK-N5RQ5JYF-q-KyMvoF.js → si-LK-N5RQ5JYF-C7DYCsOB.js} +1 -1
  117. package/dist/web/assets/{sk-SK-C5VTKIMK-tX-HO0L6.js → sk-SK-C5VTKIMK-BbBBLLCs.js} +1 -1
  118. package/dist/web/assets/{sl-SI-NN7IZMDC-Dy8vWC0s.js → sl-SI-NN7IZMDC-BIaW2Iuj.js} +1 -1
  119. package/dist/web/assets/{stateDiagram-D77RDMKH-CWDH4s-t.js → stateDiagram-D77RDMKH-CmENpSfH.js} +1 -1
  120. package/dist/web/assets/stateDiagram-v2-MP3YSRHH-BWgn52cG.js +1 -0
  121. package/dist/web/assets/subset-shared.chunk-d2GNuFHV.js +1 -0
  122. package/dist/web/assets/{subset-worker.chunk-CBZq9OSE.js → subset-worker.chunk-Bi16Jh4x.js} +1 -1
  123. package/dist/web/assets/{sv-SE-XGPEYMSR-D1ErsBn-.js → sv-SE-XGPEYMSR-D5A1U3nk.js} +1 -1
  124. package/dist/web/assets/{swimlanes-42K2YHIH-CM2OkOmc.js → swimlanes-42K2YHIH-_ymwQg8o.js} +1 -1
  125. package/dist/web/assets/swimlanesDiagram-VR7AAH4N-fzrjtpfS.js +8 -0
  126. package/dist/web/assets/{ta-IN-2NMHFXQM-PSu4eqYe.js → ta-IN-2NMHFXQM-BDzXUwiE.js} +1 -1
  127. package/dist/web/assets/{th-TH-HPSO5L25-BVu-PlXo.js → th-TH-HPSO5L25-DdVnWuWW.js} +1 -1
  128. package/dist/web/assets/{timeline-definition-24CTP7MA-Bo6sYnPJ.js → timeline-definition-24CTP7MA-CRcZde4k.js} +1 -1
  129. package/dist/web/assets/{tr-TR-DEFEU3FU-BtC_O7fA.js → tr-TR-DEFEU3FU-BQwfGN3o.js} +1 -1
  130. package/dist/web/assets/{treeView-Q6P3EWNA-B3NS1SBg.js → treeView-Q6P3EWNA-BHZZuSXr.js} +1 -1
  131. package/dist/web/assets/{treemap-WGGIJYW6-Du_VkW6s.js → treemap-WGGIJYW6-DAzotEQZ.js} +1 -1
  132. package/dist/web/assets/{uk-UA-QMV73CPH-RwWQcIwP.js → uk-UA-QMV73CPH-CFYnWqHD.js} +1 -1
  133. package/dist/web/assets/{vennDiagram-4TSXK5OY-R1EH0pXq.js → vennDiagram-4TSXK5OY-BsNz9Qnn.js} +1 -1
  134. package/dist/web/assets/{vi-VN-M7AON7JQ-CUEI6eHH.js → vi-VN-M7AON7JQ-DO3BySmm.js} +1 -1
  135. package/dist/web/assets/{wardley-WFR3VGLG-9B3cKl8K.js → wardley-WFR3VGLG-Cc2r8Vp8.js} +1 -1
  136. package/dist/web/assets/{wardleyDiagram-VM6X3IG4-XZ18gIOz.js → wardleyDiagram-VM6X3IG4-47UvJO4N.js} +1 -1
  137. package/dist/web/assets/{xychartDiagram-S5SC5T6Z-BLzXnvba.js → xychartDiagram-S5SC5T6Z-CVl63zr-.js} +1 -1
  138. package/dist/web/assets/{zh-CN-LNUGB5OW-C3asHvVp.js → zh-CN-LNUGB5OW-DKJ2CF-O.js} +1 -1
  139. package/dist/web/assets/{zh-HK-E62DVLB3-BO6FsJfO.js → zh-HK-E62DVLB3-DHW8OH5j.js} +1 -1
  140. package/dist/web/assets/{zh-TW-RAJ6MFWO-DGtaI2hh.js → zh-TW-RAJ6MFWO-B9cMDifZ.js} +1 -1
  141. package/dist/web/index.html +1 -1
  142. package/package.json +3 -2
  143. package/dist/web/assets/channel-fspI7jZI.js +0 -1
  144. package/dist/web/assets/classDiagram-ZZMXUADV-Dr-7S1cu.js +0 -1
  145. package/dist/web/assets/classDiagram-v2-VYDZK3BY-Dr-7S1cu.js +0 -1
  146. package/dist/web/assets/flowDiagram-HODETNUW-kdP64-E7.js +0 -1
  147. package/dist/web/assets/percentages-BXMCSKIN-btxXaPp4.js +0 -1
  148. package/dist/web/assets/stateDiagram-v2-MP3YSRHH-DdSAvpNH.js +0 -1
  149. package/dist/web/assets/subset-shared.chunk-D1bYkpAa.js +0 -1
  150. package/dist/web/assets/swimlanesDiagram-VR7AAH4N-CVzVUDpQ.js +0 -8
  151. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-019d66dcad46dc156b162d267f981c20.woff2 +0 -0
  152. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-04b718e5623574919c8b0dea5f301444.woff2 +0 -0
  153. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-069e77aac84590e2e991d0a0176d34f2.woff2 +0 -0
  154. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-06c77b8c66e51ed6c63ccb502dd8b8af.woff2 +0 -0
  155. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-08e0dc436ad0ad61ba5558db0674d762.woff2 +0 -0
  156. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-093b9ef39a46ceae95a1df18a0a3a326.woff2 +0 -0
  157. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-095c169f3314805276f603a362766abd.woff2 +0 -0
  158. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-09850c4077f3fffe707905872e0e2460.woff2 +0 -0
  159. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-0986d134c05864f5025962eef9f994a0.woff2 +0 -0
  160. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-0b5d723fdc4e249c140f0909e87d03b4.woff2 +0 -0
  161. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-0f626226ba1272e832aea87bafd9720e.woff2 +0 -0
  162. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-0f7fb1e0d5015bb1371343153ecf7ce3.woff2 +0 -0
  163. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-0fa55a080fcd0f9dc2e0b0058b793df8.woff2 +0 -0
  164. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-0facdf1ea213ba40261022f5d5ed4493.woff2 +0 -0
  165. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-10a7ae9a371830a80c3d844acf1c02d7.woff2 +0 -0
  166. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-112c051027b2d766c19a519f6ee1f4f7.woff2 +0 -0
  167. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-11c345711937f0ba4b8f7b6b919c8440.woff2 +0 -0
  168. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-12b52b58eb3df36804b9a654ec9ee194.woff2 +0 -0
  169. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-13ae07ed2e272d26d59bc0691cd7117a.woff2 +0 -0
  170. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-13d2887ec8ee73c43acdabc52a05af7b.woff2 +0 -0
  171. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-145aa02cdd91946e67dc934e1acffe75.woff2 +0 -0
  172. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-15dc6d811c9cd078f9086a740d5a1038.woff2 +0 -0
  173. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-173945821411c09f70c95f98d590e697.woff2 +0 -0
  174. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-1b611157cd46bb184d4fa4dae2d6a2b8.woff2 +0 -0
  175. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-1e6fd68f1f3902ce48ce8c69df385622.woff2 +0 -0
  176. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-1ee544f0f1dac422545c505baa788992.woff2 +0 -0
  177. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-1fdc0c67ed57263a80fd108c1f6ccf24.woff2 +0 -0
  178. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-203b0e569e3b14aac86a003dc3fa523e.woff2 +0 -0
  179. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-20cc1bbf50e7efb442756cb605672c1f.woff2 +0 -0
  180. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-20e7bf72fa05de9adf7dbcc7bf51dde6.woff2 +0 -0
  181. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-21430ee05a1248901da8d0de08744d47.woff2 +0 -0
  182. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-23686f7f29da6e8008c36dd3a80c83d6.woff2 +0 -0
  183. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-23ad2d71b280f00b1363b95b7bea94eb.woff2 +0 -0
  184. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-23f228f3999c01983860012330e4be08.woff2 +0 -0
  185. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-24476a126f129212beb33f66853ea151.woff2 +0 -0
  186. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-24a21c1e4449222e8d1898d69ff3a404.woff2 +0 -0
  187. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-25b7f38e18f035f96cb5e547bd2bd08c.woff2 +0 -0
  188. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-29cec36cd205b211da97acabaa62f055.woff2 +0 -0
  189. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2a26d20a23b00898ce82f09d2ee47c3f.woff2 +0 -0
  190. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2adbc89c11e65905393d3dfc468b9d5b.woff2 +0 -0
  191. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2b7441d46298788ac94e610ffcc709b6.woff2 +0 -0
  192. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2b77e8ebfb2367ab2662396a60e7d320.woff2 +0 -0
  193. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2cf96d082d35ea3d8106851223ad0d16.woff2 +0 -0
  194. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2d43040e86ff03ba677f6f9c04cd0805.woff2 +0 -0
  195. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-2e33e8dc771ef5e1d9127d60a6b73679.woff2 +0 -0
  196. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-33432927cd87d40cfe393c7482bf221f.woff2 +0 -0
  197. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-353f33792a8f60dc69323ddf635a269e.woff2 +0 -0
  198. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-36925dfe329a45086cbb7fc5c20d45ac.woff2 +0 -0
  199. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3717077e38f98d89eae729b6c14e56dc.woff2 +0 -0
  200. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3756e81d3e149cf6099163ee79944fec.woff2 +0 -0
  201. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-395c35dd584b56b0789f58a0559beaf1.woff2 +0 -0
  202. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3c9de2ae0ea4bc91a510942dfa4be8d2.woff2 +0 -0
  203. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3cc70dbb64df5b21f1326cc24dee2195.woff2 +0 -0
  204. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3e1f8f654357353bf0e04ba5c34b5f7f.woff2 +0 -0
  205. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3e63ed8162808a9e425ed80a8bc79114.woff2 +0 -0
  206. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-3eaa538115d76932653c21d8dc28f207.woff2 +0 -0
  207. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4095eb84ef3874e2600247bee0b04026.woff2 +0 -0
  208. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-41521fade99856108931b4768b1b2648.woff2 +0 -0
  209. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-450da755d5bcb70906e1295e559b9602.woff2 +0 -0
  210. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-452225341522a7942f0f6aab1a5c91a3.woff2 +0 -0
  211. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4535823663ad81405188a528d8f2b1a2.woff2 +0 -0
  212. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4806e761d750087c2d734fc64596eaff.woff2 +0 -0
  213. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4a0fdb40036e87b40aa08dd30584cb85.woff2 +0 -0
  214. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4a38cc3e9cf104e69ba246d37f8cf135.woff2 +0 -0
  215. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4aca6a43e59aceee2166b0c7e4e85ef1.woff2 +0 -0
  216. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4bfaa8ffa64c5ee560aa2daba7c9cbd3.woff2 +0 -0
  217. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4dc6d5f188d5c96d44815cd1e81aa885.woff2 +0 -0
  218. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4ddc14ed3eb0c3e46364317dfc0144a3.woff2 +0 -0
  219. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4ee10ae43505e2e0bc62656ced49c0fa.woff2 +0 -0
  220. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-4f50e5136e136527280bc902c5817561.woff2 +0 -0
  221. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-51502f1206be09c565f1547c406e9558.woff2 +0 -0
  222. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-51a0e808bbc8361236ac521a119758a3.woff2 +0 -0
  223. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-52a84a22fd1369bffeaf21da2d6158dc.woff2 +0 -0
  224. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5330a2119a716e4e7224ed108b085dac.woff2 +0 -0
  225. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-543fa46ace099a7099dad69123399400.woff2 +0 -0
  226. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-544fc28abe2c5c30e62383fd4dac255f.woff2 +0 -0
  227. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-54acdfc2166ad7fcbd074f75fd4a56ba.woff2 +0 -0
  228. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5572b3513ba8df57a3d5d7303ee6b11b.woff2 +0 -0
  229. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-56467a5c8840c4d23a60b2f935114848.woff2 +0 -0
  230. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-56a32a7689abd0326e57c10c6c069bb4.woff2 +0 -0
  231. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-57862b464a55b18c7bf234ce22907d73.woff2 +0 -0
  232. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-583d166e56ba0de4b77eabb47ef67839.woff2 +0 -0
  233. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5882ffa04f32584d26109137e2da4352.woff2 +0 -0
  234. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-58fd02350d0bc52cf1ca3bb32ce9766e.woff2 +0 -0
  235. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5935a5775af3d5c6307ac667bd9ae74e.woff2 +0 -0
  236. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-59e9ff77b0efaf684bc09274fb6908c9.woff2 +0 -0
  237. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5a1ce3117cfe90c48e8fb4a9a00f694d.woff2 +0 -0
  238. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5a45d991244d4c7140217e1e5f5ca4f4.woff2 +0 -0
  239. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5a7fac4b8b23a6e4e5ba0c9bf1756c91.woff2 +0 -0
  240. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5b0ed6971aaab9c8ad563230bd5471a7.woff2 +0 -0
  241. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-5d2898fbc097a7e24c6f38d80587621e.woff2 +0 -0
  242. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-603aefd23e350ba7eb124273e3c9bcf1.woff2 +0 -0
  243. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-60a3089806700d379f11827ee9843b6b.woff2 +0 -0
  244. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-60a41c7e1c68f22424e6d22df544bc82.woff2 +0 -0
  245. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-642b26e2e5f5fb780b51b593dbc8c851.woff2 +0 -0
  246. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-66493ba5a8367f2928812f446f47b56a.woff2 +0 -0
  247. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-670ba603758d94268e8606f240a42e12.woff2 +0 -0
  248. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-671a2c20b1eb9e4ef8a192833940e319.woff2 +0 -0
  249. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-684d65f1793cac449dde5d59cb3c47fb.woff2 +0 -0
  250. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-69c09cc5fa3e55c74fc4821f76909cc3.woff2 +0 -0
  251. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-6ae5b42180ad70b971c91e7eefb8eba2.woff2 +0 -0
  252. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-6e092f71c1e634059ada0e52abadce67.woff2 +0 -0
  253. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-6f3256af8454371776bc46670d33cc65.woff2 +0 -0
  254. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-6fe5c5973cc06f74b2387a631ea36b88.woff2 +0 -0
  255. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-70c2eb8d64e71a42a834eb857ea9df51.woff2 +0 -0
  256. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-70e811fd7994e61f408c923de6ddd078.woff2 +0 -0
  257. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7197d6fda6cba7c3874c53d6381ca239.woff2 +0 -0
  258. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-72252d73220fa3cd856677888cee1635.woff2 +0 -0
  259. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-72536a3d71b694a0d53dd90ddceae41e.woff2 +0 -0
  260. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-726303e0774b4e678bff8c2deb6ca603.woff2 +0 -0
  261. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-733171b4ffcd17ea1fe1c0ba627173bf.woff2 +0 -0
  262. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-739bc1a567439c7cffcd1614644593d2.woff2 +0 -0
  263. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-73e309718fd16cea44b4d54a33581811.woff2 +0 -0
  264. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7494dc504ae00ee9cd0505f990f88c5d.woff2 +0 -0
  265. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-74e2263a91439c25b91d5132ce9f4d62.woff2 +0 -0
  266. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-761d05e3cd968cf574166867998ef06a.woff2 +0 -0
  267. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7718fe60986d8b42b1be9c5ace5ccf25.woff2 +0 -0
  268. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-774d4f764a1299da5d28ec2f2ffe0d69.woff2 +0 -0
  269. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-79d494361ae093b69e74ee9dbe65bfd4.woff2 +0 -0
  270. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-79f007c1c6d07557120982951ea67998.woff2 +0 -0
  271. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7a07ddc0f0c0f5f4a9bad6ee3dda66b5.woff2 +0 -0
  272. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7ab2bed91166a9dca83a5ebfbe2a7f38.woff2 +0 -0
  273. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7ccce86603f80a099ddb0cb21d4ae3e3.woff2 +0 -0
  274. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7e4bde7e9c7f84cd34d8a845e384c746.woff2 +0 -0
  275. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7e929f262f30c8ee78bf398150b1a7cd.woff2 +0 -0
  276. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7eb9fffd1aa890d07d0f88cc82e6cfe4.woff2 +0 -0
  277. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-7f855356ab893b0d2b9c1c83b8116f0e.woff2 +0 -0
  278. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-829615148e6357d826b9242eb7fbbd1e.woff2 +0 -0
  279. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-866fa7613df6b3fd272bcfd4530c0bb9.woff2 +0 -0
  280. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-87599f94b6cc129d505b375798d0d751.woff2 +0 -0
  281. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-8c2f33cee3993174f7e87c28e4bf42ee.woff2 +0 -0
  282. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-8d3bcabb847b56243b16afe62adaaf21.woff2 +0 -0
  283. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-8de5b863cb50dfefdd07cb11c774d579.woff2 +0 -0
  284. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-8e9f97f01034820170065b2921b4fb5e.woff2 +0 -0
  285. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-8f476c4c99813d57cbe6eca4727388ad.woff2 +0 -0
  286. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-903bb6865f3452e2fda42e3a25547bc5.woff2 +0 -0
  287. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-91ddb2969bf2d31ba02ad82998d1314c.woff2 +0 -0
  288. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-938d90c10ff8c20386af7f242c05d6b0.woff2 +0 -0
  289. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-93fc8f28a33234bcadf1527cafabd502.woff2 +0 -0
  290. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-95429962233afd82db1c27df1500a28c.woff2 +0 -0
  291. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-9544732d2e62d1a429674f8ee41b5d3a.woff2 +0 -0
  292. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-9592bfc861f07bcb8d75c196b370e548.woff2 +0 -0
  293. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-95bfd249da4902577b4b7d76ebdd0b44.woff2 +0 -0
  294. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-968cffdc8ee679da094e77ebf50f58ef.woff2 +0 -0
  295. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-97f7f48ce90c9429bf32ae51469db74d.woff2 +0 -0
  296. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-982b630266d87db93d2539affb1275c6.woff2 +0 -0
  297. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-98f2ad84457de7f3740d9920b8fa8667.woff2 +0 -0
  298. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-99a16ef6a64934d5781933dbd9c46b2e.woff2 +0 -0
  299. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-9cfb2a77a4e45025105ad29a1748b90d.woff2 +0 -0
  300. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-9d81066dd2b337c938df6e90380a00dc.woff2 +0 -0
  301. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-9eb5a99df4e76ac3363453ac9ca288b1.woff2 +0 -0
  302. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a004ddfcb26e67bd6e678c8ed19e25ce.woff2 +0 -0
  303. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a0ca5df4258213d7fc9fce80f65ce760.woff2 +0 -0
  304. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a1f916d6039285c4ffb900cd654e418f.woff2 +0 -0
  305. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a203b91dad570bf05a58c3c3ddb529bf.woff2 +0 -0
  306. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a365e82ed54697a52f27adcea1315fe8.woff2 +0 -0
  307. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a4c34be6d42152e64b0df90bc4607f64.woff2 +0 -0
  308. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-a7accba310e821da5505f71c03b76bdb.woff2 +0 -0
  309. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-aa0d470430e6391eca720c7cfa44446f.woff2 +0 -0
  310. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-aa5c9ca6cf4fba00433b7aa3fa10671a.woff2 +0 -0
  311. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-ac9ceb44437becc3e9c4dbfebab7fc2d.woff2 +0 -0
  312. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b1220a3c61f85cc0408deedb4c5f57a2.woff2 +0 -0
  313. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b358f7a51ece39a3247942b1feabdb29.woff2 +0 -0
  314. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b57aaedfd8ebdf3931f25119dc6a5eb2.woff2 +0 -0
  315. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b5c1596551c256e0e9cf02028595b092.woff2 +0 -0
  316. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b6d128682ee29e471486354d486a1b90.woff2 +0 -0
  317. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b6fd38ca30869792244804b04bc058da.woff2 +0 -0
  318. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b7d203b051eff504ff59ddca7576b6a9.woff2 +0 -0
  319. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-b96d9226ce77ec94ceca043d712182e6.woff2 +0 -0
  320. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-ba3de316d63c7e339987b16f41a0b879.woff2 +0 -0
  321. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-bafff7a14c27403dcc6cf1432e8ea836.woff2 +0 -0
  322. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-bd77e3c7f9e0b072d96af37f73d1aa32.woff2 +0 -0
  323. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-be549ab72f0719d606a5c01e2c0219b6.woff2 +0 -0
  324. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c16ed9740b85badf16e86ea782a3062f.woff2 +0 -0
  325. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c1f94158256bb1f3bf665b053d895af9.woff2 +0 -0
  326. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c40533fdf4cc57177b12803598af7e59.woff2 +0 -0
  327. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c4a687ac4f0c2766eefc9f77ed99cddf.woff2 +0 -0
  328. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c69f61a4ab18d0488c8d1fc12e7028e8.woff2 +0 -0
  329. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c8b71798409ccc126ee264a00aadcf21.woff2 +0 -0
  330. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-c99eda15fc26a2941579560f76c3a5cf.woff2 +0 -0
  331. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cb17fc3db95f6d139afc9d31a8e93293.woff2 +0 -0
  332. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cbaaefaaf326668277aa24dfa93c4d28.woff2 +0 -0
  333. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cd145ce4a0ea18469358df53c207bc1b.woff2 +0 -0
  334. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cdbce89e82cc1ab53a2decbf5819278f.woff2 +0 -0
  335. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-ce4884f96f11589608b76b726a755803.woff2 +0 -0
  336. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cf2cc71752631e579e35b0e423bf2638.woff2 +0 -0
  337. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cf6ff4e0f491ca0cf3038187a997b9b4.woff2 +0 -0
  338. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-cfb211578629b7e8153b37240de6a9d5.woff2 +0 -0
  339. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-d0cf73942fea1c74edbdf0b3011f4656.woff2 +0 -0
  340. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-d2666cbed13462c5dc36fa2f15c202ca.woff2 +0 -0
  341. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-d3716376641d615e2995605b29bca7b6.woff2 +0 -0
  342. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-dac48066b5883d8b4551fc584f0c2a3e.woff2 +0 -0
  343. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-dbea1af6dcd9860be40c3d18254338f5.woff2 +0 -0
  344. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e11567fd2accf9957cd0d3c2be937d87.woff2 +0 -0
  345. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e2ead7ea7da0437f085f42ffc05f8d13.woff2 +0 -0
  346. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e3fcf5180fd466c8915c4e8069491054.woff2 +0 -0
  347. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e480d9c614742d05f0e78f274f1e69e6.woff2 +0 -0
  348. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e4bca6cfa53e499cae0a6be4894a90e9.woff2 +0 -0
  349. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e51ef413167c6e14e0c0fdcc585f2fc9.woff2 +0 -0
  350. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e5f453bb04da18eed01675eeebd88bf8.woff2 +0 -0
  351. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-e656f091b9dc4709722c9f4b84d3c797.woff2 +0 -0
  352. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-ec181b795ac1fb5a50d700b6e996d745.woff2 +0 -0
  353. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-ee8bae97908d5147b423f77ad0d3c1bb.woff2 +0 -0
  354. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-f0f13b5c60e0af5553bd359f5513be1b.woff2 +0 -0
  355. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-f2b54d4e7be0eaefe1c2c56836fa5368.woff2 +0 -0
  356. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-f56414bf9bced67990def8660e306759.woff2 +0 -0
  357. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-f5d079153c99a25b9be5b8583c4cc8a7.woff2 +0 -0
  358. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-f6032fc06eb20480f096199713f70885.woff2 +0 -0
  359. package/dist/web/fonts/Xiaolai/Xiaolai-Regular-f8ee5d36068a42b51d0e4a1116cfcec1.woff2 +0 -0
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  A spatial scratchboard for your Claude Code sessions, on an Excalidraw canvas.
4
4
 
5
+ ![The board: session cards triaged into lanes](https://raw.githubusercontent.com/martinkozle/excaliagent/main/docs/images/board.png)
6
+
5
7
  Every session is a card. You drag cards wherever they make sense to you (parked,
6
8
  blocked on a colleague, come back to, done) and draw anything around them. The
7
9
  app keeps each card's **color and label** in sync with the session and never
@@ -19,11 +21,13 @@ PR #12 ← last PR link
19
21
  | Color | Meaning |
20
22
  |---|---|
21
23
  | red | needs you (input, permission, trust, blocked) |
22
- | blue | busy |
24
+ | yellow | busy |
23
25
  | green | idle, prompt cache still warm: review it before it goes cold |
24
26
  | grey | idle, cache cold |
25
27
  | dashed, pale | dormant (not running) |
26
28
 
29
+ ![Right-click on a card: the excaliagent section next to the Excalidraw menu](https://raw.githubusercontent.com/martinkozle/excaliagent/main/docs/images/card-menu.png)
30
+
27
31
  ## Run
28
32
 
29
33
  ```sh
@@ -32,7 +36,10 @@ npx excaliagent
32
36
 
33
37
  It starts a server on `127.0.0.1` and opens the board in your browser.
34
38
 
35
- - **Live sessions** appear in the *inbox* rectangle by themselves.
39
+ - **Live sessions** appear in the *inbox* by themselves. A new board comes with
40
+ lanes next to it (To Do, In Progress, Review, Blocked, Parked, Done, and two
41
+ blank ones to name yourself); they are plain shapes you can rename, move or
42
+ delete. On an older board, add them from the main menu: *Add starter lanes*.
36
43
  - **Dormant sessions** are added from the **Sessions** panel (top right).
37
44
  - **Double-click a card** to jump to it: a live session focuses its
38
45
  [herdr](https://herdr.dev) pane and raises the terminal window (Hyprland,
@@ -62,6 +69,15 @@ See `npx excaliagent --help`.
62
69
  - Its only actions: focus a herdr pane, raise the terminal window, and start
63
70
  `claude --resume <id>` in a new herdr pane. It never types into a running
64
71
  session.
72
+ - The only outside request: Chinese, Japanese or Korean text on the board loads
73
+ Excalidraw's CJK font from esm.sh (it is not bundled, to keep the package
74
+ small). Everything else, including all other fonts, is served locally.
75
+
76
+ ## Platforms
77
+
78
+ Linux and macOS. Raising the terminal window after a jump works on Hyprland,
79
+ Sway and macOS. Windows is not supported yet
80
+ ([#1](https://github.com/martinkozle/excaliagent/issues/1), contributions welcome).
65
81
 
66
82
  ## herdr (optional)
67
83
 
@@ -10,6 +10,7 @@ Options:
10
10
  --claude-dir <dir> Claude Code home (default: ~/.claude)
11
11
  --no-herdr Do not link sessions to herdr panes
12
12
  --no-raise Focus the herdr pane but do not raise its terminal window
13
+ (raising supports Hyprland, Sway and macOS)
13
14
  --dev Serve the frontend through Vite with hot reload
14
15
  -h, --help Show this help
15
16
  -v, --version Show the version
@@ -28,9 +28,8 @@ function openBrowser(url) {
28
28
  async function main(args) {
29
29
  const token = randomBytes(24).toString("base64url");
30
30
  const source = createClaudeSource({ claudeDir: args.claudeDir });
31
- const panes = args.herdr
32
- ? createHerdrLink({ desktop: args.raise ? createDesktop({ env: process.env }) : undefined })
33
- : createNoPaneLink();
31
+ const desktop = args.herdr && args.raise ? createDesktop({ env: process.env }) : undefined;
32
+ const panes = args.herdr ? createHerdrLink({ desktop }) : createNoPaneLink();
34
33
  const hub = createHub({ source, panes });
35
34
  await hub.start();
36
35
  const scenes = createSceneStore(args.stateDir ?? defaultStateDir());
@@ -60,6 +59,8 @@ async function main(args) {
60
59
  console.log(`excaliagent ${args.dev ? "(dev) " : ""}listening on http://127.0.0.1:${server.port}`);
61
60
  console.log(`scene: ${scenes.path}`);
62
61
  console.log(`herdr: ${panes.available() ? "connected" : args.herdr ? "not running (will retry)" : "disabled"}`);
62
+ if (args.herdr)
63
+ console.log(`raise window on focus: ${!desktop ? "off (--no-raise)" : desktop.kind === "none" ? "unsupported here" : desktop.kind}`);
63
64
  console.log(`open: ${url}`);
64
65
  if (args.open)
65
66
  openBrowser(url);
@@ -2,102 +2,144 @@
2
2
  * Raise the desktop window that hosts a process (e.g. the terminal running a
3
3
  * herdr client), so focusing a pane also brings its terminal to the front.
4
4
  *
5
- * Walks each candidate pid's ancestors via /proc/<pid>/stat and focuses the
6
- * first ancestor that owns a window. Supported: Hyprland (hyprctl) and Sway
7
- * (swaymsg). Anything else is a no-op. Never throws.
5
+ * Walks each candidate pid's ancestors through a ProcessTable and acts on the
6
+ * first ancestor that is a window / app:
7
+ * - Linux + Hyprland: `hyprctl clients -j` → `hyprctl dispatch focuswindow address:<addr>`
8
+ * - Linux + Sway: `swaymsg -t get_tree` → `swaymsg [pid=N] focus`
9
+ * - macOS: first ancestor whose executable lives in an `.app` bundle →
10
+ * `open -a <bundle>` (activates the app; no Accessibility permission).
11
+ * Unverified on real hardware.
12
+ * - anything else: no-op.
13
+ * Never throws; raise() resolves false when nothing was raised.
8
14
  */
9
- import { execFile } from "node:child_process";
10
- import { readFile } from "node:fs/promises";
11
- import { join } from "node:path";
12
- export const defaultExec = (file, args, opts) => new Promise((resolve, reject) => {
13
- execFile(file, args, { timeout: opts.timeout, maxBuffer: 16 << 20, encoding: "utf8" }, (err, stdout) => {
14
- if (err)
15
- reject(err);
16
- else
17
- resolve({ stdout });
18
- });
19
- });
20
- /** ppid from /proc/<pid>/stat; comm (field 2) may contain spaces and parens. */
21
- export async function parentPid(procRoot, pid) {
22
- try {
23
- const stat = await readFile(join(procRoot, String(pid), "stat"), "utf8");
24
- const rest = stat.slice(stat.lastIndexOf(")") + 1).trim().split(/\s+/);
25
- const ppid = Number(rest[1]);
26
- return Number.isInteger(ppid) && ppid > 0 ? ppid : undefined;
27
- }
28
- catch {
29
- return undefined;
30
- }
31
- }
32
- /** pid, then its parents up to (excluding) init. */
33
- async function ancestry(procRoot, pid) {
15
+ import { defaultExec, defaultLog, describeExecFailure, logOnce } from "./exec.js";
16
+ import { createProcessTable } from "./process-table.js";
17
+ export { defaultExec };
18
+ /** pid, then its parents up to (excluding) init/launchd. */
19
+ async function ancestry(table, pid) {
34
20
  const chain = [];
35
21
  const seen = new Set();
36
22
  let cur = pid;
37
23
  while (cur !== undefined && cur > 1 && !seen.has(cur) && chain.length < 64) {
38
24
  seen.add(cur);
39
25
  chain.push(cur);
40
- cur = await parentPid(procRoot, cur);
26
+ cur = await table.parent(cur);
41
27
  }
42
28
  return chain;
43
29
  }
44
- function hyprland(exec, timeout) {
30
+ function windowManager(listWindows, focus) {
45
31
  return {
46
- async windows() {
47
- const { stdout } = await exec("hyprctl", ["clients", "-j"], { timeout });
48
- const out = new Map();
49
- for (const c of JSON.parse(stdout)) {
50
- if (typeof c.pid === "number" && typeof c.address === "string" && !out.has(c.pid))
51
- out.set(c.pid, c.address);
52
- }
53
- return out;
54
- },
55
- async focus(address) {
56
- await exec("hyprctl", ["dispatch", "focuswindow", `address:${address}`], { timeout });
32
+ async prepare() {
33
+ const windows = await listWindows();
34
+ return async (pid) => windows.get(pid);
57
35
  },
36
+ focus,
58
37
  };
59
38
  }
39
+ function hyprland(exec, timeout) {
40
+ return windowManager(async () => {
41
+ const { stdout } = await exec("hyprctl", ["clients", "-j"], { timeout });
42
+ const out = new Map();
43
+ for (const c of JSON.parse(stdout)) {
44
+ if (typeof c.pid === "number" && typeof c.address === "string" && !out.has(c.pid))
45
+ out.set(c.pid, c.address);
46
+ }
47
+ return out;
48
+ }, async (address) => {
49
+ await exec("hyprctl", ["dispatch", "focuswindow", `address:${address}`], { timeout });
50
+ });
51
+ }
60
52
  function sway(exec, timeout) {
53
+ return windowManager(async () => {
54
+ const { stdout } = await exec("swaymsg", ["-t", "get_tree"], { timeout });
55
+ const out = new Map();
56
+ const walk = (n) => {
57
+ if (typeof n.pid === "number")
58
+ out.set(n.pid, String(n.pid));
59
+ for (const c of [...(n.nodes ?? []), ...(n.floating_nodes ?? [])])
60
+ walk(c);
61
+ };
62
+ walk(JSON.parse(stdout));
63
+ return out;
64
+ }, async (pid) => {
65
+ await exec("swaymsg", [`[pid=${pid}]`, "focus"], { timeout });
66
+ });
67
+ }
68
+ /** Outermost `.app` bundle containing an executable path, e.g. /Applications/kitty.app. */
69
+ export function appBundleOf(exe) {
70
+ const m = /^(\/.*?\.app)\//.exec(exe);
71
+ return m?.[1];
72
+ }
73
+ function macos(exec, timeout, table, log) {
74
+ const once = logOnce(log);
61
75
  return {
62
- async windows() {
63
- const { stdout } = await exec("swaymsg", ["-t", "get_tree"], { timeout });
64
- const out = new Map();
65
- const walk = (n) => {
66
- if (typeof n.pid === "number")
67
- out.set(n.pid, String(n.pid));
68
- for (const c of [...(n.nodes ?? []), ...(n.floating_nodes ?? [])])
69
- walk(c);
76
+ async prepare() {
77
+ return async (pid) => {
78
+ const exe = await table.exe(pid);
79
+ return exe ? appBundleOf(exe) : undefined;
70
80
  };
71
- walk(JSON.parse(stdout));
72
- return out;
73
81
  },
74
- async focus(pid) {
75
- await exec("swaymsg", [`[pid=${pid}]`, "focus"], { timeout });
82
+ async focus(bundle) {
83
+ const args = ["-a", bundle];
84
+ try {
85
+ await exec("open", args, { timeout });
86
+ }
87
+ catch (e) {
88
+ once(`open:${bundle}`, `raise: ${describeExecFailure("open", args, e)}`);
89
+ throw e;
90
+ }
91
+ },
92
+ async notFound(chains) {
93
+ const shown = await Promise.all(chains.map(async (chain) => (await Promise.all(chain.map(async (p) => `${p} ${(await table.exe(p)) ?? "?"}`))).join(" <- ")));
94
+ once("no-app", `raise: no .app bundle among the ancestors of herdr client(s): ${shown.join("; ")}`);
95
+ },
96
+ noPids() {
97
+ once("no-pids", "raise: no herdr client process found (is herdr running in a terminal on this Mac?)");
76
98
  },
77
99
  };
78
100
  }
79
101
  export function createDesktop(opts = {}) {
80
- const { env = process.env, exec = defaultExec, procRoot = "/proc", timeoutMs = 2000 } = opts;
81
- const wm = env.HYPRLAND_INSTANCE_SIGNATURE
82
- ? hyprland(exec, timeoutMs)
83
- : env.SWAYSOCK
84
- ? sway(exec, timeoutMs)
85
- : undefined;
102
+ const { platform = process.platform, env = process.env, exec = defaultExec, timeoutMs = 2000 } = opts;
103
+ const table = opts.table ?? createProcessTable({ platform, procRoot: opts.procRoot, exec, timeoutMs, log: opts.log });
104
+ const log = opts.log ?? defaultLog;
105
+ const kind = platform === "darwin"
106
+ ? "macos"
107
+ : platform === "linux" && env.HYPRLAND_INSTANCE_SIGNATURE
108
+ ? "hyprland"
109
+ : platform === "linux" && env.SWAYSOCK
110
+ ? "sway"
111
+ : "none";
112
+ const raiser = kind === "macos"
113
+ ? macos(exec, timeoutMs, table, log)
114
+ : kind === "hyprland"
115
+ ? hyprland(exec, timeoutMs)
116
+ : kind === "sway"
117
+ ? sway(exec, timeoutMs)
118
+ : undefined;
86
119
  return {
120
+ kind,
87
121
  async raise(pids) {
88
- if (!wm || pids.length === 0)
122
+ if (!raiser)
89
123
  return false;
124
+ if (pids.length === 0) {
125
+ raiser.noPids?.();
126
+ return false;
127
+ }
90
128
  try {
91
- const windows = await wm.windows();
129
+ const targetOf = await raiser.prepare();
130
+ const chains = [];
92
131
  for (const pid of pids) {
93
- for (const p of await ancestry(procRoot, pid)) {
94
- const target = windows.get(p);
132
+ const chain = await ancestry(table, pid);
133
+ chains.push(chain);
134
+ for (const p of chain) {
135
+ const target = await targetOf(p);
95
136
  if (target !== undefined) {
96
- await wm.focus(target);
137
+ await raiser.focus(target);
97
138
  return true;
98
139
  }
99
140
  }
100
141
  }
142
+ await raiser.notFound?.(chains);
101
143
  }
102
144
  catch {
103
145
  // no compositor, timeout, bad output: just don't raise
@@ -0,0 +1,27 @@
1
+ import { execFile } from "node:child_process";
2
+ export const defaultExec = (file, args, opts) => new Promise((resolve, reject) => {
3
+ execFile(file, args, { timeout: opts.timeout, maxBuffer: 16 << 20, encoding: "utf8" }, (err, stdout, stderr) => {
4
+ if (err)
5
+ reject(Object.assign(err, { stderr }));
6
+ else
7
+ resolve({ stdout });
8
+ });
9
+ });
10
+ /** "`cmd args` failed: <stderr, else message>" for logs. */
11
+ export function describeExecFailure(file, args, err) {
12
+ const e = err;
13
+ const stderr = typeof e?.stderr === "string" ? e.stderr.trim() : "";
14
+ const detail = stderr || (typeof e?.message === "string" ? e.message : String(err));
15
+ return `\`${[file, ...args].join(" ")}\` failed: ${detail}`;
16
+ }
17
+ export const defaultLog = (m) => console.warn(`excaliagent: ${m}`);
18
+ /** Wraps a logger so each key is reported at most once. */
19
+ export function logOnce(log) {
20
+ const seen = new Set();
21
+ return (key, message) => {
22
+ if (seen.has(key))
23
+ return;
24
+ seen.add(key);
25
+ log(message);
26
+ };
27
+ }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Minimal process information, portable across Linux and macOS.
3
+ *
4
+ * - linux: /proc (stat, comm, cmdline, environ, exe). No subprocesses.
5
+ * - darwin: `ps -axww -o pid=,ppid=,comm=` (comm is the full executable path
6
+ * on macOS), `ps -ww -o command= -p N` for argv and `ps -E -ww -o command= -p N`
7
+ * for the environment (own-user processes only; -E = "display the environment"). argv/env are split on
8
+ * whitespace, so arguments or values containing spaces are approximate.
9
+ * Unverified on real hardware; CI runs the parsers against fixtures.
10
+ * - anything else: an empty table.
11
+ * Every method fails soft (empty / undefined).
12
+ */
13
+ import { readdir, readFile, readlink } from "node:fs/promises";
14
+ import { join } from "node:path";
15
+ import { defaultExec, defaultLog, describeExecFailure, logOnce } from "./exec.js";
16
+ const read = (p) => readFile(p, "utf8").catch(() => undefined);
17
+ function parseStat(stat) {
18
+ const open = stat.indexOf("(");
19
+ const close = stat.lastIndexOf(")");
20
+ if (open < 0 || close < open)
21
+ return undefined;
22
+ const ppid = Number(stat.slice(close + 1).trim().split(/\s+/)[1]);
23
+ return Number.isInteger(ppid) ? { comm: stat.slice(open + 1, close), ppid } : undefined;
24
+ }
25
+ function linuxTable(procRoot) {
26
+ const stat = async (pid) => {
27
+ const s = await read(join(procRoot, String(pid), "stat"));
28
+ return s === undefined ? undefined : parseStat(s);
29
+ };
30
+ return {
31
+ async list() {
32
+ let entries;
33
+ try {
34
+ entries = await readdir(procRoot);
35
+ }
36
+ catch {
37
+ return [];
38
+ }
39
+ const out = await Promise.all(entries
40
+ .filter((e) => /^\d+$/.test(e))
41
+ .map(async (e) => {
42
+ const s = await stat(Number(e));
43
+ return s ? { pid: Number(e), ppid: s.ppid, comm: s.comm } : undefined;
44
+ }));
45
+ return out.filter((p) => p !== undefined);
46
+ },
47
+ async parent(pid) {
48
+ const ppid = (await stat(pid))?.ppid;
49
+ return ppid !== undefined && ppid > 0 ? ppid : undefined;
50
+ },
51
+ async argv(pid) {
52
+ return (await read(join(procRoot, String(pid), "cmdline")))?.split("\0").filter(Boolean);
53
+ },
54
+ async env(pid) {
55
+ const environ = await read(join(procRoot, String(pid), "environ"));
56
+ if (environ === undefined)
57
+ return undefined;
58
+ const env = {};
59
+ for (const kv of environ.split("\0")) {
60
+ const i = kv.indexOf("=");
61
+ if (i > 0)
62
+ env[kv.slice(0, i)] = kv.slice(i + 1);
63
+ }
64
+ return env;
65
+ },
66
+ async exe(pid) {
67
+ return readlink(join(procRoot, String(pid), "exe")).catch(() => undefined);
68
+ },
69
+ };
70
+ }
71
+ /** Lines of `ps -o pid=,ppid=,comm=`; comm runs to end of line (may contain spaces). */
72
+ export function parsePsList(out) {
73
+ const list = [];
74
+ for (const line of out.split("\n")) {
75
+ const m = /^\s*(\d+)\s+(\d+)\s(.*)$/.exec(line);
76
+ if (m)
77
+ list.push({ pid: Number(m[1]), ppid: Number(m[2]), comm: m[3].trim() });
78
+ }
79
+ return list;
80
+ }
81
+ /**
82
+ * Environment from `ps -E -ww -o command=`: the command line followed by
83
+ * KEY=VALUE pairs. The known argv prefix is skipped; a token that is not
84
+ * KEY=VALUE continues the previous value (values with spaces).
85
+ */
86
+ export function parsePsEnv(out, argv = []) {
87
+ let rest = out.trim();
88
+ const cmd = argv.join(" ");
89
+ if (cmd && rest.startsWith(cmd))
90
+ rest = rest.slice(cmd.length);
91
+ else if (argv.length > 0)
92
+ return {};
93
+ const env = {};
94
+ let last;
95
+ for (const tok of rest.split(/\s+/).filter(Boolean)) {
96
+ const m = /^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/.exec(tok);
97
+ if (m) {
98
+ last = m[1];
99
+ env[last] = m[2];
100
+ }
101
+ else if (last !== undefined) {
102
+ env[last] += " " + tok;
103
+ }
104
+ }
105
+ return env;
106
+ }
107
+ function darwinTable(exec, timeout, cacheMs, log) {
108
+ const once = logOnce(log);
109
+ const ps = async (args, key) => {
110
+ try {
111
+ return (await exec("ps", args, { timeout })).stdout;
112
+ }
113
+ catch (e) {
114
+ once(key, `process table: ${describeExecFailure("ps", args, e)}`);
115
+ return undefined;
116
+ }
117
+ };
118
+ let cached;
119
+ const list = () => {
120
+ if (!cached || Date.now() - cached.at > cacheMs) {
121
+ const listing = ps(["-axww", "-o", "pid=,ppid=,comm="], "list").then((out) => (out === undefined ? [] : parsePsList(out)));
122
+ cached = { at: Date.now(), list: listing };
123
+ }
124
+ return cached.list;
125
+ };
126
+ // A process that exited meanwhile also makes ps fail: not worth a log line each.
127
+ const argv = async (pid) => {
128
+ const out = await ps(["-ww", "-o", "command=", "-p", String(pid)], "argv");
129
+ const parts = out?.trim().split(/\s+/).filter(Boolean) ?? [];
130
+ return parts.length > 0 ? parts : undefined;
131
+ };
132
+ return {
133
+ list,
134
+ async parent(pid) {
135
+ const ppid = (await list()).find((p) => p.pid === pid)?.ppid;
136
+ return ppid !== undefined && ppid > 0 ? ppid : undefined;
137
+ },
138
+ argv,
139
+ async env(pid) {
140
+ const args = await argv(pid);
141
+ if (!args)
142
+ return undefined;
143
+ const out = await ps(["-E", "-ww", "-o", "command=", "-p", String(pid)], "env");
144
+ return out === undefined ? undefined : parsePsEnv(out, args);
145
+ },
146
+ async exe(pid) {
147
+ const comm = (await list()).find((p) => p.pid === pid)?.comm;
148
+ return comm?.startsWith("/") ? comm : undefined;
149
+ },
150
+ };
151
+ }
152
+ const emptyTable = {
153
+ list: async () => [],
154
+ parent: async () => undefined,
155
+ argv: async () => undefined,
156
+ env: async () => undefined,
157
+ exe: async () => undefined,
158
+ };
159
+ export function createProcessTable(opts = {}) {
160
+ const { platform = process.platform, procRoot = "/proc", exec = defaultExec, timeoutMs = 2000, cacheMs = 1000 } = opts;
161
+ const log = opts.log ?? defaultLog;
162
+ if (platform === "linux")
163
+ return linuxTable(procRoot);
164
+ if (platform === "darwin")
165
+ return darwinTable(exec, timeoutMs, cacheMs, log);
166
+ return emptyTable;
167
+ }
@@ -1,58 +1,37 @@
1
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.
2
+ * Find herdr client processes (the TUI attached to a herdr server): processes
3
+ * whose executable name is "herdr" and that have no "server" argument. Clients
4
+ * whose socket is ours are preferred; if none can be tied to it (environment
5
+ * unreadable), every client is returned.
7
6
  */
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
- }
7
+ import { basename, join } from "node:path";
8
+ /**
9
+ * herdr's API socket for an environment (checked on herdr 0.9.0 / Linux):
10
+ * HERDR_SOCKET_PATH, else $XDG_CONFIG_HOME/herdr/herdr.sock, else
11
+ * $HOME/.config/herdr/herdr.sock. The binary has no macOS-specific path
12
+ * (no ~/Library); assumed the same there (unverified on real hardware).
13
+ */
14
+ export function herdrSocketPath(env, home) {
15
+ if (env.HERDR_SOCKET_PATH)
16
+ return env.HERDR_SOCKET_PATH;
17
+ if (env.XDG_CONFIG_HOME)
18
+ return join(env.XDG_CONFIG_HOME, "herdr", "herdr.sock");
19
+ const h = env.HOME || home;
20
+ return h ? join(h, ".config", "herdr", "herdr.sock") : undefined;
17
21
  }
18
22
  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 = [];
23
+ const { table } = opts;
24
+ const candidates = (await table.list()).filter((p) => basename(p.comm) === "herdr");
25
+ const all = [];
28
26
  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);
27
+ await Promise.all(candidates.map(async ({ pid }) => {
28
+ const argv = await table.argv(pid);
29
+ if (argv?.slice(1).includes("server"))
42
30
  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)
31
+ all.push(pid);
32
+ const env = await table.env(pid);
33
+ if (env && herdrSocketPath(env) === opts.socketPath)
55
34
  ours.push(pid);
56
35
  }));
57
- return (ours.length > 0 ? ours : unknown).sort((a, b) => a - b);
36
+ return (ours.length > 0 ? ours : all).sort((a, b) => a - b);
58
37
  }
@@ -7,7 +7,8 @@
7
7
  import { homedir } from "node:os";
8
8
  import { basename, join } from "node:path";
9
9
  import { createHerdrClient, HerdrError } from "./herdr-client.js";
10
- import { findHerdrClientPids } from "./herdr-clients.js";
10
+ import { createProcessTable } from "../desktop/process-table.js";
11
+ import { findHerdrClientPids, herdrSocketPath } from "./herdr-clients.js";
11
12
  export { createNoPaneLink } from "./none.js";
12
13
  export const HERDR_SUBSCRIPTIONS = [
13
14
  { type: "pane.created" },
@@ -46,7 +47,7 @@ export function pickWorkspace(panes, root) {
46
47
  return pick ? (pick.workspace_id ?? workspaceOf(pick.pane_id)) : undefined;
47
48
  }
48
49
  export function defaultHerdrSocketPath() {
49
- return process.env.HERDR_SOCKET_PATH || join(homedir(), ".config/herdr/herdr.sock");
50
+ return herdrSocketPath(process.env, homedir()) ?? join(homedir(), ".config", "herdr", "herdr.sock");
50
51
  }
51
52
  const workspaceOf = (paneId) => paneId.split(":")[0] ?? paneId;
52
53
  /** pid → pane for every foreground process of every pane; `panes` supplies ids and labels. */
@@ -79,7 +80,8 @@ function sameMap(a, b) {
79
80
  export function createHerdrLink(opts = {}) {
80
81
  const { resyncMs = 30_000 } = opts;
81
82
  const socketPath = opts.socketPath ?? defaultHerdrSocketPath();
82
- const clientPids = () => findHerdrClientPids({ socketPath, procRoot: opts.procRoot });
83
+ const table = opts.processTable ?? createProcessTable();
84
+ const clientPids = () => findHerdrClientPids({ socketPath, table });
83
85
  let map = new Map();
84
86
  const listeners = new Set();
85
87
  let closed = false;
@@ -1 +1 @@
1
- import{n as e}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as t}from"./src-BWF7jMDv.js";import"./chunk-DU6HZSFF-W9nFVr4b.js";import"./dist-BPnbDAwD.js";import{n,r,t as i}from"./chunk-SVP7TREG-Bbvoxr5d.js";import{t as a}from"./chunk-JWPE2WC7-DVXcaiue.js";import{E as o,t as s}from"./mermaid-parser.core-DA_7CZUN.js";var c=o().RailroadAbnf.parser.LangiumParser,l=e(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=e(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=e(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=e(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=e(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=e(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=e(e=>{a(e,i),e.title&&i.setTitle(e.title),e.rules.map(e=>i.addRule(m(e)))},`populateDb`),g={parser:{parse:e(e=>{i.clear(),t.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new s(n);let r=n.value;t.debug(`[ABNF Parser] Parsed rules:`,r.rules.length),h(r),t.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:i}},db:i,renderer:r,styles:n};export{g as diagram};
1
+ import{n as e}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as t}from"./src-BWF7jMDv.js";import"./chunk-DU6HZSFF-DYHa8ENH.js";import"./dist-D-3cz42D.js";import{n,r,t as i}from"./chunk-SVP7TREG-CaeKcCSu.js";import{t as a}from"./chunk-JWPE2WC7-DVXcaiue.js";import{E as o,t as s}from"./mermaid-parser.core-Da_XEVmR.js";var c=o().RailroadAbnf.parser.LangiumParser,l=e(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=e(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=e(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=e(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=e(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=e(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=e(e=>{a(e,i),e.title&&i.setTitle(e.title),e.rules.map(e=>i.addRule(m(e)))},`populateDb`),g={parser:{parse:e(e=>{i.clear(),t.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new s(n);let r=n.value;t.debug(`[ABNF Parser] Parsed rules:`,r.rules.length),h(r),t.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:i}},db:i,renderer:r,styles:n};export{g as diagram};