collabmd 0.1.48 → 0.1.51

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 (482) hide show
  1. package/README.md +15 -608
  2. package/bin/collabmd.js +39 -20
  3. package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-Crf9Y3Q6.js +1 -0
  4. package/dist/client/assets/abnfDiagram-VCTEODGH-PuinKbSQ.js +1 -0
  5. package/dist/client/assets/ar-SA-5WIASEJP-Di7OimCN.js +10 -0
  6. package/dist/client/assets/{architectureDiagram-5GKGNRK7-I39sYjHI.js → architectureDiagram-5GKGNRK7-46hPkrZv.js} +3 -3
  7. package/dist/client/assets/az-AZ-V5EUQD6C-C19OGTT_.js +1 -0
  8. package/dist/client/assets/bg-BG-EXASCMTR-BIt0xWyb.js +5 -0
  9. package/dist/client/assets/{blockDiagram-NRAW4CY4-C6DtJy5Y.js → blockDiagram-I7D4REHJ-C1S5Bzf8.js} +4 -4
  10. package/dist/client/assets/bn-BD-U4SYNFCO-CdNaPy4Q.js +3 -0
  11. package/dist/client/assets/bn-IN-HKDJIITE-CdNaPy4Q.js +3 -0
  12. package/dist/client/assets/{browser-BKLM0ThC-IxjwuOIz-BBqQnUEb.js → browser-BKLM0ThC-IxjwuOIz-DyJcVMFR.js} +1 -1
  13. package/dist/client/assets/browser-utils-DbXSMI-6.js +1 -0
  14. package/dist/client/assets/{c4Diagram-UCG6FXSJ-CtWtxS9_.js → c4Diagram-7LVT6UL2-VAk1HPmz.js} +1 -1
  15. package/dist/client/assets/ca-ES-2KGUU5XB-C9t-c0cH.js +8 -0
  16. package/dist/client/assets/channel-jwdhnPiV.js +1 -0
  17. package/dist/client/assets/chunk-2E4U76K2-Ba8Wf22k.js +1 -0
  18. package/dist/client/assets/{chunk-TEH6E4GO-DVayPj-q.js → chunk-4HAMMTFA-Ht-73lsT.js} +20 -20
  19. package/dist/client/assets/chunk-5XKZK2GL-D4UAZSOJ.js +1 -0
  20. package/dist/client/assets/{chunk-75Z2AOVW-CdFSaPjz.js → chunk-75Z2AOVW-B2cZexqK.js} +1 -1
  21. package/dist/client/assets/{chunk-CLGD4ZFX-DQLgbQrv.js → chunk-CLGD4ZFX-Cmtx89ht.js} +1 -1
  22. package/dist/client/assets/chunk-DU6HZSFF-C6d6PJfE.js +127 -0
  23. package/dist/client/assets/{chunk-F27PBJKO-CNHIFhjo.js → chunk-F27PBJKO-Dg3H6KLL.js} +1 -1
  24. package/dist/client/assets/{chunk-GMAD6QVW-CbcBqPM5.js → chunk-GMAD6QVW-DUfjx_d5.js} +1 -1
  25. package/dist/client/assets/{chunk-OBVCFTLP-BJR7u1jh.js → chunk-GVQU2GXP-D1l7oRGR.js} +1 -1
  26. package/dist/client/assets/{chunk-G27WJ6UU-D9-eg537.js → chunk-IMKFNOWR-3F6NhHUP.js} +2 -2
  27. package/dist/client/assets/{chunk-JQ64N6SF-DSFNH4bh.js → chunk-L3NEJ4N5-BmCVn4y-.js} +1 -1
  28. package/dist/client/assets/chunk-OSK3NFVY-CWHXAmfx.js +10 -0
  29. package/dist/client/assets/{chunk-P2QGCYS3-BRpqY32H.js → chunk-P2QGCYS3-Du8EtwOa.js} +1 -1
  30. package/dist/client/assets/{chunk-POPQ4Y6H-Cb4SlVZF.js → chunk-POPQ4Y6H-B5yJIrZE.js} +1 -1
  31. package/dist/client/assets/{chunk-PWAF6VOD-Cz8IwBB5.js → chunk-PWAF6VOD-B3gML4ps.js} +1 -1
  32. package/dist/client/assets/{chunk-RHFEMEQ7-CWY8cf4H.js → chunk-SHT3W25Y-BKaI8jZO.js} +5 -5
  33. package/dist/client/assets/{chunk-SVP7TREG-CyHOmcac.js → chunk-SVP7TREG-XlsB_ZMZ.js} +1 -1
  34. package/dist/client/assets/{chunk-LCL6LL3I-DmDkVukh.js → chunk-TICWLB2K-Cpp2z8yK.js} +4 -4
  35. package/dist/client/assets/chunk-TLUHSLCS-Yl7B0Vrz.js +1 -0
  36. package/dist/client/assets/chunk-ZNVOA63L-BmCQjhx-.js +40 -0
  37. package/dist/client/assets/{chunk-FLYJHZSQ-Be7lKF17.js → chunk-ZPMXAHWN-Dt0TxJa6.js} +2 -2
  38. package/dist/client/assets/classDiagram-ZZMXUADV-BRw9vo8U.js +1 -0
  39. package/dist/client/assets/classDiagram-v2-VYDZK3BY-BRw9vo8U.js +1 -0
  40. package/dist/client/assets/comment-markdown-renderer-B9_vPc3F.js +1 -0
  41. package/dist/client/assets/comment-thread-store-NNHqRVsX.js +1 -0
  42. package/dist/client/assets/comment-threads-nJhK1yfc.js +4 -0
  43. package/dist/client/assets/cs-CZ-VUCGPRML-BfCoYAgj.js +7 -0
  44. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-CdTPi2yO.js → cynefinDiagram-5FMLGOSQ-BRoCEoZM.js} +1 -1
  45. package/dist/client/assets/da-DK-NNDP2IVP-DBw9ZNTR.js +2 -0
  46. package/dist/client/assets/{dagre-3AP2YEHR-5gtJtd0O.js → dagre-GXQ25YYZ-BSfKCfy7.js} +2 -2
  47. package/dist/client/assets/de-CH-I7RAVIZN-DYW18Vsr.js +11 -0
  48. package/dist/client/assets/de-DE-WBQ3DQLR-DYW18Vsr.js +11 -0
  49. package/dist/client/assets/deferred-collab-rBe4nuQ2.css +1 -0
  50. package/dist/client/assets/deferred-git-BHKtkFYi.css +1 -0
  51. package/dist/client/assets/deferred-preview-pe7Iwwx3.css +1 -0
  52. package/dist/client/assets/{diagram-S7CK7UJ4-BudWz9WU.js → diagram-S7CK7UJ4-D7KaM9yj.js} +2 -2
  53. package/dist/client/assets/{diagram-UQ7AKVKN-3v4rbH-s.js → diagram-UQ7AKVKN-JevUZuYi.js} +1 -1
  54. package/dist/client/assets/diagram-VSXAHHWV-B3-U-Q2E.js +3 -0
  55. package/dist/client/assets/{diagram-VX7I27RA-C_-rj0sw.js → diagram-VX7I27RA-pSD4HMh1.js} +1 -1
  56. package/dist/client/assets/{diagram-Z3DM3KII-B4yxavgj.js → diagram-Z3DM3KII-D8r1_CIb.js} +1 -1
  57. package/dist/client/assets/{direct-engine-DdrQKpgq-CtKfQzCt.js → direct-engine-DdrQKpgq-B5zIoeQw.js} +1 -1
  58. package/dist/client/assets/dist-B3HdUPsK.js +1 -0
  59. package/dist/client/assets/{dist-Tw-Fxpeb.js → dist-B7XMN9AT.js} +1 -1
  60. package/dist/client/assets/dist-BIRygGYH.js +1 -0
  61. package/dist/client/assets/dist-BPyOlNLY.js +2 -0
  62. package/dist/client/assets/{dist-D5wCC32z.js → dist-BR81yxMt.js} +1 -1
  63. package/dist/client/assets/{dist-Bw3VIE_v.js → dist-B_B4XLmq.js} +1 -1
  64. package/dist/client/assets/dist-Bdy9ZRzd.js +9 -0
  65. package/dist/client/assets/{dist-netZOQtD.js → dist-Bfxzlnrf.js} +1 -1
  66. package/dist/client/assets/{dist-CietwTVS.js → dist-Bx3QkS-3.js} +1 -1
  67. package/dist/client/assets/{dist-mj2Ht75J.js → dist-By7ieqAf.js} +1 -1
  68. package/dist/client/assets/dist-ByhQbe-x.js +1 -0
  69. package/dist/client/assets/{dist-CdmKGRGr.js → dist-BzFSJM0U.js} +1 -1
  70. package/dist/client/assets/dist-C5NkYKAa.js +1 -0
  71. package/dist/client/assets/{dist-D3fehAZ2.js → dist-CELhfKzh.js} +1 -1
  72. package/dist/client/assets/dist-CEirJSxk.js +1 -0
  73. package/dist/client/assets/dist-CO0-4CuV.js +39 -0
  74. package/dist/client/assets/dist-CRnJ0D9h.js +1 -0
  75. package/dist/client/assets/{dist-DDUn5zTz.js → dist-CbDyXgCo.js} +1 -1
  76. package/dist/client/assets/{dist-BeajGMhO.js → dist-CqXVyYoH.js} +1 -1
  77. package/dist/client/assets/{dist-LQ4kDCKz.js → dist-CrWzIWEE.js} +1 -1
  78. package/dist/client/assets/dist-CyNrloSI.js +1 -0
  79. package/dist/client/assets/dist-D60_kdpQ.js +1 -0
  80. package/dist/client/assets/{dist-DuH3ZrHo.js → dist-DCpIH3-_.js} +1 -1
  81. package/dist/client/assets/{dist-BPHLJ09L.js → dist-DJAMplZI.js} +2 -2
  82. package/dist/client/assets/{dist-DGEbEfw4.js → dist-DVXzbeDx.js} +1 -1
  83. package/dist/client/assets/{dist-C5NgpdG5.js → dist-Drv_wZYC.js} +1 -1
  84. package/dist/client/assets/{dist-DVy5woUy.js → dist-EWJYvBK1.js} +1 -1
  85. package/dist/client/assets/dist-Hdhj3L3t.js +1 -0
  86. package/dist/client/assets/{dist-B_yQaEv_.js → dist-gRRhmB-2.js} +3 -3
  87. package/dist/client/assets/dist-kWb2d1CH.js +1 -0
  88. package/dist/client/assets/dist-kiD2GIsD.js +13 -0
  89. package/dist/client/assets/dist-l-56SowH.js +19 -0
  90. package/dist/client/assets/{dist-BK9QvQrc.js → dist-nxQErAaK.js} +2 -2
  91. package/dist/client/assets/dist-sLzRQQk7.js +1 -0
  92. package/dist/client/assets/{document-formatter-Dxl_a8XO.js → document-formatter-Qdiq9uJs.js} +1 -2
  93. package/dist/client/assets/drawioEditor-CHf1vtdQ.js +9 -0
  94. package/dist/client/assets/ebnfDiagram-PWID7BFC-UJ0Fz5ci.js +1 -0
  95. package/dist/client/assets/editor-session-4Bn81iWm.js +14 -0
  96. package/dist/client/assets/el-GR-TYQHVGXW-Dx82YYAS.js +7 -0
  97. package/dist/client/assets/embedded-editor-base-jK221GC8.css +1 -0
  98. package/dist/client/assets/{embedpdf-DA4bA119-BPqZxwjc.js → embedpdf-DA4bA119-E8wZ11J2.js} +2 -3
  99. package/dist/client/assets/{embedpdf-BmE13ZZ0.js → embedpdf-LUXDBD3-.js} +1 -1
  100. package/dist/client/assets/{en-SJ2YIMFF-CJBL3nkq.js → en-2RFA324Y-BsuNJTcL.js} +1 -1
  101. package/dist/client/assets/{erDiagram-SSCWMZ5O-C-iy6VkX.js → erDiagram-RLTQ6QDP-CWrH1UJ9.js} +2 -2
  102. package/dist/client/assets/es-ES-JEUOREKJ-Rx0NUQDl.js +12 -0
  103. package/dist/client/assets/eu-ES-SO5DEEAN-CDYm-BcK.js +8 -0
  104. package/dist/client/assets/excalidraw-element-link-iA6zo0_f.js +7 -0
  105. package/dist/client/assets/{excalidraw-scene-BOben2gr.js → excalidraw-scene-6uROebca.js} +1 -1
  106. package/dist/client/assets/{excalidraw-editor-BbSbI80a.css → excalidrawEditor-DDE0n1Pk.css} +1 -1
  107. package/dist/client/assets/excalidrawEditor-WIuguTz7.js +9 -0
  108. package/dist/client/assets/export-page-AN-wI5p4.js +56 -0
  109. package/dist/client/assets/exportDocument-B7IagJhQ.css +1 -0
  110. package/dist/client/assets/exportDocument-B9xNKpQe.js +2 -0
  111. package/dist/client/assets/fa-IR-FIYUE2GQ-C865Nx3X.js +9 -0
  112. package/dist/client/assets/fi-FI-REAEF6HQ-BIpjJqIb.js +6 -0
  113. package/dist/client/assets/flowDiagram-HODETNUW-kb1lUSBo.js +1 -0
  114. package/dist/client/assets/fr-FR-SUCL7J6B-DGAKE8jH.js +12 -0
  115. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-DtKHAbez.js → ganttDiagram-EL5Y4UJY-BBNzDfaV.js} +1 -1
  116. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-oue8fQ5o.js → gitGraphDiagram-WWUBYQGX-Csf0Dm_1.js} +1 -1
  117. package/dist/client/assets/gl-ES-KHCSOGVH-DWKh0CMu.js +6 -0
  118. package/dist/client/assets/he-IL-JYXVXV2Q-zqbcM-4g.js +9 -0
  119. package/dist/client/assets/hi-IN-BU52H3BO-CY8v6eG9.js +3 -0
  120. package/dist/client/assets/highlight-theme-CzNkO-IJ.js +1 -0
  121. package/dist/client/assets/hu-HU-OWADXDQ3-CEl6Udfh.js +3 -0
  122. package/dist/client/assets/id-ID-EOMR5R3I-CGQwUjoL.js +8 -0
  123. package/dist/client/assets/image-2QKV3NAF-BUbX0y5Y.js +1 -0
  124. package/dist/client/assets/index-BAmZnTFV.css +1 -0
  125. package/dist/client/assets/index-mWiw418b.js +1111 -0
  126. package/dist/client/assets/{infoDiagram-RXCK75RN-BMzo6KIn.js → infoDiagram-27XIBGKW-Bzy6kCbb.js} +1 -1
  127. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-BIM3h287.js → ishikawaDiagram-5VMMS53U-CRy9vIS5.js} +1 -1
  128. package/dist/client/assets/it-IT-FC2VTM3L-KTijNcUe.js +12 -0
  129. package/dist/client/assets/ja-JP-JBNTKYP4-BflWlGhw.js +12 -0
  130. package/dist/client/assets/{journeyDiagram-EYS64GPL-mF6Lh8O-.js → journeyDiagram-3NMN7TZE-D4ZR_s9J.js} +2 -2
  131. package/dist/client/assets/kaa-TC3VIB7V-B-xtZfy0.js +1 -0
  132. package/dist/client/assets/kab-KAB-UOUDSQKM-BmO0O4Y4.js +4 -0
  133. package/dist/client/assets/{kanban-definition-3QL26DDD-DLN2NyoR.js → kanban-definition-UXKFOSKX-CIDTmu5g.js} +4 -4
  134. package/dist/client/assets/kk-KZ-P5H2X7YS-CSQFB8IN.js +1 -0
  135. package/dist/client/assets/{km-KH-PCWDKPHP-DSmy5shj.js → km-KH-IHMV2US7-BxrjuEzr.js} +4 -4
  136. package/dist/client/assets/ko-KR-ZTMANIDF-BnNRXd5J.js +5 -0
  137. package/dist/client/assets/ku-TR-GPJTRB5G-BZM7f2aT.js +6 -0
  138. package/dist/client/assets/{line-BfTWJmgf.js → line-DSWLHgpx.js} +1 -1
  139. package/dist/client/assets/lobby-presence-Rdjnc0_0.js +1 -0
  140. package/dist/client/assets/lt-LT-V3XDOK3P-MVQBOHmF.js +3 -0
  141. package/dist/client/assets/lv-LV-DVQ3FADO-CrenwAhS.js +4 -0
  142. package/dist/client/assets/markdown-it-CocJWnjv.js +13 -0
  143. package/dist/client/assets/mermaid-parser.core-DrdLA3p0.js +3 -0
  144. package/dist/client/assets/mermaid.core-C_FK-7n4.js +1 -0
  145. package/dist/client/assets/mermaid.core-D0cMM4Rl.js +10 -0
  146. package/dist/client/assets/{mindmap-definition-FBJOCRG2-CRyHaHTk.js → mindmap-definition-YA3MSWOX-DO8NB9VH.js} +8 -8
  147. package/dist/client/assets/mr-IN-VZ6HH5FE-B-PHPglH.js +9 -0
  148. package/dist/client/assets/my-MM-XYKWHRK6-Be5sYp5q.js +1 -0
  149. package/dist/client/assets/nb-NO-UNO2GGZJ-BvSKGdja.js +8 -0
  150. package/dist/client/assets/nl-NL-76EFHT4P-C2yNx1Cj.js +13 -0
  151. package/dist/client/assets/nn-NO-CFKD7ABE-4NsqlDRP.js +4 -0
  152. package/dist/client/assets/oc-FR-YBJTCJ3J-B4OTQsWW.js +4 -0
  153. package/dist/client/assets/pa-IN-SNOXSMRV-CKj_sOG7.js +4 -0
  154. package/dist/client/assets/pegDiagram-XKGWAZYB-DS6Ab21R.js +1 -0
  155. package/dist/client/assets/percentages-Q7USCRWZ-DWE6uvTs.js +1 -0
  156. package/dist/client/assets/{pieDiagram-E7YTZNPT-B5OZPb88.js → pieDiagram-E7YTZNPT-BbFe6Tgs.js} +1 -1
  157. package/dist/client/assets/pl-PL-BSY6YFZ3-CFuzA6L0.js +12 -0
  158. package/dist/client/assets/preload-helper-CtT0-S4g.js +1 -0
  159. package/dist/client/assets/preview-render-compiler-C_7J7eia.js +43 -0
  160. package/dist/client/assets/preview-render-compiler-DzJ1KR_M.js +1 -0
  161. package/dist/client/assets/preview-render-worker-1DoIDllV.js +59 -0
  162. package/dist/client/assets/prod-D5TxmmoB.js +1 -0
  163. package/dist/client/assets/prod-pbFU4TaM.js +145 -0
  164. package/dist/client/assets/pt-BR-CZDV62R3-CkPMtyNx.js +10 -0
  165. package/dist/client/assets/pt-PT-JO57XJJW-CBSnfGtF.js +12 -0
  166. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-Drrw14YH.js → quadrantDiagram-AXDQQJYC-fJE7iAxt.js} +1 -1
  167. package/dist/client/assets/quick-switcher-De4PjZFC.css +1 -0
  168. package/dist/client/assets/quick-switcher-controller-CUajuy78.js +1 -0
  169. package/dist/client/assets/railroadDiagram-O6MQD6OU-CUQKqbCK.js +1 -0
  170. package/dist/client/assets/{requirementDiagram-EFPCY7ZU-CRZG6mRB.js → requirementDiagram-BXWQKSXE-Balm0WW8.js} +2 -2
  171. package/dist/client/assets/ro-RO-UZ5ICYYN-BOuntc_r.js +12 -0
  172. package/dist/client/assets/room-DX7lIfnu.js +1 -0
  173. package/dist/client/assets/ru-RU-AN7JPREC-D-ow3SNR.js +10 -0
  174. package/dist/client/assets/runtime-config-BFVdhnJu.js +1 -0
  175. package/dist/client/assets/runtime-paths-Cn0snt_9.js +1 -0
  176. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-DvarEJpo.js → sankeyDiagram-P5KCCOFB-CcbMqrlQ.js} +1 -1
  177. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-B4oWlb-w.js → sequenceDiagram-WJ2MYXX4-BL1j3Sn-.js} +6 -6
  178. package/dist/client/assets/si-LK-7CBLD6QQ-c91EepX0.js +1 -0
  179. package/dist/client/assets/sk-SK-SWR6DKBI-D5vFMIL6.js +7 -0
  180. package/dist/client/assets/sl-SI-JRML4FIH-D53L_0S2.js +6 -0
  181. package/dist/client/assets/{stateDiagram-HBIQ2CUA-qbHIIqRZ.js → stateDiagram-D77RDMKH-DNi924hh.js} +1 -1
  182. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-C62JEwak.js +1 -0
  183. package/dist/client/assets/sv-SE-4ZPKFFXF-DT-G7RCI.js +12 -0
  184. package/dist/client/assets/{swimlanes-XN3QIQJK-xB6CtUGj.js → swimlanes-42K2YHIH-ColgjSH4.js} +1 -1
  185. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-B9UZhEj4.js +8 -0
  186. package/dist/client/assets/ta-IN-V6NHHU6Z-D5jy7_AE.js +6 -0
  187. package/dist/client/assets/th-TH-P7CTMGDK-6sy0NO7K.js +1 -0
  188. package/dist/client/assets/{timeline-definition-24CTP7MA-Lj_yTNlY.js → timeline-definition-24CTP7MA-7pch5JAr.js} +1 -1
  189. package/dist/client/assets/tr-TR-GUFYG22B-ClVaf8h1.js +4 -0
  190. package/dist/client/assets/uk-UA-K6SV5NFQ-BLTTtyNB.js +6 -0
  191. package/dist/client/assets/uz-UZ-TVKTZO2G-Bm02Eg3D.js +1 -0
  192. package/dist/client/assets/vault-api-client-QjZ_T03l.js +7 -0
  193. package/dist/client/assets/vault-utils-Bct69Xw2.js +1 -0
  194. package/dist/client/assets/{vennDiagram-4TSXK5OY-BekRp5Y0.js → vennDiagram-4TSXK5OY-C5taziCX.js} +1 -1
  195. package/dist/client/assets/vi-VN-7FKFXJNO-CL3WPhmG.js +7 -0
  196. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-kdnV_Hdm.js → wardleyDiagram-VM6X3IG4-BbSlUwuM.js} +1 -1
  197. package/dist/client/assets/wiki-link-resolver-C2P_WmTV.js +1 -0
  198. package/dist/client/assets/{worker-engine-m0rlHn8R-S8mpn_O0.js → worker-engine-m0rlHn8R-eSDcDGEI.js} +1 -1
  199. package/dist/client/assets/workspace-change-CVA9dVmy.js +1 -0
  200. package/dist/client/assets/workspace-sync-client-D4nblH_2.js +1 -0
  201. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-DufGwNSB.js → xychartDiagram-S5SC5T6Z-D06X1arY.js} +1 -1
  202. package/dist/client/assets/yjs-B41tM6Sz.js +4 -0
  203. package/dist/client/assets/yjs-provider-reset-guard-R43MnLNc.js +1 -0
  204. package/dist/client/assets/zh-CN-AOKVLNNK-DGidDH2b.js +11 -0
  205. package/dist/client/assets/zh-HK-CDKPF5DC-CRcNR3rk.js +1 -0
  206. package/dist/client/assets/zh-TW-ZVGYESGW-C7Qji1y6.js +13 -0
  207. package/dist/client/drawio-editor.html +12 -5
  208. package/dist/client/excalidraw-editor.html +46 -5
  209. package/dist/client/export-document.html +6 -8
  210. package/dist/client/index.html +79 -43
  211. package/package.json +39 -36
  212. package/src/client/app/drawio-editor.html +3 -3
  213. package/src/client/app/excalidraw-editor.html +3 -3
  214. package/src/client/app/export-document.html +2 -2
  215. package/src/client/app/index.html +77 -37
  216. package/src/client/app/main-entry.js +13 -17
  217. package/src/client/application/app-shell/chat-feature.js +7 -22
  218. package/src/client/application/app-shell/comments-feature.js +6 -0
  219. package/src/client/application/app-shell/git-feature.js +23 -5
  220. package/src/client/application/app-shell/presence-feature.js +8 -25
  221. package/src/client/application/app-shell/ui-feature-shell.js +172 -149
  222. package/src/client/application/app-shell/ui-feature-sidebar.js +43 -7
  223. package/src/client/application/app-shell/ui-feature-tab-activity.js +27 -9
  224. package/src/client/application/app-shell/ui-feature-toolbar.js +16 -129
  225. package/src/client/application/app-shell-elements.js +9 -0
  226. package/src/client/application/highlight-theme.js +16 -0
  227. package/src/client/application/preview-render-compiler.js +44 -107
  228. package/src/client/application/preview-render-executor.js +0 -26
  229. package/src/client/application/preview-render-scheduler.js +8 -24
  230. package/src/client/application/preview-renderer.js +26 -9
  231. package/src/client/application/webmcp-diagram-renderer.js +47 -0
  232. package/src/client/application/workspace-coordinator.js +23 -22
  233. package/src/client/application/workspace-route-controller.js +7 -0
  234. package/src/client/bootstrap/collabmd-app-shell.js +148 -35
  235. package/src/client/bootstrap/lazy-collab-clients.js +90 -0
  236. package/src/client/domain/excalidraw-element-link.js +73 -0
  237. package/src/client/domain/excalidraw-scene-reconcile.js +5 -2
  238. package/src/client/domain/excalidraw-scene.js +21 -0
  239. package/src/client/domain/hash-routes.js +13 -0
  240. package/src/client/domain/highlight-runtime.js +47 -0
  241. package/src/client/domain/lobby-chat.js +2 -0
  242. package/src/client/domain/room.js +1 -5
  243. package/src/client/domain/runtime-paths.js +61 -7
  244. package/src/client/domain/vault-utils.js +11 -0
  245. package/src/client/excalidraw-editor.js +155 -14
  246. package/src/client/export/export-host.js +3 -1
  247. package/src/client/export/export-pipeline.js +4 -17
  248. package/src/client/infrastructure/agent-connection-api-client.js +23 -0
  249. package/src/client/infrastructure/auth-client.js +4 -15
  250. package/src/client/infrastructure/browser-preferences-port.js +16 -0
  251. package/src/client/infrastructure/editor-session.js +11 -0
  252. package/src/client/infrastructure/editor-view-adapter.js +56 -8
  253. package/src/client/infrastructure/excalidraw-room-client.js +89 -2
  254. package/src/client/infrastructure/git-api-client.js +39 -33
  255. package/src/client/infrastructure/hosted-api-client.js +60 -0
  256. package/src/client/infrastructure/lobby-presence.js +4 -7
  257. package/src/client/infrastructure/runtime-config.js +14 -2
  258. package/src/client/infrastructure/tab-activity-lock.js +2 -5
  259. package/src/client/infrastructure/vault-api-client.js +33 -26
  260. package/src/client/infrastructure/webmcp-tool-registry.js +297 -0
  261. package/src/client/infrastructure/workspace-sync-client.js +6 -4
  262. package/src/client/presentation/agent-connection-controller.js +255 -0
  263. package/src/client/presentation/backlinks-panel.js +3 -0
  264. package/src/client/presentation/bases-preview-controller.js +27 -18
  265. package/src/client/presentation/comment-markdown-renderer.js +2 -14
  266. package/src/client/presentation/comment-overview-controller.js +1 -2
  267. package/src/client/presentation/comment-ui/comment-ui-card.js +4 -2
  268. package/src/client/presentation/comment-ui/comment-ui-shared.js +5 -2
  269. package/src/client/presentation/create-menu-presenter.js +19 -16
  270. package/src/client/presentation/excalidraw-embed-controller.js +164 -4
  271. package/src/client/presentation/file-explorer-controller.js +3 -0
  272. package/src/client/presentation/file-explorer-view.js +338 -182
  273. package/src/client/presentation/file-history-view-controller.js +13 -11
  274. package/src/client/presentation/git-diff-view-controller.js +35 -43
  275. package/src/client/presentation/git-panel-controller.js +78 -28
  276. package/src/client/presentation/hosted-workspace-gate-controller.js +180 -0
  277. package/src/client/presentation/image-lightbox-controller.js +20 -16
  278. package/src/client/presentation/layout-controller.js +13 -2
  279. package/src/client/presentation/quick-switcher-controller.js +20 -78
  280. package/src/client/presentation/quick-switcher-text-search.js +10 -14
  281. package/src/client/presentation/team-settings-controller.js +228 -0
  282. package/src/client/styles/components/navigation.css +1 -2
  283. package/src/client/styles/deferred-collab.css +5 -0
  284. package/src/client/styles/deferred-git.css +7 -0
  285. package/src/client/styles/deferred-preview.css +6 -0
  286. package/src/client/styles/features/agent-connection.css +202 -0
  287. package/src/client/styles/features/collaboration-chat.css +8 -1
  288. package/src/client/styles/features/collaboration-dialogs.css +16 -1
  289. package/src/client/styles/features/collaboration-presence.css +17 -4
  290. package/src/client/styles/features/diagram-preview.css +0 -15
  291. package/src/client/styles/features/diff-toolbar.css +1 -1
  292. package/src/client/styles/features/media-lightbox.css +12 -3
  293. package/src/client/styles/features/outline.css +4 -2
  294. package/src/client/styles/features/preview-markdown.css +25 -11
  295. package/src/client/styles/features/quick-switcher.css +20 -11
  296. package/src/client/styles/features/team-settings.css +162 -0
  297. package/src/client/styles/foundation/themes.css +2 -0
  298. package/src/client/styles/foundation/tokens.css +2 -2
  299. package/src/client/styles/layout/editor-page.css +25 -24
  300. package/src/client/styles/layout/overlays.css +16 -0
  301. package/src/client/styles/layout/responsive.css +7 -25
  302. package/src/client/styles/layout/shell.css +21 -1
  303. package/src/client/styles/layout/sidebar.css +99 -7
  304. package/src/client/styles/primitives/controls.css +21 -54
  305. package/src/client/styles/style.css +4 -19
  306. package/src/domain/agent-tool-definitions.js +872 -0
  307. package/src/domain/collabmd-content-capabilities.js +149 -0
  308. package/src/domain/collaboration-protocol.js +2 -0
  309. package/src/domain/comment-threads.js +3 -5
  310. package/src/domain/diagram-source.js +50 -0
  311. package/src/domain/editable-content-revision.js +10 -0
  312. package/src/domain/editable-text.js +3 -0
  313. package/src/domain/exact-text-edits.js +69 -0
  314. package/src/domain/excalidraw-agent-scene.js +624 -0
  315. package/src/domain/excalidraw-agent-verification.js +554 -0
  316. package/src/domain/excalidraw-room-codec.js +13 -6
  317. package/src/domain/literal-text-search.js +13 -0
  318. package/src/domain/video-embed.js +76 -0
  319. package/src/server/application/agent-connection-service.js +178 -0
  320. package/src/server/application/agent-content-service.js +841 -0
  321. package/src/server/application/workspace-reconciliation.js +5 -7
  322. package/src/server/config/env.js +147 -6
  323. package/src/server/create-app-server.js +47 -141
  324. package/src/server/domain/bases/base-query-service.js +1 -5
  325. package/src/server/domain/collaboration/collaboration-room.js +121 -25
  326. package/src/server/domain/collaboration/protocol.js +4 -0
  327. package/src/server/domain/hosted-workspace.js +31 -1
  328. package/src/server/domain/markdown-reference-extractor.js +15 -1
  329. package/src/server/domain/ripgrep-search-service.js +68 -21
  330. package/src/server/infrastructure/git/git-service.js +19 -1
  331. package/src/server/infrastructure/git/history-service.js +1 -1
  332. package/src/server/infrastructure/git/local-exclude.js +37 -0
  333. package/src/server/infrastructure/git/parsers.js +19 -17
  334. package/src/server/infrastructure/git/path-utils.js +0 -16
  335. package/src/server/infrastructure/git/status-service.js +1 -1
  336. package/src/server/infrastructure/git/untracked-files.js +12 -21
  337. package/src/server/infrastructure/http/create-agent-api-handler.js +171 -0
  338. package/src/server/infrastructure/http/create-git-api-command-handler.js +32 -0
  339. package/src/server/infrastructure/http/create-hosted-api-handler.js +5 -0
  340. package/src/server/infrastructure/http/create-request-handler.js +123 -26
  341. package/src/server/infrastructure/http/create-static-handler.js +9 -0
  342. package/src/server/infrastructure/http/create-vault-api-query-handler.js +15 -2
  343. package/src/server/infrastructure/mcp/create-agent-mcp-handler.js +200 -0
  344. package/src/server/infrastructure/persistence/agent-connection-store.js +120 -0
  345. package/src/server/infrastructure/persistence/pull-backup-store.js +2 -27
  346. package/src/server/infrastructure/persistence/sidecar-store.js +12 -5
  347. package/src/server/infrastructure/persistence/vault-file-store.js +11 -5
  348. package/src/server/infrastructure/websocket/attach-collaboration-gateway.js +48 -22
  349. package/src/server/shared/agent-tool-image.js +22 -0
  350. package/src/server/shared/agent-tool-rate-limiter.js +27 -0
  351. package/src/server/startup/git-remote-bootstrap.js +58 -79
  352. package/src/server/vault-registry.js +251 -0
  353. package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-BPH4FJkv.js +0 -1
  354. package/dist/client/assets/abnfDiagram-VCTEODGH-BNDLzJ7L.js +0 -1
  355. package/dist/client/assets/ar-SA-PQUY64WN-xjXgbW6d.js +0 -10
  356. package/dist/client/assets/az-AZ-OXJXL76K-4JkO4Pca.js +0 -1
  357. package/dist/client/assets/base-CaIEJUF9.css +0 -1
  358. package/dist/client/assets/bg-BG-W2GKIJDF-DnkH_o81.js +0 -5
  359. package/dist/client/assets/bn-BD-TGL7M4PJ-CG4JkmtP.js +0 -3
  360. package/dist/client/assets/bn-IN-BKETKYEH-CG4JkmtP.js +0 -3
  361. package/dist/client/assets/browser-utils--H_DkyEF.js +0 -1
  362. package/dist/client/assets/ca-ES-LD5SCRVV-U6_TVMX9.js +0 -8
  363. package/dist/client/assets/channel-CaoKA_We.js +0 -1
  364. package/dist/client/assets/chunk-7XWMRXBY-CfMzEq80.js +0 -1
  365. package/dist/client/assets/chunk-CKBBP62Z-DG26UiBv.js +0 -2
  366. package/dist/client/assets/chunk-DSNCTWBM-8xkug7fQ.js +0 -2
  367. package/dist/client/assets/chunk-DU6HZSFF-COXDzJK1.js +0 -127
  368. package/dist/client/assets/chunk-R7TYR2AO-CTd0Yj98.js +0 -10
  369. package/dist/client/assets/chunk-RM4UPSZO-CWRwxNWJ.js +0 -41
  370. package/dist/client/assets/classDiagram-DTDB5LWJ-7fEmn0zV.js +0 -1
  371. package/dist/client/assets/classDiagram-v2-JRS7N3AN-7fEmn0zV.js +0 -1
  372. package/dist/client/assets/comment-thread-store-CdcwrObc.js +0 -1
  373. package/dist/client/assets/comment-threads-9J6Em-_y.js +0 -4
  374. package/dist/client/assets/comment-ui-shared-DuoyznXW.js +0 -7
  375. package/dist/client/assets/cs-CZ-OFPU5DBV-BmFAIhqX.js +0 -7
  376. package/dist/client/assets/da-DK-FRDJFYWF-H387Jw8B.js +0 -2
  377. package/dist/client/assets/de-CH-ZG7H3QK3-C_groygo.js +0 -11
  378. package/dist/client/assets/de-DE-SIJYH4IH-C_groygo.js +0 -11
  379. package/dist/client/assets/diagram-VSXAHHWV-CQRVEZR7.js +0 -3
  380. package/dist/client/assets/dist-73RPdcyU.js +0 -1
  381. package/dist/client/assets/dist-BJ1bJs33.js +0 -1
  382. package/dist/client/assets/dist-ByrG2qBA.js +0 -1
  383. package/dist/client/assets/dist-CH-sQu3r.js +0 -1
  384. package/dist/client/assets/dist-CKS_-are.js +0 -1
  385. package/dist/client/assets/dist-D37Hyu3h.js +0 -9
  386. package/dist/client/assets/dist-DZAAWTG-.js +0 -1
  387. package/dist/client/assets/dist-Dir5dDKZ.js +0 -1
  388. package/dist/client/assets/dist-Dl_tpDSr.js +0 -1
  389. package/dist/client/assets/dist-DutPuFmC.js +0 -1
  390. package/dist/client/assets/dist-RKBTaQMb.js +0 -13
  391. package/dist/client/assets/dist-eBx8q6Sy.js +0 -1
  392. package/dist/client/assets/drawio-editor-BVaNNtYp.js +0 -9
  393. package/dist/client/assets/drawioEditor-BkIBlXx0.js +0 -2
  394. package/dist/client/assets/ebnfDiagram-PWID7BFC-OXa8VEp1.js +0 -1
  395. package/dist/client/assets/editor-session-DMyVdHLj.js +0 -54
  396. package/dist/client/assets/el-GR-IEE2CGI2-BkT6YT54.js +0 -7
  397. package/dist/client/assets/embedded-editor-base-B3l6Xy65.css +0 -1
  398. package/dist/client/assets/es-ES-TVVPWKV5-CpPKJXTM.js +0 -12
  399. package/dist/client/assets/eu-ES-CGBMFQDT-Bu3N2493.js +0 -8
  400. package/dist/client/assets/excalidraw-editor-BjYaNEMY.js +0 -9
  401. package/dist/client/assets/excalidraw-mermaid-stub-BNckbX2n.js +0 -1
  402. package/dist/client/assets/excalidraw-mermaid-stub-DE5FTiZB.js +0 -1
  403. package/dist/client/assets/excalidrawEditor-ChqF_d82.js +0 -2
  404. package/dist/client/assets/export-page-Dyu0XCbu.js +0 -57
  405. package/dist/client/assets/exportDocument-CJBx4Xjx.css +0 -1
  406. package/dist/client/assets/exportDocument-Dgvfa2Sd.js +0 -2
  407. package/dist/client/assets/fa-IR-IE6XAPR4-BEvLCORD.js +0 -9
  408. package/dist/client/assets/fi-FI-P7TKNHRM-DI0q8iSX.js +0 -6
  409. package/dist/client/assets/file-icon-svg-Y_kpF957.js +0 -1
  410. package/dist/client/assets/flowDiagram-A5DVABFB-CiW1eN8C.js +0 -1
  411. package/dist/client/assets/fr-FR-QI2XZNT7-y8kXd8LA.js +0 -12
  412. package/dist/client/assets/gl-ES-TLYCNOZZ-Br-Fhff-.js +0 -6
  413. package/dist/client/assets/he-IL-ZX43XLGP-qKQq6V9X.js +0 -9
  414. package/dist/client/assets/hi-IN-UTYRMTUF-DOUcwrDO.js +0 -3
  415. package/dist/client/assets/hu-HU-AJOSEBW6-FqTyvHlD.js +0 -3
  416. package/dist/client/assets/id-ID-ETLTVG6C-CQqh3CLS.js +0 -8
  417. package/dist/client/assets/image-ZVKINSPA-0zXSnE7M.js +0 -1
  418. package/dist/client/assets/index-CSNIMyOP.css +0 -1
  419. package/dist/client/assets/index-DG3N2Ps-.js +0 -2
  420. package/dist/client/assets/it-IT-B4B6TP6L-V-yK3SZz.js +0 -12
  421. package/dist/client/assets/ja-JP-IYKVURR5-BQKBXRpX.js +0 -12
  422. package/dist/client/assets/kaa-SE2BUIKX-CZ5kfwPg.js +0 -1
  423. package/dist/client/assets/kab-KAB-Y3GLKXLR-Do7GWfuN.js +0 -4
  424. package/dist/client/assets/kk-KZ-ABWUFVOH-BpqVciQz.js +0 -1
  425. package/dist/client/assets/ko-KR-7JQDXKGM-N42lep78.js +0 -5
  426. package/dist/client/assets/ku-TR-NAH2Q5B7-K8LLl9fk.js +0 -6
  427. package/dist/client/assets/lt-LT-VQFYRSNQ-BmOd0ALn.js +0 -3
  428. package/dist/client/assets/lv-LV-T62VSYUM-B22WdPhp.js +0 -4
  429. package/dist/client/assets/main-D0wCxpVn.js +0 -903
  430. package/dist/client/assets/mermaid-parser.core-Bl0efOMt.js +0 -4
  431. package/dist/client/assets/mermaid.core-BJRLUQZE.js +0 -11
  432. package/dist/client/assets/modulepreload-polyfill-P2Xu9kJm.js +0 -1
  433. package/dist/client/assets/mr-IN-V4FHLCJE-XX069tpm.js +0 -9
  434. package/dist/client/assets/my-MM-E3SQ6E54-cst_-5SB.js +0 -1
  435. package/dist/client/assets/nb-NO-MLNOFN5H-Bu2URWko.js +0 -8
  436. package/dist/client/assets/nl-NL-D5L3ZV4M-BqrV0btt.js +0 -13
  437. package/dist/client/assets/nn-NO-NNHDGPKB-DK-xZaWM.js +0 -4
  438. package/dist/client/assets/oc-FR-DWCRF55G-BZ5Po5R6.js +0 -4
  439. package/dist/client/assets/pa-IN-3JSAY44M-BZQSjKrS.js +0 -4
  440. package/dist/client/assets/pegDiagram-XKGWAZYB-B31fKPR2.js +0 -1
  441. package/dist/client/assets/percentages-ETZPVQEE-DFxFqXgH.js +0 -1
  442. package/dist/client/assets/pl-PL-ACURYKP3-qcEOSfCk.js +0 -12
  443. package/dist/client/assets/preload-helper-HclGiUj8.js +0 -1
  444. package/dist/client/assets/preview-render-compiler-CrJIooVD.js +0 -35
  445. package/dist/client/assets/preview-render-compiler-O0JxBVNF.js +0 -1
  446. package/dist/client/assets/preview-render-profile-B4RWYWHt.js +0 -1
  447. package/dist/client/assets/preview-render-worker-_QTxqKvP.js +0 -60
  448. package/dist/client/assets/prod-BiYPMR1i.js +0 -177
  449. package/dist/client/assets/prod-VxdGZ5Ly.js +0 -1
  450. package/dist/client/assets/pt-BR-LOX7MLGD-DLueHSyZ.js +0 -10
  451. package/dist/client/assets/pt-PT-CZ2U2RFQ-BJ-GAEm6.js +0 -12
  452. package/dist/client/assets/quick-switcher-controller-CaEjEtq_.js +0 -1
  453. package/dist/client/assets/railroadDiagram-O6MQD6OU-BPifP0MB.js +0 -1
  454. package/dist/client/assets/ro-RO-2HECL2X6-CJUvKAf0.js +0 -12
  455. package/dist/client/assets/ru-RU-HAYNXO46-BWSlvTrt.js +0 -10
  456. package/dist/client/assets/runtime-config-BLrEKVO1.js +0 -1
  457. package/dist/client/assets/si-LK-W5KNS4H6-DGGCsn7k.js +0 -1
  458. package/dist/client/assets/sk-SK-7K2CFGDV-CY4uTYgQ.js +0 -7
  459. package/dist/client/assets/sl-SI-OXV2QZWW-2-weqaBY.js +0 -6
  460. package/dist/client/assets/stateDiagram-v2-4QOOHH4V-B--gjrit.js +0 -1
  461. package/dist/client/assets/sv-SE-JTOBZRGL-9-IUtVkO.js +0 -12
  462. package/dist/client/assets/swimlanesDiagram-VK2B7HYN-DO8XNXEg.js +0 -8
  463. package/dist/client/assets/ta-IN-KFAVKXGT-gHO6Q_DH.js +0 -6
  464. package/dist/client/assets/th-TH-VDMSCPDL-BvJuw6PJ.js +0 -1
  465. package/dist/client/assets/tr-TR-CEZ6GX45-CG6UU3Su.js +0 -4
  466. package/dist/client/assets/uk-UA-Q3H3OXQC-CSuIg_DY.js +0 -6
  467. package/dist/client/assets/uz-UZ-NGCSWWPX-mom7rxSP.js +0 -1
  468. package/dist/client/assets/vault-api-client-BkwdFjx0.js +0 -6
  469. package/dist/client/assets/vault-utils-DvoSftJT.js +0 -22
  470. package/dist/client/assets/vi-VN-P3NDEVPS-BB0Fu9ck.js +0 -7
  471. package/dist/client/assets/yjs-provider-reset-guard-DE0vINDP.js +0 -4
  472. package/dist/client/assets/zh-CN-SS3O57GA-Bj8wsiMe.js +0 -11
  473. package/dist/client/assets/zh-HK-LWJT3VCF-DOTquTCh.js +0 -1
  474. package/dist/client/assets/zh-TW-VJXC72RT-B48PRo-l.js +0 -13
  475. package/src/client/app/drawio-editor-entry.js +0 -1
  476. package/src/client/app/excalidraw-editor-entry.js +0 -1
  477. package/src/client/excalidraw-mermaid-stub.js +0 -7
  478. package/src/client/main.js +0 -16
  479. /package/dist/client/assets/{vault-api-client-C3mlS_4N.css → auth-gate-C3mlS_4N.css} +0 -0
  480. /package/dist/client/assets/{drawio-editor-UQQ8XHou.css → drawioEditor-UQQ8XHou.css} +0 -0
  481. /package/dist/client/assets/{base-BYODPHdS.js → github.min-DBihDoic.js} +0 -0
  482. /package/dist/client/assets/{sizeCapture-X5ZJPWSS-B0uUizjq.js → sizeCapture-INFHLROL-B0uUizjq.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { decodeQuotedPath, parseRenamePath, stripDiffPrefix } from './path-utils.js';
1
+ import { decodeQuotedPath, stripDiffPrefix } from './path-utils.js';
2
2
  import { createEmptyBranchStatus, createStatusInfo } from './responses.js';
3
3
 
4
4
  function parseBranchLine(line) {
@@ -91,11 +91,8 @@ export function splitContentLines(content) {
91
91
  }
92
92
 
93
93
  export function parseStatusOutput(output) {
94
- const lines = String(output ?? '')
95
- .split(/\r?\n/u)
96
- .filter(Boolean);
97
- const [branchLine = '', ...statusLines] = lines;
98
- const branch = parseBranchLine(branchLine);
94
+ const records = String(output ?? '').split('\0');
95
+ const branch = parseBranchLine(records.shift() || '');
99
96
  const sections = {
100
97
  staged: [],
101
98
  'working-tree': [],
@@ -103,14 +100,15 @@ export function parseStatusOutput(output) {
103
100
  };
104
101
  const uniquePaths = new Set();
105
102
 
106
- for (const line of statusLines) {
107
- if (line.length < 3) {
103
+ for (let index = 0; index < records.length; index += 1) {
104
+ const record = records[index];
105
+ if (record.length < 3) {
108
106
  continue;
109
107
  }
110
108
 
111
- const indexStatus = line[0];
112
- const workTreeStatus = line[1];
113
- const rawPath = line.slice(3);
109
+ const indexStatus = record[0];
110
+ const workTreeStatus = record[1];
111
+ const path = record.slice(3);
114
112
 
115
113
  if (indexStatus === '!' && workTreeStatus === '!') {
116
114
  continue;
@@ -120,7 +118,7 @@ export function parseStatusOutput(output) {
120
118
  const file = {
121
119
  ...createStatusInfo('?'),
122
120
  oldPath: null,
123
- path: decodeQuotedPath(rawPath),
121
+ path,
124
122
  scope: 'untracked',
125
123
  };
126
124
  sections.untracked.push(file);
@@ -128,13 +126,17 @@ export function parseStatusOutput(output) {
128
126
  continue;
129
127
  }
130
128
 
131
- const parsedPath = parseRenamePath(rawPath);
129
+ const hasSourcePath = ['R', 'C'].includes(indexStatus) || ['R', 'C'].includes(workTreeStatus);
130
+ const oldPath = hasSourcePath ? records[index + 1] || null : null;
131
+ if (hasSourcePath) {
132
+ index += 1;
133
+ }
132
134
 
133
135
  if (indexStatus !== ' ') {
134
136
  const file = {
135
137
  ...createStatusInfo(indexStatus),
136
- oldPath: parsedPath.oldPath,
137
- path: parsedPath.path,
138
+ oldPath,
139
+ path,
138
140
  scope: 'staged',
139
141
  };
140
142
  sections.staged.push(file);
@@ -144,8 +146,8 @@ export function parseStatusOutput(output) {
144
146
  if (workTreeStatus !== ' ') {
145
147
  const file = {
146
148
  ...createStatusInfo(workTreeStatus),
147
- oldPath: parsedPath.oldPath,
148
- path: parsedPath.path,
149
+ oldPath,
150
+ path,
149
151
  scope: 'working-tree',
150
152
  };
151
153
  sections['working-tree'].push(file);
@@ -34,22 +34,6 @@ export function normalizeRelativeGitPath(pathValue) {
34
34
  return normalized.join('/');
35
35
  }
36
36
 
37
- export function parseRenamePath(rawPath) {
38
- const decodedPath = decodeQuotedPath(rawPath);
39
- const separator = ' -> ';
40
- const separatorIndex = decodedPath.indexOf(separator);
41
- if (separatorIndex === -1) {
42
- return {
43
- oldPath: null,
44
- path: decodedPath,
45
- };
46
- }
47
-
48
- return {
49
- oldPath: decodedPath.slice(0, separatorIndex),
50
- path: decodedPath.slice(separatorIndex + separator.length),
51
- };
52
- }
53
37
 
54
38
  export function stripDiffPrefix(pathValue) {
55
39
  const normalizedPath = String(pathValue ?? '').replace(/\s+$/u, '');
@@ -42,7 +42,7 @@ export class GitStatusService {
42
42
 
43
43
  const statusPromise = (async () => {
44
44
  const parsed = parseStatusOutput(
45
- await this.commandRunner.execGit(['status', '--porcelain=v1', '--branch', '--untracked-files=all']),
45
+ await this.commandRunner.execGit(['status', '--porcelain=v1', '-z', '--branch', '--untracked-files=all']),
46
46
  );
47
47
  const sections = [
48
48
  { files: parsed.sections.staged, key: 'staged', label: 'Staged Changes' },
@@ -1,6 +1,7 @@
1
1
  import { createReadStream } from 'node:fs';
2
2
  import { readFile } from 'node:fs/promises';
3
3
  import { join } from 'node:path';
4
+ import { createInterface } from 'node:readline';
4
5
 
5
6
  import { getVaultFileKind, isImageAttachmentFilePath } from '../../../domain/file-kind.js';
6
7
  import { mapWithConcurrency } from '../../shared/async-utils.js';
@@ -13,29 +14,19 @@ async function countFileLines(filePath) {
13
14
  return 0;
14
15
  }
15
16
 
16
- return new Promise((resolve, reject) => {
17
- const stream = createReadStream(filePath, { encoding: 'utf8' });
18
- let lineCount = 0;
19
- let sawData = false;
20
- let lastCharacter = '\n';
17
+ const lines = createInterface({
18
+ crlfDelay: Infinity,
19
+ input: createReadStream(filePath, { encoding: 'utf8' }),
20
+ });
21
+ let lineCount = 0;
21
22
 
22
- stream.on('data', (chunk) => {
23
- if (!chunk) {
24
- return;
25
- }
23
+ for await (const line of lines) {
24
+ if (typeof line === 'string') {
25
+ lineCount += 1;
26
+ }
27
+ }
26
28
 
27
- sawData = true;
28
- lastCharacter = chunk[chunk.length - 1];
29
- lineCount += chunk.match(/\n/gu)?.length ?? 0;
30
- });
31
- stream.on('error', reject);
32
- stream.on('end', () => {
33
- if (sawData && lastCharacter !== '\n') {
34
- lineCount += 1;
35
- }
36
- resolve(lineCount);
37
- });
38
- });
29
+ return lineCount;
39
30
  }
40
31
 
41
32
  function buildSyntheticAddedFileDiff(pathValue, content) {
@@ -0,0 +1,171 @@
1
+ import { fromJsonSchema } from '@modelcontextprotocol/server';
2
+
3
+ import { getAgentToolDefinition } from '../../../domain/agent-tool-definitions.js';
4
+ import { encodeAgentToolImage } from '../../shared/agent-tool-image.js';
5
+ import { readRequestId } from './http-request-helpers.js';
6
+ import { jsonResponse } from './http-response.js';
7
+ import { parseJsonBody } from './request-body.js';
8
+
9
+ const WEBMCP_TOOL_PATH = '/api/agent/tools/';
10
+ const WEBMCP_INPUT_SCHEMAS = new Map();
11
+
12
+ function createAgentError(code, message, statusCode) {
13
+ const error = new Error(message);
14
+ error.code = code;
15
+ error.statusCode = statusCode;
16
+ return error;
17
+ }
18
+
19
+ function sendAgentError(req, res, error) {
20
+ const statusCode = Number(error?.statusCode) || 500;
21
+ if (statusCode >= 500) console.error('[agent] Request failed:', error.message);
22
+ jsonResponse(req, res, statusCode, {
23
+ code: error?.code || 'AGENT_REQUEST_FAILED',
24
+ error: statusCode >= 500 ? 'Agent request failed' : error.message,
25
+ ...(Number.isFinite(error?.retryAfterMs) ? { retryAfterMs: error.retryAfterMs } : {}),
26
+ });
27
+ }
28
+
29
+ async function validateWebMcpInput(definition, input) {
30
+ let schema = WEBMCP_INPUT_SCHEMAS.get(definition.name);
31
+ if (!schema) {
32
+ schema = fromJsonSchema(definition.inputSchema);
33
+ WEBMCP_INPUT_SCHEMAS.set(definition.name, schema);
34
+ }
35
+ const validation = await schema['~standard'].validate(input);
36
+ if (validation.issues?.length) {
37
+ throw createAgentError('AGENT_INPUT_INVALID', 'WebMCP tool input does not match its schema', 400);
38
+ }
39
+ }
40
+
41
+ async function createWebMcpActor({ agentConnectionService, authService, config, req }) {
42
+ let subject;
43
+ if (config.auth.strategy === 'none') {
44
+ subject = {
45
+ collaborator: null,
46
+ subjectId: req.socket?.remoteAddress || 'unknown',
47
+ subjectType: 'anonymous',
48
+ };
49
+ } else {
50
+ const user = authService.getAuthenticatedUser?.(req) ?? null;
51
+ subject = await agentConnectionService.resolveManagementSubject(user);
52
+ }
53
+ const actorId = `webmcp:${subject.subjectType}:${subject.subjectId}`;
54
+ return {
55
+ collaborator: subject.collaborator,
56
+ connectionId: actorId,
57
+ origin: 'webmcp',
58
+ rateLimitKey: actorId,
59
+ requestId: readRequestId(req),
60
+ scopes: ['vault:edit', 'vault:read'],
61
+ sourceRef: 'webmcp',
62
+ };
63
+ }
64
+
65
+ async function mapWebMcpResult(definition, value) {
66
+ if (value.svg && ['image', 'optional-image'].includes(definition.resultKind)) {
67
+ const { data, mimeType, structuredContent } = await encodeAgentToolImage(value);
68
+ return {
69
+ ...structuredContent,
70
+ image: { data, encoding: 'base64', mimeType },
71
+ scene: value.scene,
72
+ };
73
+ }
74
+ if (definition.resultKind === 'optional-image' && value.verification?.svg) {
75
+ const { verification, ...result } = value;
76
+ const { data, mimeType, structuredContent } = await encodeAgentToolImage(verification);
77
+ return {
78
+ ...result,
79
+ image: { data, encoding: 'base64', mimeType },
80
+ verification: {
81
+ ...structuredContent,
82
+ scene: verification.scene,
83
+ },
84
+ };
85
+ }
86
+ return value;
87
+ }
88
+
89
+ export function createAgentApiHandler({
90
+ agentConnectionService,
91
+ agentContentService,
92
+ authService,
93
+ config,
94
+ rateLimiter,
95
+ }) {
96
+ return async function handleAgentApi(req, res, requestUrl) {
97
+ if (!requestUrl.pathname.startsWith('/api/agent')) return false;
98
+
99
+ try {
100
+ if (requestUrl.pathname.startsWith(WEBMCP_TOOL_PATH)) {
101
+ if (req.method !== 'POST') {
102
+ throw createAgentError('AGENT_METHOD_NOT_ALLOWED', 'WebMCP tools require POST', 405);
103
+ }
104
+ const name = decodeURIComponent(requestUrl.pathname.slice(WEBMCP_TOOL_PATH.length));
105
+ const definition = getAgentToolDefinition(name);
106
+ if (!definition?.webMcp) {
107
+ throw createAgentError('AGENT_TOOL_NOT_FOUND', 'WebMCP tool not found', 404);
108
+ }
109
+ const input = await parseJsonBody(req);
110
+ await validateWebMcpInput(definition, input);
111
+ const actor = await createWebMcpActor({
112
+ agentConnectionService,
113
+ authService,
114
+ config,
115
+ req,
116
+ });
117
+ rateLimiter(actor.rateLimitKey);
118
+ const cancellation = new AbortController();
119
+ const abort = () => cancellation.abort();
120
+ req.once('aborted', abort);
121
+ try {
122
+ const value = await agentContentService[definition.method](actor, {
123
+ ...input,
124
+ signal: cancellation.signal,
125
+ });
126
+ jsonResponse(req, res, 200, await mapWebMcpResult(definition, value));
127
+ } finally {
128
+ req.off('aborted', abort);
129
+ }
130
+ return true;
131
+ }
132
+
133
+ if (!config.agentAccess?.enabled) {
134
+ jsonResponse(req, res, 404, { error: 'Agent Access is not enabled' });
135
+ return true;
136
+ }
137
+ const user = authService.getAuthenticatedUser?.(req) ?? null;
138
+ if (requestUrl.pathname === '/api/agent/connections' && req.method === 'GET') {
139
+ jsonResponse(req, res, 200, {
140
+ connections: await agentConnectionService.listConnections(user),
141
+ });
142
+ return true;
143
+ }
144
+ if (requestUrl.pathname === '/api/agent/connections' && req.method === 'POST') {
145
+ const body = await parseJsonBody(req);
146
+ jsonResponse(req, res, 201, await agentConnectionService.createConnection({
147
+ clientKind: body?.clientKind,
148
+ label: body?.label,
149
+ scopes: body?.scopes,
150
+ user,
151
+ }));
152
+ return true;
153
+ }
154
+ if (requestUrl.pathname.startsWith('/api/agent/connections/') && req.method === 'DELETE') {
155
+ const connectionId = decodeURIComponent(
156
+ requestUrl.pathname.slice('/api/agent/connections/'.length).split('/')[0] || '',
157
+ );
158
+ jsonResponse(req, res, 200, await agentConnectionService.revokeConnection({
159
+ connectionId,
160
+ user,
161
+ }));
162
+ return true;
163
+ }
164
+ jsonResponse(req, res, 404, { error: 'Agent endpoint not found' });
165
+ return true;
166
+ } catch (error) {
167
+ sendAgentError(req, res, error);
168
+ return true;
169
+ }
170
+ };
171
+ }
@@ -84,6 +84,38 @@ export function createGitApiCommandHandler({
84
84
  return true;
85
85
  }
86
86
 
87
+ if (requestUrl.pathname === '/api/git/stage-all' && req.method === 'POST') {
88
+ try {
89
+ jsonResponse(req, res, 200, await applyWorkspaceMutationEffects({
90
+ action: 'stage-all',
91
+ req,
92
+ responsePayload: await workspaceMutationCoordinator.runManagedWorkspaceMutation(
93
+ () => gitService.stageAll(),
94
+ ),
95
+ workspaceMutationCoordinator,
96
+ }));
97
+ } catch (error) {
98
+ handleApiError(req, res, error, '[api] Failed to stage all git changes:', 'Failed to stage all git changes');
99
+ }
100
+ return true;
101
+ }
102
+
103
+ if (requestUrl.pathname === '/api/git/unstage-all' && req.method === 'POST') {
104
+ try {
105
+ jsonResponse(req, res, 200, await applyWorkspaceMutationEffects({
106
+ action: 'unstage-all',
107
+ req,
108
+ responsePayload: await workspaceMutationCoordinator.runManagedWorkspaceMutation(
109
+ () => gitService.unstageAll(),
110
+ ),
111
+ workspaceMutationCoordinator,
112
+ }));
113
+ } catch (error) {
114
+ handleApiError(req, res, error, '[api] Failed to unstage all git changes:', 'Failed to unstage all git changes');
115
+ }
116
+ return true;
117
+ }
118
+
87
119
  if (requestUrl.pathname === '/api/git/commit' && req.method === 'POST') {
88
120
  try {
89
121
  const body = await parseRequiredBody(req, res, 'message');
@@ -43,6 +43,11 @@ export function createHostedApiHandler({
43
43
  user,
44
44
  }));
45
45
  }],
46
+ ['POST /api/hosted/setup/complete', async ({ req, res, user }) => {
47
+ const admin = await hostedWorkspaceService.requireAdmin(user);
48
+ const team = await hostedWorkspaceService.completeWorkspaceSetup({ user: admin });
49
+ jsonResponse(req, res, 200, { ok: true, setupComplete: true, team });
50
+ }],
46
51
  ['GET /api/hosted/vault-source', async ({ req, res, user }) => {
47
52
  jsonResponse(req, res, 200, { vaultSource: await hostedWorkspaceService.getVaultSource(user) });
48
53
  }],
@@ -1,3 +1,6 @@
1
+ import { createAgentApiHandler } from './create-agent-api-handler.js';
2
+ import { createAgentMcpHandler } from '../mcp/create-agent-mcp-handler.js';
3
+ import { createAgentToolRateLimiter } from '../../shared/agent-tool-rate-limiter.js';
1
4
  import { createAuthApiHandler } from './create-auth-api-handler.js';
2
5
  import { createGitApiCommandHandler } from './create-git-api-command-handler.js';
3
6
  import { createGitApiQueryHandler } from './create-git-api-query-handler.js';
@@ -38,6 +41,8 @@ export function createRequestHandler(
38
41
  hostedWorkspaceService = null,
39
42
  githubSetupFlow = null,
40
43
  structurizrWorkspaceService = null,
44
+ agentIntegration = null,
45
+ vaultRegistry = null,
41
46
  ) {
42
47
  const handleStaticRequest = createStaticHandler(config, authService, searchService);
43
48
  const handleAuthApi = createAuthApiHandler({ authService });
@@ -46,33 +51,114 @@ export function createRequestHandler(
46
51
  githubSetupFlow,
47
52
  hostedWorkspaceService,
48
53
  });
49
- const handleGitApiQuery = createGitApiQueryHandler({ gitService });
50
- const handleGitApiCommand = createGitApiCommandHandler({
51
- authService,
52
- gitService,
53
- workspaceMutationCoordinator,
54
- });
55
- const handleVaultApiQuery = createVaultApiQueryHandler({
56
- baseQueryService,
57
- backlinkIndex,
58
- config,
59
- searchService,
60
- vaultFileStore,
61
- workspaceMutationCoordinator,
62
- });
63
- const handleVaultApiCommand = createVaultApiCommandHandler({
64
- backlinkIndex,
65
- maxPdfUploadBytes: config.maxPdfUploadBytes,
66
- renderDocx,
67
- roomRegistry,
68
- vaultFileStore,
69
- workspaceMutationCoordinator,
70
- });
54
+ // ponytail: one builder for legacy primary paths and scoped vaults; only the parts differ
55
+ const vaultHandlerCache = new Map();
56
+ function getVaultHandlers(id, parts) {
57
+ let handlers = vaultHandlerCache.get(id);
58
+ if (!handlers) {
59
+ handlers = {
60
+ command: createVaultApiCommandHandler({
61
+ backlinkIndex: parts.backlinkIndex,
62
+ maxPdfUploadBytes: config.maxPdfUploadBytes,
63
+ renderDocx,
64
+ roomRegistry: parts.roomRegistry,
65
+ vaultFileStore: parts.vaultFileStore,
66
+ workspaceMutationCoordinator: parts.workspaceMutationCoordinator,
67
+ }),
68
+ gitCommand: createGitApiCommandHandler({
69
+ authService,
70
+ gitService: parts.gitService,
71
+ workspaceMutationCoordinator: parts.workspaceMutationCoordinator,
72
+ }),
73
+ gitQuery: createGitApiQueryHandler({ gitService: parts.gitService }),
74
+ query: createVaultApiQueryHandler({
75
+ baseQueryService: parts.baseQueryService,
76
+ backlinkIndex: parts.backlinkIndex,
77
+ config,
78
+ searchService: parts.searchService,
79
+ vaultFileStore: parts.vaultFileStore,
80
+ workspaceMutationCoordinator: parts.workspaceMutationCoordinator,
81
+ }),
82
+ };
83
+ vaultHandlerCache.set(id, handlers);
84
+ }
85
+ return handlers;
86
+ }
87
+ const primaryHandlers = getVaultHandlers(
88
+ vaultRegistry?.getPrimaryContext?.()?.def.id ?? '__primary__',
89
+ { backlinkIndex, baseQueryService, gitService, roomRegistry, searchService, vaultFileStore, workspaceMutationCoordinator },
90
+ );
71
91
  const handlePlantUmlApi = createPlantUmlApiHandler({ plantUmlRenderer });
72
92
  const handleStructurizrApi = createStructurizrApiHandler({
73
93
  basePath: config.basePath,
74
94
  service: structurizrWorkspaceService,
75
95
  });
96
+ const agentToolRateLimiter = createAgentToolRateLimiter(config.agentAccess.requestsPerMinute);
97
+ const handleAgentApi = createAgentApiHandler({
98
+ agentConnectionService: agentIntegration?.connectionService,
99
+ agentContentService: agentIntegration?.contentService,
100
+ authService,
101
+ config,
102
+ rateLimiter: agentToolRateLimiter,
103
+ });
104
+ const handleAgentMcp = config.agentAccess.enabled && agentIntegration
105
+ ? createAgentMcpHandler({
106
+ agentConnectionService: agentIntegration.connectionService,
107
+ agentContentService: agentIntegration.contentService,
108
+ config,
109
+ rateLimiter: agentToolRateLimiter,
110
+ })
111
+ : async () => false;
112
+
113
+ function parseVaultScope(pathname) {
114
+ if (!pathname.startsWith('/api/v/')) {
115
+ return null;
116
+ }
117
+ const rest = pathname.slice('/api/v/'.length);
118
+ const slashIndex = rest.indexOf('/');
119
+ if (slashIndex === -1) {
120
+ return null;
121
+ }
122
+ const vaultId = rest.slice(0, slashIndex);
123
+ if (!vaultId) {
124
+ return null;
125
+ }
126
+ return { subPath: `/api${rest.slice(slashIndex)}`, vaultId };
127
+ }
128
+
129
+ async function handleVaultScopedApi(req, res, requestUrl) {
130
+ const scope = parseVaultScope(requestUrl.pathname);
131
+ if (!scope || !vaultRegistry) {
132
+ return false;
133
+ }
134
+ let context;
135
+ try {
136
+ context = await vaultRegistry.getOrCreateContextAsync(scope.vaultId);
137
+ } catch (error) {
138
+ jsonResponse(req, res, error?.statusCode || 500, { error: error?.message || 'Vault unavailable' });
139
+ return true;
140
+ }
141
+ const subUrl = new URL(requestUrl.toString());
142
+ subUrl.pathname = scope.subPath;
143
+ const handlers = getVaultHandlers(context.def.id, context);
144
+ if (await handlers.query(req, res, subUrl)) {
145
+ return true;
146
+ }
147
+ if (await handlers.command(req, res, subUrl)) {
148
+ return true;
149
+ }
150
+ if (subUrl.pathname.startsWith('/api/git')) {
151
+ if (await handlers.gitQuery(req, res, subUrl)) {
152
+ return true;
153
+ }
154
+ if (await handlers.gitCommand(req, res, subUrl)) {
155
+ return true;
156
+ }
157
+ jsonResponse(req, res, 404, { error: 'Git API endpoint not found' });
158
+ return true;
159
+ }
160
+ return false;
161
+ }
76
162
 
77
163
  function handleBasePathRedirect(req, res, originalRequestUrl) {
78
164
  if (
@@ -182,6 +268,10 @@ export function createRequestHandler(
182
268
  return;
183
269
  }
184
270
 
271
+ if (await handleAgentMcp(req, res, requestUrl)) {
272
+ return;
273
+ }
274
+
185
275
  if (requestUrl.pathname.startsWith('/api/') || handleStructurizrApi.requiresAuthorization(requestUrl)) {
186
276
  const authorization = authService.authorizeApiRequest(req);
187
277
  if (!authorization.ok) {
@@ -198,15 +288,22 @@ export function createRequestHandler(
198
288
  }
199
289
  }
200
290
 
291
+ if (await handleAgentApi(req, res, requestUrl)) {
292
+ return;
293
+ }
294
+
201
295
  if (await handleStructurizrApi(req, res, requestUrl)) {
202
296
  return;
203
297
  }
204
298
 
205
299
  if (requestUrl.pathname.startsWith('/api/')) {
206
- if (await handleVaultApiQuery(req, res, requestUrl)) {
300
+ if (await handleVaultScopedApi(req, res, requestUrl)) {
301
+ return;
302
+ }
303
+ if (await primaryHandlers.query(req, res, requestUrl)) {
207
304
  return;
208
305
  }
209
- if (await handleVaultApiCommand(req, res, requestUrl)) {
306
+ if (await primaryHandlers.command(req, res, requestUrl)) {
210
307
  return;
211
308
  }
212
309
  if (await handlePlantUmlApi(req, res, requestUrl)) {
@@ -219,10 +316,10 @@ export function createRequestHandler(
219
316
  jsonResponse(req, res, 503, { error: 'Git integration is not configured' });
220
317
  return;
221
318
  }
222
- if (await handleGitApiQuery(req, res, requestUrl)) {
319
+ if (await primaryHandlers.gitQuery(req, res, requestUrl)) {
223
320
  return;
224
321
  }
225
- if (await handleGitApiCommand(req, res, requestUrl)) {
322
+ if (await primaryHandlers.gitCommand(req, res, requestUrl)) {
226
323
  return;
227
324
  }
228
325
  jsonResponse(req, res, 404, { error: 'Git API endpoint not found' });
@@ -45,6 +45,7 @@ function getStaticCacheControl(pathname = '', extension = '') {
45
45
  }
46
46
 
47
47
  function buildRuntimeConfig({
48
+ agentAccess,
48
49
  auth,
49
50
  basePath,
50
51
  build,
@@ -57,8 +58,15 @@ function buildRuntimeConfig({
57
58
  structurizr,
58
59
  wikiLinkAutoCreate,
59
60
  wsBasePath,
61
+ vaults,
60
62
  }) {
61
63
  return `window.__COLLABMD_CONFIG__ = ${JSON.stringify({
64
+ activeVault: vaults?.[0]?.id ?? '',
65
+ agentAccess: {
66
+ enabled: Boolean(agentAccess?.enabled),
67
+ endpoint: agentAccess?.endpoint || '',
68
+ managed: Boolean(agentAccess?.enabled && auth?.strategy !== 'none'),
69
+ },
62
70
  auth,
63
71
  basePath,
64
72
  build,
@@ -73,6 +81,7 @@ function buildRuntimeConfig({
73
81
  structurizrEnabled: Boolean(structurizr?.enabled ?? structurizr?.serverUrl),
74
82
  wikiLinkAutoCreate,
75
83
  wsBasePath,
84
+ vaults: (vaults ?? []).map(({ id }) => ({ id })),
76
85
  })};\n`;
77
86
  }
78
87
 
@@ -274,14 +274,20 @@ async function handleFileTree(req, res, _requestUrl, { vaultFileStore, workspace
274
274
  }
275
275
  }
276
276
 
277
- async function handleCommentOverview(req, res, _requestUrl, { vaultFileStore }) {
277
+ async function handleCommentOverview(req, res, _requestUrl, {
278
+ vaultFileStore,
279
+ workspaceMutationCoordinator,
280
+ }) {
278
281
  try {
279
282
  if (typeof vaultFileStore.readCommentOverview !== 'function') {
280
283
  jsonResponse(req, res, 503, { error: 'Comment overview is unavailable' });
281
284
  return;
282
285
  }
283
286
 
284
- const overview = await vaultFileStore.readCommentOverview();
287
+ const workspaceState = await workspaceMutationCoordinator.getWorkspaceStateSnapshot();
288
+ const overview = await vaultFileStore.readCommentOverview({
289
+ filePaths: workspaceState.filePaths,
290
+ });
285
291
  jsonResponse(req, res, 200, { overview });
286
292
  } catch (error) {
287
293
  console.error('[api] Failed to read comment overview:', error.message);
@@ -486,6 +492,12 @@ async function handleSearch(req, res, requestUrl, { searchService }) {
486
492
  }
487
493
  }
488
494
 
495
+ async function handleVaultList(req, res, _requestUrl, { config }) {
496
+ // ponytail: ids only — absolute vault dirs are operator internals
497
+ const vaults = (config?.vaults ?? []).map(({ id }) => ({ id }));
498
+ jsonResponse(req, res, 200, { activeVault: vaults[0]?.id ?? null, vaults });
499
+ }
500
+
489
501
  // --- Route table ---
490
502
 
491
503
  function createRouteTable(context) {
@@ -494,6 +506,7 @@ function createRouteTable(context) {
494
506
  { method: 'POST', path: '/api/base/property-values', handler: handleBasePropertyValues },
495
507
  { method: 'POST', path: '/api/base/transform', handler: handleBaseTransform },
496
508
  { method: 'POST', path: '/api/base/export', handler: handleBaseExport },
509
+ { method: 'GET', path: '/api/vaults', handler: handleVaultList },
497
510
  { method: 'GET', path: '/api/files', handler: handleFileTree },
498
511
  { method: 'GET', path: '/api/comments/overview', handler: handleCommentOverview },
499
512
  { method: 'GET', path: '/api/file', handler: handleFileRead },