mulmoclaude 0.9.0 → 0.9.2

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 (458) hide show
  1. package/README.md +95 -38
  2. package/bin/mulmoclaude.js +1 -2
  3. package/client/assets/JsonEditor-CPJfn76E.css +1 -0
  4. package/client/assets/JsonEditor-CoWGJG3Y.js +10 -0
  5. package/client/assets/abnfDiagram-VRR7QNED-6nNByj6v-By7GJ3xW.js +1 -0
  6. package/client/assets/abnfDiagram-VRR7QNED-BrQlVixL.js +1 -0
  7. package/client/assets/arc-BXutyUAX.js +1 -0
  8. package/client/assets/arc-zT0wd74V-DulGJNnb.js +1 -0
  9. package/client/assets/architecture-TIHT7OUA-CYMWc3UT-C7HoFzWN.js +1 -0
  10. package/client/assets/architecture-TIHT7OUA-aml8u-G9.js +1 -0
  11. package/client/assets/architectureDiagram-ZJ3FMSHR-Bgnyaj_i-CCpEsCHN.js +36 -0
  12. package/client/assets/architectureDiagram-ZJ3FMSHR-DJTFpPjB.js +36 -0
  13. package/client/assets/array-BifhSqXX.js +1 -0
  14. package/client/assets/array-CApNbSU9-BifhSqXX.js +1 -0
  15. package/client/assets/blockDiagram-677ZJIJ3-DQ35o5E4-BXS11D3J.js +132 -0
  16. package/client/assets/blockDiagram-677ZJIJ3-aYvCODxv.js +132 -0
  17. package/client/assets/c4Diagram-LMCZKHZV-Bau6RMBb.js +10 -0
  18. package/client/assets/c4Diagram-LMCZKHZV-ClWZeiWo-DXGnOOUf.js +10 -0
  19. package/client/assets/channel-D9VSi_QV.js +1 -0
  20. package/client/assets/channel-Di5rtkx0-C3gZcytF.js +1 -0
  21. package/client/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  22. package/client/assets/chunk-2Q5K7J3B-DfKpwyl9-DTxwf5E9.js +1 -0
  23. package/client/assets/chunk-32BRIVSS-CCt9wtYd-Cwa_IP35.js +1 -0
  24. package/client/assets/chunk-32BRIVSS-CxzHeys5.js +1 -0
  25. package/client/assets/chunk-52WLFC77-BtNjbTdw.js +10 -0
  26. package/client/assets/chunk-52WLFC77-FbBbR4uI-wsNC5d-f.js +10 -0
  27. package/client/assets/chunk-5VM5RSS4-BYnnUiN6-C4rOnu9A.js +15 -0
  28. package/client/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  29. package/client/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
  30. package/client/assets/chunk-7BUUIJ7U-hh8aCuGX-mGEpPzQy.js +1 -0
  31. package/client/assets/chunk-C7G6YPKG-BE8ehsnc.js +1 -0
  32. package/client/assets/chunk-C7G6YPKG-C87hlS9c-BitbJpTa.js +1 -0
  33. package/client/assets/{chunk-D8eiyYIV-BY16KEZc.js → chunk-D8eiyYIV-BeeEsA1B.js} +1 -1
  34. package/client/assets/chunk-EX3LRPZG-Bhgskzyy.js +231 -0
  35. package/client/assets/chunk-EX3LRPZG-BqGqMXLN-Cl2Eo1_u.js +231 -0
  36. package/client/assets/chunk-FWX5IMBZ-BkbSAAuW-C2r4AuAO.js +2 -0
  37. package/client/assets/chunk-FWX5IMBZ-D9sskZb_.js +2 -0
  38. package/client/assets/chunk-HOUHSVGY-CBCXk7rb.js +1 -0
  39. package/client/assets/chunk-HOUHSVGY-Cxu0eDlh-owg_DcY0.js +1 -0
  40. package/client/assets/chunk-ICXQ74PX-DTqPpDQ9.js +2 -0
  41. package/client/assets/chunk-ICXQ74PX-hiraF_Xj-CdaEwVin.js +2 -0
  42. package/client/assets/chunk-JWPE2WC7-BQ3zXr2k-DSd3Ct95.js +1 -0
  43. package/client/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  44. package/client/assets/chunk-KEIR6QF5-DNzq6p3w.js +161 -0
  45. package/client/assets/chunk-MOJQB5TN-CqxshQHA-Cn_EpDyZ.js +88 -0
  46. package/client/assets/chunk-MOJQB5TN-D1s_zUGz.js +88 -0
  47. package/client/assets/chunk-OGEWGWER-CjCr7ceX-Dfk5-70y.js +1 -0
  48. package/client/assets/chunk-OGEWGWER-DzfhxoQd.js +1 -0
  49. package/client/assets/chunk-PUDLZKDR-BZlebNhn.js +156 -0
  50. package/client/assets/chunk-PUDLZKDR-Dx6M-vz1-CLyVurOz.js +156 -0
  51. package/client/assets/chunk-Q4XR5HBZ-BcJb7mwA.js +70 -0
  52. package/client/assets/chunk-Q4XR5HBZ-CZd-9lTB-qPEYoRNc.js +11 -0
  53. package/client/assets/chunk-RYQCIY6F-B_IgMG7T.js +1 -0
  54. package/client/assets/chunk-RYQCIY6F-YkbemkCt-CX4fncTQ.js +1 -0
  55. package/client/assets/chunk-V7JOEXUC-Buce04o6.js +206 -0
  56. package/client/assets/chunk-V7JOEXUC-rI0xlC_O-C607vJXy.js +206 -0
  57. package/client/assets/chunk-VAUOI2AC-CxhkzXN0.js +1 -0
  58. package/client/assets/chunk-VAUOI2AC-DrcykVNK-CSROJWdE.js +1 -0
  59. package/client/assets/chunk-VR4S4FIN-D5afNrsS.js +1 -0
  60. package/client/assets/chunk-VR4S4FIN-O6iF8Yvf-CLIwrgqU.js +1 -0
  61. package/client/assets/chunk-WYO6CB5R-B83L_z6I-Cs8mg9If.js +127 -0
  62. package/client/assets/chunk-WYO6CB5R-BXTIdTMw.js +125 -0
  63. package/client/assets/chunk-XXDRQBXY-DFXH_lWn-B5HjCp2c.js +1 -0
  64. package/client/assets/chunk-XXDRQBXY-DXMD6ofA.js +1 -0
  65. package/client/assets/chunk-Y2CYZVJY-Bdt8pFDJ-DsF7k-Jl.js +1 -0
  66. package/client/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  67. package/client/assets/chunk-ZGVPDNZ5-BpFv9JSP-CHYySMjV.js +62 -0
  68. package/client/assets/chunk-ZGVPDNZ5-CYusI0J_.js +62 -0
  69. package/client/assets/chunk-ZIRB5QZD-Biy6ZNFG-D1maAiXb.js +32 -0
  70. package/client/assets/chunk-ZIRB5QZD-C6fEPe3t.js +32 -0
  71. package/client/assets/classDiagram-OUVF2IWQ-BgAZMSbT-BgxEE1D3.js +1 -0
  72. package/client/assets/classDiagram-OUVF2IWQ-CBD3Eidl.js +1 -0
  73. package/client/assets/classDiagram-v2-EOCWNBFH-CBD3Eidl.js +1 -0
  74. package/client/assets/classDiagram-v2-EOCWNBFH-DxHTyui1-BgxEE1D3.js +1 -0
  75. package/client/assets/cose-bilkent-JH36ORCC-CuSL2tA8-aMIqISfj.js +1 -0
  76. package/client/assets/cose-bilkent-JH36ORCC-WAJDBXv1.js +1 -0
  77. package/client/assets/cynefin-VYW2F7L2-DH2qkJKw.js +1 -0
  78. package/client/assets/cynefin-VYW2F7L2-DqA3n9nY-BNWhIK_n.js +1 -0
  79. package/client/assets/cynefinDiagram-TSTJHNR4-CUvPV9MV.js +62 -0
  80. package/client/assets/cynefinDiagram-TSTJHNR4-x0-0sQ15-Cq1gFcFu.js +62 -0
  81. package/client/assets/cytoscape.esm-CzdwbRaj-Djp6vQyU.js +321 -0
  82. package/client/assets/cytoscape.esm-Djp6vQyU.js +321 -0
  83. package/client/assets/dagre-CXRCoUWR.js +1 -0
  84. package/client/assets/dagre-VKFMJZFB-CQdfl-bx-CzZZuace.js +4 -0
  85. package/client/assets/dagre-VKFMJZFB-C_9IS7mB.js +4 -0
  86. package/client/assets/dagre-wczQIDso-CfevN9RO.js +1 -0
  87. package/client/assets/defaultLocale-C8Fc0cco.js +1 -0
  88. package/client/assets/defaultLocale-DUNguUWs-BbDo_yJX.js +1 -0
  89. package/client/assets/diagram-FQU43EPY-BOSB6VUb-isPdQ8WX.js +3 -0
  90. package/client/assets/diagram-FQU43EPY-BP8N00-b.js +3 -0
  91. package/client/assets/diagram-G47NLZAW-DLXrcXsN-BIqj7RKy.js +24 -0
  92. package/client/assets/diagram-G47NLZAW-ulE1JlWG.js +24 -0
  93. package/client/assets/diagram-NH7WQ7WH-BMQp1rkF-D6-fOq_v.js +24 -0
  94. package/client/assets/diagram-NH7WQ7WH-D_IXrL3i.js +24 -0
  95. package/client/assets/diagram-OA4YK3LP-C-pC6Eyu.js +30 -0
  96. package/client/assets/diagram-OA4YK3LP-D1wQ0vUj-BNi6QLCK.js +30 -0
  97. package/client/assets/diagram-WEI45ONY-Di9m35i-.js +41 -0
  98. package/client/assets/diagram-WEI45ONY-RR0DpF8R-BS3nrb3w.js +41 -0
  99. package/client/assets/dist-BQBs5pjy-BmtZ7Oc2.js +1 -0
  100. package/client/assets/dist-CQ3HaWOk.js +1 -0
  101. package/client/assets/ebnfDiagram-CCIWWBDH-Cbwnim2x.js +1 -0
  102. package/client/assets/ebnfDiagram-CCIWWBDH-M123uVJ8-9-dq55nQ.js +1 -0
  103. package/client/assets/erDiagram-Q63AITRT-BWx_-PXG-CWGfG4z5.js +85 -0
  104. package/client/assets/erDiagram-Q63AITRT-CMbtO3Sm.js +85 -0
  105. package/client/assets/eventmodeling-45OFAUF4--32SIpkL.js +1 -0
  106. package/client/assets/eventmodeling-45OFAUF4-_BVSjAXf-DQdL0Icr.js +1 -0
  107. package/client/assets/flowDiagram-23GEKE2U-BeOc_anm-CuVzKmmU.js +1 -0
  108. package/client/assets/flowDiagram-23GEKE2U-Dofa_qxG.js +1 -0
  109. package/client/assets/ganttDiagram-NO4QXBWP-BOoJ1eTw-TWoNmSvq.js +292 -0
  110. package/client/assets/ganttDiagram-NO4QXBWP-BgoAVKuc.js +292 -0
  111. package/client/assets/gitGraph-TEB2WS4Q-CH12KLTN-Bz4frAhV.js +1 -0
  112. package/client/assets/gitGraph-TEB2WS4Q-DIMvNvqt.js +1 -0
  113. package/client/assets/gitGraphDiagram-IHSO6WYX-B2CJhk_G-ClOKkjxw.js +106 -0
  114. package/client/assets/gitGraphDiagram-IHSO6WYX-Dmb6KnPz.js +106 -0
  115. package/client/assets/graphlib-B8gBHxth.js +1 -0
  116. package/client/assets/graphlib-hY-1btwe-DQjxxcnr.js +1 -0
  117. package/client/assets/{html2canvas-CDGcmOD3-CKJ6vKPo.js → html2canvas-CDGcmOD3-DRL9pFVl.js} +2 -2
  118. package/client/assets/{index-9lmYSaus.js → index-Dc0R-HW5.js} +129 -190
  119. package/client/assets/index-Dxo1Zdd-.css +2 -0
  120. package/client/assets/{index.es-DqtpmBm8-DFXjJgCa.js → index.es-DqtpmBm8-EQk3NgR8.js} +1 -1
  121. package/client/assets/info-DKCQHKI2-Cbw3mbiK-GsDZz9IO.js +1 -0
  122. package/client/assets/info-DKCQHKI2-ViCqobGo.js +1 -0
  123. package/client/assets/infoDiagram-FWYZ7A6U-HKV7LIG-.js +2 -0
  124. package/client/assets/infoDiagram-FWYZ7A6U-Mp1X3pBP-ATJv87Ur.js +2 -0
  125. package/client/assets/init-D6jRqBbL.js +1 -0
  126. package/client/assets/init-DEsX3bhM-D6jRqBbL.js +1 -0
  127. package/client/assets/ishikawaDiagram-FXEZZL3T-BNG7tkJu-CGCeOIlJ.js +70 -0
  128. package/client/assets/ishikawaDiagram-FXEZZL3T-CVDUj46f.js +70 -0
  129. package/client/assets/journeyDiagram-5HDEW3XC-BA-ESGLP.js +139 -0
  130. package/client/assets/journeyDiagram-5HDEW3XC-Dbp_hY9X-Bx-IoCe9.js +139 -0
  131. package/client/assets/kanban-definition-HUTT4EX6-Bqaet01L.js +89 -0
  132. package/client/assets/kanban-definition-HUTT4EX6-DSTc5u3q-C0JGckt1.js +89 -0
  133. package/client/assets/katex-CddkPoXu.js +257 -0
  134. package/client/assets/katex-M0IxphGf-CddkPoXu.js +257 -0
  135. package/client/assets/lib-4Tgx7rAy.js +114 -0
  136. package/client/assets/line-B1wBwzrY-f5wxpqoF.js +1 -0
  137. package/client/assets/line-CkyHfW7d.js +1 -0
  138. package/client/assets/linear-B9fuEF4c.js +1 -0
  139. package/client/assets/linear-lrGinF5_-CqNBync7.js +1 -0
  140. package/client/assets/map-CgrwEyH7-DWQFomlZ.js +1 -0
  141. package/client/assets/map-DsCK-0Cs.js +1 -0
  142. package/client/assets/marked.esm-CIU5FDdN.js +64 -0
  143. package/client/assets/marp-CSq0PPfK.js +3448 -0
  144. package/client/assets/material-symbols-outlined-DdRFxZLh.woff2 +0 -0
  145. package/client/assets/mermaid-parser.core-DC7NPJ_M-Ca6XzwfM.js +166 -0
  146. package/client/assets/mermaid-parser.core-SAwSf4_o.js +7 -0
  147. package/client/assets/mermaid.core-BBEQfkdJ.js +11 -0
  148. package/client/assets/mermaid.core-DZM3Ha-E-BxOo-RYG.js +11 -0
  149. package/client/assets/mindmap-definition-LN4V7U3C-B4BN0efL.js +96 -0
  150. package/client/assets/mindmap-definition-LN4V7U3C-DYtgcMsY-DynyLTNv.js +96 -0
  151. package/client/assets/ordinal-B9_Llu10-CU85fhaB.js +1 -0
  152. package/client/assets/ordinal-CopWnP7w.js +1 -0
  153. package/client/assets/packet-7NZHBO7P-CY4XRk9N.js +1 -0
  154. package/client/assets/packet-7NZHBO7P-lwb58iYx--vqSg65J.js +1 -0
  155. package/client/assets/path-BWPyau1x.js +1 -0
  156. package/client/assets/path-COivZ1Gw-C5riojK2.js +1 -0
  157. package/client/assets/pegDiagram-2B236MQR-BOKErjUu.js +1 -0
  158. package/client/assets/pegDiagram-2B236MQR-C43eIpKM-Bi_5Sxjt.js +1 -0
  159. package/client/assets/pie-RZYD4A2V-6BHB7bAx.js +1 -0
  160. package/client/assets/pie-RZYD4A2V-B1UWb4Gu-Dmn2hLWH.js +1 -0
  161. package/client/assets/pieDiagram-ENE6RG2P-BkTqgJyR-Bcdm19kR.js +39 -0
  162. package/client/assets/pieDiagram-ENE6RG2P-DtNjvz-U.js +39 -0
  163. package/client/assets/preload-helper-CZgWQFsJ.js +1 -0
  164. package/client/assets/purify.es-DY32g7DN.js +3 -0
  165. package/client/assets/quadrantDiagram-ABIIQ3AL-BQmAJL2v.js +7 -0
  166. package/client/assets/quadrantDiagram-ABIIQ3AL-Bm1Zjm45-B3orqx_f.js +7 -0
  167. package/client/assets/radar-I7S5WNFK-7CKcb_l--CqKdnR0v.js +1 -0
  168. package/client/assets/radar-I7S5WNFK-R7Jhjfdt.js +1 -0
  169. package/client/assets/railroad-3IZDKUUU-BepSPyHI.js +1 -0
  170. package/client/assets/railroad-3IZDKUUU-gCySKdnW-CKU26HTP.js +1 -0
  171. package/client/assets/railroad-abnf-AHOZXSZD-BlsHsp3c.js +1 -0
  172. package/client/assets/railroad-abnf-AHOZXSZD-BophH4r--CGkGHq54.js +1 -0
  173. package/client/assets/railroad-ebnf-EBAXGLYW-AZNjl_Zu-B7bn_PF3.js +1 -0
  174. package/client/assets/railroad-ebnf-EBAXGLYW-B4fMcGEH.js +1 -0
  175. package/client/assets/railroad-peg-LSFZ7HO6-B1ZrjJIu.js +1 -0
  176. package/client/assets/railroad-peg-LSFZ7HO6-BSiEEyeb-CP_B-N5g.js +1 -0
  177. package/client/assets/railroadDiagram-RFXS5EU6-8cz0Iby3.js +1 -0
  178. package/client/assets/railroadDiagram-RFXS5EU6-BkfbdeAs-Di6jH5I6.js +1 -0
  179. package/client/assets/requirementDiagram-TGXJPOKE-CrGTTjYg-DmIC7Shp.js +84 -0
  180. package/client/assets/requirementDiagram-TGXJPOKE-Dlqoe9TY.js +84 -0
  181. package/client/assets/rough.esm-CSKSodPl.js +1 -0
  182. package/client/assets/rough.esm-wVmwlXu7-CSKSodPl.js +1 -0
  183. package/client/assets/runtime-protocol-vue-WG3JLsjz.js +1 -0
  184. package/client/assets/runtime-vue-lHsY5zMj.js +1 -0
  185. package/client/assets/sankeyDiagram-HTMAVEWB-BkTKgu8Q.js +40 -0
  186. package/client/assets/sankeyDiagram-HTMAVEWB-rWXPf03Z-CjV9pCSJ.js +40 -0
  187. package/client/assets/{schemas-D_RbFtuQ.js → schemas-DGvl73AE.js} +3 -3
  188. package/client/assets/sequenceDiagram-DBY2YBRQ-BpuXUcFy.js +162 -0
  189. package/client/assets/sequenceDiagram-DBY2YBRQ-nkJYWO2m-BqS_sTCH.js +162 -0
  190. package/client/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
  191. package/client/assets/sizeCapture-X5ZJPWSS-F5SadAuT-VHIb4_NU.js +1 -0
  192. package/client/assets/src-Brzfja-q-DNc4Or4z.js +1 -0
  193. package/client/assets/src-Cqa3Jy1j.js +1 -0
  194. package/client/assets/stateDiagram-2N3HPSRC-CdlGXuo7.js +1 -0
  195. package/client/assets/stateDiagram-2N3HPSRC-T4-clK8b-DQRiB4va.js +1 -0
  196. package/client/assets/stateDiagram-v2-6OUMAXLB-BN8Jr3ZM.js +1 -0
  197. package/client/assets/stateDiagram-v2-6OUMAXLB-DIp7nhRd-DbrOhUn_.js +1 -0
  198. package/client/assets/swimlanes-5IMT3BWC-HmQNEntu-CNBgZdur.js +2 -0
  199. package/client/assets/swimlanes-5IMT3BWC-iEJg5gki.js +2 -0
  200. package/client/assets/swimlanesDiagram-G3AALYLV-BeoZhwg7-DpqgeNRA.js +8 -0
  201. package/client/assets/swimlanesDiagram-G3AALYLV-o-sS6aEP.js +8 -0
  202. package/client/assets/timeline-definition-FHXFAJF6-Bjh-7QmL.js +120 -0
  203. package/client/assets/timeline-definition-FHXFAJF6-CNc9jSTP-BKNSymgY.js +120 -0
  204. package/client/assets/treeView-QDETBFTQ-D3cqRl6k.js +1 -0
  205. package/client/assets/treeView-QDETBFTQ-nIQcG1h9-O_ri9HxD.js +1 -0
  206. package/client/assets/treemap-6X3UGDF4-BnsvC8yL-Cfsty1e3.js +1 -0
  207. package/client/assets/treemap-6X3UGDF4-DGkZcvDG.js +1 -0
  208. package/client/assets/v4-B29ayslu.js +1 -0
  209. package/client/assets/vennDiagram-L72KCM5P-Cz3dbe7b.js +34 -0
  210. package/client/assets/vennDiagram-L72KCM5P-Dr3pTJ_0-C38xwcVo.js +34 -0
  211. package/client/assets/vue-C6d2VveO.js +1 -0
  212. package/client/assets/vue-i18n-CL-ejuNu.js +3 -0
  213. package/client/assets/vue.runtime.esm-bundler-BeoTfMNc.js +4 -0
  214. package/client/assets/wardley-OPB4EBWU-8Odxkx6V-CCDIVuBs.js +1 -0
  215. package/client/assets/wardley-OPB4EBWU-CZsCDvKk.js +1 -0
  216. package/client/assets/wardleyDiagram-EHGQE667-DSFc7ZZa-mlWXRiWx.js +78 -0
  217. package/client/assets/wardleyDiagram-EHGQE667-DiyoyO_X.js +78 -0
  218. package/client/assets/xychartDiagram-FW5EYKEG-BP0Nn4Pp-DRRiStGZ.js +7 -0
  219. package/client/assets/xychartDiagram-FW5EYKEG-DhY1_UGM.js +7 -0
  220. package/client/index.html +16 -12
  221. package/package.json +17 -19
  222. package/server/agent/backend/types.ts +1 -1
  223. package/server/agent/backgroundSessions.ts +43 -0
  224. package/server/agent/config.ts +3 -2
  225. package/server/agent/mcp-tools/manageCollection.ts +4 -4
  226. package/server/agent/sandboxMounts.ts +1 -1
  227. package/server/agent/stream.ts +1 -3
  228. package/server/api/auth/viewToken.ts +1 -1
  229. package/server/api/bridge/sessionRole.ts +47 -0
  230. package/server/api/routes/agent.ts +79 -2
  231. package/server/api/routes/collections.ts +60 -7
  232. package/server/api/routes/collectionsRegistry.ts +113 -0
  233. package/server/api/routes/dashboard.ts +47 -0
  234. package/server/api/routes/feeds.ts +2 -2
  235. package/server/api/routes/files.ts +1 -2
  236. package/server/api/routes/pdf.ts +48 -9
  237. package/server/api/routes/plugins.ts +2 -2
  238. package/server/api/routes/remoteHost.ts +55 -0
  239. package/server/api/routes/sessions.ts +20 -11
  240. package/server/api/routes/share.ts +105 -0
  241. package/server/api/routes/transcribe.ts +1 -1
  242. package/server/api/routes/wiki/history.ts +2 -2
  243. package/server/api/routes/wiki.ts +29 -177
  244. package/server/api/sandboxStatus.ts +1 -1
  245. package/server/build/dispatcher.mjs +25 -14928
  246. package/server/events/collection-change.ts +4 -4
  247. package/server/events/file-change.ts +2 -2
  248. package/server/events/scheduler-adapter.ts +3 -3
  249. package/server/events/task-manager/index.ts +3 -3
  250. package/server/index.ts +53 -17
  251. package/server/notifier/engine.ts +3 -3
  252. package/server/notifier/types.ts +2 -2
  253. package/server/plugins/html-builtin.ts +15 -1
  254. package/server/prompts/system/system.md +4 -0
  255. package/server/remoteHost/auth.ts +29 -0
  256. package/server/remoteHost/commandChannel.ts +56 -0
  257. package/server/remoteHost/firebase.ts +16 -0
  258. package/server/remoteHost/handlers/collectionPage.ts +29 -0
  259. package/server/remoteHost/handlers/getCollection.ts +32 -0
  260. package/server/remoteHost/handlers/getFeed.ts +35 -0
  261. package/server/remoteHost/handlers/index.ts +19 -0
  262. package/server/remoteHost/handlers/listCollections.ts +29 -0
  263. package/server/remoteHost/handlers/listFeeds.ts +37 -0
  264. package/server/remoteHost/handlers/listShortcuts.ts +24 -0
  265. package/server/remoteHost/handlers/startChat.ts +78 -0
  266. package/server/remoteHost/hostRunner.ts +122 -0
  267. package/server/remoteHost/index.ts +117 -0
  268. package/server/system/config.ts +1 -1
  269. package/server/system/credentials.ts +2 -3
  270. package/server/system/docker.ts +9 -8
  271. package/server/system/env.ts +8 -0
  272. package/server/system/whisper/index.ts +4 -4
  273. package/server/utils/claudeConfigPath.ts +57 -0
  274. package/server/utils/files/dashboard-io.ts +87 -0
  275. package/server/utils/files/session-io.ts +11 -0
  276. package/server/utils/markdown/frontmatter.ts +8 -4
  277. package/server/utils/regex.ts +4 -3
  278. package/server/utils/share/packHtml.ts +108 -0
  279. package/server/utils/share/rewriteAssets.ts +178 -0
  280. package/server/workspace/chat-index/paths.ts +8 -2
  281. package/server/workspace/chat-index/summarizer.ts +23 -15
  282. package/server/workspace/collections/configure.ts +5 -3
  283. package/server/workspace/collections/index.ts +8 -6
  284. package/server/workspace/collections/notifications.ts +3 -3
  285. package/server/workspace/collections/types.ts +2 -2
  286. package/server/workspace/collections/watcher.ts +2 -2
  287. package/server/workspace/feeds/configure.ts +24 -0
  288. package/server/workspace/hooks/handlers/skillBridge.ts +2 -2
  289. package/server/workspace/hooks/handlers/wikiSnapshot.ts +1 -1
  290. package/server/workspace/paths.ts +8 -1
  291. package/server/workspace/skills/catalog.ts +1 -3
  292. package/server/workspace/skills/external/catalog.ts +1 -3
  293. package/server/workspace/skills/paths.ts +4 -3
  294. package/server/workspace/skills/writer.ts +1 -4
  295. package/server/workspace/skills-preset.ts +3 -3
  296. package/server/workspace/wiki-pages/io.ts +2 -2
  297. package/server/workspace/workspace.ts +2 -2
  298. package/src/App.vue +41 -18
  299. package/src/components/ChatInput.vue +1 -1
  300. package/src/components/DashboardView.vue +372 -0
  301. package/src/components/FileContentRenderer.vue +32 -7
  302. package/src/components/JsonEditor.vue +1 -1
  303. package/src/components/PluginLauncher.vue +122 -79
  304. package/src/components/RemoteHostControl.vue +159 -0
  305. package/src/components/SessionCountBadges.vue +32 -0
  306. package/src/components/SessionHeaderControls.vue +1 -8
  307. package/src/components/SessionHistoryPanel.vue +2 -0
  308. package/src/components/SessionHistoryToggleButton.vue +1 -15
  309. package/src/components/SidebarHeader.vue +2 -0
  310. package/src/components/collectionTypes.ts +2 -2
  311. package/src/composables/accountingHost.ts +24 -0
  312. package/src/composables/collections/uiHost.ts +17 -2
  313. package/src/composables/useDashboard.ts +191 -0
  314. package/src/composables/useMarkdownZip.ts +51 -0
  315. package/src/composables/useNotifications.ts +1 -4
  316. package/src/composables/useSharePack.ts +60 -0
  317. package/src/composables/useTranslatedQueries.ts +15 -95
  318. package/src/composables/useTranslatedStrings.ts +68 -0
  319. package/src/composables/useVoiceInput.ts +3 -3
  320. package/src/config/apiRoutes.ts +57 -9
  321. package/src/config/createFilePolicy.ts +1 -1
  322. package/src/config/firebase.ts +12 -0
  323. package/src/config/firebaseConfig.ts +18 -0
  324. package/src/config/historyFilters.ts +7 -0
  325. package/src/config/pubsubChannels.ts +7 -27
  326. package/src/config/roles.ts +12 -10
  327. package/src/config/workspacePaths.ts +10 -0
  328. package/src/index.css +1 -1
  329. package/src/lang/de.ts +39 -220
  330. package/src/lang/en.ts +39 -191
  331. package/src/lang/es.ts +39 -218
  332. package/src/lang/fr.ts +39 -220
  333. package/src/lang/ja.ts +39 -216
  334. package/src/lang/ko.ts +39 -216
  335. package/src/lang/pt-BR.ts +39 -217
  336. package/src/lang/zh.ts +39 -215
  337. package/src/main.ts +3 -0
  338. package/src/plugins/accounting/definition.ts +12 -8
  339. package/src/plugins/accounting/index.ts +7 -4
  340. package/src/plugins/accounting/meta.ts +23 -60
  341. package/src/plugins/manageSkills/View.vue +9 -1
  342. package/src/plugins/photoLocations/View.vue +2 -2
  343. package/src/plugins/presentCollection/definition.ts +2 -2
  344. package/src/plugins/presentCollection/plugin.ts +2 -2
  345. package/src/plugins/presentCollection/types.ts +2 -2
  346. package/src/plugins/presentHtml/definition.ts +1 -1
  347. package/src/plugins/presentMulmoScript/View.vue +2 -2
  348. package/src/plugins/presentMulmoScript/helpers.ts +1 -1
  349. package/src/plugins/presentSVG/View.vue +2 -2
  350. package/src/plugins/scheduler/TasksTab.vue +1 -2
  351. package/src/plugins/skill/View.vue +7 -3
  352. package/src/plugins/spreadsheet/View.vue +3 -3
  353. package/src/plugins/spreadsheet/engine/functions/logical.ts +8 -1
  354. package/src/plugins/textResponse/View.vue +43 -16
  355. package/src/plugins/wiki/View.vue +29 -2
  356. package/src/plugins/wiki/components/WikiGraphView.vue +1 -1
  357. package/src/plugins/wiki/components/WikiPageBody.vue +4 -1
  358. package/src/plugins/wiki/helpers.ts +13 -81
  359. package/src/plugins/wiki/index.ts +1 -1
  360. package/src/router/guards.ts +1 -1
  361. package/src/router/index.ts +12 -0
  362. package/src/router/pageRoutes.ts +2 -0
  363. package/src/types/dashboard.ts +40 -0
  364. package/src/types/session.ts +3 -0
  365. package/src/utils/blobDownload.ts +19 -0
  366. package/src/utils/collections/presentSeed.ts +1 -1
  367. package/src/utils/html/customViewSrcdoc.ts +31 -3
  368. package/src/utils/html/previewCsp.ts +1 -1
  369. package/src/utils/id.ts +1 -1
  370. package/src/utils/image/htmlSrcAttrs.ts +1 -1
  371. package/src/utils/markdown/frontmatter.ts +12 -7
  372. package/src/utils/markdown/highlight.ts +22 -0
  373. package/src/utils/markdown/marpCustomSize.ts +2 -2
  374. package/src/utils/markdown/mermaidExtension.ts +56 -0
  375. package/src/utils/markdown/mermaidRender.ts +147 -0
  376. package/src/utils/markdown/setup.ts +17 -4
  377. package/src/utils/markdown/useMermaid.ts +33 -0
  378. package/src/utils/session/longRunning.ts +33 -0
  379. package/src/utils/session/mergeSessions.ts +1 -1
  380. package/client/assets/JsonEditor-Di5xGeZY.css +0 -1
  381. package/client/assets/JsonEditor-o5--tPQH.js +0 -10
  382. package/client/assets/index-tOu5ArRZ.css +0 -2
  383. package/client/assets/lib-D6Xy0IFc.js +0 -114
  384. package/client/assets/marp-D6GXA-EB.js +0 -3452
  385. package/client/assets/material-symbols-outlined-DtIK7AQn.woff2 +0 -0
  386. package/client/assets/runtime-protocol-vue-pU0Mw7Zm.js +0 -1
  387. package/client/assets/runtime-vue-fFYhnNg3.js +0 -1
  388. package/client/assets/vue-UDIWDtr8.js +0 -1
  389. package/client/assets/vue-i18n-CQbxVmNs.js +0 -3
  390. package/client/assets/vue.runtime.esm-bundler-BTyIdNAI.js +0 -4
  391. package/server/accounting/accountNormalize.ts +0 -32
  392. package/server/accounting/defaultAccounts.ts +0 -87
  393. package/server/accounting/eventPublisher.ts +0 -52
  394. package/server/accounting/journal.ts +0 -252
  395. package/server/accounting/openingBalances.ts +0 -114
  396. package/server/accounting/report.ts +0 -237
  397. package/server/accounting/service.ts +0 -718
  398. package/server/accounting/snapshotCache.ts +0 -334
  399. package/server/accounting/timeSeries.ts +0 -265
  400. package/server/accounting/types.ts +0 -148
  401. package/server/api/routes/accounting.ts +0 -373
  402. package/server/api/routes/wiki/frontmatter.ts +0 -34
  403. package/server/api/routes/wiki/pageIndex.ts +0 -53
  404. package/server/system/logs/aaa +0 -737
  405. package/server/system/logs/bb +0 -446
  406. package/server/utils/files/accounting-io.ts +0 -294
  407. package/server/workspace/feeds/engine.ts +0 -143
  408. package/server/workspace/feeds/fetch/httpClient.ts +0 -127
  409. package/server/workspace/feeds/fetch/rssParser.ts +0 -117
  410. package/server/workspace/feeds/index.ts +0 -8
  411. package/server/workspace/feeds/ingestTypes.ts +0 -62
  412. package/server/workspace/feeds/pathResolver.ts +0 -74
  413. package/server/workspace/feeds/paths.ts +0 -30
  414. package/server/workspace/feeds/projectItem.ts +0 -92
  415. package/server/workspace/feeds/registry.ts +0 -43
  416. package/server/workspace/feeds/retrievers/httpJson.ts +0 -19
  417. package/server/workspace/feeds/retrievers/index.ts +0 -27
  418. package/server/workspace/feeds/retrievers/registerAll.ts +0 -5
  419. package/server/workspace/feeds/retrievers/rss.ts +0 -24
  420. package/server/workspace/feeds/state.ts +0 -55
  421. package/src/composables/useAccountingChannel.ts +0 -58
  422. package/src/lib/wiki-page/graph.ts +0 -108
  423. package/src/lib/wiki-page/index-parse.ts +0 -221
  424. package/src/lib/wiki-page/link.ts +0 -62
  425. package/src/lib/wiki-page/lint.ts +0 -105
  426. package/src/lib/wiki-page/paths.ts +0 -35
  427. package/src/lib/wiki-page/slug.ts +0 -54
  428. package/src/plugins/accounting/Preview.vue +0 -103
  429. package/src/plugins/accounting/View.vue +0 -633
  430. package/src/plugins/accounting/actions.ts +0 -34
  431. package/src/plugins/accounting/api.ts +0 -301
  432. package/src/plugins/accounting/components/AccountEditor.vue +0 -250
  433. package/src/plugins/accounting/components/AccountRow.vue +0 -50
  434. package/src/plugins/accounting/components/AccountsList.vue +0 -102
  435. package/src/plugins/accounting/components/AccountsModal.vue +0 -301
  436. package/src/plugins/accounting/components/BalanceSheet.vue +0 -186
  437. package/src/plugins/accounting/components/BookSettings.vue +0 -284
  438. package/src/plugins/accounting/components/BookSwitcher.vue +0 -78
  439. package/src/plugins/accounting/components/DateRangePicker.vue +0 -140
  440. package/src/plugins/accounting/components/JournalEntryForm.vue +0 -505
  441. package/src/plugins/accounting/components/JournalList.vue +0 -554
  442. package/src/plugins/accounting/components/Ledger.vue +0 -206
  443. package/src/plugins/accounting/components/NewBookForm.vue +0 -211
  444. package/src/plugins/accounting/components/OpeningBalancesForm.vue +0 -272
  445. package/src/plugins/accounting/components/ProfitLoss.vue +0 -160
  446. package/src/plugins/accounting/components/accountDraft.ts +0 -13
  447. package/src/plugins/accounting/components/accountNumbering.ts +0 -103
  448. package/src/plugins/accounting/components/accountValidation.ts +0 -75
  449. package/src/plugins/accounting/components/useLatestRequest.ts +0 -44
  450. package/src/plugins/accounting/countries.ts +0 -158
  451. package/src/plugins/accounting/currencies.ts +0 -77
  452. package/src/plugins/accounting/dates.ts +0 -51
  453. package/src/plugins/accounting/fiscalYear.ts +0 -136
  454. package/src/plugins/accounting/timeSeriesEnums.ts +0 -16
  455. package/src/plugins/wiki/route.ts +0 -137
  456. /package/client/assets/{_plugin-vue_export-helper-B67ILkmu.js → _plugin-vue_export-helper-BDNMzG2s.js} +0 -0
  457. /package/client/assets/{purify.es-B27wDFIb-51iYcXuK.js → purify.es-B27wDFIb-Bu4Grnl0.js} +0 -0
  458. /package/client/assets/{typeof-DBp4T-Ny-z2wCIsir.js → typeof-DBp4T-Ny-B5XbjTb1.js} +0 -0
@@ -1,633 +0,0 @@
1
- <template>
2
- <!-- Full <AccountingApp> mounted via the openBook tool result.
3
- Talks to /api/accounting directly for browse / form ops; only
4
- the entry gate (this mount) runs through the LLM. Pub/sub
5
- refetches keep multi-tab / sibling-window views in sync. -->
6
- <div class="h-full bg-white flex flex-col" data-testid="accounting-app">
7
- <NewBookForm v-if="showFirstRunForm" first-run full-page @created="onFirstBookCreated" />
8
- <template v-else>
9
- <header class="flex items-center justify-between gap-2 px-3 py-2 border-b border-gray-100 shrink-0">
10
- <div class="flex items-center gap-2 min-w-0">
11
- <span class="material-icons text-gray-600">account_balance</span>
12
- <h2 class="text-lg font-semibold text-gray-800">{{ t("pluginAccounting.title") }}</h2>
13
- </div>
14
- <BookSwitcher
15
- v-if="initialLoadDone"
16
- :model-value="activeBookId ?? ''"
17
- :books="books"
18
- @update:model-value="onBookSelected"
19
- @books-changed="refetchBooks"
20
- @book-created="onBookCreated"
21
- />
22
- </header>
23
- <nav class="flex items-center gap-0.5 px-3 py-1.5 border-b border-gray-100 shrink-0 overflow-x-auto" data-testid="accounting-tabs">
24
- <button
25
- v-for="tab in visibleTabs"
26
- :key="tab.key"
27
- :class="[
28
- 'h-8 px-2.5 flex items-center gap-1 rounded text-sm whitespace-nowrap',
29
- deletedNoticeName !== null
30
- ? 'text-gray-400 cursor-not-allowed'
31
- : currentTab === tab.key
32
- ? 'bg-blue-50 text-blue-600 font-medium'
33
- : 'text-gray-600 hover:bg-gray-50',
34
- ]"
35
- :data-testid="`accounting-tab-${tab.key}`"
36
- :disabled="deletedNoticeName !== null"
37
- @click="currentTab = tab.key"
38
- >
39
- <span class="material-icons text-base">{{ tab.icon }}</span>
40
- <span>{{ t(tab.labelKey) }}</span>
41
- </button>
42
- </nav>
43
- <main class="flex-1 overflow-auto p-4">
44
- <div
45
- v-if="deletedNoticeName !== null"
46
- class="text-center text-sm text-gray-600 flex flex-col gap-2 items-center justify-center h-full"
47
- data-testid="accounting-deleted-notice"
48
- >
49
- <span class="material-icons text-gray-400" style="font-size: 48px">delete_outline</span>
50
- <p class="font-medium" data-testid="accounting-deleted-notice-title">
51
- {{ t("pluginAccounting.deletedNotice.title", { bookName: deletedNoticeName }) }}
52
- </p>
53
- <p class="text-xs text-gray-500">{{ t("pluginAccounting.deletedNotice.body") }}</p>
54
- </div>
55
- <p v-else-if="loadingBooks && !initialLoadDone" class="text-sm text-gray-400">{{ t("pluginAccounting.common.loading") }}</p>
56
- <p v-else-if="bookLoadError" class="text-sm text-red-500" data-testid="accounting-load-error">
57
- {{ t("pluginAccounting.common.error", { error: bookLoadError }) }}
58
- </p>
59
- <p v-else-if="!activeBookId" class="text-sm text-gray-500" data-testid="accounting-no-book">{{ t("pluginAccounting.noBook") }}</p>
60
- <template v-else-if="activeBookId">
61
- <JournalList
62
- v-if="currentTab === 'journal'"
63
- :book-id="activeBookId"
64
- :accounts="accounts"
65
- :currency="activeCurrency"
66
- :country="activeCountry"
67
- :version="bookVersion"
68
- :fiscal-year-end="activeFiscalYearEnd"
69
- :opening-date="activeOpeningDate"
70
- :preselect-entry-id="journalPreselectEntryId"
71
- @edit-opening="currentTab = 'opening'"
72
- @preselect-consumed="journalPreselectEntryId = undefined"
73
- />
74
- <OpeningBalancesForm
75
- v-else-if="currentTab === 'opening'"
76
- :book-id="activeBookId"
77
- :accounts="accounts"
78
- :currency="activeCurrency"
79
- :version="bookVersion"
80
- @submitted="onEntrySubmitted"
81
- />
82
- <AccountsList v-else-if="currentTab === 'accounts'" :book-id="activeBookId" :accounts="accounts" @select-account="onAccountSelected" />
83
- <Ledger
84
- v-else-if="currentTab === 'ledger'"
85
- :book-id="activeBookId"
86
- :accounts="accounts"
87
- :currency="activeCurrency"
88
- :version="bookVersion"
89
- :fiscal-year-end="activeFiscalYearEnd"
90
- :opening-date="activeOpeningDate"
91
- :preselect-account-code="ledgerPreselectAccountCode"
92
- />
93
- <BalanceSheet
94
- v-else-if="currentTab === 'balanceSheet'"
95
- :book-id="activeBookId"
96
- :currency="activeCurrency"
97
- :version="bookVersion"
98
- @select-account="onAccountSelected"
99
- />
100
- <ProfitLoss
101
- v-else-if="currentTab === 'profitLoss'"
102
- :book-id="activeBookId"
103
- :currency="activeCurrency"
104
- :version="bookVersion"
105
- :fiscal-year-end="activeFiscalYearEnd"
106
- :opening-date="activeOpeningDate"
107
- @select-account="onAccountSelected"
108
- />
109
- <BookSettings
110
- v-else-if="currentTab === 'settings'"
111
- :book-id="activeBookId"
112
- :book-name="activeBookName"
113
- :currency="activeCurrency"
114
- :country="activeCountry"
115
- :fiscal-year-end="activeFiscalYearEnd"
116
- @deleted="onBookDeleted"
117
- @books-changed="refetchBooks"
118
- />
119
- </template>
120
- </main>
121
- </template>
122
- </div>
123
- </template>
124
-
125
- <script setup lang="ts">
126
- import { computed, ref, watch } from "vue";
127
- import { useI18n } from "vue-i18n";
128
- import type { ToolResultComplete } from "gui-chat-protocol/vue";
129
- import BookSwitcher from "./components/BookSwitcher.vue";
130
- import NewBookForm from "./components/NewBookForm.vue";
131
- import JournalList from "./components/JournalList.vue";
132
- import OpeningBalancesForm from "./components/OpeningBalancesForm.vue";
133
- import AccountsList from "./components/AccountsList.vue";
134
- import Ledger from "./components/Ledger.vue";
135
- import BalanceSheet from "./components/BalanceSheet.vue";
136
- import ProfitLoss from "./components/ProfitLoss.vue";
137
- import BookSettings from "./components/BookSettings.vue";
138
- import { getOpeningBalances, getAccounts, getBooks, type Account, type BookSummary } from "./api";
139
- import { ACCOUNTING_ACTIONS } from "./actions";
140
- import { useAccountingChannel, useAccountingBooksChannel } from "../../composables/useAccountingChannel";
141
- import { errorMessage } from "../../utils/errors";
142
-
143
- const { t } = useI18n();
144
-
145
- interface AccountingAppPayload {
146
- kind?: string;
147
- bookId?: string;
148
- initialTab?: string;
149
- /** Dispatch verb stamped onto every accounting tool-result envelope
150
- * (server/api/routes/accounting.ts dispatch()). We read it here to
151
- * pick the canvas tab + journal preselect for each PREVIEW action. */
152
- action?: string;
153
- /** Present on `addEntries` envelopes — the freshly-built journal
154
- * entries returned by the service. Each carries a server-stamped
155
- * `id` we use to highlight the row in JournalList. */
156
- entries?: { id?: string }[];
157
- /** Present on `voidEntry` envelopes — the kind="void-marker" row
158
- * posted alongside the reversing entry. We surface this row (not
159
- * the reverseEntry) because the marker is the visual "this entry
160
- * was voided here" indicator the user is looking for. */
161
- markerEntry?: { id?: string };
162
- }
163
-
164
- const props = defineProps<{ selectedResult?: ToolResultComplete<AccountingAppPayload, AccountingAppPayload> }>();
165
-
166
- const TAB_KEYS = ["journal", "opening", "accounts", "ledger", "balanceSheet", "profitLoss", "settings"] as const;
167
- type TabKey = (typeof TAB_KEYS)[number];
168
-
169
- interface TabDef {
170
- key: TabKey;
171
- icon: string;
172
- labelKey: string;
173
- }
174
-
175
- const TABS: readonly TabDef[] = [
176
- { key: "journal", icon: "list", labelKey: "pluginAccounting.tabs.journal" },
177
- { key: "opening", icon: "play_arrow", labelKey: "pluginAccounting.tabs.opening" },
178
- { key: "accounts", icon: "list_alt", labelKey: "pluginAccounting.tabs.accounts" },
179
- { key: "ledger", icon: "menu_book", labelKey: "pluginAccounting.tabs.ledger" },
180
- { key: "balanceSheet", icon: "balance", labelKey: "pluginAccounting.tabs.balanceSheet" },
181
- { key: "profitLoss", icon: "trending_up", labelKey: "pluginAccounting.tabs.profitLoss" },
182
- { key: "settings", icon: "settings", labelKey: "pluginAccounting.tabs.settings" },
183
- ];
184
-
185
- function isTabKey(value: string | undefined): value is TabKey {
186
- return typeof value === "string" && (TAB_KEYS as readonly string[]).includes(value);
187
- }
188
-
189
- const initialPayload = computed<AccountingAppPayload>(() => props.selectedResult?.data ?? props.selectedResult?.jsonData ?? {});
190
- const initialTab = computed<TabKey>(() => (isTabKey(initialPayload.value.initialTab) ? initialPayload.value.initialTab : "journal"));
191
-
192
- const currentTab = ref<TabKey>(initialTab.value);
193
- const books = ref<BookSummary[]>([]);
194
- const activeBookId = ref<string | null>(null);
195
- const accounts = ref<Account[]>([]);
196
- const loadingBooks = ref(true);
197
- // Sticky once the first books fetch lands. Lets the BookSwitcher stay
198
- // mounted across subsequent refetches (delete, create, pubsub-driven)
199
- // so the user sees the dropdown smoothly update its selection rather
200
- // than having the whole component flash in and out via `v-if`.
201
- const initialLoadDone = ref(false);
202
- // First-run flow: when the user opens the app on a fresh
203
- // workspace (zero books), we render NewBookForm in full-page
204
- // mode in place of the regular chrome (header + tabs + main),
205
- // so the user MUST pick a name + currency before proceeding —
206
- // no popup, no dismiss. Distinct from the modal opened via
207
- // BookSwitcher's "+ New book" sentinel option, which reuses the
208
- // same component but with the overlay layout.
209
- const showFirstRunForm = ref(false);
210
- const firstRunHandled = ref(false);
211
- // Distinct from "books is empty" so we don't show the "+ New
212
- // book" CTA when the real problem is a transport / server failure
213
- // fetching the list.
214
- const bookLoadError = ref<string | null>(null);
215
- // Tracks whether the active book has an opening entry on file.
216
- // `null` = unknown / loading; the gate only activates on an
217
- // explicit `false` so we don't disable tabs during the cold load
218
- // while the first getOpeningBalances request is still in flight.
219
- const hasOpening = ref<boolean | null>(null);
220
- // Date of the active book's opening entry, plumbed down to the
221
- // DateRangePicker via the children so "All" can resolve to
222
- // (openingDate → today). `undefined` while loading / for books
223
- // without an opening on file (the opening gate prevents any tab
224
- // that would care from being shown in that state).
225
- const activeOpeningDate = ref<string | undefined>(undefined);
226
- // Special "you just deleted this book" UI state. When set to a
227
- // non-null book name, the entire tab strip + main content are
228
- // replaced by an explicit "<book> has been deleted — pick another
229
- // from the dropdown" panel. Cleared the moment the user picks a
230
- // book from the BookSwitcher (or creates a new one). The View does
231
- // NOT auto-route to books[0] because that hides the fact that the
232
- // previously-active book is gone — issue #1126 (1) calls this
233
- // experience "very confusing".
234
- const deletedNoticeName = ref<string | null>(null);
235
-
236
- const activeBook = computed(() => books.value.find((book) => book.id === activeBookId.value) ?? null);
237
- const activeBookName = computed(() => activeBook.value?.name ?? "");
238
- const activeCurrency = computed(() => activeBook.value?.currency ?? "USD");
239
- const activeCountry = computed(() => activeBook.value?.country);
240
- const activeFiscalYearEnd = computed(() => activeBook.value?.fiscalYearEnd);
241
-
242
- // Single sync signal: every mutating service function publishes on
243
- // the accounting book channel after its write, so the sender's own
244
- // SSE round-trip drives the table/report refetch. No parallel
245
- // localVersion bump — it only ever fired the same watchers a second
246
- // time in the same tick.
247
- const { version: bookVersion } = useAccountingChannel(activeBookId);
248
- useAccountingBooksChannel(() => void refetchBooks());
249
-
250
- function pickInitialBookId(): string | null {
251
- // Priority: explicit `initialPayload.bookId` (carried in the
252
- // tool-result envelope by openBook / createBook / addEntries / …) →
253
- // first book in the list → null (empty workspace). The candidate
254
- // is validated against the live book list so a stale id from a
255
- // deleted book doesn't poison the View.
256
- if (books.value.length === 0) return null;
257
- const requested = initialPayload.value.bookId;
258
- if (requested && books.value.some((book) => book.id === requested)) return requested;
259
- return books.value[0].id;
260
- }
261
-
262
- async function refetchBooks(): Promise<void> {
263
- loadingBooks.value = true;
264
- bookLoadError.value = null;
265
- // Capture the current active book BEFORE the fetch so we can
266
- // surface its name in the deleted-notice panel if the fetch
267
- // reveals it's gone. Without this snapshot, an SSE-driven refetch
268
- // racing ahead of the local deleteBook HTTP response would resolve
269
- // with `activeBook` already pointing at a now-stale entry.
270
- const previousActive = activeBook.value;
271
- try {
272
- const result = await getBooks();
273
- if (!result.ok) {
274
- // Surface load failures as a distinct error state so the user
275
- // doesn't see "No books yet" (and the auto-open modal) when
276
- // the real cause is a transport / server problem.
277
- bookLoadError.value = result.error;
278
- return;
279
- }
280
- books.value = result.data.books;
281
- // Sticky-true once a successful fetch lands. Setting it here (in
282
- // the success branch) rather than in `finally` means a first-load
283
- // transport / 5xx failure leaves BookSwitcher hidden — the user
284
- // sees only the `accounting-load-error` message rather than an
285
- // empty dropdown with a live "+ New book" path that has nothing
286
- // to fall back on.
287
- initialLoadDone.value = true;
288
- // While the deleted-notice panel is already up, leave activeBookId
289
- // alone — the user has to pick the next book themselves via
290
- // the BookSwitcher (and onBookSelected then clears the notice).
291
- // Otherwise pickInitialBookId would silently re-select books[0]
292
- // and undo the entire deletion-state UX.
293
- if (deletedNoticeName.value === null) {
294
- const stillExists = activeBookId.value !== null && books.value.some((book) => book.id === activeBookId.value);
295
- if (!stillExists) {
296
- // The active book just disappeared from the server's list.
297
- // Race-source possibilities, all converging here:
298
- // • local deleteBook → publishBooksChanged → SSE arrives
299
- // before the HTTP response handler can call onBookDeleted;
300
- // • a sibling tab / LLM tool deleted the book out-of-band.
301
- // In all cases the user needs to know what happened — show
302
- // the deleted-notice panel keyed off the previously-active
303
- // book's name, rather than silently snapping to books[0].
304
- // Falls back to the previous pickInitialBookId behaviour only
305
- // when there was no active book to lose (cold start).
306
- if (previousActive) {
307
- activeBookId.value = null;
308
- deletedNoticeName.value = previousActive.name;
309
- } else {
310
- activeBookId.value = pickInitialBookId();
311
- }
312
- }
313
- }
314
- // Auto-open the New Book modal exactly once on first arrival
315
- // when the workspace is empty. After that, the user can still
316
- // open it manually via the "+ New book" button.
317
- if (!firstRunHandled.value && books.value.length === 0) {
318
- firstRunHandled.value = true;
319
- showFirstRunForm.value = true;
320
- }
321
- } catch (err) {
322
- bookLoadError.value = errorMessage(err);
323
- } finally {
324
- loadingBooks.value = false;
325
- }
326
- }
327
-
328
- async function onFirstBookCreated(book: BookSummary): Promise<void> {
329
- showFirstRunForm.value = false;
330
- await refetchBooks();
331
- activeBookId.value = book.id;
332
- }
333
-
334
- // Optimistically insert the new book and set the selection
335
- // BEFORE the refetch round-trip. Two reasons this beats the
336
- // previous await-refetch-then-select shape:
337
- // 1. The pubsub handler `useAccountingBooksChannel` fires its
338
- // own concurrent `refetchBooks` the instant the server
339
- // publishes books-changed. With await-then-select, that
340
- // concurrent refetch's stillExists guard reads the OLD
341
- // activeBookId (we haven't updated it yet) and — because
342
- // OLD is still in the books list — leaves the selection
343
- // pointing at OLD. Our update lands AFTER, but BookSwitcher
344
- // remounts under `v-if="!loadingBooks"` mid-flight, so the
345
- // user sees the dropdown stick on OLD.
346
- // 2. With activeBookId already set to NEW and books pre-
347
- // populated to include NEW, every concurrent refetch's
348
- // stillExists check passes for NEW and leaves the selection
349
- // alone — order-independent by construction.
350
- async function onBookCreated(book: BookSummary): Promise<void> {
351
- if (!books.value.some((existing) => existing.id === book.id)) {
352
- books.value = [...books.value, book];
353
- }
354
- activeBookId.value = book.id;
355
- // Creating a new book is also the "exit" out of the deleted-notice
356
- // panel — the user explicitly chose the new book, so re-enable the
357
- // tab strip and let the opening-gate watcher route them to Opening.
358
- deletedNoticeName.value = null;
359
- // currentTab may be on "settings" (the user opened the create
360
- // modal from there) — reset to journal so the openingGateActive
361
- // watcher's "if (currentTab.value === 'opening') return" gate
362
- // doesn't strand the user on settings while the gate is active.
363
- currentTab.value = "journal";
364
- await refetchBooks();
365
- }
366
-
367
- async function refetchAccounts(): Promise<void> {
368
- if (!activeBookId.value) {
369
- accounts.value = [];
370
- return;
371
- }
372
- const result = await getAccounts(activeBookId.value);
373
- if (!result.ok) return;
374
- accounts.value = result.data.accounts;
375
- }
376
-
377
- async function refetchOpening(): Promise<void> {
378
- if (!activeBookId.value) {
379
- hasOpening.value = null;
380
- activeOpeningDate.value = undefined;
381
- return;
382
- }
383
- const result = await getOpeningBalances(activeBookId.value);
384
- if (!result.ok) return;
385
- hasOpening.value = result.data.opening !== null;
386
- activeOpeningDate.value = result.data.opening?.date;
387
- }
388
-
389
- // A book without an opening on file is in "gated" mode: the user
390
- // must save an opening (empty is fine — see OpeningBalancesForm)
391
- // before journal / report tabs unlock. Settings stays accessible
392
- // so the user can delete the book if they don't want to proceed.
393
- const openingGateActive = computed(() => activeBookId.value !== null && hasOpening.value === false);
394
-
395
- // Gated → only Opening + Settings render in the strip. Ungated →
396
- // Opening hides itself; users reach the form via the Edit button
397
- // on the active opening row in the journal, which transiently
398
- // switches `currentTab` to "opening" (kept visible while there).
399
- const visibleTabs = computed<readonly TabDef[]>(() => {
400
- if (openingGateActive.value) return TABS.filter((tab) => tab.key === "opening" || tab.key === "settings");
401
- return TABS.filter((tab) => tab.key !== "opening" || currentTab.value === "opening");
402
- });
403
-
404
- function onBookSelected(bookId: string): void {
405
- activeBookId.value = bookId;
406
- // Picking a book from the dropdown is the explicit "I'm done
407
- // looking at the deleted notice" exit. Clear it so the tab strip
408
- // re-enables for the freshly selected book.
409
- deletedNoticeName.value = null;
410
- }
411
-
412
- // Entry id to surface in JournalList after an `addEntries` tool
413
- // result lands — the LLM just posted a journal entry and we want
414
- // the user's eye on the new row. Multi-entry batches highlight the
415
- // LAST entry only (matches the "you ended up here" intent of a
416
- // scroll-to-cursor).
417
- const journalPreselectEntryId = ref<string | undefined>(undefined);
418
-
419
- // Account preselected by the Accounts tab → click handoff. Cleared
420
- // once the user picks a different account from the Ledger's own
421
- // dropdown so a stale preselection doesn't override later edits.
422
- const ledgerPreselectAccountCode = ref<string | undefined>(undefined);
423
-
424
- function onAccountSelected(code: string): void {
425
- // Force the ref to a fresh value even when the user clicks the
426
- // same account a second time — the Ledger's `watch(preselect…)`
427
- // ignores no-op updates, so we'd otherwise leave the user on a
428
- // stale Ledger state if they navigated away and clicked back.
429
- ledgerPreselectAccountCode.value = undefined;
430
- Promise.resolve().then(() => {
431
- ledgerPreselectAccountCode.value = code;
432
- });
433
- currentTab.value = "ledger";
434
- }
435
-
436
- function onEntrySubmitted(): void {
437
- // After saving an opening, switch to the journal so the user
438
- // immediately sees the unlocked tabs. The server-side
439
- // publishBookChange triggers the bookVersion watcher over SSE,
440
- // which refetches hasOpening, so the gate auto-lifts shortly after
441
- // the tab switch — no manual unlock needed here. Normal entries
442
- // are now posted from the inline form inside JournalList; that
443
- // form drives its own dismissal and the journal repaints in
444
- // place.
445
- if (currentTab.value === "opening") {
446
- currentTab.value = "journal";
447
- }
448
- }
449
-
450
- async function onBookDeleted(deletedName: string): Promise<void> {
451
- // Reset the tab BEFORE awaiting so a fast delete-then-create
452
- // can't race: if the new book's gate engages while we're still
453
- // awaiting refetchBooks, the gate watcher needs to see a
454
- // non-"settings" currentTab to route the user to Opening.
455
- currentTab.value = "journal";
456
- // Drop the active selection so refetchBooks doesn't auto-pick
457
- // books[0] — the user should see the deleted-notice panel and
458
- // explicitly switch via the BookSwitcher rather than be silently
459
- // moved to a different book (issue #1126).
460
- activeBookId.value = null;
461
- deletedNoticeName.value = deletedName;
462
- await refetchBooks();
463
- }
464
-
465
- // Refetch the chart of accounts whenever the active book changes
466
- // or any pub/sub / child action bumps bookVersion (e.g. an
467
- // upsertAccount from the Manage Accounts modal, or an LLM-driven
468
- // upsert in another tab). The list is small JSON; the cost of
469
- // over-fetching on entry / void / opening events is negligible
470
- // against the staleness bug it removes.
471
- watch(
472
- () => [activeBookId.value, bookVersion.value],
473
- () => {
474
- if (activeBookId.value) void refetchAccounts();
475
- },
476
- { immediate: true },
477
- );
478
-
479
- // Drop any leftover Accounts → Ledger preselection when the active
480
- // book changes. Without this, picking account "1000" in book A's
481
- // Accounts tab and then switching to book B would carry the hint
482
- // across, so book B's Ledger would auto-select "1000" (which may
483
- // be an unrelated account in B's chart, or absent entirely).
484
- watch(activeBookId, () => {
485
- ledgerPreselectAccountCode.value = undefined;
486
- });
487
-
488
- // Stash a target bookId that we want to land on but haven't been
489
- // able to apply yet (book not in `books` at the moment the
490
- // tool-result fired). Cleared as soon as the books list catches up.
491
- const pendingTargetBookId = ref<string | null>(null);
492
-
493
- function applyTargetBookId(target: string): void {
494
- if (books.value.some((book) => book.id === target)) {
495
- activeBookId.value = target;
496
- pendingTargetBookId.value = null;
497
- return;
498
- }
499
- pendingTargetBookId.value = target;
500
- }
501
-
502
- // When the selected tool-result changes (user clicks a different
503
- // preview card in the sidebar), follow the new result's bookId so
504
- // the canvas lands on the book that action just touched. Skipped
505
- // when the new result has no bookId (silent reads / actions that
506
- // don't carry one). When the target isn't in `books` yet — common
507
- // race after a fresh `createBook → openBook(bookId)` handoff where
508
- // the result envelope arrives before refetchBooks completes — the
509
- // id is stashed and applied by the books watcher below as soon as
510
- // the list catches up.
511
- watch(
512
- () => initialPayload.value.bookId,
513
- (next) => {
514
- if (!next) return;
515
- applyTargetBookId(next);
516
- },
517
- );
518
-
519
- // Drains the pending target once `books` includes it (typically
520
- // after a pub/sub-driven refetch resolves the createBook write).
521
- // No-op when nothing is pending or the target is still missing.
522
- watch(books, () => {
523
- const pending = pendingTargetBookId.value;
524
- if (pending) applyTargetBookId(pending);
525
- });
526
-
527
- // Map a PREVIEW action to the canvas tab the user should land on.
528
- // Honours an explicit `initialTab` from the envelope (the LLM's
529
- // stated intent) over the action-default below — only `openBook`
530
- // currently ships initialTab, but the override is plugin-wide.
531
- //
532
- // The `balanceSheet` default for openBook / createBook /
533
- // setOpeningBalances assumes the book has an opening on file. For a
534
- // fresh book without one, the existing `openingGateActive` watcher
535
- // redirects to "opening" — we don't try to short-circuit that here
536
- // because hasOpening hasn't necessarily resolved when this runs.
537
- function pickTabForAction(payload: AccountingAppPayload): TabKey | null {
538
- if (isTabKey(payload.initialTab)) return payload.initialTab;
539
- switch (payload.action) {
540
- case ACCOUNTING_ACTIONS.addEntries:
541
- case ACCOUNTING_ACTIONS.voidEntry:
542
- return "journal";
543
- case ACCOUNTING_ACTIONS.upsertAccount:
544
- return "accounts";
545
- case ACCOUNTING_ACTIONS.updateBook:
546
- return "settings";
547
- case ACCOUNTING_ACTIONS.openBook:
548
- case ACCOUNTING_ACTIONS.createBook:
549
- case ACCOUNTING_ACTIONS.setOpeningBalances:
550
- return "balanceSheet";
551
- default:
552
- return null;
553
- }
554
- }
555
-
556
- // For tool results that should auto-expand a row in JournalList,
557
- // derive the entry id from the action's payload. addEntries picks
558
- // the LAST entry in the batch ("you ended up here" cursor); voidEntry
559
- // picks the void-MARKER (the visual "voided here" indicator), not
560
- // the reversing entry.
561
- function pickJournalPreselectId(payload: AccountingAppPayload): string | undefined {
562
- if (payload.action === ACCOUNTING_ACTIONS.addEntries) {
563
- const entries = Array.isArray(payload.entries) ? payload.entries : [];
564
- return entries[entries.length - 1]?.id;
565
- }
566
- if (payload.action === ACCOUNTING_ACTIONS.voidEntry) {
567
- return payload.markerEntry?.id;
568
- }
569
- return undefined;
570
- }
571
-
572
- // Drive canvas tab + journal preselect from the active tool-result
573
- // envelope. The route handler stamps `data: { action, bookId, … }`
574
- // onto every PREVIEW action's response (server/api/routes/
575
- // accounting.ts dispatch + PREVIEW_ACTIONS). `immediate: true` so a
576
- // cold open with the result already selected (e.g., reload after
577
- // the LLM dispatched) routes to the right surface too.
578
- //
579
- // Preselect is *always* assigned (not `if (preselect)`) so a
580
- // subsequent non-addEntries/voidEntry tool result clears any stale
581
- // id left over from a prior addEntries the user has already seen —
582
- // otherwise the next JournalList remount would replay it. The child
583
- // also emits `preselectConsumed` after expanding for the same
584
- // reason.
585
- watch(
586
- () => initialPayload.value,
587
- (payload) => {
588
- const targetTab = pickTabForAction(payload);
589
- if (targetTab) currentTab.value = targetTab;
590
- journalPreselectEntryId.value = pickJournalPreselectId(payload);
591
- },
592
- { immediate: true },
593
- );
594
-
595
- // Drop the journal preselect on a real book SWITCH — leftover ids
596
- // from the prior book don't exist in the new one. The cold-load
597
- // transition (null → bookId) doesn't qualify: refetchBooks resolves
598
- // activeBookId asynchronously and would otherwise clobber a
599
- // preselect the addEntries watcher just set on initial mount.
600
- watch(activeBookId, (_next, prev) => {
601
- if (!prev) return;
602
- journalPreselectEntryId.value = undefined;
603
- });
604
-
605
- // Refetch the opening status whenever the active book changes or
606
- // any pub/sub / child action bumps bookVersion (e.g. an opening
607
- // got saved or voided). Clears hasOpening when the book goes null
608
- // so a stale "true" doesn't carry over between books.
609
- watch(
610
- () => [activeBookId.value, bookVersion.value],
611
- () => void refetchOpening(),
612
- { immediate: true },
613
- );
614
-
615
- // Force-route to the Opening tab whenever the gate engages.
616
- // Other tabs are hidden from the strip while gated, but this
617
- // watcher handles the programmatic case where currentTab still
618
- // points at a now-hidden tab (book switch, initial mount with a
619
- // no-opening book, LLM-supplied initialTab pointing at a gated
620
- // tab, or fresh-book creation right after deleting from the
621
- // settings tab) — without it, `<main>` would render nothing or
622
- // the user would be stranded on the prior book's settings view.
623
- // We don't exempt "settings" here: the user can still click back
624
- // to it from the (gated) tab strip if they want to delete the
625
- // new book instead of setting it up.
626
- watch(openingGateActive, (active) => {
627
- if (!active) return;
628
- if (currentTab.value === "opening") return;
629
- currentTab.value = "opening";
630
- });
631
-
632
- void refetchBooks();
633
- </script>
@@ -1,34 +0,0 @@
1
- // Single source of truth for the manageAccounting LLM-facing action
2
- // names. Used by:
3
- // - definition.ts (the JSON-schema action enum exposed to the LLM)
4
- // - api.ts (the View's REST helpers — `call(action, args)`)
5
- // - server/api/routes/accounting.ts (handler-table keys, PREVIEW
6
- // and MESSAGE_BUILDERS membership)
7
- // - e2e/fixtures/accounting.ts (mock dispatcher's handler-table)
8
- //
9
- // Stays in its own module so server-side callers can import the
10
- // const without pulling in apiPost / Vue plumbing from `api.ts`.
11
- //
12
- // CLAUDE.md "no magic literals — use existing `as const` objects"
13
- // applies here: never reference an action by raw string at any of
14
- // the call sites above.
15
-
16
- export const ACCOUNTING_ACTIONS = {
17
- openBook: "openBook",
18
- getBooks: "getBooks",
19
- createBook: "createBook",
20
- updateBook: "updateBook",
21
- deleteBook: "deleteBook",
22
- getAccounts: "getAccounts",
23
- upsertAccount: "upsertAccount",
24
- addEntries: "addEntries",
25
- voidEntry: "voidEntry",
26
- getJournalEntries: "getJournalEntries",
27
- getOpeningBalances: "getOpeningBalances",
28
- setOpeningBalances: "setOpeningBalances",
29
- getReport: "getReport",
30
- getTimeSeries: "getTimeSeries",
31
- rebuildSnapshots: "rebuildSnapshots",
32
- } as const;
33
-
34
- export type AccountingAction = (typeof ACCOUNTING_ACTIONS)[keyof typeof ACCOUNTING_ACTIONS];