termdock 1.4.178 → 1.4.179

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 (333) hide show
  1. package/dist/client/assets/App-DXq9kwY5.js +150 -0
  2. package/dist/client/assets/App-DXq9kwY5.js.br +0 -0
  3. package/dist/client/assets/App-DXq9kwY5.js.gz +0 -0
  4. package/dist/client/assets/{ChangeWalkthroughPanel-BNWqAnqc.js → ChangeWalkthroughPanel-DWUBYx6Q.js} +2 -2
  5. package/dist/client/assets/ChangeWalkthroughPanel-DWUBYx6Q.js.br +0 -0
  6. package/dist/client/assets/ChangeWalkthroughPanel-DWUBYx6Q.js.gz +0 -0
  7. package/dist/client/assets/{DagPlayground-IlTGwr-I.js → DagPlayground-DyczrcHM.js} +1 -1
  8. package/dist/client/assets/DagPlayground-DyczrcHM.js.br +0 -0
  9. package/dist/client/assets/DagPlayground-DyczrcHM.js.gz +0 -0
  10. package/dist/client/assets/{DiffLab-CwhNpJvo.js → DiffLab-D5wb-H7y.js} +1 -1
  11. package/dist/client/assets/DiffLab-D5wb-H7y.js.br +0 -0
  12. package/dist/client/assets/DiffLab-D5wb-H7y.js.gz +0 -0
  13. package/dist/client/assets/{DiffReview-DyhINv0F.js → DiffReview-CVIz-B5T.js} +1 -1
  14. package/dist/client/assets/DiffReview-CVIz-B5T.js.br +0 -0
  15. package/dist/client/assets/DiffReview-CVIz-B5T.js.gz +0 -0
  16. package/dist/client/assets/{DiffReviewLab-D9Kt5VwB.js → DiffReviewLab-99hTNRaj.js} +1 -1
  17. package/dist/client/assets/DiffReviewLab-99hTNRaj.js.br +0 -0
  18. package/dist/client/assets/DiffReviewLab-99hTNRaj.js.gz +0 -0
  19. package/dist/client/assets/{DiffViewer-3zz2PI-8.js → DiffViewer-BPor2_7o.js} +1 -1
  20. package/dist/client/assets/DiffViewer-BPor2_7o.js.br +0 -0
  21. package/dist/client/assets/DiffViewer-BPor2_7o.js.gz +0 -0
  22. package/dist/client/assets/{ModelPreview-CN8xsiGC.js → ModelPreview-DpImj4vY.js} +1 -1
  23. package/dist/client/assets/ModelPreview-DpImj4vY.js.br +0 -0
  24. package/dist/client/assets/ModelPreview-DpImj4vY.js.gz +0 -0
  25. package/dist/client/assets/RightSidebar-BW8SSsoA.js +79 -0
  26. package/dist/client/assets/RightSidebar-BW8SSsoA.js.br +0 -0
  27. package/dist/client/assets/RightSidebar-BW8SSsoA.js.gz +0 -0
  28. package/dist/client/assets/{abnfDiagram-VCTEODGH-DkdoJ2ZH.js → abnfDiagram-VCTEODGH-CNWmFVMh.js} +1 -1
  29. package/dist/client/assets/abnfDiagram-VCTEODGH-CNWmFVMh.js.br +0 -0
  30. package/dist/client/assets/abnfDiagram-VCTEODGH-CNWmFVMh.js.gz +0 -0
  31. package/dist/client/assets/app-Pl7tV8Be.js +34 -0
  32. package/dist/client/assets/app-Pl7tV8Be.js.br +0 -0
  33. package/dist/client/assets/app-Pl7tV8Be.js.gz +0 -0
  34. package/dist/client/assets/{arc-ctzz5PcK.js → arc-Z8mcHjh7.js} +1 -1
  35. package/dist/client/assets/arc-Z8mcHjh7.js.br +0 -0
  36. package/dist/client/assets/arc-Z8mcHjh7.js.gz +0 -0
  37. package/dist/client/assets/{architectureDiagram-5GKGNRK7-DNLcYfGQ.js → architectureDiagram-5GKGNRK7-DuxbAeFP.js} +1 -1
  38. package/dist/client/assets/architectureDiagram-5GKGNRK7-DuxbAeFP.js.br +0 -0
  39. package/dist/client/assets/architectureDiagram-5GKGNRK7-DuxbAeFP.js.gz +0 -0
  40. package/dist/client/assets/{blockDiagram-I7D4REHJ-Coye1ou5.js → blockDiagram-I7D4REHJ-SxAFw0An.js} +1 -1
  41. package/dist/client/assets/blockDiagram-I7D4REHJ-SxAFw0An.js.br +0 -0
  42. package/dist/client/assets/blockDiagram-I7D4REHJ-SxAFw0An.js.gz +0 -0
  43. package/dist/client/assets/{c4Diagram-7LVT6UL2-DTa8jyPp.js → c4Diagram-7LVT6UL2-CcRdiWo7.js} +1 -1
  44. package/dist/client/assets/{c4Diagram-7LVT6UL2-DTa8jyPp.js.br → c4Diagram-7LVT6UL2-CcRdiWo7.js.br} +0 -0
  45. package/dist/client/assets/c4Diagram-7LVT6UL2-CcRdiWo7.js.gz +0 -0
  46. package/dist/client/assets/channel-nXn0ntBk.js +1 -0
  47. package/dist/client/assets/{chunk-2Q5K7J3B-BpDyjNfs.js → chunk-2Q5K7J3B-DJ_qzvZZ.js} +1 -1
  48. package/dist/client/assets/{chunk-5VM5RSS4-DgwdqXKl.js → chunk-5VM5RSS4-l3H0C2ci.js} +1 -1
  49. package/dist/client/assets/{chunk-F27PBJKO-DWf2gZ96.js → chunk-F27PBJKO-B7xASv8n.js} +1 -1
  50. package/dist/client/assets/chunk-F27PBJKO-B7xASv8n.js.br +0 -0
  51. package/dist/client/assets/chunk-F27PBJKO-B7xASv8n.js.gz +0 -0
  52. package/dist/client/assets/{chunk-IMKFNOWR-l42o_E2c.js → chunk-IMKFNOWR-Wg5gR7sZ.js} +1 -1
  53. package/dist/client/assets/chunk-IMKFNOWR-Wg5gR7sZ.js.br +0 -0
  54. package/dist/client/assets/chunk-IMKFNOWR-Wg5gR7sZ.js.gz +0 -0
  55. package/dist/client/assets/{chunk-JWPE2WC7-8CkEf05l.js → chunk-JWPE2WC7-BlXUS79m.js} +1 -1
  56. package/dist/client/assets/{chunk-POPQ4Y6H-BKKOfbdg.js → chunk-POPQ4Y6H-CU38G8hb.js} +1 -1
  57. package/dist/client/assets/{chunk-SVP7TREG-RORrf2aM.js → chunk-SVP7TREG-D-yZlXqX.js} +1 -1
  58. package/dist/client/assets/chunk-SVP7TREG-D-yZlXqX.js.br +0 -0
  59. package/dist/client/assets/chunk-SVP7TREG-D-yZlXqX.js.gz +0 -0
  60. package/dist/client/assets/{chunk-TICWLB2K-hPqafEtC.js → chunk-TICWLB2K-DrOYmcBB.js} +1 -1
  61. package/dist/client/assets/{chunk-TICWLB2K-hPqafEtC.js.br → chunk-TICWLB2K-DrOYmcBB.js.br} +0 -0
  62. package/dist/client/assets/chunk-TICWLB2K-DrOYmcBB.js.gz +0 -0
  63. package/dist/client/assets/{chunk-XXDRQBXY-CrvjJwms.js → chunk-XXDRQBXY-BbsHtVFa.js} +1 -1
  64. package/dist/client/assets/classDiagram-ZZMXUADV-DxqN38m7.js +1 -0
  65. package/dist/client/assets/classDiagram-v2-VYDZK3BY-DxqN38m7.js +1 -0
  66. package/dist/client/assets/{cose-bilkent-JH36ORCC-CwRSiQLa.js → cose-bilkent-JH36ORCC-_wKUNL8T.js} +1 -1
  67. package/dist/client/assets/cose-bilkent-JH36ORCC-_wKUNL8T.js.br +0 -0
  68. package/dist/client/assets/cose-bilkent-JH36ORCC-_wKUNL8T.js.gz +0 -0
  69. package/dist/client/assets/{cynefin-OW5HDTMX-CXnppZ8I.js → cynefin-OW5HDTMX-CPr--Wnc.js} +1 -1
  70. package/dist/client/assets/cynefin-OW5HDTMX-CPr--Wnc.js.br +0 -0
  71. package/dist/client/assets/cynefin-OW5HDTMX-CPr--Wnc.js.gz +0 -0
  72. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-BSDrHSIA.js → cynefinDiagram-5FMLGOSQ-5ygpPOWT.js} +1 -1
  73. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-5ygpPOWT.js.br +0 -0
  74. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-5ygpPOWT.js.gz +0 -0
  75. package/dist/client/assets/{dagre-GXQ25YYZ-d-5j4vkq.js → dagre-GXQ25YYZ-Cvx65nHO.js} +1 -1
  76. package/dist/client/assets/dagre-GXQ25YYZ-Cvx65nHO.js.br +0 -0
  77. package/dist/client/assets/dagre-GXQ25YYZ-Cvx65nHO.js.gz +0 -0
  78. package/dist/client/assets/{diagram-S7CK7UJ4-DizMBpGW.js → diagram-S7CK7UJ4-Dw5cp_BA.js} +1 -1
  79. package/dist/client/assets/diagram-S7CK7UJ4-Dw5cp_BA.js.br +0 -0
  80. package/dist/client/assets/diagram-S7CK7UJ4-Dw5cp_BA.js.gz +0 -0
  81. package/dist/client/assets/{diagram-UQ7AKVKN-CNQK26rH.js → diagram-UQ7AKVKN-D8BZ5Tp3.js} +1 -1
  82. package/dist/client/assets/diagram-UQ7AKVKN-D8BZ5Tp3.js.br +0 -0
  83. package/dist/client/assets/diagram-UQ7AKVKN-D8BZ5Tp3.js.gz +0 -0
  84. package/dist/client/assets/{diagram-VSXAHHWV-Dua-2_46.js → diagram-VSXAHHWV-BxJD7ZWH.js} +1 -1
  85. package/dist/client/assets/diagram-VSXAHHWV-BxJD7ZWH.js.br +0 -0
  86. package/dist/client/assets/diagram-VSXAHHWV-BxJD7ZWH.js.gz +0 -0
  87. package/dist/client/assets/{diagram-VX7I27RA-CIq-4729.js → diagram-VX7I27RA-CvzlU0bI.js} +1 -1
  88. package/dist/client/assets/diagram-VX7I27RA-CvzlU0bI.js.br +0 -0
  89. package/dist/client/assets/diagram-VX7I27RA-CvzlU0bI.js.gz +0 -0
  90. package/dist/client/assets/{diagram-Z3DM3KII-BukQ0u-x.js → diagram-Z3DM3KII-Be4HdFlL.js} +1 -1
  91. package/dist/client/assets/diagram-Z3DM3KII-Be4HdFlL.js.br +0 -0
  92. package/dist/client/assets/diagram-Z3DM3KII-Be4HdFlL.js.gz +0 -0
  93. package/dist/client/assets/{ebnfDiagram-PWID7BFC-D2zRkRBI.js → ebnfDiagram-PWID7BFC-C_wrrPjF.js} +1 -1
  94. package/dist/client/assets/ebnfDiagram-PWID7BFC-C_wrrPjF.js.br +0 -0
  95. package/dist/client/assets/ebnfDiagram-PWID7BFC-C_wrrPjF.js.gz +0 -0
  96. package/dist/client/assets/{erDiagram-RLTQ6QDP-DbX6A3ls.js → erDiagram-RLTQ6QDP-IHyLgV6M.js} +1 -1
  97. package/dist/client/assets/erDiagram-RLTQ6QDP-IHyLgV6M.js.br +0 -0
  98. package/dist/client/assets/erDiagram-RLTQ6QDP-IHyLgV6M.js.gz +0 -0
  99. package/dist/client/assets/{flowDiagram-HODETNUW-YECDWA2G.js → flowDiagram-HODETNUW-CpfW88Uc.js} +1 -1
  100. package/dist/client/assets/flowDiagram-HODETNUW-CpfW88Uc.js.br +0 -0
  101. package/dist/client/assets/flowDiagram-HODETNUW-CpfW88Uc.js.gz +0 -0
  102. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-D3EJdUov.js → ganttDiagram-EL5Y4UJY-CsbQ6KLb.js} +1 -1
  103. package/dist/client/assets/ganttDiagram-EL5Y4UJY-CsbQ6KLb.js.br +0 -0
  104. package/dist/client/assets/ganttDiagram-EL5Y4UJY-CsbQ6KLb.js.gz +0 -0
  105. package/dist/client/assets/{gestureArbiter-D3IZpZS7.js → gestureArbiter-CJQ8K48V.js} +1 -1
  106. package/dist/client/assets/gestureArbiter-CJQ8K48V.js.br +0 -0
  107. package/dist/client/assets/gestureArbiter-CJQ8K48V.js.gz +0 -0
  108. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-tr_HKoQK.js → gitGraphDiagram-WWUBYQGX-DJZqSGtH.js} +1 -1
  109. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DJZqSGtH.js.br +0 -0
  110. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DJZqSGtH.js.gz +0 -0
  111. package/dist/client/assets/{index-C4Ny0NDQ.css → index-PWu1VEN_.css} +1 -1
  112. package/dist/client/assets/index-PWu1VEN_.css.br +0 -0
  113. package/dist/client/assets/index-PWu1VEN_.css.gz +0 -0
  114. package/dist/client/assets/{infoDiagram-27XIBGKW-xBV63YYg.js → infoDiagram-27XIBGKW-D6sSgR2Y.js} +1 -1
  115. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-BrYSZu1R.js → ishikawaDiagram-5VMMS53U-BJJSUXep.js} +1 -1
  116. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BJJSUXep.js.br +0 -0
  117. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BJJSUXep.js.gz +0 -0
  118. package/dist/client/assets/{journeyDiagram-3NMN7TZE-C9Ft--aA.js → journeyDiagram-3NMN7TZE-ou1XS2DP.js} +1 -1
  119. package/dist/client/assets/journeyDiagram-3NMN7TZE-ou1XS2DP.js.br +0 -0
  120. package/dist/client/assets/journeyDiagram-3NMN7TZE-ou1XS2DP.js.gz +0 -0
  121. package/dist/client/assets/{kanban-definition-UXKFOSKX-FCxqSu11.js → kanban-definition-UXKFOSKX-BFQGYQzd.js} +1 -1
  122. package/dist/client/assets/kanban-definition-UXKFOSKX-BFQGYQzd.js.br +0 -0
  123. package/dist/client/assets/kanban-definition-UXKFOSKX-BFQGYQzd.js.gz +0 -0
  124. package/dist/client/assets/{layout-BqjIyPqO.js → layout-zUU3xcam.js} +1 -1
  125. package/dist/client/assets/layout-zUU3xcam.js.br +0 -0
  126. package/dist/client/assets/layout-zUU3xcam.js.gz +0 -0
  127. package/dist/client/assets/{linear-CEAGQX5N.js → linear-CYwYQI2I.js} +1 -1
  128. package/dist/client/assets/linear-CYwYQI2I.js.br +0 -0
  129. package/dist/client/assets/linear-CYwYQI2I.js.gz +0 -0
  130. package/dist/client/assets/{mermaid.core-DvAY78t_.js → mermaid.core-91Llsw5j.js} +5 -5
  131. package/dist/client/assets/mermaid.core-91Llsw5j.js.br +0 -0
  132. package/dist/client/assets/mermaid.core-91Llsw5j.js.gz +0 -0
  133. package/dist/client/assets/{mindmap-definition-YA3MSWOX-D7_qIQ9H.js → mindmap-definition-YA3MSWOX-RWG074lb.js} +1 -1
  134. package/dist/client/assets/mindmap-definition-YA3MSWOX-RWG074lb.js.br +0 -0
  135. package/dist/client/assets/mindmap-definition-YA3MSWOX-RWG074lb.js.gz +0 -0
  136. package/dist/client/assets/{passwordBootstrap-Dksfdvk3.js → passwordBootstrap-DRknuNUN.js} +1 -1
  137. package/dist/client/assets/passwordBootstrap-DRknuNUN.js.br +0 -0
  138. package/dist/client/assets/passwordBootstrap-DRknuNUN.js.gz +0 -0
  139. package/dist/client/assets/{pegDiagram-XKGWAZYB-DeTIBKGC.js → pegDiagram-XKGWAZYB-Dyh2rzGS.js} +1 -1
  140. package/dist/client/assets/pegDiagram-XKGWAZYB-Dyh2rzGS.js.br +0 -0
  141. package/dist/client/assets/pegDiagram-XKGWAZYB-Dyh2rzGS.js.gz +0 -0
  142. package/dist/client/assets/{pieDiagram-E7YTZNPT-z5IcoVwx.js → pieDiagram-E7YTZNPT-CL3UcUfh.js} +1 -1
  143. package/dist/client/assets/pieDiagram-E7YTZNPT-CL3UcUfh.js.br +0 -0
  144. package/dist/client/assets/pieDiagram-E7YTZNPT-CL3UcUfh.js.gz +0 -0
  145. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-B-zCZvES.js → quadrantDiagram-AXDQQJYC-DOkejMel.js} +1 -1
  146. package/dist/client/assets/quadrantDiagram-AXDQQJYC-DOkejMel.js.br +0 -0
  147. package/dist/client/assets/quadrantDiagram-AXDQQJYC-DOkejMel.js.gz +0 -0
  148. package/dist/client/assets/{railroadDiagram-O6MQD6OU-DbpeB7P2.js → railroadDiagram-O6MQD6OU-BC780Uh3.js} +1 -1
  149. package/dist/client/assets/railroadDiagram-O6MQD6OU-BC780Uh3.js.br +0 -0
  150. package/dist/client/assets/railroadDiagram-O6MQD6OU-BC780Uh3.js.gz +0 -0
  151. package/dist/client/assets/{referenceLongPress-p56g9xFb.js → referenceLongPress-Dlc0425_.js} +1 -1
  152. package/dist/client/assets/referenceLongPress-Dlc0425_.js.br +0 -0
  153. package/dist/client/assets/referenceLongPress-Dlc0425_.js.gz +0 -0
  154. package/dist/client/assets/{requirementDiagram-BXWQKSXE-UhJYMJ_U.js → requirementDiagram-BXWQKSXE-CwCGr0qR.js} +1 -1
  155. package/dist/client/assets/requirementDiagram-BXWQKSXE-CwCGr0qR.js.br +0 -0
  156. package/dist/client/assets/requirementDiagram-BXWQKSXE-CwCGr0qR.js.gz +0 -0
  157. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-xKsuFR17.js → sankeyDiagram-P5KCCOFB-CYDYBwJQ.js} +1 -1
  158. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CYDYBwJQ.js.br +0 -0
  159. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CYDYBwJQ.js.gz +0 -0
  160. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-DrjBl65C.js → sequenceDiagram-WJ2MYXX4-DhHsZi3K.js} +1 -1
  161. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DhHsZi3K.js.br +0 -0
  162. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DhHsZi3K.js.gz +0 -0
  163. package/dist/client/assets/{sizeCapture-INFHLROL-BIlGJ9tm.js → sizeCapture-INFHLROL-4oUXWvYA.js} +1 -1
  164. package/dist/client/assets/sizeCapture-INFHLROL-4oUXWvYA.js.br +0 -0
  165. package/dist/client/assets/sizeCapture-INFHLROL-4oUXWvYA.js.gz +0 -0
  166. package/dist/client/assets/{sparkles-B-uEi0Pa.js → sparkles-gqiuBkfP.js} +1 -1
  167. package/dist/client/assets/{stateDiagram-D77RDMKH-C3k9XvA6.js → stateDiagram-D77RDMKH-7hUELZGo.js} +1 -1
  168. package/dist/client/assets/stateDiagram-D77RDMKH-7hUELZGo.js.br +0 -0
  169. package/dist/client/assets/stateDiagram-D77RDMKH-7hUELZGo.js.gz +0 -0
  170. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-MO84Jqt6.js +1 -0
  171. package/dist/client/assets/{swimlanes-42K2YHIH-BN-x1rXp.js → swimlanes-42K2YHIH-E1qoordP.js} +1 -1
  172. package/dist/client/assets/swimlanes-42K2YHIH-E1qoordP.js.br +0 -0
  173. package/dist/client/assets/swimlanes-42K2YHIH-E1qoordP.js.gz +0 -0
  174. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DnSXMnZQ.js +8 -0
  175. package/dist/client/assets/{timeline-definition-24CTP7MA-Dcedjtic.js → timeline-definition-24CTP7MA-CTYyCnUW.js} +1 -1
  176. package/dist/client/assets/timeline-definition-24CTP7MA-CTYyCnUW.js.br +0 -0
  177. package/dist/client/assets/timeline-definition-24CTP7MA-CTYyCnUW.js.gz +0 -0
  178. package/dist/client/assets/{triangle-alert-BSNAwyll.js → triangle-alert-DrBuMUPw.js} +1 -1
  179. package/dist/client/assets/{vennDiagram-4TSXK5OY-DAIk-5Rt.js → vennDiagram-4TSXK5OY-DVWbhWsS.js} +1 -1
  180. package/dist/client/assets/vennDiagram-4TSXK5OY-DVWbhWsS.js.br +0 -0
  181. package/dist/client/assets/vennDiagram-4TSXK5OY-DVWbhWsS.js.gz +0 -0
  182. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-3iXOTpAg.js → wardleyDiagram-VM6X3IG4-BFAwOxhc.js} +1 -1
  183. package/dist/client/assets/wardleyDiagram-VM6X3IG4-BFAwOxhc.js.br +0 -0
  184. package/dist/client/assets/wardleyDiagram-VM6X3IG4-BFAwOxhc.js.gz +0 -0
  185. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-OD1a_9Qg.js → xychartDiagram-S5SC5T6Z-DYXOiBiX.js} +1 -1
  186. package/dist/client/assets/xychartDiagram-S5SC5T6Z-DYXOiBiX.js.br +0 -0
  187. package/dist/client/assets/xychartDiagram-S5SC5T6Z-DYXOiBiX.js.gz +0 -0
  188. package/dist/client/index.html +2 -2
  189. package/dist/client/index.html.br +0 -0
  190. package/dist/client/index.html.gz +0 -0
  191. package/dist/client/sw-notifications.js +5 -45
  192. package/dist/client/sw-notifications.js.br +0 -0
  193. package/dist/client/sw-notifications.js.gz +0 -0
  194. package/dist/client/sw.js +1 -1
  195. package/dist/client/sw.js.br +0 -0
  196. package/dist/client/sw.js.gz +0 -0
  197. package/dist/server/agent/collaborationCli.js +10 -3
  198. package/dist/server/agent/collaborationDeliveryWorker.js +154 -0
  199. package/dist/server/agent/collaborationRoutes.js +15 -4
  200. package/dist/server/agent/collaborationRouting.js +94 -0
  201. package/dist/server/agent/collaborationStore.js +6 -1
  202. package/dist/server/agent/collaborationTmuxDelivery.js +10 -0
  203. package/dist/server/agent/sessionBindingRecovery.js +59 -0
  204. package/dist/server/entry.js +30 -13
  205. package/dist/server/federation/desktopTargets.js +64 -0
  206. package/dist/server/federation/directRoutes.js +27 -19
  207. package/dist/server/federation/routeAccess.js +14 -7
  208. package/dist/server/federation/trustedCa.js +55 -0
  209. package/dist/server/routes/terminal.js +242 -67
  210. package/package.json +1 -1
  211. package/runtime-manifest.json +3 -3
  212. package/dist/client/assets/App-CAEtVL8Z.js +0 -150
  213. package/dist/client/assets/App-CAEtVL8Z.js.br +0 -0
  214. package/dist/client/assets/App-CAEtVL8Z.js.gz +0 -0
  215. package/dist/client/assets/ChangeWalkthroughPanel-BNWqAnqc.js.br +0 -0
  216. package/dist/client/assets/ChangeWalkthroughPanel-BNWqAnqc.js.gz +0 -0
  217. package/dist/client/assets/DagPlayground-IlTGwr-I.js.br +0 -0
  218. package/dist/client/assets/DagPlayground-IlTGwr-I.js.gz +0 -0
  219. package/dist/client/assets/DiffLab-CwhNpJvo.js.br +0 -0
  220. package/dist/client/assets/DiffLab-CwhNpJvo.js.gz +0 -0
  221. package/dist/client/assets/DiffReview-DyhINv0F.js.br +0 -0
  222. package/dist/client/assets/DiffReview-DyhINv0F.js.gz +0 -0
  223. package/dist/client/assets/DiffReviewLab-D9Kt5VwB.js.br +0 -0
  224. package/dist/client/assets/DiffReviewLab-D9Kt5VwB.js.gz +0 -0
  225. package/dist/client/assets/DiffViewer-3zz2PI-8.js.br +0 -0
  226. package/dist/client/assets/DiffViewer-3zz2PI-8.js.gz +0 -0
  227. package/dist/client/assets/ModelPreview-CN8xsiGC.js.br +0 -0
  228. package/dist/client/assets/ModelPreview-CN8xsiGC.js.gz +0 -0
  229. package/dist/client/assets/RightSidebar-DQk1cwKH.js +0 -79
  230. package/dist/client/assets/RightSidebar-DQk1cwKH.js.br +0 -0
  231. package/dist/client/assets/RightSidebar-DQk1cwKH.js.gz +0 -0
  232. package/dist/client/assets/abnfDiagram-VCTEODGH-DkdoJ2ZH.js.br +0 -0
  233. package/dist/client/assets/abnfDiagram-VCTEODGH-DkdoJ2ZH.js.gz +0 -0
  234. package/dist/client/assets/app-B42CoF1r.js +0 -34
  235. package/dist/client/assets/app-B42CoF1r.js.br +0 -0
  236. package/dist/client/assets/app-B42CoF1r.js.gz +0 -0
  237. package/dist/client/assets/arc-ctzz5PcK.js.br +0 -0
  238. package/dist/client/assets/arc-ctzz5PcK.js.gz +0 -0
  239. package/dist/client/assets/architectureDiagram-5GKGNRK7-DNLcYfGQ.js.br +0 -0
  240. package/dist/client/assets/architectureDiagram-5GKGNRK7-DNLcYfGQ.js.gz +0 -0
  241. package/dist/client/assets/blockDiagram-I7D4REHJ-Coye1ou5.js.br +0 -0
  242. package/dist/client/assets/blockDiagram-I7D4REHJ-Coye1ou5.js.gz +0 -0
  243. package/dist/client/assets/c4Diagram-7LVT6UL2-DTa8jyPp.js.gz +0 -0
  244. package/dist/client/assets/channel-CzvSDv06.js +0 -1
  245. package/dist/client/assets/chunk-F27PBJKO-DWf2gZ96.js.br +0 -0
  246. package/dist/client/assets/chunk-F27PBJKO-DWf2gZ96.js.gz +0 -0
  247. package/dist/client/assets/chunk-IMKFNOWR-l42o_E2c.js.br +0 -0
  248. package/dist/client/assets/chunk-IMKFNOWR-l42o_E2c.js.gz +0 -0
  249. package/dist/client/assets/chunk-SVP7TREG-RORrf2aM.js.br +0 -0
  250. package/dist/client/assets/chunk-SVP7TREG-RORrf2aM.js.gz +0 -0
  251. package/dist/client/assets/chunk-TICWLB2K-hPqafEtC.js.gz +0 -0
  252. package/dist/client/assets/classDiagram-ZZMXUADV-CDknJfE0.js +0 -1
  253. package/dist/client/assets/classDiagram-v2-VYDZK3BY-CDknJfE0.js +0 -1
  254. package/dist/client/assets/cose-bilkent-JH36ORCC-CwRSiQLa.js.br +0 -0
  255. package/dist/client/assets/cose-bilkent-JH36ORCC-CwRSiQLa.js.gz +0 -0
  256. package/dist/client/assets/cynefin-OW5HDTMX-CXnppZ8I.js.br +0 -0
  257. package/dist/client/assets/cynefin-OW5HDTMX-CXnppZ8I.js.gz +0 -0
  258. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-BSDrHSIA.js.br +0 -0
  259. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-BSDrHSIA.js.gz +0 -0
  260. package/dist/client/assets/dagre-GXQ25YYZ-d-5j4vkq.js.br +0 -0
  261. package/dist/client/assets/dagre-GXQ25YYZ-d-5j4vkq.js.gz +0 -0
  262. package/dist/client/assets/diagram-S7CK7UJ4-DizMBpGW.js.br +0 -0
  263. package/dist/client/assets/diagram-S7CK7UJ4-DizMBpGW.js.gz +0 -0
  264. package/dist/client/assets/diagram-UQ7AKVKN-CNQK26rH.js.br +0 -0
  265. package/dist/client/assets/diagram-UQ7AKVKN-CNQK26rH.js.gz +0 -0
  266. package/dist/client/assets/diagram-VSXAHHWV-Dua-2_46.js.br +0 -0
  267. package/dist/client/assets/diagram-VSXAHHWV-Dua-2_46.js.gz +0 -0
  268. package/dist/client/assets/diagram-VX7I27RA-CIq-4729.js.br +0 -0
  269. package/dist/client/assets/diagram-VX7I27RA-CIq-4729.js.gz +0 -0
  270. package/dist/client/assets/diagram-Z3DM3KII-BukQ0u-x.js.br +0 -0
  271. package/dist/client/assets/diagram-Z3DM3KII-BukQ0u-x.js.gz +0 -0
  272. package/dist/client/assets/ebnfDiagram-PWID7BFC-D2zRkRBI.js.br +0 -0
  273. package/dist/client/assets/ebnfDiagram-PWID7BFC-D2zRkRBI.js.gz +0 -0
  274. package/dist/client/assets/erDiagram-RLTQ6QDP-DbX6A3ls.js.br +0 -0
  275. package/dist/client/assets/erDiagram-RLTQ6QDP-DbX6A3ls.js.gz +0 -0
  276. package/dist/client/assets/flowDiagram-HODETNUW-YECDWA2G.js.br +0 -0
  277. package/dist/client/assets/flowDiagram-HODETNUW-YECDWA2G.js.gz +0 -0
  278. package/dist/client/assets/ganttDiagram-EL5Y4UJY-D3EJdUov.js.br +0 -0
  279. package/dist/client/assets/ganttDiagram-EL5Y4UJY-D3EJdUov.js.gz +0 -0
  280. package/dist/client/assets/gestureArbiter-D3IZpZS7.js.br +0 -0
  281. package/dist/client/assets/gestureArbiter-D3IZpZS7.js.gz +0 -0
  282. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-tr_HKoQK.js.br +0 -0
  283. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-tr_HKoQK.js.gz +0 -0
  284. package/dist/client/assets/index-C4Ny0NDQ.css.br +0 -0
  285. package/dist/client/assets/index-C4Ny0NDQ.css.gz +0 -0
  286. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BrYSZu1R.js.br +0 -0
  287. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BrYSZu1R.js.gz +0 -0
  288. package/dist/client/assets/journeyDiagram-3NMN7TZE-C9Ft--aA.js.br +0 -0
  289. package/dist/client/assets/journeyDiagram-3NMN7TZE-C9Ft--aA.js.gz +0 -0
  290. package/dist/client/assets/kanban-definition-UXKFOSKX-FCxqSu11.js.br +0 -0
  291. package/dist/client/assets/kanban-definition-UXKFOSKX-FCxqSu11.js.gz +0 -0
  292. package/dist/client/assets/layout-BqjIyPqO.js.br +0 -0
  293. package/dist/client/assets/layout-BqjIyPqO.js.gz +0 -0
  294. package/dist/client/assets/linear-CEAGQX5N.js.br +0 -0
  295. package/dist/client/assets/linear-CEAGQX5N.js.gz +0 -0
  296. package/dist/client/assets/mermaid.core-DvAY78t_.js.br +0 -0
  297. package/dist/client/assets/mermaid.core-DvAY78t_.js.gz +0 -0
  298. package/dist/client/assets/mindmap-definition-YA3MSWOX-D7_qIQ9H.js.br +0 -0
  299. package/dist/client/assets/mindmap-definition-YA3MSWOX-D7_qIQ9H.js.gz +0 -0
  300. package/dist/client/assets/passwordBootstrap-Dksfdvk3.js.br +0 -0
  301. package/dist/client/assets/passwordBootstrap-Dksfdvk3.js.gz +0 -0
  302. package/dist/client/assets/pegDiagram-XKGWAZYB-DeTIBKGC.js.br +0 -0
  303. package/dist/client/assets/pegDiagram-XKGWAZYB-DeTIBKGC.js.gz +0 -0
  304. package/dist/client/assets/pieDiagram-E7YTZNPT-z5IcoVwx.js.br +0 -0
  305. package/dist/client/assets/pieDiagram-E7YTZNPT-z5IcoVwx.js.gz +0 -0
  306. package/dist/client/assets/quadrantDiagram-AXDQQJYC-B-zCZvES.js.br +0 -0
  307. package/dist/client/assets/quadrantDiagram-AXDQQJYC-B-zCZvES.js.gz +0 -0
  308. package/dist/client/assets/railroadDiagram-O6MQD6OU-DbpeB7P2.js.br +0 -0
  309. package/dist/client/assets/railroadDiagram-O6MQD6OU-DbpeB7P2.js.gz +0 -0
  310. package/dist/client/assets/referenceLongPress-p56g9xFb.js.br +0 -0
  311. package/dist/client/assets/referenceLongPress-p56g9xFb.js.gz +0 -0
  312. package/dist/client/assets/requirementDiagram-BXWQKSXE-UhJYMJ_U.js.br +0 -0
  313. package/dist/client/assets/requirementDiagram-BXWQKSXE-UhJYMJ_U.js.gz +0 -0
  314. package/dist/client/assets/sankeyDiagram-P5KCCOFB-xKsuFR17.js.br +0 -0
  315. package/dist/client/assets/sankeyDiagram-P5KCCOFB-xKsuFR17.js.gz +0 -0
  316. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DrjBl65C.js.br +0 -0
  317. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DrjBl65C.js.gz +0 -0
  318. package/dist/client/assets/sizeCapture-INFHLROL-BIlGJ9tm.js.br +0 -0
  319. package/dist/client/assets/sizeCapture-INFHLROL-BIlGJ9tm.js.gz +0 -0
  320. package/dist/client/assets/stateDiagram-D77RDMKH-C3k9XvA6.js.br +0 -0
  321. package/dist/client/assets/stateDiagram-D77RDMKH-C3k9XvA6.js.gz +0 -0
  322. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-B7GnCu2o.js +0 -1
  323. package/dist/client/assets/swimlanes-42K2YHIH-BN-x1rXp.js.br +0 -0
  324. package/dist/client/assets/swimlanes-42K2YHIH-BN-x1rXp.js.gz +0 -0
  325. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-BH_gm34Y.js +0 -8
  326. package/dist/client/assets/timeline-definition-24CTP7MA-Dcedjtic.js.br +0 -0
  327. package/dist/client/assets/timeline-definition-24CTP7MA-Dcedjtic.js.gz +0 -0
  328. package/dist/client/assets/vennDiagram-4TSXK5OY-DAIk-5Rt.js.br +0 -0
  329. package/dist/client/assets/vennDiagram-4TSXK5OY-DAIk-5Rt.js.gz +0 -0
  330. package/dist/client/assets/wardleyDiagram-VM6X3IG4-3iXOTpAg.js.br +0 -0
  331. package/dist/client/assets/wardleyDiagram-VM6X3IG4-3iXOTpAg.js.gz +0 -0
  332. package/dist/client/assets/xychartDiagram-S5SC5T6Z-OD1a_9Qg.js.br +0 -0
  333. package/dist/client/assets/xychartDiagram-S5SC5T6Z-OD1a_9Qg.js.gz +0 -0
@@ -8,11 +8,13 @@ export class RouteAccess {
8
8
  filePath;
9
9
  now;
10
10
  canRouteSubject;
11
+ additionalTargets;
11
12
  tickets = new Map();
12
- constructor(filePath, now = Date.now, canRouteSubject = () => false) {
13
+ constructor(filePath, now = Date.now, canRouteSubject = () => false, additionalTargets = () => []) {
13
14
  this.filePath = filePath;
14
15
  this.now = now;
15
16
  this.canRouteSubject = canRouteSubject;
17
+ this.additionalTargets = additionalTargets;
16
18
  }
17
19
  registry() {
18
20
  const empty = { relays: [], directTargets: [] };
@@ -32,8 +34,8 @@ export class RouteAccess {
32
34
  }
33
35
  const targetIds = new Set();
34
36
  for (const target of directTargets) {
35
- if (!target || typeof target !== 'object' || Array.isArray(target) || Object.keys(target).some(key => !['serviceId', 'url', 'caPath'].includes(key))
36
- || !validId(target.serviceId) || targetIds.has(target.serviceId) || typeof target.url !== 'string' || (target.caPath !== undefined && typeof target.caPath !== 'string'))
37
+ if (!target || typeof target !== 'object' || Array.isArray(target) || Object.keys(target).some(key => !['serviceId', 'url', 'caPath', 'label'].includes(key))
38
+ || (target.label !== undefined && (typeof target.label !== 'string' || target.label.length > 120)) || !validId(target.serviceId) || targetIds.has(target.serviceId) || typeof target.url !== 'string' || (target.caPath !== undefined && typeof target.caPath !== 'string'))
37
39
  return empty;
38
40
  const url = new URL(target.url);
39
41
  if (!['https:', 'wss:'].includes(url.protocol) || url.username || url.password || url.search || url.hash || !['/', '/api/federation/secure'].includes(url.pathname))
@@ -90,7 +92,7 @@ export class RouteAccess {
90
92
  if (!validId(serviceId))
91
93
  return false;
92
94
  const registry = this.registry();
93
- return registry.relays.some(relay => relay.targets.includes(serviceId)) || registry.directTargets.some(target => target.serviceId === serviceId);
95
+ return registry.relays.some(relay => relay.targets.includes(serviceId)) || registry.directTargets.some(target => target.serviceId === serviceId) || this.additionalTargets().some(target => target.serviceId === serviceId);
94
96
  }
95
97
  addDirectTarget(target) {
96
98
  const url = new URL(target.url);
@@ -120,17 +122,22 @@ export class RouteAccess {
120
122
  writeFileSync(temporary, JSON.stringify(data, null, 2), { mode: 0o600 });
121
123
  renameSync(temporary, this.filePath);
122
124
  }
123
- configuredDirectTargets() { return this.registry().directTargets; }
125
+ configuredDirectTargets() {
126
+ const targets = new Map(this.additionalTargets().map(target => [target.serviceId, target]));
127
+ for (const target of this.registry().directTargets)
128
+ targets.set(target.serviceId, target);
129
+ return [...targets.values()];
130
+ }
124
131
  configuredTargets() {
125
132
  const registry = this.registry();
126
133
  const targets = new Map();
127
134
  for (const relay of registry.relays)
128
135
  for (const serviceId of relay.targets)
129
136
  targets.set(serviceId, { serviceId });
130
- for (const target of registry.directTargets) {
137
+ for (const target of this.configuredDirectTargets()) {
131
138
  const url = new URL(target.url);
132
139
  url.protocol = 'https:';
133
- targets.set(target.serviceId, { serviceId: target.serviceId, url: url.origin });
140
+ targets.set(target.serviceId, { serviceId: target.serviceId, url: url.origin, ...(target.label ? { label: target.label } : {}) });
134
141
  }
135
142
  return [...targets.values()];
136
143
  }
@@ -0,0 +1,55 @@
1
+ import { X509Certificate } from 'node:crypto';
2
+ import { get } from 'node:https';
3
+ const cache = new Map();
4
+ /** Only the CA download is unauthenticated. Its exact SHA-256 fingerprint was
5
+ * already approved locally for this origin; the subsequent WSS connection must
6
+ * still pass normal TLS chain, hostname and expiry checks using this CA.
7
+ */
8
+ export function readPinnedCertificateAuthority(origin, fingerprint) {
9
+ const url = new URL('/onboarding/ca.crt', origin);
10
+ if (url.protocol !== 'https:' || url.username || url.password || !/^(?:[\da-f]{2}:){31}[\da-f]{2}$/i.test(fingerprint))
11
+ return Promise.reject(new Error('Invalid pinned certificate authority'));
12
+ const key = `${url.origin}:${fingerprint.toUpperCase()}`;
13
+ const cached = cache.get(key);
14
+ if (cached && cached.expires > Date.now())
15
+ return cached.value;
16
+ const value = new Promise((resolve, reject) => {
17
+ const request = get(url, { agent: false, rejectUnauthorized: false, signal: AbortSignal.timeout(5000) }, response => {
18
+ if (response.statusCode !== 200) {
19
+ response.resume();
20
+ reject(new Error('Pinned certificate authority unavailable'));
21
+ return;
22
+ }
23
+ const chunks = [];
24
+ let size = 0;
25
+ response.on('data', (chunk) => {
26
+ size += chunk.length;
27
+ if (size > 256 * 1024) {
28
+ request.destroy(new Error('Certificate authority is too large'));
29
+ return;
30
+ }
31
+ chunks.push(chunk);
32
+ });
33
+ response.on('error', reject);
34
+ response.on('end', () => {
35
+ try {
36
+ const pem = Buffer.concat(chunks), certificate = new X509Certificate(pem);
37
+ if (!certificate.ca || certificate.fingerprint256 !== fingerprint.toUpperCase()
38
+ || Date.now() < Date.parse(certificate.validFrom) || Date.now() > Date.parse(certificate.validTo))
39
+ throw new Error('Certificate authority no longer matches Desktop trust');
40
+ resolve(pem);
41
+ }
42
+ catch (error) {
43
+ reject(error);
44
+ }
45
+ });
46
+ });
47
+ request.on('error', reject);
48
+ });
49
+ if (cache.size >= 64)
50
+ cache.delete(cache.keys().next().value);
51
+ cache.set(key, { expires: Date.now() + 120_000, value });
52
+ void value.catch(() => { if (cache.get(key)?.value === value)
53
+ cache.delete(key); });
54
+ return value;
55
+ }
@@ -39,6 +39,10 @@ import { CollaborationStore } from '../agent/collaborationStore.js';
39
39
  import { formatCollaborationDelivery } from '../agent/collaborationPrompt.js';
40
40
  import { resolveCollaborationSpawnMode } from '../agent/collaborationSpawn.js';
41
41
  import { SessionSearchStore } from '../agent/sessionSearchStore.js';
42
+ import { resolveCollaborationBackend } from '../agent/sessionBindingRecovery.js';
43
+ import { CollaborationRoutingStore, selectCollaborationPane } from '../agent/collaborationRouting.js';
44
+ import { CollaborationDeliveryWorker } from '../agent/collaborationDeliveryWorker.js';
45
+ import { writeCollaborationTmuxPane } from '../agent/collaborationTmuxDelivery.js';
42
46
  import { listAllHookAgents, refreshStaleHooksAtLaunch, installHooksForSlug, uninstallHooksForSlug, } from '../agent/installers.js';
43
47
  import { loadPlugins, savePlugin, removePlugin, readPluginIcon, validateManifest, } from '../agent/plugins.js';
44
48
  import { TmuxLifecycleCoordinator } from '../utils/tmuxLifecycle.js';
@@ -60,6 +64,14 @@ const execFileAsync = promisify(execFile);
60
64
  const TERMDOCK_DIR = `${os.homedir()}/.termdock`;
61
65
  const automationStore = new AutomationStore(`${TERMDOCK_DIR}/automations.json`);
62
66
  const collaborationStore = new CollaborationStore(`${TERMDOCK_DIR}/collaboration-groups.json`);
67
+ const collaborationRouting = new CollaborationRoutingStore(`${TERMDOCK_DIR}/collaboration-routing.json`);
68
+ const collaborationDeliveryWorker = new CollaborationDeliveryWorker({
69
+ store: collaborationStore,
70
+ peers: () => collaborationStore.list().filter((group) => !group.deleted).flatMap((group) => group.sessionIds),
71
+ isLocal: (id) => !id.startsWith('remote:'),
72
+ resolve: resolveCollaborationRoute,
73
+ onError: (error) => console.warn('[collaboration] background delivery failed:', getErrorMessage(error)),
74
+ });
63
75
  const sessionSearchStore = new SessionSearchStore(`${TERMDOCK_DIR}/session-search`);
64
76
  let atomicJsonWriteSequence = 0;
65
77
  async function readJsonFileIfExists(filePath) {
@@ -572,6 +584,7 @@ void (async () => {
572
584
  });
573
585
  pruneOrphanSessions();
574
586
  await backfillPersistedTmuxMetadata();
587
+ collaborationDeliveryWorker.start();
575
588
  })();
576
589
  caffeinateManager.startNetworkMonitor();
577
590
  // 清理磁盘恢复后后端已不存在的 session 引用。
@@ -1002,6 +1015,16 @@ function upsertGlobalSessionRecord(record) {
1002
1015
  sessions: deduplicateGlobalSessions(next),
1003
1016
  updatedAt: Date.now(),
1004
1017
  };
1018
+ // Capture server-observed bindings when sessions are created/adopted. Client
1019
+ // projections may later lose their backend id; the routing registry must not.
1020
+ if (normalized.backendSessionId && terminalSessions.has(normalized.backendSessionId)) {
1021
+ try {
1022
+ resolveOrchestrationBackend(normalized);
1023
+ }
1024
+ catch (error) {
1025
+ console.warn('[collaboration] binding persistence failed:', getErrorMessage(error));
1026
+ }
1027
+ }
1005
1028
  return normalized;
1006
1029
  }
1007
1030
  function removeGlobalSessionRecord(frontendSessionId) {
@@ -1011,8 +1034,10 @@ function removeGlobalSessionRecord(frontendSessionId) {
1011
1034
  updatedAt: Date.now(),
1012
1035
  };
1013
1036
  const changed = globalSessionState.sessions.length !== before;
1014
- if (changed)
1037
+ if (changed) {
1015
1038
  collaborationStore.removeSession(frontendSessionId);
1039
+ collaborationRouting.remove(frontendSessionId);
1040
+ }
1016
1041
  return changed;
1017
1042
  }
1018
1043
  function archiveAgentResumeRecord(record, reason) {
@@ -1263,19 +1288,48 @@ async function openInventorySession(req, input) {
1263
1288
  reused,
1264
1289
  };
1265
1290
  }
1291
+ function resolveOrchestrationBackend(record) {
1292
+ const recovered = resolveCollaborationBackend(record, globalSessionState.sessions, terminalSessions, collaborationRouting);
1293
+ if (!recovered)
1294
+ return null;
1295
+ const [backendSessionId, backend] = recovered;
1296
+ const changed = record.backendSessionId !== backendSessionId || record.tmuxSessionName !== backend.tmuxSessionName || record.mode !== backend.mode;
1297
+ record.backendSessionId = backendSessionId;
1298
+ record.mode = backend.mode;
1299
+ record.tmuxSessionName = backend.tmuxSessionName;
1300
+ record.cwd = backend.cwd ?? record.cwd;
1301
+ if (changed) {
1302
+ globalSessionState.updatedAt = Date.now();
1303
+ schedulePersistGlobalState();
1304
+ const metadata = searchMetadataForBackend(backendSessionId, backend);
1305
+ if (metadata)
1306
+ sessionSearchStore.update(metadata);
1307
+ }
1308
+ return backend;
1309
+ }
1266
1310
  function orchestrationSessionSnapshot(record) {
1267
- const backend = record.backendSessionId ? terminalSessions.get(record.backendSessionId) : null;
1268
- const agent = backend?.agent ?? (record.agentResume?.slug ? agentBySlug(record.agentResume.slug) : null);
1269
- const latestPrompt = backend?.autoTitlePromptPayloads.at(-1)?.trim() ?? '';
1311
+ const binding = collaborationRouting.get(record.sessionId);
1312
+ const backendId = binding?.backendSessionId ?? record.backendSessionId;
1313
+ const backend = backendId ? terminalSessions.get(backendId) : null;
1314
+ const route = collaborationDeliveryWorker.state(record.sessionId);
1315
+ const slug = binding?.pane?.agentSlug ?? binding?.agentSlug ?? record.agentResume?.slug;
1316
+ const agent = slug ? agentBySlug(slug) : backend?.agent;
1317
+ const sameNativeSession = !binding?.pane || Boolean(binding.pane.nativeSessionId
1318
+ && binding.pane.nativeSessionId === backend?.agentSession?.sessionId && binding.pane.agentSlug === backend?.agent?.slug);
1319
+ const turnState = sameNativeSession ? backend?.agentSession?.status : undefined;
1320
+ const latestPrompt = sameNativeSession ? backend?.autoTitlePromptPayloads.at(-1)?.trim() ?? '' : '';
1270
1321
  return {
1271
- ...collaborationStore.sessionFacts(record.sessionId, Boolean(backend), backend?.agentSession?.status),
1322
+ ...collaborationStore.sessionFacts(record.sessionId, route.state === 'ready', turnState),
1323
+ route_state: route.state,
1324
+ route_error: route.reason,
1325
+ route_checked_at: route.checkedAt,
1272
1326
  sessionId: record.sessionId,
1273
- agentNativeSessionId: backend?.agentSession?.sessionId ?? record.agentResume?.sessionId ?? null,
1274
- backendSessionId: record.backendSessionId ?? null,
1327
+ agentNativeSessionId: binding?.pane ? binding.pane.nativeSessionId : binding?.nativeSessionId ?? backend?.agentSession?.sessionId ?? record.agentResume?.sessionId ?? null,
1328
+ backendSessionId: backendId ?? null,
1275
1329
  name: record.name,
1276
1330
  cwd: backend?.cwd ?? record.cwd ?? '',
1277
1331
  agent: agent ? { slug: agent.slug, displayName: agent.displayName } : null,
1278
- status: backend?.agentSession?.status ?? (backend ? 'shell' : 'offline'),
1332
+ status: route.state === 'ready' ? turnState ?? 'ready' : route.state,
1279
1333
  capability: agent
1280
1334
  ? [agent.displayName, ...(agent.capabilities ?? []), backend?.activeProgram?.command || record.activeProgram || 'Agent 会话'].join(' · ')
1281
1335
  : (backend?.activeProgram?.command || record.activeProgram || 'Shell 终端'),
@@ -1361,11 +1415,19 @@ function resolveFrontendSessionId(input) {
1361
1415
  return sessionId;
1362
1416
  const backendSessionId = typeof input.backendSessionId === 'string' ? input.backendSessionId.trim() : '';
1363
1417
  if (backendSessionId) {
1418
+ const owner = collaborationRouting.ownerOfBackend(backendSessionId);
1419
+ if (owner && globalSessionState.sessions.some((record) => record.sessionId === owner))
1420
+ return owner;
1364
1421
  const resolved = globalSessionState.sessions.find((record) => record.backendSessionId === backendSessionId)?.sessionId;
1365
1422
  if (resolved)
1366
1423
  return resolved;
1367
1424
  }
1368
1425
  const tmuxSessionName = typeof input.tmuxSessionName === 'string' ? input.tmuxSessionName.trim() : '';
1426
+ if (!tmuxSessionName)
1427
+ return null;
1428
+ const bound = globalSessionState.sessions.find((record) => collaborationRouting.get(record.sessionId)?.tmuxSessionName === tmuxSessionName);
1429
+ if (bound)
1430
+ return bound.sessionId;
1369
1431
  return globalSessionState.sessions.find((record) => record.tmuxSessionName === tmuxSessionName)?.sessionId ?? null;
1370
1432
  }
1371
1433
  function collaborationRemoteSessions() {
@@ -1381,45 +1443,154 @@ function tryDeliverCollaborationInbox(frontendSessionId) {
1381
1443
  ? `服务 ${remote.serviceLabel} 不可达:消息尚未送达,仅保存在待发送队列;请勿等待对方已收到的回复,服务重连且 Mac 客户端运行后重试投递。`
1382
1444
  : '跨服务消息尚未确认送达,正在等待 Mac 客户端转发。' };
1383
1445
  }
1384
- const record = globalSessionState.sessions.find((candidate) => candidate.sessionId === frontendSessionId);
1385
- const session = record?.backendSessionId ? terminalSessions.get(record.backendSessionId) : null;
1386
- const pending = collaborationStore.inbox(frontendSessionId, { pendingOnly: true, limit: 10 });
1387
- // Submit to every online Agent immediately. Its TUI owns ordering while a
1388
- // turn is active; Termdock only retains messages when the Agent is offline.
1389
- if (!session || !canDeliverPromptToAgent(session) || pending.length === 0) {
1390
- return { delivered: [], pending: pending.length };
1391
- }
1392
- const prompt = formatCollaborationDelivery({
1393
- targetSessionId: frontendSessionId,
1394
- messages: pending,
1446
+ collaborationDeliveryWorker.wake(frontendSessionId);
1447
+ const route = collaborationDeliveryWorker.state(frontendSessionId);
1448
+ return { delivered: [], pending: collaborationStore.pendingCount(frontendSessionId),
1449
+ reason: route.reason ?? '消息已入队,后台正在恢复路由并投递' };
1450
+ }
1451
+ function formatLocalCollaborationMessages(frontendSessionId, messages) {
1452
+ return formatCollaborationDelivery({ targetSessionId: frontendSessionId, messages,
1395
1453
  groups: collaborationStore.groupsForSession(frontendSessionId),
1396
- sessions: [...collaborationRemoteSessions(), ...globalSessionState.sessions.map((candidate) => {
1397
- const snapshot = orchestrationSessionSnapshot(candidate);
1398
- return {
1399
- sessionId: snapshot.sessionId,
1400
- agentNativeSessionId: snapshot.agentNativeSessionId,
1401
- name: snapshot.name,
1402
- status: snapshot.status,
1403
- };
1404
- })],
1454
+ sessions: [...collaborationRemoteSessions(), ...globalSessionState.sessions.map(orchestrationSessionSnapshot)],
1405
1455
  });
1456
+ }
1457
+ async function inspectCollaborationTmux(binding, requestedPane) {
1458
+ if (!binding.tmuxSessionName)
1459
+ return { state: 'offline', reason: 'TMUX_BINDING_MISSING' };
1460
+ const name = `=${binding.tmuxSessionName}`;
1406
1461
  try {
1407
- session.ptyProcess.write(buildBracketedSubmitBytes(prompt));
1462
+ await runTmux(['has-session', '-t', name]);
1408
1463
  }
1409
1464
  catch (error) {
1410
- for (const message of pending)
1411
- collaborationStore.recordTransport(message.id, {
1412
- relay_online: null, peer_reachable: true, attempt_count: (collaborationStore.diagnostic(message.id)?.attempt_count ?? 0) + 1,
1413
- next_retry_at: Date.now() + 2_000, last_error: `PTY_WRITE_FAILED: ${getErrorMessage(error)}`, checked_at: Date.now(),
1414
- });
1415
- setTimeout(() => tryDeliverCollaborationInbox(frontendSessionId), 2_000).unref?.();
1416
- return { delivered: [], pending: collaborationStore.pendingCount(frontendSessionId), reason: '终端写入失败,消息已保留并等待重试' };
1465
+ if (/can't find session|no server running|no sessions|error connecting.*No such file/i.test(getErrorMessage(error))) {
1466
+ return { state: 'offline', reason: 'TMUX_SESSION_NOT_RUNNING' };
1467
+ }
1468
+ throw error;
1417
1469
  }
1418
- collaborationStore.markDelivered(pending.map((message) => message.id));
1419
- const remaining = collaborationStore.pendingCount(frontendSessionId);
1420
- if (remaining)
1421
- setTimeout(() => tryDeliverCollaborationInbox(frontendSessionId), 300).unref?.();
1422
- return { delivered: pending.map((message) => message.id), pending: remaining };
1470
+ const layout = await getTmuxLayout(binding.tmuxSessionName);
1471
+ if (layout.sessionName !== binding.tmuxSessionName)
1472
+ throw new Error('TMUX_SESSION_IDENTITY_CHANGED');
1473
+ const serverPid = Number((await runTmux(['display-message', '-p', '#{pid}'])).trim());
1474
+ if (!Number.isInteger(serverPid) || serverPid <= 0)
1475
+ throw new Error('TMUX_SERVER_IDENTITY_UNAVAILABLE');
1476
+ const panes = await Promise.all(layout.windows.flatMap((window) => window.panes).map(async (pane) => {
1477
+ const program = await resolveTmuxPaneProgram(pane);
1478
+ const agent = detectAgentFromCommand(program?.rawArgs ?? program?.command ?? '', agentCustomCommands());
1479
+ const nativeSessionId = agent && program?.rawArgs ? inferResumeSessionId(agent, splitCommandToArgv(program.rawArgs)) : null;
1480
+ return { serverPid, sessionId: layout.sessionId, paneId: pane.id, panePid: pane.pid,
1481
+ agentSlug: agent?.slug ?? '', nativeSessionId, cwd: pane.currentPath };
1482
+ }));
1483
+ return selectCollaborationPane(binding, requestedPane ? panes.filter((pane) => pane.paneId === requestedPane) : panes);
1484
+ }
1485
+ async function rebindCollaborationRoute(frontendSessionId, paneId) {
1486
+ await collaborationDeliveryWorker.reconfigure(frontendSessionId, async () => {
1487
+ const record = globalSessionState.sessions.find((candidate) => candidate.sessionId === frontendSessionId);
1488
+ if (!record)
1489
+ throw new Error('SESSION_REMOVED');
1490
+ const previous = collaborationRouting.get(frontendSessionId);
1491
+ const binding = {
1492
+ sessionId: frontendSessionId, backendSessionId: previous?.backendSessionId ?? record.backendSessionId,
1493
+ mode: record.mode, tmuxSessionName: record.tmuxSessionName ?? previous?.tmuxSessionName ?? null,
1494
+ agentSlug: null, nativeSessionId: null, pane: null,
1495
+ };
1496
+ if (binding.mode === 'tmux') {
1497
+ const inspected = await inspectCollaborationTmux(binding, paneId);
1498
+ if (inspected.state !== 'ready' || !inspected.pane)
1499
+ throw new Error(inspected.reason ?? 'AGENT_NOT_RUNNING');
1500
+ const pane = inspected.pane;
1501
+ binding.pane = { serverPid: pane.serverPid, sessionId: pane.sessionId, paneId: pane.paneId, panePid: pane.panePid,
1502
+ agentSlug: pane.agentSlug, nativeSessionId: pane.nativeSessionId };
1503
+ binding.agentSlug = pane.agentSlug;
1504
+ binding.nativeSessionId = pane.nativeSessionId;
1505
+ }
1506
+ else {
1507
+ if (paneId)
1508
+ throw new Error('PANE_REQUIRES_TMUX');
1509
+ const backend = binding.backendSessionId ? terminalSessions.get(binding.backendSessionId) : null;
1510
+ if (!backend)
1511
+ throw new Error('SHELL_BACKEND_NOT_RUNNING');
1512
+ await refreshCollaborationAgentIdentity(binding.backendSessionId, backend);
1513
+ const agent = detectSessionAgent(backend);
1514
+ if (!agent)
1515
+ throw new Error('AGENT_NOT_RUNNING');
1516
+ binding.agentSlug = agent.slug;
1517
+ binding.nativeSessionId = backend.agentSession?.sessionId ?? null;
1518
+ }
1519
+ if (!globalSessionState.sessions.some((candidate) => candidate.sessionId === frontendSessionId))
1520
+ throw new Error('SESSION_REMOVED');
1521
+ collaborationRouting.bind(binding);
1522
+ });
1523
+ collaborationDeliveryWorker.wake(frontendSessionId);
1524
+ return { ...collaborationRouting.get(frontendSessionId), state: 'recovering' };
1525
+ }
1526
+ async function resolveCollaborationRoute(frontendSessionId) {
1527
+ let record = globalSessionState.sessions.find((candidate) => candidate.sessionId === frontendSessionId);
1528
+ if (!record)
1529
+ return { state: 'offline', reason: 'SESSION_REMOVED' };
1530
+ let backend = resolveOrchestrationBackend(record);
1531
+ let binding = collaborationRouting.get(frontendSessionId) ?? {
1532
+ sessionId: record.sessionId, backendSessionId: null, mode: record.mode, tmuxSessionName: record.tmuxSessionName,
1533
+ agentSlug: record.agentResume?.slug ?? null, nativeSessionId: record.agentResume?.sessionId ?? null, pane: null,
1534
+ };
1535
+ if (binding.mode === 'tmux') {
1536
+ const inspected = await inspectCollaborationTmux(binding);
1537
+ if (inspected.state !== 'ready' || !inspected.pane)
1538
+ return inspected;
1539
+ record = globalSessionState.sessions.find((candidate) => candidate.sessionId === frontendSessionId);
1540
+ if (!record)
1541
+ return { state: 'offline', reason: 'SESSION_REMOVED_DURING_RECOVERY' };
1542
+ const pane = inspected.pane;
1543
+ // Remember the target before attachment. A failed attachment must not let
1544
+ // a subsequent active-pane change silently choose another recipient.
1545
+ const pinned = { serverPid: pane.serverPid, sessionId: pane.sessionId, paneId: pane.paneId, panePid: pane.panePid,
1546
+ agentSlug: pane.agentSlug, nativeSessionId: pane.nativeSessionId ?? binding.nativeSessionId };
1547
+ binding = { ...binding, pane: pinned, agentSlug: pinned.agentSlug, nativeSessionId: pinned.nativeSessionId };
1548
+ collaborationRouting.bind(binding);
1549
+ if (!backend) {
1550
+ const cwd = pane.cwd || record.cwd;
1551
+ if (!cwd)
1552
+ return { state: 'detached', reason: 'TMUX_ATTACH_CWD_UNAVAILABLE' };
1553
+ await pathValidator.allowSessionCwd(cwd);
1554
+ // Attach only. Never recreate a vanished session or launch/resume an
1555
+ // Agent in response to a queued collaboration message.
1556
+ const spawned = await spawnTerminalSession({}, { cwd, mode: 'tmux',
1557
+ tmuxSessionName: binding.tmuxSessionName, attachExistingOnly: true, tmuxAttachTarget: pane.sessionId });
1558
+ record = globalSessionState.sessions.find((candidate) => candidate.sessionId === frontendSessionId);
1559
+ if (!record)
1560
+ return { state: 'offline', reason: 'SESSION_REMOVED_DURING_RECOVERY' };
1561
+ if (!terminalSessions.has(spawned.sessionId))
1562
+ return { state: 'detached', reason: 'TMUX_ATTACH_EXITED' };
1563
+ binding = { ...binding, backendSessionId: spawned.sessionId };
1564
+ collaborationRouting.bind(binding);
1565
+ backend = resolveOrchestrationBackend(record);
1566
+ }
1567
+ if (!backend)
1568
+ return { state: 'detached', reason: 'TMUX_BACKEND_UNAVAILABLE' };
1569
+ return { state: 'ready', write: async (messages) => {
1570
+ if (!globalSessionState.sessions.some((candidate) => candidate.sessionId === frontendSessionId))
1571
+ throw new Error('SESSION_REMOVED');
1572
+ await writeCollaborationTmuxPane(runTmux, pinned, formatLocalCollaborationMessages(frontendSessionId, messages));
1573
+ backend.lastActivity = Date.now();
1574
+ } };
1575
+ }
1576
+ if (!backend || !binding.backendSessionId)
1577
+ return { state: 'offline', reason: 'SHELL_BACKEND_NOT_RUNNING' };
1578
+ await refreshCollaborationAgentIdentity(binding.backendSessionId, backend);
1579
+ if (!detectSessionAgent(backend))
1580
+ return { state: 'agent-exited', reason: 'AGENT_NOT_RUNNING' };
1581
+ if ((binding.agentSlug && backend.agent?.slug !== binding.agentSlug)
1582
+ || (binding.nativeSessionId && backend.agentSession?.sessionId && backend.agentSession.sessionId !== binding.nativeSessionId)) {
1583
+ return { state: 'identity-mismatch', reason: 'AGENT_IDENTITY_CHANGED' };
1584
+ }
1585
+ const target = backend;
1586
+ return { state: 'ready', write: async (messages) => {
1587
+ if (!globalSessionState.sessions.some((candidate) => candidate.sessionId === frontendSessionId))
1588
+ throw new Error('SESSION_REMOVED');
1589
+ if (terminalSessions.get(binding.backendSessionId) !== target)
1590
+ throw new Error('SHELL_BACKEND_CHANGED');
1591
+ target.ptyProcess.write(buildBracketedSubmitBytes(formatLocalCollaborationMessages(frontendSessionId, messages)));
1592
+ target.lastActivity = Date.now();
1593
+ } };
1423
1594
  }
1424
1595
  async function refreshCollaborationAgentIdentity(backendSessionId, session) {
1425
1596
  let activeProgram = null;
@@ -1434,33 +1605,12 @@ async function refreshCollaborationAgentIdentity(backendSessionId, session) {
1434
1605
  ? { ...resolved, updatedAt: Date.now() }
1435
1606
  : getActiveProgramFromTmuxLayout(layout);
1436
1607
  }
1437
- if (!activeProgram)
1438
- return;
1439
1608
  session.activeProgram = activeProgram;
1440
- persistActiveProgramBinding(backendSessionId, activeProgram.command);
1609
+ persistActiveProgramBinding(backendSessionId, activeProgram?.command);
1441
1610
  syncAgentIdentity(backendSessionId, session);
1442
1611
  }
1443
1612
  function deliverCollaborationInboxWhenAgentReady(frontendSessionId, backendSessionId, attempt = 0) {
1444
- const session = terminalSessions.get(backendSessionId);
1445
- if (!session)
1446
- return;
1447
- if (canDeliverPromptToAgent(session)) {
1448
- setTimeout(() => tryDeliverCollaborationInbox(frontendSessionId), 300).unref?.();
1449
- return;
1450
- }
1451
- if (attempt >= 60)
1452
- return;
1453
- void refreshCollaborationAgentIdentity(backendSessionId, session)
1454
- .catch(() => undefined)
1455
- .finally(() => {
1456
- if (canDeliverPromptToAgent(session)) {
1457
- setTimeout(() => tryDeliverCollaborationInbox(frontendSessionId), 300).unref?.();
1458
- return;
1459
- }
1460
- setTimeout(() => {
1461
- deliverCollaborationInboxWhenAgentReady(frontendSessionId, backendSessionId, attempt + 1);
1462
- }, 250).unref?.();
1463
- });
1613
+ collaborationDeliveryWorker.wake(frontendSessionId);
1464
1614
  }
1465
1615
  async function spawnCollaborationAgentSession(req, group, sourceSessionId, input) {
1466
1616
  const agentSlug = typeof input.agentSlug === 'string' ? input.agentSlug.trim().toLowerCase() : '';
@@ -4435,7 +4585,22 @@ function ptyHostShellModeEnabled() {
4435
4585
  const isBun = typeof globalThis.Bun !== 'undefined';
4436
4586
  return process.platform !== 'win32' && !isBun && process.env.TERMDOCK_PTY_HOST !== 'off';
4437
4587
  }
4588
+ const tmuxBackendSpawns = new Map();
4438
4589
  async function spawnTerminalSession(req, input) {
4590
+ const name = input.mode === 'tmux' && input.tmuxSessionName ? normalizeTmuxSessionName(input.tmuxSessionName) : null;
4591
+ if (!name)
4592
+ return spawnTerminalSessionUnlocked(req, input);
4593
+ const pending = tmuxBackendSpawns.get(name);
4594
+ if (pending)
4595
+ return pending;
4596
+ const existing = findBackendSessionForTmux(name);
4597
+ if (existing)
4598
+ return { sessionId: existing[0], session: existing[1], cols: existing[1].cols, rows: existing[1].rows };
4599
+ const operation = spawnTerminalSessionUnlocked(req, input).finally(() => tmuxBackendSpawns.delete(name));
4600
+ tmuxBackendSpawns.set(name, operation);
4601
+ return operation;
4602
+ }
4603
+ async function spawnTerminalSessionUnlocked(req, input) {
4439
4604
  const cwd = await resolveWorkingDirectory(req, input.cwd);
4440
4605
  const cols = input.cols || 80;
4441
4606
  const rows = input.rows || 24;
@@ -4446,19 +4611,28 @@ async function spawnTerminalSession(req, input) {
4446
4611
  if (mode === 'tmux') {
4447
4612
  const tmuxStatus = await getTmuxStatus();
4448
4613
  if (!tmuxStatus.available) {
4614
+ if (input.attachExistingOnly)
4615
+ throw new Error('TMUX_UNAVAILABLE');
4449
4616
  console.warn('[termdock] tmux not available, falling back to shell mode:', tmuxStatus.reason);
4450
4617
  mode = 'shell';
4451
4618
  }
4452
4619
  }
4453
4620
  const tmuxSessionName = mode === 'tmux' ? normalizeTmuxSessionName(input.tmuxSessionName) : null;
4454
4621
  if (mode === 'tmux' && tmuxSessionName) {
4455
- await prepareManagedTmuxSession(tmuxSessionName, cwd);
4622
+ if (input.attachExistingOnly) {
4623
+ if (!await tmuxSessionExists(input.tmuxAttachTarget ?? `=${tmuxSessionName}`))
4624
+ throw new Error('TMUX_SESSION_NOT_RUNNING');
4625
+ }
4626
+ else
4627
+ await prepareManagedTmuxSession(tmuxSessionName, cwd);
4456
4628
  }
4457
4629
  const command = mode === 'tmux'
4458
4630
  ? getTmuxBinary()
4459
4631
  : (process.platform === 'win32' ? 'powershell.exe' : resolveShellCandidates()[0]);
4632
+ const supportsFeatures = mode === 'tmux' && await supportsTmuxClientFeatures(command);
4460
4633
  const args = mode === 'tmux' && tmuxSessionName
4461
- ? buildTmuxAttachArgs(tmuxSessionName, await supportsTmuxClientFeatures(command))
4634
+ ? [...buildTmuxAttachArgs(input.tmuxAttachTarget ?? tmuxSessionName, supportsFeatures),
4635
+ ...(input.attachExistingOnly && supportsFeatures ? ['-f', 'ignore-size'] : [])]
4462
4636
  : (process.platform === 'win32' ? buildPowerShellCwdHookArgs() : []);
4463
4637
  const envPath = buildAugmentedPath();
4464
4638
  const resolvedEnv = buildInteractiveColorEnvironment({
@@ -5393,7 +5567,8 @@ router.post('/operations/orchestration/spawn', async (req, res) => {
5393
5567
  res.status(400).json({ error: getErrorMessage(error) });
5394
5568
  }
5395
5569
  });
5396
- router.use('/operations/orchestration', collaborationRoutes({ store: collaborationStore, resolveSession: resolveFrontendSessionId, deliver: tryDeliverCollaborationInbox }));
5570
+ router.use('/operations/orchestration', collaborationRoutes({ store: collaborationStore, resolveSession: resolveFrontendSessionId,
5571
+ deliver: tryDeliverCollaborationInbox, rebind: rebindCollaborationRoute }));
5397
5572
  router.get('/operations/session-search', (req, res) => {
5398
5573
  const query = typeof req.query.q === 'string' ? req.query.q : '';
5399
5574
  const results = sessionSearchStore.search(query, Number(req.query.limit) || 30).map((result) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "termdock",
3
- "version": "1.4.178",
3
+ "version": "1.4.179",
4
4
  "description": "A complete web-based terminal application with modern UI",
5
5
  "type": "module",
6
6
  "main": ".desktop-dist/main.js",
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "packageName": "termdock",
4
- "version": "1.4.178",
4
+ "version": "1.4.179",
5
5
  "runtimeProtocolVersion": 1,
6
6
  "minimumDesktopVersion": "1.4.46",
7
7
  "nodeMajor": 22,
8
8
  "dependencyHash": "sha256-kSujny2SLOFnZ1ffxm1FYtli7g1vEN8d3vj1oQeLLdc=",
9
- "serverBundleHash": "sha256-wG7h9fvsMN8idDY+H+dioaPsjuM+ojnCMxgwFMeS61M=",
10
- "clientBundleHash": "sha256-Wjd5odYe+uZp1t365akaiTeCrJ6DjjG2XFJwMyCO3Cg=",
9
+ "serverBundleHash": "sha256-AQUq3XFy+cNp7XbeVQmCnE6m5odhlqCbuU3LbvxFjt0=",
10
+ "clientBundleHash": "sha256-jofF5lZQ8B7W5pmfclW2tlMMp+FlTHRi8am3AscU2CE=",
11
11
  "entrypoint": "dist/server/cli.js",
12
12
  "clientEntrypoint": "dist/client/index.html"
13
13
  }