termdock 1.4.178 → 1.4.180

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 (345) hide show
  1. package/.desktop-dist/main.js +1 -1
  2. package/dist/client/assets/App-DBds0RoW.js +150 -0
  3. package/dist/client/assets/App-DBds0RoW.js.br +0 -0
  4. package/dist/client/assets/App-DBds0RoW.js.gz +0 -0
  5. package/dist/client/assets/{ChangeWalkthroughPanel-BNWqAnqc.js → ChangeWalkthroughPanel-DonkfMV2.js} +2 -2
  6. package/dist/client/assets/ChangeWalkthroughPanel-DonkfMV2.js.br +0 -0
  7. package/dist/client/assets/ChangeWalkthroughPanel-DonkfMV2.js.gz +0 -0
  8. package/dist/client/assets/{DagPlayground-IlTGwr-I.js → DagPlayground-CYL8vhaU.js} +1 -1
  9. package/dist/client/assets/DagPlayground-CYL8vhaU.js.br +0 -0
  10. package/dist/client/assets/DagPlayground-CYL8vhaU.js.gz +0 -0
  11. package/dist/client/assets/{DiffLab-CwhNpJvo.js → DiffLab-COUjebir.js} +1 -1
  12. package/dist/client/assets/DiffLab-COUjebir.js.br +0 -0
  13. package/dist/client/assets/DiffLab-COUjebir.js.gz +0 -0
  14. package/dist/client/assets/{DiffReview-DyhINv0F.js → DiffReview-DqiRXomQ.js} +1 -1
  15. package/dist/client/assets/DiffReview-DqiRXomQ.js.br +0 -0
  16. package/dist/client/assets/DiffReview-DqiRXomQ.js.gz +0 -0
  17. package/dist/client/assets/{DiffReviewLab-D9Kt5VwB.js → DiffReviewLab-Aqib8Qr6.js} +1 -1
  18. package/dist/client/assets/DiffReviewLab-Aqib8Qr6.js.br +0 -0
  19. package/dist/client/assets/DiffReviewLab-Aqib8Qr6.js.gz +0 -0
  20. package/dist/client/assets/{DiffViewer-3zz2PI-8.js → DiffViewer-KR2GhX72.js} +1 -1
  21. package/dist/client/assets/DiffViewer-KR2GhX72.js.br +0 -0
  22. package/dist/client/assets/DiffViewer-KR2GhX72.js.gz +0 -0
  23. package/dist/client/assets/{ModelPreview-CN8xsiGC.js → ModelPreview-Bo6giTPm.js} +1 -1
  24. package/dist/client/assets/ModelPreview-Bo6giTPm.js.br +0 -0
  25. package/dist/client/assets/ModelPreview-Bo6giTPm.js.gz +0 -0
  26. package/dist/client/assets/RightSidebar-rROjRuPY.js +1678 -0
  27. package/dist/client/assets/RightSidebar-rROjRuPY.js.br +0 -0
  28. package/dist/client/assets/RightSidebar-rROjRuPY.js.gz +0 -0
  29. package/dist/client/assets/{abnfDiagram-VCTEODGH-DkdoJ2ZH.js → abnfDiagram-VCTEODGH-m85vHRkF.js} +1 -1
  30. package/dist/client/assets/abnfDiagram-VCTEODGH-m85vHRkF.js.br +0 -0
  31. package/dist/client/assets/abnfDiagram-VCTEODGH-m85vHRkF.js.gz +0 -0
  32. package/dist/client/assets/app-Djvvt1Mi.js +34 -0
  33. package/dist/client/assets/app-Djvvt1Mi.js.br +0 -0
  34. package/dist/client/assets/app-Djvvt1Mi.js.gz +0 -0
  35. package/dist/client/assets/{arc-ctzz5PcK.js → arc-DmZ3EVhj.js} +1 -1
  36. package/dist/client/assets/arc-DmZ3EVhj.js.br +0 -0
  37. package/dist/client/assets/arc-DmZ3EVhj.js.gz +0 -0
  38. package/dist/client/assets/{architectureDiagram-5GKGNRK7-DNLcYfGQ.js → architectureDiagram-5GKGNRK7-C8yGaNGM.js} +1 -1
  39. package/dist/client/assets/architectureDiagram-5GKGNRK7-C8yGaNGM.js.br +0 -0
  40. package/dist/client/assets/architectureDiagram-5GKGNRK7-C8yGaNGM.js.gz +0 -0
  41. package/dist/client/assets/{blockDiagram-I7D4REHJ-Coye1ou5.js → blockDiagram-I7D4REHJ-CZhh__cR.js} +1 -1
  42. package/dist/client/assets/blockDiagram-I7D4REHJ-CZhh__cR.js.br +0 -0
  43. package/dist/client/assets/blockDiagram-I7D4REHJ-CZhh__cR.js.gz +0 -0
  44. package/dist/client/assets/{c4Diagram-7LVT6UL2-DTa8jyPp.js → c4Diagram-7LVT6UL2-py7O2OOO.js} +1 -1
  45. package/dist/client/assets/c4Diagram-7LVT6UL2-py7O2OOO.js.br +0 -0
  46. package/dist/client/assets/c4Diagram-7LVT6UL2-py7O2OOO.js.gz +0 -0
  47. package/dist/client/assets/channel-BnKOV34C.js +1 -0
  48. package/dist/client/assets/{chunk-2Q5K7J3B-BpDyjNfs.js → chunk-2Q5K7J3B-SXGoQcYW.js} +1 -1
  49. package/dist/client/assets/{chunk-5VM5RSS4-DgwdqXKl.js → chunk-5VM5RSS4-1ZVyPSGv.js} +1 -1
  50. package/dist/client/assets/{chunk-F27PBJKO-DWf2gZ96.js → chunk-F27PBJKO-DkIqnjYj.js} +1 -1
  51. package/dist/client/assets/chunk-F27PBJKO-DkIqnjYj.js.br +0 -0
  52. package/dist/client/assets/chunk-F27PBJKO-DkIqnjYj.js.gz +0 -0
  53. package/dist/client/assets/{chunk-IMKFNOWR-l42o_E2c.js → chunk-IMKFNOWR-CLS_EByq.js} +1 -1
  54. package/dist/client/assets/chunk-IMKFNOWR-CLS_EByq.js.br +0 -0
  55. package/dist/client/assets/chunk-IMKFNOWR-CLS_EByq.js.gz +0 -0
  56. package/dist/client/assets/{chunk-JWPE2WC7-8CkEf05l.js → chunk-JWPE2WC7-8LtK4UYW.js} +1 -1
  57. package/dist/client/assets/{chunk-POPQ4Y6H-BKKOfbdg.js → chunk-POPQ4Y6H-D1PhOQEv.js} +1 -1
  58. package/dist/client/assets/{chunk-SVP7TREG-RORrf2aM.js → chunk-SVP7TREG-cVWIfR_4.js} +1 -1
  59. package/dist/client/assets/chunk-SVP7TREG-cVWIfR_4.js.br +0 -0
  60. package/dist/client/assets/chunk-SVP7TREG-cVWIfR_4.js.gz +0 -0
  61. package/dist/client/assets/{chunk-TICWLB2K-hPqafEtC.js → chunk-TICWLB2K-BiO8AIZ7.js} +1 -1
  62. package/dist/client/assets/chunk-TICWLB2K-BiO8AIZ7.js.br +0 -0
  63. package/dist/client/assets/chunk-TICWLB2K-BiO8AIZ7.js.gz +0 -0
  64. package/dist/client/assets/{chunk-XXDRQBXY-CrvjJwms.js → chunk-XXDRQBXY-CwP0rAj8.js} +1 -1
  65. package/dist/client/assets/classDiagram-ZZMXUADV-CZ5ElqWa.js +1 -0
  66. package/dist/client/assets/classDiagram-v2-VYDZK3BY-CZ5ElqWa.js +1 -0
  67. package/dist/client/assets/{cose-bilkent-JH36ORCC-CwRSiQLa.js → cose-bilkent-JH36ORCC-Dv9GK27H.js} +1 -1
  68. package/dist/client/assets/cose-bilkent-JH36ORCC-Dv9GK27H.js.br +0 -0
  69. package/dist/client/assets/{cose-bilkent-JH36ORCC-CwRSiQLa.js.gz → cose-bilkent-JH36ORCC-Dv9GK27H.js.gz} +0 -0
  70. package/dist/client/assets/{cynefin-OW5HDTMX-CXnppZ8I.js → cynefin-OW5HDTMX-DDI6luT6.js} +1 -1
  71. package/dist/client/assets/cynefin-OW5HDTMX-DDI6luT6.js.br +0 -0
  72. package/dist/client/assets/cynefin-OW5HDTMX-DDI6luT6.js.gz +0 -0
  73. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-BSDrHSIA.js → cynefinDiagram-5FMLGOSQ-DQpaBQcE.js} +1 -1
  74. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-DQpaBQcE.js.br +0 -0
  75. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-DQpaBQcE.js.gz +0 -0
  76. package/dist/client/assets/{dagre-GXQ25YYZ-d-5j4vkq.js → dagre-GXQ25YYZ-CZ-1rzmK.js} +1 -1
  77. package/dist/client/assets/dagre-GXQ25YYZ-CZ-1rzmK.js.br +0 -0
  78. package/dist/client/assets/dagre-GXQ25YYZ-CZ-1rzmK.js.gz +0 -0
  79. package/dist/client/assets/{diagram-S7CK7UJ4-DizMBpGW.js → diagram-S7CK7UJ4-DeYvGv1c.js} +1 -1
  80. package/dist/client/assets/diagram-S7CK7UJ4-DeYvGv1c.js.br +0 -0
  81. package/dist/client/assets/diagram-S7CK7UJ4-DeYvGv1c.js.gz +0 -0
  82. package/dist/client/assets/{diagram-UQ7AKVKN-CNQK26rH.js → diagram-UQ7AKVKN-BaYQC1t6.js} +1 -1
  83. package/dist/client/assets/diagram-UQ7AKVKN-BaYQC1t6.js.br +0 -0
  84. package/dist/client/assets/diagram-UQ7AKVKN-BaYQC1t6.js.gz +0 -0
  85. package/dist/client/assets/{diagram-VSXAHHWV-Dua-2_46.js → diagram-VSXAHHWV-B517BnK0.js} +1 -1
  86. package/dist/client/assets/diagram-VSXAHHWV-B517BnK0.js.br +0 -0
  87. package/dist/client/assets/diagram-VSXAHHWV-B517BnK0.js.gz +0 -0
  88. package/dist/client/assets/{diagram-VX7I27RA-CIq-4729.js → diagram-VX7I27RA-DyjVlDcv.js} +1 -1
  89. package/dist/client/assets/diagram-VX7I27RA-DyjVlDcv.js.br +0 -0
  90. package/dist/client/assets/diagram-VX7I27RA-DyjVlDcv.js.gz +0 -0
  91. package/dist/client/assets/{diagram-Z3DM3KII-BukQ0u-x.js → diagram-Z3DM3KII-Cy9JXHOz.js} +1 -1
  92. package/dist/client/assets/diagram-Z3DM3KII-Cy9JXHOz.js.br +0 -0
  93. package/dist/client/assets/diagram-Z3DM3KII-Cy9JXHOz.js.gz +0 -0
  94. package/dist/client/assets/{ebnfDiagram-PWID7BFC-D2zRkRBI.js → ebnfDiagram-PWID7BFC-xvEH045b.js} +1 -1
  95. package/dist/client/assets/ebnfDiagram-PWID7BFC-xvEH045b.js.br +0 -0
  96. package/dist/client/assets/ebnfDiagram-PWID7BFC-xvEH045b.js.gz +0 -0
  97. package/dist/client/assets/{erDiagram-RLTQ6QDP-DbX6A3ls.js → erDiagram-RLTQ6QDP-BTJDgwKq.js} +1 -1
  98. package/dist/client/assets/{erDiagram-RLTQ6QDP-DbX6A3ls.js.br → erDiagram-RLTQ6QDP-BTJDgwKq.js.br} +0 -0
  99. package/dist/client/assets/erDiagram-RLTQ6QDP-BTJDgwKq.js.gz +0 -0
  100. package/dist/client/assets/{flowDiagram-HODETNUW-YECDWA2G.js → flowDiagram-HODETNUW-6pq1SF-S.js} +1 -1
  101. package/dist/client/assets/flowDiagram-HODETNUW-6pq1SF-S.js.br +0 -0
  102. package/dist/client/assets/flowDiagram-HODETNUW-6pq1SF-S.js.gz +0 -0
  103. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-D3EJdUov.js → ganttDiagram-EL5Y4UJY-DS_l5v9m.js} +1 -1
  104. package/dist/client/assets/ganttDiagram-EL5Y4UJY-DS_l5v9m.js.br +0 -0
  105. package/dist/client/assets/ganttDiagram-EL5Y4UJY-DS_l5v9m.js.gz +0 -0
  106. package/dist/client/assets/{gestureArbiter-D3IZpZS7.js → gestureArbiter-FtwbRpdp.js} +1 -1
  107. package/dist/client/assets/gestureArbiter-FtwbRpdp.js.br +0 -0
  108. package/dist/client/assets/gestureArbiter-FtwbRpdp.js.gz +0 -0
  109. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-tr_HKoQK.js → gitGraphDiagram-WWUBYQGX-DEGFo3aa.js} +1 -1
  110. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DEGFo3aa.js.br +0 -0
  111. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DEGFo3aa.js.gz +0 -0
  112. package/dist/client/assets/{index-C4Ny0NDQ.css → index-PWu1VEN_.css} +1 -1
  113. package/dist/client/assets/index-PWu1VEN_.css.br +0 -0
  114. package/dist/client/assets/index-PWu1VEN_.css.gz +0 -0
  115. package/dist/client/assets/{infoDiagram-27XIBGKW-xBV63YYg.js → infoDiagram-27XIBGKW-CFVSyJdD.js} +1 -1
  116. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-BrYSZu1R.js → ishikawaDiagram-5VMMS53U-_YX0U_wu.js} +1 -1
  117. package/dist/client/assets/ishikawaDiagram-5VMMS53U-_YX0U_wu.js.br +0 -0
  118. package/dist/client/assets/ishikawaDiagram-5VMMS53U-_YX0U_wu.js.gz +0 -0
  119. package/dist/client/assets/{journeyDiagram-3NMN7TZE-C9Ft--aA.js → journeyDiagram-3NMN7TZE-DCujswss.js} +1 -1
  120. package/dist/client/assets/journeyDiagram-3NMN7TZE-DCujswss.js.br +0 -0
  121. package/dist/client/assets/journeyDiagram-3NMN7TZE-DCujswss.js.gz +0 -0
  122. package/dist/client/assets/{kanban-definition-UXKFOSKX-FCxqSu11.js → kanban-definition-UXKFOSKX-DC6lqIBi.js} +1 -1
  123. package/dist/client/assets/kanban-definition-UXKFOSKX-DC6lqIBi.js.br +0 -0
  124. package/dist/client/assets/kanban-definition-UXKFOSKX-DC6lqIBi.js.gz +0 -0
  125. package/dist/client/assets/{layout-BqjIyPqO.js → layout-D_hlL0MC.js} +1 -1
  126. package/dist/client/assets/layout-D_hlL0MC.js.br +0 -0
  127. package/dist/client/assets/layout-D_hlL0MC.js.gz +0 -0
  128. package/dist/client/assets/{linear-CEAGQX5N.js → linear-BxpjJ2yt.js} +1 -1
  129. package/dist/client/assets/linear-BxpjJ2yt.js.br +0 -0
  130. package/dist/client/assets/linear-BxpjJ2yt.js.gz +0 -0
  131. package/dist/client/assets/{mermaid.core-DvAY78t_.js → mermaid.core-BRLYB1Uj.js} +5 -5
  132. package/dist/client/assets/mermaid.core-BRLYB1Uj.js.br +0 -0
  133. package/dist/client/assets/mermaid.core-BRLYB1Uj.js.gz +0 -0
  134. package/dist/client/assets/{mindmap-definition-YA3MSWOX-D7_qIQ9H.js → mindmap-definition-YA3MSWOX-BF2f-Z54.js} +1 -1
  135. package/dist/client/assets/mindmap-definition-YA3MSWOX-BF2f-Z54.js.br +0 -0
  136. package/dist/client/assets/mindmap-definition-YA3MSWOX-BF2f-Z54.js.gz +0 -0
  137. package/dist/client/assets/{passwordBootstrap-Dksfdvk3.js → passwordBootstrap-hj2Lcgoj.js} +1 -1
  138. package/dist/client/assets/passwordBootstrap-hj2Lcgoj.js.br +0 -0
  139. package/dist/client/assets/passwordBootstrap-hj2Lcgoj.js.gz +0 -0
  140. package/dist/client/assets/{pegDiagram-XKGWAZYB-DeTIBKGC.js → pegDiagram-XKGWAZYB-FxHPBhCy.js} +1 -1
  141. package/dist/client/assets/pegDiagram-XKGWAZYB-FxHPBhCy.js.br +0 -0
  142. package/dist/client/assets/pegDiagram-XKGWAZYB-FxHPBhCy.js.gz +0 -0
  143. package/dist/client/assets/{pieDiagram-E7YTZNPT-z5IcoVwx.js → pieDiagram-E7YTZNPT-DqAcArGH.js} +1 -1
  144. package/dist/client/assets/pieDiagram-E7YTZNPT-DqAcArGH.js.br +0 -0
  145. package/dist/client/assets/pieDiagram-E7YTZNPT-DqAcArGH.js.gz +0 -0
  146. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-B-zCZvES.js → quadrantDiagram-AXDQQJYC-31lk30-Y.js} +1 -1
  147. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-B-zCZvES.js.br → quadrantDiagram-AXDQQJYC-31lk30-Y.js.br} +0 -0
  148. package/dist/client/assets/quadrantDiagram-AXDQQJYC-31lk30-Y.js.gz +0 -0
  149. package/dist/client/assets/{railroadDiagram-O6MQD6OU-DbpeB7P2.js → railroadDiagram-O6MQD6OU-C-Jt17Wl.js} +1 -1
  150. package/dist/client/assets/railroadDiagram-O6MQD6OU-C-Jt17Wl.js.br +0 -0
  151. package/dist/client/assets/railroadDiagram-O6MQD6OU-C-Jt17Wl.js.gz +0 -0
  152. package/dist/client/assets/{referenceLongPress-p56g9xFb.js → referenceLongPress-BPFSnCDQ.js} +1 -1
  153. package/dist/client/assets/referenceLongPress-BPFSnCDQ.js.br +0 -0
  154. package/dist/client/assets/referenceLongPress-BPFSnCDQ.js.gz +0 -0
  155. package/dist/client/assets/{requirementDiagram-BXWQKSXE-UhJYMJ_U.js → requirementDiagram-BXWQKSXE-DdrbsuCJ.js} +1 -1
  156. package/dist/client/assets/requirementDiagram-BXWQKSXE-DdrbsuCJ.js.br +0 -0
  157. package/dist/client/assets/requirementDiagram-BXWQKSXE-DdrbsuCJ.js.gz +0 -0
  158. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-xKsuFR17.js → sankeyDiagram-P5KCCOFB-CZjs9KFo.js} +1 -1
  159. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CZjs9KFo.js.br +0 -0
  160. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CZjs9KFo.js.gz +0 -0
  161. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-DrjBl65C.js → sequenceDiagram-WJ2MYXX4-CkD1f6v4.js} +1 -1
  162. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-CkD1f6v4.js.br +0 -0
  163. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-CkD1f6v4.js.gz +0 -0
  164. package/dist/client/assets/{sizeCapture-INFHLROL-BIlGJ9tm.js → sizeCapture-INFHLROL-BMuKV0gL.js} +1 -1
  165. package/dist/client/assets/sizeCapture-INFHLROL-BMuKV0gL.js.br +0 -0
  166. package/dist/client/assets/sizeCapture-INFHLROL-BMuKV0gL.js.gz +0 -0
  167. package/dist/client/assets/{sparkles-B-uEi0Pa.js → sparkles-DuRvUCWG.js} +1 -1
  168. package/dist/client/assets/{stateDiagram-D77RDMKH-C3k9XvA6.js → stateDiagram-D77RDMKH-B1lLo2WA.js} +1 -1
  169. package/dist/client/assets/stateDiagram-D77RDMKH-B1lLo2WA.js.br +0 -0
  170. package/dist/client/assets/stateDiagram-D77RDMKH-B1lLo2WA.js.gz +0 -0
  171. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-F5MbngH8.js +1 -0
  172. package/dist/client/assets/{swimlanes-42K2YHIH-BN-x1rXp.js → swimlanes-42K2YHIH-CfC5CNjA.js} +1 -1
  173. package/dist/client/assets/swimlanes-42K2YHIH-CfC5CNjA.js.br +0 -0
  174. package/dist/client/assets/swimlanes-42K2YHIH-CfC5CNjA.js.gz +0 -0
  175. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-BqbZwNvL.js +8 -0
  176. package/dist/client/assets/{timeline-definition-24CTP7MA-Dcedjtic.js → timeline-definition-24CTP7MA-0mM-Skdo.js} +1 -1
  177. package/dist/client/assets/timeline-definition-24CTP7MA-0mM-Skdo.js.br +0 -0
  178. package/dist/client/assets/timeline-definition-24CTP7MA-0mM-Skdo.js.gz +0 -0
  179. package/dist/client/assets/{triangle-alert-BSNAwyll.js → triangle-alert-wyGdnPOg.js} +1 -1
  180. package/dist/client/assets/{vennDiagram-4TSXK5OY-DAIk-5Rt.js → vennDiagram-4TSXK5OY-BYsJo_hU.js} +1 -1
  181. package/dist/client/assets/vennDiagram-4TSXK5OY-BYsJo_hU.js.br +0 -0
  182. package/dist/client/assets/vennDiagram-4TSXK5OY-BYsJo_hU.js.gz +0 -0
  183. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-3iXOTpAg.js → wardleyDiagram-VM6X3IG4-ree3u-pI.js} +1 -1
  184. package/dist/client/assets/wardleyDiagram-VM6X3IG4-ree3u-pI.js.br +0 -0
  185. package/dist/client/assets/wardleyDiagram-VM6X3IG4-ree3u-pI.js.gz +0 -0
  186. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-OD1a_9Qg.js → xychartDiagram-S5SC5T6Z-DDono4Wc.js} +1 -1
  187. package/dist/client/assets/xychartDiagram-S5SC5T6Z-DDono4Wc.js.br +0 -0
  188. package/dist/client/assets/xychartDiagram-S5SC5T6Z-DDono4Wc.js.gz +0 -0
  189. package/dist/client/index.html +2 -2
  190. package/dist/client/index.html.br +0 -0
  191. package/dist/client/index.html.gz +0 -0
  192. package/dist/client/sw-downloads.js +40 -0
  193. package/dist/client/sw-downloads.js.br +0 -0
  194. package/dist/client/sw-downloads.js.gz +0 -0
  195. package/dist/client/sw-encrypted-background.js +25 -0
  196. package/dist/client/sw-encrypted-background.js.br +0 -0
  197. package/dist/client/sw-encrypted-background.js.gz +0 -0
  198. package/dist/client/sw-notifications.js +11 -43
  199. package/dist/client/sw-notifications.js.br +0 -0
  200. package/dist/client/sw-notifications.js.gz +0 -0
  201. package/dist/client/sw.js +1 -1
  202. package/dist/client/sw.js.br +0 -0
  203. package/dist/client/sw.js.gz +0 -0
  204. package/dist/server/agent/collaborationCli.js +10 -3
  205. package/dist/server/agent/collaborationDeliveryWorker.js +154 -0
  206. package/dist/server/agent/collaborationRoutes.js +15 -4
  207. package/dist/server/agent/collaborationRouting.js +94 -0
  208. package/dist/server/agent/collaborationStore.js +6 -1
  209. package/dist/server/agent/collaborationTmuxDelivery.js +10 -0
  210. package/dist/server/agent/sessionBindingRecovery.js +80 -0
  211. package/dist/server/cli.js +9 -5
  212. package/dist/server/entry.js +32 -13
  213. package/dist/server/federation/desktopTargets.js +64 -0
  214. package/dist/server/federation/directRoutes.js +27 -19
  215. package/dist/server/federation/requestContext.js +7 -1
  216. package/dist/server/federation/routeAccess.js +14 -7
  217. package/dist/server/federation/runtime.js +5 -3
  218. package/dist/server/federation/trustedCa.js +55 -0
  219. package/dist/server/notifications/pushService.js +3 -0
  220. package/dist/server/routes/notifications.js +4 -0
  221. package/dist/server/routes/terminal.js +235 -78
  222. package/dist/server/utils/publicSecurity.js +1 -1
  223. package/package.json +2 -1
  224. package/runtime-manifest.json +3 -3
  225. package/dist/client/assets/App-CAEtVL8Z.js +0 -150
  226. package/dist/client/assets/App-CAEtVL8Z.js.br +0 -0
  227. package/dist/client/assets/App-CAEtVL8Z.js.gz +0 -0
  228. package/dist/client/assets/ChangeWalkthroughPanel-BNWqAnqc.js.br +0 -0
  229. package/dist/client/assets/ChangeWalkthroughPanel-BNWqAnqc.js.gz +0 -0
  230. package/dist/client/assets/DagPlayground-IlTGwr-I.js.br +0 -0
  231. package/dist/client/assets/DagPlayground-IlTGwr-I.js.gz +0 -0
  232. package/dist/client/assets/DiffLab-CwhNpJvo.js.br +0 -0
  233. package/dist/client/assets/DiffLab-CwhNpJvo.js.gz +0 -0
  234. package/dist/client/assets/DiffReview-DyhINv0F.js.br +0 -0
  235. package/dist/client/assets/DiffReview-DyhINv0F.js.gz +0 -0
  236. package/dist/client/assets/DiffReviewLab-D9Kt5VwB.js.br +0 -0
  237. package/dist/client/assets/DiffReviewLab-D9Kt5VwB.js.gz +0 -0
  238. package/dist/client/assets/DiffViewer-3zz2PI-8.js.br +0 -0
  239. package/dist/client/assets/DiffViewer-3zz2PI-8.js.gz +0 -0
  240. package/dist/client/assets/ModelPreview-CN8xsiGC.js.br +0 -0
  241. package/dist/client/assets/ModelPreview-CN8xsiGC.js.gz +0 -0
  242. package/dist/client/assets/RightSidebar-DQk1cwKH.js +0 -79
  243. package/dist/client/assets/RightSidebar-DQk1cwKH.js.br +0 -0
  244. package/dist/client/assets/RightSidebar-DQk1cwKH.js.gz +0 -0
  245. package/dist/client/assets/abnfDiagram-VCTEODGH-DkdoJ2ZH.js.br +0 -0
  246. package/dist/client/assets/abnfDiagram-VCTEODGH-DkdoJ2ZH.js.gz +0 -0
  247. package/dist/client/assets/app-B42CoF1r.js +0 -34
  248. package/dist/client/assets/app-B42CoF1r.js.br +0 -0
  249. package/dist/client/assets/app-B42CoF1r.js.gz +0 -0
  250. package/dist/client/assets/arc-ctzz5PcK.js.br +0 -0
  251. package/dist/client/assets/arc-ctzz5PcK.js.gz +0 -0
  252. package/dist/client/assets/architectureDiagram-5GKGNRK7-DNLcYfGQ.js.br +0 -0
  253. package/dist/client/assets/architectureDiagram-5GKGNRK7-DNLcYfGQ.js.gz +0 -0
  254. package/dist/client/assets/blockDiagram-I7D4REHJ-Coye1ou5.js.br +0 -0
  255. package/dist/client/assets/blockDiagram-I7D4REHJ-Coye1ou5.js.gz +0 -0
  256. package/dist/client/assets/c4Diagram-7LVT6UL2-DTa8jyPp.js.br +0 -0
  257. package/dist/client/assets/c4Diagram-7LVT6UL2-DTa8jyPp.js.gz +0 -0
  258. package/dist/client/assets/channel-CzvSDv06.js +0 -1
  259. package/dist/client/assets/chunk-F27PBJKO-DWf2gZ96.js.br +0 -0
  260. package/dist/client/assets/chunk-F27PBJKO-DWf2gZ96.js.gz +0 -0
  261. package/dist/client/assets/chunk-IMKFNOWR-l42o_E2c.js.br +0 -0
  262. package/dist/client/assets/chunk-IMKFNOWR-l42o_E2c.js.gz +0 -0
  263. package/dist/client/assets/chunk-SVP7TREG-RORrf2aM.js.br +0 -0
  264. package/dist/client/assets/chunk-SVP7TREG-RORrf2aM.js.gz +0 -0
  265. package/dist/client/assets/chunk-TICWLB2K-hPqafEtC.js.br +0 -0
  266. package/dist/client/assets/chunk-TICWLB2K-hPqafEtC.js.gz +0 -0
  267. package/dist/client/assets/classDiagram-ZZMXUADV-CDknJfE0.js +0 -1
  268. package/dist/client/assets/classDiagram-v2-VYDZK3BY-CDknJfE0.js +0 -1
  269. package/dist/client/assets/cose-bilkent-JH36ORCC-CwRSiQLa.js.br +0 -0
  270. package/dist/client/assets/cynefin-OW5HDTMX-CXnppZ8I.js.br +0 -0
  271. package/dist/client/assets/cynefin-OW5HDTMX-CXnppZ8I.js.gz +0 -0
  272. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-BSDrHSIA.js.br +0 -0
  273. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-BSDrHSIA.js.gz +0 -0
  274. package/dist/client/assets/dagre-GXQ25YYZ-d-5j4vkq.js.br +0 -0
  275. package/dist/client/assets/dagre-GXQ25YYZ-d-5j4vkq.js.gz +0 -0
  276. package/dist/client/assets/diagram-S7CK7UJ4-DizMBpGW.js.br +0 -0
  277. package/dist/client/assets/diagram-S7CK7UJ4-DizMBpGW.js.gz +0 -0
  278. package/dist/client/assets/diagram-UQ7AKVKN-CNQK26rH.js.br +0 -0
  279. package/dist/client/assets/diagram-UQ7AKVKN-CNQK26rH.js.gz +0 -0
  280. package/dist/client/assets/diagram-VSXAHHWV-Dua-2_46.js.br +0 -0
  281. package/dist/client/assets/diagram-VSXAHHWV-Dua-2_46.js.gz +0 -0
  282. package/dist/client/assets/diagram-VX7I27RA-CIq-4729.js.br +0 -0
  283. package/dist/client/assets/diagram-VX7I27RA-CIq-4729.js.gz +0 -0
  284. package/dist/client/assets/diagram-Z3DM3KII-BukQ0u-x.js.br +0 -0
  285. package/dist/client/assets/diagram-Z3DM3KII-BukQ0u-x.js.gz +0 -0
  286. package/dist/client/assets/ebnfDiagram-PWID7BFC-D2zRkRBI.js.br +0 -0
  287. package/dist/client/assets/ebnfDiagram-PWID7BFC-D2zRkRBI.js.gz +0 -0
  288. package/dist/client/assets/erDiagram-RLTQ6QDP-DbX6A3ls.js.gz +0 -0
  289. package/dist/client/assets/flowDiagram-HODETNUW-YECDWA2G.js.br +0 -0
  290. package/dist/client/assets/flowDiagram-HODETNUW-YECDWA2G.js.gz +0 -0
  291. package/dist/client/assets/ganttDiagram-EL5Y4UJY-D3EJdUov.js.br +0 -0
  292. package/dist/client/assets/ganttDiagram-EL5Y4UJY-D3EJdUov.js.gz +0 -0
  293. package/dist/client/assets/gestureArbiter-D3IZpZS7.js.br +0 -0
  294. package/dist/client/assets/gestureArbiter-D3IZpZS7.js.gz +0 -0
  295. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-tr_HKoQK.js.br +0 -0
  296. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-tr_HKoQK.js.gz +0 -0
  297. package/dist/client/assets/index-C4Ny0NDQ.css.br +0 -0
  298. package/dist/client/assets/index-C4Ny0NDQ.css.gz +0 -0
  299. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BrYSZu1R.js.br +0 -0
  300. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BrYSZu1R.js.gz +0 -0
  301. package/dist/client/assets/journeyDiagram-3NMN7TZE-C9Ft--aA.js.br +0 -0
  302. package/dist/client/assets/journeyDiagram-3NMN7TZE-C9Ft--aA.js.gz +0 -0
  303. package/dist/client/assets/kanban-definition-UXKFOSKX-FCxqSu11.js.br +0 -0
  304. package/dist/client/assets/kanban-definition-UXKFOSKX-FCxqSu11.js.gz +0 -0
  305. package/dist/client/assets/layout-BqjIyPqO.js.br +0 -0
  306. package/dist/client/assets/layout-BqjIyPqO.js.gz +0 -0
  307. package/dist/client/assets/linear-CEAGQX5N.js.br +0 -0
  308. package/dist/client/assets/linear-CEAGQX5N.js.gz +0 -0
  309. package/dist/client/assets/mermaid.core-DvAY78t_.js.br +0 -0
  310. package/dist/client/assets/mermaid.core-DvAY78t_.js.gz +0 -0
  311. package/dist/client/assets/mindmap-definition-YA3MSWOX-D7_qIQ9H.js.br +0 -0
  312. package/dist/client/assets/mindmap-definition-YA3MSWOX-D7_qIQ9H.js.gz +0 -0
  313. package/dist/client/assets/passwordBootstrap-Dksfdvk3.js.br +0 -0
  314. package/dist/client/assets/passwordBootstrap-Dksfdvk3.js.gz +0 -0
  315. package/dist/client/assets/pegDiagram-XKGWAZYB-DeTIBKGC.js.br +0 -0
  316. package/dist/client/assets/pegDiagram-XKGWAZYB-DeTIBKGC.js.gz +0 -0
  317. package/dist/client/assets/pieDiagram-E7YTZNPT-z5IcoVwx.js.br +0 -0
  318. package/dist/client/assets/pieDiagram-E7YTZNPT-z5IcoVwx.js.gz +0 -0
  319. package/dist/client/assets/quadrantDiagram-AXDQQJYC-B-zCZvES.js.gz +0 -0
  320. package/dist/client/assets/railroadDiagram-O6MQD6OU-DbpeB7P2.js.br +0 -0
  321. package/dist/client/assets/railroadDiagram-O6MQD6OU-DbpeB7P2.js.gz +0 -0
  322. package/dist/client/assets/referenceLongPress-p56g9xFb.js.br +0 -0
  323. package/dist/client/assets/referenceLongPress-p56g9xFb.js.gz +0 -0
  324. package/dist/client/assets/requirementDiagram-BXWQKSXE-UhJYMJ_U.js.br +0 -0
  325. package/dist/client/assets/requirementDiagram-BXWQKSXE-UhJYMJ_U.js.gz +0 -0
  326. package/dist/client/assets/sankeyDiagram-P5KCCOFB-xKsuFR17.js.br +0 -0
  327. package/dist/client/assets/sankeyDiagram-P5KCCOFB-xKsuFR17.js.gz +0 -0
  328. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DrjBl65C.js.br +0 -0
  329. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DrjBl65C.js.gz +0 -0
  330. package/dist/client/assets/sizeCapture-INFHLROL-BIlGJ9tm.js.br +0 -0
  331. package/dist/client/assets/sizeCapture-INFHLROL-BIlGJ9tm.js.gz +0 -0
  332. package/dist/client/assets/stateDiagram-D77RDMKH-C3k9XvA6.js.br +0 -0
  333. package/dist/client/assets/stateDiagram-D77RDMKH-C3k9XvA6.js.gz +0 -0
  334. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-B7GnCu2o.js +0 -1
  335. package/dist/client/assets/swimlanes-42K2YHIH-BN-x1rXp.js.br +0 -0
  336. package/dist/client/assets/swimlanes-42K2YHIH-BN-x1rXp.js.gz +0 -0
  337. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-BH_gm34Y.js +0 -8
  338. package/dist/client/assets/timeline-definition-24CTP7MA-Dcedjtic.js.br +0 -0
  339. package/dist/client/assets/timeline-definition-24CTP7MA-Dcedjtic.js.gz +0 -0
  340. package/dist/client/assets/vennDiagram-4TSXK5OY-DAIk-5Rt.js.br +0 -0
  341. package/dist/client/assets/vennDiagram-4TSXK5OY-DAIk-5Rt.js.gz +0 -0
  342. package/dist/client/assets/wardleyDiagram-VM6X3IG4-3iXOTpAg.js.br +0 -0
  343. package/dist/client/assets/wardleyDiagram-VM6X3IG4-3iXOTpAg.js.gz +0 -0
  344. package/dist/client/assets/xychartDiagram-S5SC5T6Z-OD1a_9Qg.js.br +0 -0
  345. package/dist/client/assets/xychartDiagram-S5SC5T6Z-OD1a_9Qg.js.gz +0 -0
@@ -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, resolveCollaborationSessionId } 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 终端'),
@@ -1356,17 +1410,7 @@ async function runAgentAutomation(automation, req) {
1356
1410
  }
1357
1411
  }
1358
1412
  function resolveFrontendSessionId(input) {
1359
- const sessionId = typeof input.sessionId === 'string' ? input.sessionId.trim() : '';
1360
- if (sessionId && globalSessionState.sessions.some((record) => record.sessionId === sessionId))
1361
- return sessionId;
1362
- const backendSessionId = typeof input.backendSessionId === 'string' ? input.backendSessionId.trim() : '';
1363
- if (backendSessionId) {
1364
- const resolved = globalSessionState.sessions.find((record) => record.backendSessionId === backendSessionId)?.sessionId;
1365
- if (resolved)
1366
- return resolved;
1367
- }
1368
- const tmuxSessionName = typeof input.tmuxSessionName === 'string' ? input.tmuxSessionName.trim() : '';
1369
- return globalSessionState.sessions.find((record) => record.tmuxSessionName === tmuxSessionName)?.sessionId ?? null;
1413
+ return resolveCollaborationSessionId(input, globalSessionState.sessions, collaborationRouting);
1370
1414
  }
1371
1415
  function collaborationRemoteSessions() {
1372
1416
  return Array.from(new Map(collaborationStore.list().flatMap((group) => group.remoteSessions ?? [])
@@ -1381,45 +1425,154 @@ function tryDeliverCollaborationInbox(frontendSessionId) {
1381
1425
  ? `服务 ${remote.serviceLabel} 不可达:消息尚未送达,仅保存在待发送队列;请勿等待对方已收到的回复,服务重连且 Mac 客户端运行后重试投递。`
1382
1426
  : '跨服务消息尚未确认送达,正在等待 Mac 客户端转发。' };
1383
1427
  }
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,
1428
+ collaborationDeliveryWorker.wake(frontendSessionId);
1429
+ const route = collaborationDeliveryWorker.state(frontendSessionId);
1430
+ return { delivered: [], pending: collaborationStore.pendingCount(frontendSessionId),
1431
+ reason: route.reason ?? '消息已入队,后台正在恢复路由并投递' };
1432
+ }
1433
+ function formatLocalCollaborationMessages(frontendSessionId, messages) {
1434
+ return formatCollaborationDelivery({ targetSessionId: frontendSessionId, messages,
1395
1435
  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
- })],
1436
+ sessions: [...collaborationRemoteSessions(), ...globalSessionState.sessions.map(orchestrationSessionSnapshot)],
1405
1437
  });
1438
+ }
1439
+ async function inspectCollaborationTmux(binding, requestedPane) {
1440
+ if (!binding.tmuxSessionName)
1441
+ return { state: 'offline', reason: 'TMUX_BINDING_MISSING' };
1442
+ const name = `=${binding.tmuxSessionName}`;
1406
1443
  try {
1407
- session.ptyProcess.write(buildBracketedSubmitBytes(prompt));
1444
+ await runTmux(['has-session', '-t', name]);
1408
1445
  }
1409
1446
  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: '终端写入失败,消息已保留并等待重试' };
1447
+ if (/can't find session|no server running|no sessions|error connecting.*No such file/i.test(getErrorMessage(error))) {
1448
+ return { state: 'offline', reason: 'TMUX_SESSION_NOT_RUNNING' };
1449
+ }
1450
+ throw error;
1417
1451
  }
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 };
1452
+ const layout = await getTmuxLayout(binding.tmuxSessionName);
1453
+ if (layout.sessionName !== binding.tmuxSessionName)
1454
+ throw new Error('TMUX_SESSION_IDENTITY_CHANGED');
1455
+ const serverPid = Number((await runTmux(['display-message', '-p', '#{pid}'])).trim());
1456
+ if (!Number.isInteger(serverPid) || serverPid <= 0)
1457
+ throw new Error('TMUX_SERVER_IDENTITY_UNAVAILABLE');
1458
+ const panes = await Promise.all(layout.windows.flatMap((window) => window.panes).map(async (pane) => {
1459
+ const program = await resolveTmuxPaneProgram(pane);
1460
+ const agent = detectAgentFromCommand(program?.rawArgs ?? program?.command ?? '', agentCustomCommands());
1461
+ const nativeSessionId = agent && program?.rawArgs ? inferResumeSessionId(agent, splitCommandToArgv(program.rawArgs)) : null;
1462
+ return { serverPid, sessionId: layout.sessionId, paneId: pane.id, panePid: pane.pid,
1463
+ agentSlug: agent?.slug ?? '', nativeSessionId, cwd: pane.currentPath };
1464
+ }));
1465
+ return selectCollaborationPane(binding, requestedPane ? panes.filter((pane) => pane.paneId === requestedPane) : panes);
1466
+ }
1467
+ async function rebindCollaborationRoute(frontendSessionId, paneId) {
1468
+ await collaborationDeliveryWorker.reconfigure(frontendSessionId, async () => {
1469
+ const record = globalSessionState.sessions.find((candidate) => candidate.sessionId === frontendSessionId);
1470
+ if (!record)
1471
+ throw new Error('SESSION_REMOVED');
1472
+ const previous = collaborationRouting.get(frontendSessionId);
1473
+ const binding = {
1474
+ sessionId: frontendSessionId, backendSessionId: previous?.backendSessionId ?? record.backendSessionId,
1475
+ mode: record.mode, tmuxSessionName: record.tmuxSessionName ?? previous?.tmuxSessionName ?? null,
1476
+ agentSlug: null, nativeSessionId: null, pane: null,
1477
+ };
1478
+ if (binding.mode === 'tmux') {
1479
+ const inspected = await inspectCollaborationTmux(binding, paneId);
1480
+ if (inspected.state !== 'ready' || !inspected.pane)
1481
+ throw new Error(inspected.reason ?? 'AGENT_NOT_RUNNING');
1482
+ const pane = inspected.pane;
1483
+ binding.pane = { serverPid: pane.serverPid, sessionId: pane.sessionId, paneId: pane.paneId, panePid: pane.panePid,
1484
+ agentSlug: pane.agentSlug, nativeSessionId: pane.nativeSessionId };
1485
+ binding.agentSlug = pane.agentSlug;
1486
+ binding.nativeSessionId = pane.nativeSessionId;
1487
+ }
1488
+ else {
1489
+ if (paneId)
1490
+ throw new Error('PANE_REQUIRES_TMUX');
1491
+ const backend = binding.backendSessionId ? terminalSessions.get(binding.backendSessionId) : null;
1492
+ if (!backend)
1493
+ throw new Error('SHELL_BACKEND_NOT_RUNNING');
1494
+ await refreshCollaborationAgentIdentity(binding.backendSessionId, backend);
1495
+ const agent = detectSessionAgent(backend);
1496
+ if (!agent)
1497
+ throw new Error('AGENT_NOT_RUNNING');
1498
+ binding.agentSlug = agent.slug;
1499
+ binding.nativeSessionId = backend.agentSession?.sessionId ?? null;
1500
+ }
1501
+ if (!globalSessionState.sessions.some((candidate) => candidate.sessionId === frontendSessionId))
1502
+ throw new Error('SESSION_REMOVED');
1503
+ collaborationRouting.bind(binding);
1504
+ });
1505
+ collaborationDeliveryWorker.wake(frontendSessionId);
1506
+ return { ...collaborationRouting.get(frontendSessionId), state: 'recovering' };
1507
+ }
1508
+ async function resolveCollaborationRoute(frontendSessionId) {
1509
+ let record = globalSessionState.sessions.find((candidate) => candidate.sessionId === frontendSessionId);
1510
+ if (!record)
1511
+ return { state: 'offline', reason: 'SESSION_REMOVED' };
1512
+ let backend = resolveOrchestrationBackend(record);
1513
+ let binding = collaborationRouting.get(frontendSessionId) ?? {
1514
+ sessionId: record.sessionId, backendSessionId: null, mode: record.mode, tmuxSessionName: record.tmuxSessionName,
1515
+ agentSlug: record.agentResume?.slug ?? null, nativeSessionId: record.agentResume?.sessionId ?? null, pane: null,
1516
+ };
1517
+ if (binding.mode === 'tmux') {
1518
+ const inspected = await inspectCollaborationTmux(binding);
1519
+ if (inspected.state !== 'ready' || !inspected.pane)
1520
+ return inspected;
1521
+ record = globalSessionState.sessions.find((candidate) => candidate.sessionId === frontendSessionId);
1522
+ if (!record)
1523
+ return { state: 'offline', reason: 'SESSION_REMOVED_DURING_RECOVERY' };
1524
+ const pane = inspected.pane;
1525
+ // Remember the target before attachment. A failed attachment must not let
1526
+ // a subsequent active-pane change silently choose another recipient.
1527
+ const pinned = { serverPid: pane.serverPid, sessionId: pane.sessionId, paneId: pane.paneId, panePid: pane.panePid,
1528
+ agentSlug: pane.agentSlug, nativeSessionId: pane.nativeSessionId ?? binding.nativeSessionId };
1529
+ binding = { ...binding, pane: pinned, agentSlug: pinned.agentSlug, nativeSessionId: pinned.nativeSessionId };
1530
+ collaborationRouting.bind(binding);
1531
+ if (!backend) {
1532
+ const cwd = pane.cwd || record.cwd;
1533
+ if (!cwd)
1534
+ return { state: 'detached', reason: 'TMUX_ATTACH_CWD_UNAVAILABLE' };
1535
+ await pathValidator.allowSessionCwd(cwd);
1536
+ // Attach only. Never recreate a vanished session or launch/resume an
1537
+ // Agent in response to a queued collaboration message.
1538
+ const spawned = await spawnTerminalSession({}, { cwd, mode: 'tmux',
1539
+ tmuxSessionName: binding.tmuxSessionName, attachExistingOnly: true, tmuxAttachTarget: pane.sessionId });
1540
+ record = globalSessionState.sessions.find((candidate) => candidate.sessionId === frontendSessionId);
1541
+ if (!record)
1542
+ return { state: 'offline', reason: 'SESSION_REMOVED_DURING_RECOVERY' };
1543
+ if (!terminalSessions.has(spawned.sessionId))
1544
+ return { state: 'detached', reason: 'TMUX_ATTACH_EXITED' };
1545
+ binding = { ...binding, backendSessionId: spawned.sessionId };
1546
+ collaborationRouting.bind(binding);
1547
+ backend = resolveOrchestrationBackend(record);
1548
+ }
1549
+ if (!backend)
1550
+ return { state: 'detached', reason: 'TMUX_BACKEND_UNAVAILABLE' };
1551
+ return { state: 'ready', write: async (messages) => {
1552
+ if (!globalSessionState.sessions.some((candidate) => candidate.sessionId === frontendSessionId))
1553
+ throw new Error('SESSION_REMOVED');
1554
+ await writeCollaborationTmuxPane(runTmux, pinned, formatLocalCollaborationMessages(frontendSessionId, messages));
1555
+ backend.lastActivity = Date.now();
1556
+ } };
1557
+ }
1558
+ if (!backend || !binding.backendSessionId)
1559
+ return { state: 'offline', reason: 'SHELL_BACKEND_NOT_RUNNING' };
1560
+ await refreshCollaborationAgentIdentity(binding.backendSessionId, backend);
1561
+ if (!detectSessionAgent(backend))
1562
+ return { state: 'agent-exited', reason: 'AGENT_NOT_RUNNING' };
1563
+ if ((binding.agentSlug && backend.agent?.slug !== binding.agentSlug)
1564
+ || (binding.nativeSessionId && backend.agentSession?.sessionId && backend.agentSession.sessionId !== binding.nativeSessionId)) {
1565
+ return { state: 'identity-mismatch', reason: 'AGENT_IDENTITY_CHANGED' };
1566
+ }
1567
+ const target = backend;
1568
+ return { state: 'ready', write: async (messages) => {
1569
+ if (!globalSessionState.sessions.some((candidate) => candidate.sessionId === frontendSessionId))
1570
+ throw new Error('SESSION_REMOVED');
1571
+ if (terminalSessions.get(binding.backendSessionId) !== target)
1572
+ throw new Error('SHELL_BACKEND_CHANGED');
1573
+ target.ptyProcess.write(buildBracketedSubmitBytes(formatLocalCollaborationMessages(frontendSessionId, messages)));
1574
+ target.lastActivity = Date.now();
1575
+ } };
1423
1576
  }
1424
1577
  async function refreshCollaborationAgentIdentity(backendSessionId, session) {
1425
1578
  let activeProgram = null;
@@ -1434,33 +1587,12 @@ async function refreshCollaborationAgentIdentity(backendSessionId, session) {
1434
1587
  ? { ...resolved, updatedAt: Date.now() }
1435
1588
  : getActiveProgramFromTmuxLayout(layout);
1436
1589
  }
1437
- if (!activeProgram)
1438
- return;
1439
1590
  session.activeProgram = activeProgram;
1440
- persistActiveProgramBinding(backendSessionId, activeProgram.command);
1591
+ persistActiveProgramBinding(backendSessionId, activeProgram?.command);
1441
1592
  syncAgentIdentity(backendSessionId, session);
1442
1593
  }
1443
1594
  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
- });
1595
+ collaborationDeliveryWorker.wake(frontendSessionId);
1464
1596
  }
1465
1597
  async function spawnCollaborationAgentSession(req, group, sourceSessionId, input) {
1466
1598
  const agentSlug = typeof input.agentSlug === 'string' ? input.agentSlug.trim().toLowerCase() : '';
@@ -4435,7 +4567,22 @@ function ptyHostShellModeEnabled() {
4435
4567
  const isBun = typeof globalThis.Bun !== 'undefined';
4436
4568
  return process.platform !== 'win32' && !isBun && process.env.TERMDOCK_PTY_HOST !== 'off';
4437
4569
  }
4570
+ const tmuxBackendSpawns = new Map();
4438
4571
  async function spawnTerminalSession(req, input) {
4572
+ const name = input.mode === 'tmux' && input.tmuxSessionName ? normalizeTmuxSessionName(input.tmuxSessionName) : null;
4573
+ if (!name)
4574
+ return spawnTerminalSessionUnlocked(req, input);
4575
+ const pending = tmuxBackendSpawns.get(name);
4576
+ if (pending)
4577
+ return pending;
4578
+ const existing = findBackendSessionForTmux(name);
4579
+ if (existing)
4580
+ return { sessionId: existing[0], session: existing[1], cols: existing[1].cols, rows: existing[1].rows };
4581
+ const operation = spawnTerminalSessionUnlocked(req, input).finally(() => tmuxBackendSpawns.delete(name));
4582
+ tmuxBackendSpawns.set(name, operation);
4583
+ return operation;
4584
+ }
4585
+ async function spawnTerminalSessionUnlocked(req, input) {
4439
4586
  const cwd = await resolveWorkingDirectory(req, input.cwd);
4440
4587
  const cols = input.cols || 80;
4441
4588
  const rows = input.rows || 24;
@@ -4446,19 +4593,28 @@ async function spawnTerminalSession(req, input) {
4446
4593
  if (mode === 'tmux') {
4447
4594
  const tmuxStatus = await getTmuxStatus();
4448
4595
  if (!tmuxStatus.available) {
4596
+ if (input.attachExistingOnly)
4597
+ throw new Error('TMUX_UNAVAILABLE');
4449
4598
  console.warn('[termdock] tmux not available, falling back to shell mode:', tmuxStatus.reason);
4450
4599
  mode = 'shell';
4451
4600
  }
4452
4601
  }
4453
4602
  const tmuxSessionName = mode === 'tmux' ? normalizeTmuxSessionName(input.tmuxSessionName) : null;
4454
4603
  if (mode === 'tmux' && tmuxSessionName) {
4455
- await prepareManagedTmuxSession(tmuxSessionName, cwd);
4604
+ if (input.attachExistingOnly) {
4605
+ if (!await tmuxSessionExists(input.tmuxAttachTarget ?? `=${tmuxSessionName}`))
4606
+ throw new Error('TMUX_SESSION_NOT_RUNNING');
4607
+ }
4608
+ else
4609
+ await prepareManagedTmuxSession(tmuxSessionName, cwd);
4456
4610
  }
4457
4611
  const command = mode === 'tmux'
4458
4612
  ? getTmuxBinary()
4459
4613
  : (process.platform === 'win32' ? 'powershell.exe' : resolveShellCandidates()[0]);
4614
+ const supportsFeatures = mode === 'tmux' && await supportsTmuxClientFeatures(command);
4460
4615
  const args = mode === 'tmux' && tmuxSessionName
4461
- ? buildTmuxAttachArgs(tmuxSessionName, await supportsTmuxClientFeatures(command))
4616
+ ? [...buildTmuxAttachArgs(input.tmuxAttachTarget ?? tmuxSessionName, supportsFeatures),
4617
+ ...(input.attachExistingOnly && supportsFeatures ? ['-f', 'ignore-size'] : [])]
4462
4618
  : (process.platform === 'win32' ? buildPowerShellCwdHookArgs() : []);
4463
4619
  const envPath = buildAugmentedPath();
4464
4620
  const resolvedEnv = buildInteractiveColorEnvironment({
@@ -5393,7 +5549,8 @@ router.post('/operations/orchestration/spawn', async (req, res) => {
5393
5549
  res.status(400).json({ error: getErrorMessage(error) });
5394
5550
  }
5395
5551
  });
5396
- router.use('/operations/orchestration', collaborationRoutes({ store: collaborationStore, resolveSession: resolveFrontendSessionId, deliver: tryDeliverCollaborationInbox }));
5552
+ router.use('/operations/orchestration', collaborationRoutes({ store: collaborationStore, resolveSession: resolveFrontendSessionId,
5553
+ deliver: tryDeliverCollaborationInbox, rebind: rebindCollaborationRoute }));
5397
5554
  router.get('/operations/session-search', (req, res) => {
5398
5555
  const query = typeof req.query.q === 'string' ? req.query.q : '';
5399
5556
  const results = sessionSearchStore.search(query, Number(req.query.limit) || 30).map((result) => {
@@ -34,7 +34,7 @@ export const securityHeaders = (req, res, next) => {
34
34
  const shellSource = /^[a-z0-9.\-:\[\]]+$/i.test(host) ? `http://${host}/preview-shell.html https://${host}/preview-shell.html` : "'none'";
35
35
  const shell = req.path === '/preview-shell.html';
36
36
  res.setHeader('Content-Security-Policy', shell
37
- ? "sandbox allow-scripts; default-src 'none'; script-src 'unsafe-inline' blob: https: http:; style-src 'unsafe-inline' blob: https:; img-src blob: data: https:; font-src blob: data: https:; media-src blob: data: https:; connect-src https:; frame-src 'none'; frame-ancestors 'self'; object-src 'none'; base-uri https://termdock-preview.invalid; form-action 'none'"
37
+ ? "sandbox allow-scripts; default-src 'none'; script-src 'unsafe-inline' 'wasm-unsafe-eval' blob: https: http:; style-src 'unsafe-inline' blob: https:; img-src blob: data: https:; font-src blob: data: https:; media-src blob: data: https:; connect-src blob: https: wss:; worker-src blob:; frame-src 'none'; frame-ancestors 'self'; object-src 'none'; base-uri https://termdock-preview.invalid; form-action 'none'"
38
38
  : preview
39
39
  ? "sandbox allow-scripts; frame-ancestors 'self'; object-src 'none'; base-uri 'self'"
40
40
  : `script-src 'self' 'wasm-unsafe-eval'; script-src-attr 'none'; worker-src 'self' blob:; frame-src ${shellSource}; frame-ancestors 'self'; object-src 'none'; base-uri 'self'`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "termdock",
3
- "version": "1.4.178",
3
+ "version": "1.4.180",
4
4
  "description": "A complete web-based terminal application with modern UI",
5
5
  "type": "module",
6
6
  "main": ".desktop-dist/main.js",
@@ -119,6 +119,7 @@
119
119
  "concurrently": "^8.2.0",
120
120
  "cross-env": "^10.1.0",
121
121
  "electron": "^43.2.0",
122
+ "es-module-shims": "^2.8.4",
122
123
  "esbuild": "^0.27.7",
123
124
  "eslint": "^9.39.2",
124
125
  "jsdom": "^24.0.0",
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "packageName": "termdock",
4
- "version": "1.4.178",
4
+ "version": "1.4.180",
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-OJ83J67z97pdLmRW6AEkj8r5LkhdkmNIeAxu2L4niig=",
10
+ "clientBundleHash": "sha256-uS0kVZf+KwoYUsvNs5oQQ2EOdE7L45iUtfuHunLnQ2Q=",
11
11
  "entrypoint": "dist/server/cli.js",
12
12
  "clientEntrypoint": "dist/client/index.html"
13
13
  }