termdock 1.4.321 → 1.4.324

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 (375) hide show
  1. package/dist/client/assets/App-7IUcmCLC.js +186 -0
  2. package/dist/client/assets/App-7IUcmCLC.js.br +0 -0
  3. package/dist/client/assets/App-7IUcmCLC.js.gz +0 -0
  4. package/dist/client/assets/{ArchitecturePanel-BIlIOGx7.js → ArchitecturePanel-CUAB0wFe.js} +6 -6
  5. package/dist/client/assets/ArchitecturePanel-CUAB0wFe.js.br +0 -0
  6. package/dist/client/assets/ArchitecturePanel-CUAB0wFe.js.gz +0 -0
  7. package/dist/client/assets/{ChangeWalkthroughPanel-BtXqyUzD.js → ChangeWalkthroughPanel-CKIG8diY.js} +2 -2
  8. package/dist/client/assets/ChangeWalkthroughPanel-CKIG8diY.js.br +0 -0
  9. package/dist/client/assets/ChangeWalkthroughPanel-CKIG8diY.js.gz +0 -0
  10. package/dist/client/assets/CollaborationMainWorkspace-CIq-JAbF.js +1 -0
  11. package/dist/client/assets/CollaborationMainWorkspace-CIq-JAbF.js.br +0 -0
  12. package/dist/client/assets/CollaborationMainWorkspace-CIq-JAbF.js.gz +0 -0
  13. package/dist/client/assets/CollaborationTaskContent-7vWDzH-d.js +2 -0
  14. package/dist/client/assets/{ComputerControlView-D81udDZO.js → ComputerControlView-CPSI-M86.js} +2 -2
  15. package/dist/client/assets/ComputerControlView-CPSI-M86.js.br +0 -0
  16. package/dist/client/assets/ComputerControlView-CPSI-M86.js.gz +0 -0
  17. package/dist/client/assets/{DagPlayground-B3hTlIFu.js → DagPlayground-BxocNRPm.js} +1 -1
  18. package/dist/client/assets/DagPlayground-BxocNRPm.js.br +0 -0
  19. package/dist/client/assets/DagPlayground-BxocNRPm.js.gz +0 -0
  20. package/dist/client/assets/{DiffLab-C5sDPAZ5.js → DiffLab-COGOFO0s.js} +2 -2
  21. package/dist/client/assets/DiffLab-COGOFO0s.js.br +0 -0
  22. package/dist/client/assets/DiffLab-COGOFO0s.js.gz +0 -0
  23. package/dist/client/assets/{DiffReview-DQFgOJPF.js → DiffReview-5ERdwz1C.js} +1 -1
  24. package/dist/client/assets/DiffReview-5ERdwz1C.js.br +0 -0
  25. package/dist/client/assets/DiffReview-5ERdwz1C.js.gz +0 -0
  26. package/dist/client/assets/{DiffReviewLab-CZvBmujD.js → DiffReviewLab-BSz9IND6.js} +1 -1
  27. package/dist/client/assets/DiffReviewLab-BSz9IND6.js.br +0 -0
  28. package/dist/client/assets/DiffReviewLab-BSz9IND6.js.gz +0 -0
  29. package/dist/client/assets/{DiffViewer-DOvGC9bh.js → DiffViewer-RT-p-ZBo.js} +8 -8
  30. package/dist/client/assets/DiffViewer-RT-p-ZBo.js.br +0 -0
  31. package/dist/client/assets/DiffViewer-RT-p-ZBo.js.gz +0 -0
  32. package/dist/client/assets/{ModelPreview-ClKH4BQ7.js → ModelPreview-DI9anVWA.js} +1 -1
  33. package/dist/client/assets/ModelPreview-DI9anVWA.js.br +0 -0
  34. package/dist/client/assets/ModelPreview-DI9anVWA.js.gz +0 -0
  35. package/dist/client/assets/{RightSidebar-BeegDfBO.js → RightSidebar-DOLn8R7c.js} +36 -36
  36. package/dist/client/assets/RightSidebar-DOLn8R7c.js.br +0 -0
  37. package/dist/client/assets/RightSidebar-DOLn8R7c.js.gz +0 -0
  38. package/dist/client/assets/{abnfDiagram-VCTEODGH-CHUZIHQo.js → abnfDiagram-VCTEODGH-CXd0unH5.js} +1 -1
  39. package/dist/client/assets/abnfDiagram-VCTEODGH-CXd0unH5.js.br +0 -0
  40. package/dist/client/assets/abnfDiagram-VCTEODGH-CXd0unH5.js.gz +0 -0
  41. package/dist/client/assets/app-DCFOZi_L.js +35 -0
  42. package/dist/client/assets/app-DCFOZi_L.js.br +0 -0
  43. package/dist/client/assets/app-DCFOZi_L.js.gz +0 -0
  44. package/dist/client/assets/{arc-CIJEXYV7.js → arc-DCqJmX8M.js} +1 -1
  45. package/dist/client/assets/arc-DCqJmX8M.js.br +0 -0
  46. package/dist/client/assets/arc-DCqJmX8M.js.gz +0 -0
  47. package/dist/client/assets/{architectureDiagram-5GKGNRK7-CcX1UBXG.js → architectureDiagram-5GKGNRK7-DGu_m54H.js} +1 -1
  48. package/dist/client/assets/architectureDiagram-5GKGNRK7-DGu_m54H.js.br +0 -0
  49. package/dist/client/assets/architectureDiagram-5GKGNRK7-DGu_m54H.js.gz +0 -0
  50. package/dist/client/assets/{blockDiagram-I7D4REHJ-gDLrIBDk.js → blockDiagram-I7D4REHJ-BI0gsxDN.js} +1 -1
  51. package/dist/client/assets/blockDiagram-I7D4REHJ-BI0gsxDN.js.br +0 -0
  52. package/dist/client/assets/blockDiagram-I7D4REHJ-BI0gsxDN.js.gz +0 -0
  53. package/dist/client/assets/{c4Diagram-7LVT6UL2-BQA7WLEL.js → c4Diagram-7LVT6UL2-Ct3xzGtD.js} +1 -1
  54. package/dist/client/assets/c4Diagram-7LVT6UL2-Ct3xzGtD.js.br +0 -0
  55. package/dist/client/assets/c4Diagram-7LVT6UL2-Ct3xzGtD.js.gz +0 -0
  56. package/dist/client/assets/channel-BLSCUksA.js +1 -0
  57. package/dist/client/assets/{chunk-2Q5K7J3B-CPCY618J.js → chunk-2Q5K7J3B-BPd2UShA.js} +1 -1
  58. package/dist/client/assets/{chunk-5VM5RSS4-Cc3Czx6A.js → chunk-5VM5RSS4-CoFZ5Fo3.js} +1 -1
  59. package/dist/client/assets/{chunk-F27PBJKO-3scxqZTK.js → chunk-F27PBJKO-C5gZrGp4.js} +1 -1
  60. package/dist/client/assets/chunk-F27PBJKO-C5gZrGp4.js.br +0 -0
  61. package/dist/client/assets/chunk-F27PBJKO-C5gZrGp4.js.gz +0 -0
  62. package/dist/client/assets/{chunk-IMKFNOWR-BOCOE1VY.js → chunk-IMKFNOWR-GW8b9ya-.js} +1 -1
  63. package/dist/client/assets/chunk-IMKFNOWR-GW8b9ya-.js.br +0 -0
  64. package/dist/client/assets/chunk-IMKFNOWR-GW8b9ya-.js.gz +0 -0
  65. package/dist/client/assets/{chunk-JWPE2WC7-DX2Onu68.js → chunk-JWPE2WC7-GpMoViQf.js} +1 -1
  66. package/dist/client/assets/{chunk-POPQ4Y6H-C4MN3QRd.js → chunk-POPQ4Y6H-C_vgVPaw.js} +1 -1
  67. package/dist/client/assets/{chunk-SVP7TREG-DOKo3BNt.js → chunk-SVP7TREG-bA7RXwWn.js} +1 -1
  68. package/dist/client/assets/chunk-SVP7TREG-bA7RXwWn.js.br +0 -0
  69. package/dist/client/assets/chunk-SVP7TREG-bA7RXwWn.js.gz +0 -0
  70. package/dist/client/assets/{chunk-TICWLB2K-CPpFFmO9.js → chunk-TICWLB2K-BG8DAtll.js} +1 -1
  71. package/dist/client/assets/chunk-TICWLB2K-BG8DAtll.js.br +0 -0
  72. package/dist/client/assets/chunk-TICWLB2K-BG8DAtll.js.gz +0 -0
  73. package/dist/client/assets/{chunk-XXDRQBXY-Zp_XOFU2.js → chunk-XXDRQBXY-Ces56sud.js} +1 -1
  74. package/dist/client/assets/classDiagram-ZZMXUADV-DkVIqOvw.js +1 -0
  75. package/dist/client/assets/classDiagram-v2-VYDZK3BY-DkVIqOvw.js +1 -0
  76. package/dist/client/assets/{cose-bilkent-JH36ORCC-iYXdWZMG.js → cose-bilkent-JH36ORCC-Bwch0qL5.js} +1 -1
  77. package/dist/client/assets/cose-bilkent-JH36ORCC-Bwch0qL5.js.br +0 -0
  78. package/dist/client/assets/cose-bilkent-JH36ORCC-Bwch0qL5.js.gz +0 -0
  79. package/dist/client/assets/{cynefin-OW5HDTMX-CXRpxmcA.js → cynefin-OW5HDTMX-CrAXyA2Z.js} +1 -1
  80. package/dist/client/assets/cynefin-OW5HDTMX-CrAXyA2Z.js.br +0 -0
  81. package/dist/client/assets/cynefin-OW5HDTMX-CrAXyA2Z.js.gz +0 -0
  82. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-CH1TQhgO.js → cynefinDiagram-5FMLGOSQ-YlP0Q93l.js} +1 -1
  83. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-YlP0Q93l.js.br +0 -0
  84. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-YlP0Q93l.js.gz +0 -0
  85. package/dist/client/assets/{dagre-GXQ25YYZ-BdshuKJr.js → dagre-GXQ25YYZ-CZ4XcPK9.js} +1 -1
  86. package/dist/client/assets/dagre-GXQ25YYZ-CZ4XcPK9.js.br +0 -0
  87. package/dist/client/assets/dagre-GXQ25YYZ-CZ4XcPK9.js.gz +0 -0
  88. package/dist/client/assets/{diagram-S7CK7UJ4-VbNBimIR.js → diagram-S7CK7UJ4-c_8HfHGA.js} +1 -1
  89. package/dist/client/assets/diagram-S7CK7UJ4-c_8HfHGA.js.br +0 -0
  90. package/dist/client/assets/diagram-S7CK7UJ4-c_8HfHGA.js.gz +0 -0
  91. package/dist/client/assets/{diagram-UQ7AKVKN-D_NUFcq3.js → diagram-UQ7AKVKN-BGtRfxMR.js} +1 -1
  92. package/dist/client/assets/diagram-UQ7AKVKN-BGtRfxMR.js.br +0 -0
  93. package/dist/client/assets/diagram-UQ7AKVKN-BGtRfxMR.js.gz +0 -0
  94. package/dist/client/assets/{diagram-VSXAHHWV-CfYRQ4mq.js → diagram-VSXAHHWV-_9yZnhuv.js} +1 -1
  95. package/dist/client/assets/diagram-VSXAHHWV-_9yZnhuv.js.br +0 -0
  96. package/dist/client/assets/diagram-VSXAHHWV-_9yZnhuv.js.gz +0 -0
  97. package/dist/client/assets/{diagram-VX7I27RA-YHy6vMjY.js → diagram-VX7I27RA-C_mnc4_u.js} +1 -1
  98. package/dist/client/assets/diagram-VX7I27RA-C_mnc4_u.js.br +0 -0
  99. package/dist/client/assets/diagram-VX7I27RA-C_mnc4_u.js.gz +0 -0
  100. package/dist/client/assets/{diagram-Z3DM3KII-DvHqYL0O.js → diagram-Z3DM3KII-sZ_AiSpj.js} +1 -1
  101. package/dist/client/assets/diagram-Z3DM3KII-sZ_AiSpj.js.br +0 -0
  102. package/dist/client/assets/diagram-Z3DM3KII-sZ_AiSpj.js.gz +0 -0
  103. package/dist/client/assets/{ebnfDiagram-PWID7BFC-Bl9bDxAP.js → ebnfDiagram-PWID7BFC-Dm-BXeqS.js} +1 -1
  104. package/dist/client/assets/ebnfDiagram-PWID7BFC-Dm-BXeqS.js.br +0 -0
  105. package/dist/client/assets/ebnfDiagram-PWID7BFC-Dm-BXeqS.js.gz +0 -0
  106. package/dist/client/assets/{erDiagram-RLTQ6QDP-DauNoBZZ.js → erDiagram-RLTQ6QDP-Dz4cBepd.js} +1 -1
  107. package/dist/client/assets/erDiagram-RLTQ6QDP-Dz4cBepd.js.br +0 -0
  108. package/dist/client/assets/erDiagram-RLTQ6QDP-Dz4cBepd.js.gz +0 -0
  109. package/dist/client/assets/{flowDiagram-HODETNUW-D6eDWfJY.js → flowDiagram-HODETNUW-CbRG8-WW.js} +1 -1
  110. package/dist/client/assets/flowDiagram-HODETNUW-CbRG8-WW.js.br +0 -0
  111. package/dist/client/assets/flowDiagram-HODETNUW-CbRG8-WW.js.gz +0 -0
  112. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-CWHSwTR6.js → ganttDiagram-EL5Y4UJY-CmBXWlr0.js} +1 -1
  113. package/dist/client/assets/ganttDiagram-EL5Y4UJY-CmBXWlr0.js.br +0 -0
  114. package/dist/client/assets/ganttDiagram-EL5Y4UJY-CmBXWlr0.js.gz +0 -0
  115. package/dist/client/assets/{gestureArbiter-nU4jhK3S.js → gestureArbiter-B26W6rS7.js} +1 -1
  116. package/dist/client/assets/gestureArbiter-B26W6rS7.js.br +0 -0
  117. package/dist/client/assets/gestureArbiter-B26W6rS7.js.gz +0 -0
  118. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-BHYt5-_X.js → gitGraphDiagram-WWUBYQGX-JW5QMYEk.js} +1 -1
  119. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-JW5QMYEk.js.br +0 -0
  120. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-JW5QMYEk.js.gz +0 -0
  121. package/dist/client/assets/index-Ctz-IDjR.css +1 -0
  122. package/dist/client/assets/index-Ctz-IDjR.css.br +0 -0
  123. package/dist/client/assets/{index-B4bEMUyn.css.gz → index-Ctz-IDjR.css.gz} +0 -0
  124. package/dist/client/assets/{infoDiagram-27XIBGKW-DPmlcUaZ.js → infoDiagram-27XIBGKW-CsA6WdPn.js} +1 -1
  125. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-DAn65XKZ.js → ishikawaDiagram-5VMMS53U-CsKPUwTw.js} +1 -1
  126. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-DAn65XKZ.js.br → ishikawaDiagram-5VMMS53U-CsKPUwTw.js.br} +0 -0
  127. package/dist/client/assets/ishikawaDiagram-5VMMS53U-CsKPUwTw.js.gz +0 -0
  128. package/dist/client/assets/{journeyDiagram-3NMN7TZE-B2c5x9jb.js → journeyDiagram-3NMN7TZE-DpN98gN0.js} +1 -1
  129. package/dist/client/assets/journeyDiagram-3NMN7TZE-DpN98gN0.js.br +0 -0
  130. package/dist/client/assets/journeyDiagram-3NMN7TZE-DpN98gN0.js.gz +0 -0
  131. package/dist/client/assets/{kanban-definition-UXKFOSKX-CMeEp_9r.js → kanban-definition-UXKFOSKX-RHO--43O.js} +1 -1
  132. package/dist/client/assets/kanban-definition-UXKFOSKX-RHO--43O.js.br +0 -0
  133. package/dist/client/assets/kanban-definition-UXKFOSKX-RHO--43O.js.gz +0 -0
  134. package/dist/client/assets/{layout-Db99ysGT.js → layout-Cm_prknW.js} +1 -1
  135. package/dist/client/assets/layout-Cm_prknW.js.br +0 -0
  136. package/dist/client/assets/layout-Cm_prknW.js.gz +0 -0
  137. package/dist/client/assets/{linear-B6mREmTG.js → linear-BVAsPkvS.js} +1 -1
  138. package/dist/client/assets/linear-BVAsPkvS.js.br +0 -0
  139. package/dist/client/assets/linear-BVAsPkvS.js.gz +0 -0
  140. package/dist/client/assets/{mermaid.core-DndzUmju.js → mermaid.core-ufe77Xaz.js} +5 -5
  141. package/dist/client/assets/mermaid.core-ufe77Xaz.js.br +0 -0
  142. package/dist/client/assets/mermaid.core-ufe77Xaz.js.gz +0 -0
  143. package/dist/client/assets/{mindmap-definition-YA3MSWOX-qYAlDvc4.js → mindmap-definition-YA3MSWOX-CRyy1U2d.js} +1 -1
  144. package/dist/client/assets/mindmap-definition-YA3MSWOX-CRyy1U2d.js.br +0 -0
  145. package/dist/client/assets/mindmap-definition-YA3MSWOX-CRyy1U2d.js.gz +0 -0
  146. package/dist/client/assets/passwordBootstrap-3_SIzSH7.js +2 -0
  147. package/dist/client/assets/passwordBootstrap-3_SIzSH7.js.br +0 -0
  148. package/dist/client/assets/passwordBootstrap-3_SIzSH7.js.gz +0 -0
  149. package/dist/client/assets/{pegDiagram-XKGWAZYB-Dg5DCFIn.js → pegDiagram-XKGWAZYB-DSHgdU9q.js} +1 -1
  150. package/dist/client/assets/pegDiagram-XKGWAZYB-DSHgdU9q.js.br +0 -0
  151. package/dist/client/assets/pegDiagram-XKGWAZYB-DSHgdU9q.js.gz +0 -0
  152. package/dist/client/assets/{pieDiagram-E7YTZNPT-dje1AAFI.js → pieDiagram-E7YTZNPT-lIUeAuhN.js} +1 -1
  153. package/dist/client/assets/pieDiagram-E7YTZNPT-lIUeAuhN.js.br +0 -0
  154. package/dist/client/assets/pieDiagram-E7YTZNPT-lIUeAuhN.js.gz +0 -0
  155. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-DLXI6hrS.js → quadrantDiagram-AXDQQJYC-CIgG9vBX.js} +1 -1
  156. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CIgG9vBX.js.br +0 -0
  157. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CIgG9vBX.js.gz +0 -0
  158. package/dist/client/assets/{railroadDiagram-O6MQD6OU-DcY-P8Q_.js → railroadDiagram-O6MQD6OU-DjP8oesA.js} +1 -1
  159. package/dist/client/assets/railroadDiagram-O6MQD6OU-DjP8oesA.js.br +0 -0
  160. package/dist/client/assets/railroadDiagram-O6MQD6OU-DjP8oesA.js.gz +0 -0
  161. package/dist/client/assets/{rdpSession-JkZuPKb3.js → rdpSession-BshIobdj.js} +1 -1
  162. package/dist/client/assets/rdpSession-BshIobdj.js.br +0 -0
  163. package/dist/client/assets/rdpSession-BshIobdj.js.gz +0 -0
  164. package/dist/client/assets/{referenceLongPress-CR3uo3V0.js → referenceLongPress-DBJnfFHa.js} +1 -1
  165. package/dist/client/assets/referenceLongPress-DBJnfFHa.js.br +0 -0
  166. package/dist/client/assets/referenceLongPress-DBJnfFHa.js.gz +0 -0
  167. package/dist/client/assets/{requirementDiagram-BXWQKSXE-B-GLzS7h.js → requirementDiagram-BXWQKSXE-Dbvu6IC_.js} +1 -1
  168. package/dist/client/assets/requirementDiagram-BXWQKSXE-Dbvu6IC_.js.br +0 -0
  169. package/dist/client/assets/requirementDiagram-BXWQKSXE-Dbvu6IC_.js.gz +0 -0
  170. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-CINtGjgu.js → sankeyDiagram-P5KCCOFB-1mZ4s-lv.js} +1 -1
  171. package/dist/client/assets/sankeyDiagram-P5KCCOFB-1mZ4s-lv.js.br +0 -0
  172. package/dist/client/assets/sankeyDiagram-P5KCCOFB-1mZ4s-lv.js.gz +0 -0
  173. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-BRE-_raI.js → sequenceDiagram-WJ2MYXX4-Cu3hhzlV.js} +1 -1
  174. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-Cu3hhzlV.js.br +0 -0
  175. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-Cu3hhzlV.js.gz +0 -0
  176. package/dist/client/assets/{sizeCapture-INFHLROL-v2bGYNk3.js → sizeCapture-INFHLROL-xfm69HlR.js} +1 -1
  177. package/dist/client/assets/sizeCapture-INFHLROL-xfm69HlR.js.br +0 -0
  178. package/dist/client/assets/sizeCapture-INFHLROL-xfm69HlR.js.gz +0 -0
  179. package/dist/client/assets/{sparkles-Dx518Xui.js → sparkles-CDonlwGu.js} +1 -1
  180. package/dist/client/assets/{stateDiagram-D77RDMKH-CIQ1zGkb.js → stateDiagram-D77RDMKH-u-bh6mDK.js} +1 -1
  181. package/dist/client/assets/stateDiagram-D77RDMKH-u-bh6mDK.js.br +0 -0
  182. package/dist/client/assets/stateDiagram-D77RDMKH-u-bh6mDK.js.gz +0 -0
  183. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-BQ_m8Gzd.js +1 -0
  184. package/dist/client/assets/{swimlanes-42K2YHIH-DEjGaJr6.js → swimlanes-42K2YHIH-U8WN__SO.js} +1 -1
  185. package/dist/client/assets/swimlanes-42K2YHIH-U8WN__SO.js.br +0 -0
  186. package/dist/client/assets/swimlanes-42K2YHIH-U8WN__SO.js.gz +0 -0
  187. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-FDEo3QWw.js +8 -0
  188. package/dist/client/assets/{timeline-definition-24CTP7MA-BPbZrudq.js → timeline-definition-24CTP7MA-CMsoNo4F.js} +1 -1
  189. package/dist/client/assets/timeline-definition-24CTP7MA-CMsoNo4F.js.br +0 -0
  190. package/dist/client/assets/timeline-definition-24CTP7MA-CMsoNo4F.js.gz +0 -0
  191. package/dist/client/assets/{triangle-alert-CVm2qdGE.js → triangle-alert-BgErMO2V.js} +1 -1
  192. package/dist/client/assets/{vennDiagram-4TSXK5OY-CAsKNSfN.js → vennDiagram-4TSXK5OY-CPE6pVwh.js} +1 -1
  193. package/dist/client/assets/vennDiagram-4TSXK5OY-CPE6pVwh.js.br +0 -0
  194. package/dist/client/assets/vennDiagram-4TSXK5OY-CPE6pVwh.js.gz +0 -0
  195. package/dist/client/assets/{videoCompression-CCOgxfhm.js → videoCompression-BWkZvEjM.js} +1 -1
  196. package/dist/client/assets/videoCompression-BWkZvEjM.js.br +0 -0
  197. package/dist/client/assets/videoCompression-BWkZvEjM.js.gz +0 -0
  198. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-EeabO9yU.js → wardleyDiagram-VM6X3IG4-4lWd-R4N.js} +1 -1
  199. package/dist/client/assets/wardleyDiagram-VM6X3IG4-4lWd-R4N.js.br +0 -0
  200. package/dist/client/assets/wardleyDiagram-VM6X3IG4-4lWd-R4N.js.gz +0 -0
  201. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-MSUoQl2z.js → xychartDiagram-S5SC5T6Z-CpKJMCWV.js} +1 -1
  202. package/dist/client/assets/xychartDiagram-S5SC5T6Z-CpKJMCWV.js.br +0 -0
  203. package/dist/client/assets/xychartDiagram-S5SC5T6Z-CpKJMCWV.js.gz +0 -0
  204. package/dist/client/index.html +2 -2
  205. package/dist/client/index.html.br +0 -0
  206. package/dist/client/index.html.gz +0 -0
  207. package/dist/client/sw-encrypted-background.js +1 -1
  208. package/dist/client/sw-encrypted-background.js.br +0 -0
  209. package/dist/client/sw-encrypted-background.js.gz +0 -0
  210. package/dist/client/sw.js +1 -1
  211. package/dist/client/sw.js.br +0 -0
  212. package/dist/client/sw.js.gz +0 -0
  213. package/dist/server/agent/collaborationCli.js +5 -1
  214. package/dist/server/agent/collaborationGroupRoutes.js +15 -0
  215. package/dist/server/agent/collaborationRoutes.js +2 -0
  216. package/dist/server/agent/collaborationStore.js +63 -2
  217. package/dist/server/agent/collaborationTaskCli.js +1 -1
  218. package/dist/server/agent/collaborationTaskGuidance.js +2 -0
  219. package/dist/server/agent/collaborationTaskRoutes.js +5 -1
  220. package/dist/server/agent/collaborationTaskStore.js +18 -11
  221. package/dist/server/agent/collaborationTmuxDelivery.js +3 -2
  222. package/dist/server/agent/integrationCli.js +44 -20
  223. package/dist/server/agent/integrationServer.js +20 -1
  224. package/dist/server/agent/promptDelivery.js +2 -2
  225. package/dist/server/agent/sessionLaunchState.js +20 -0
  226. package/dist/server/agent/terminalInput.js +17 -0
  227. package/dist/server/federation/packets.js +179 -28
  228. package/dist/server/federation/requestContext.js +6 -1
  229. package/dist/server/federation/runtime.js +19 -8
  230. package/dist/server/routes/terminal.js +108 -57
  231. package/dist/server/utils/autoUpdate.js +55 -8
  232. package/dist/server/utils/npmUpdate.js +84 -8
  233. package/dist/server/utils/terminalPasteBuffer.js +66 -0
  234. package/dist/server/utils/tmuxClientCapabilities.js +4 -0
  235. package/dist/server/utils/tmuxCopySelection.js +94 -0
  236. package/dist/server/utils/tmuxEmptyServerProbe.js +15 -0
  237. package/docs/integrations.md +85 -0
  238. package/package.json +5 -2
  239. package/runtime-manifest.json +3 -3
  240. package/.desktop-dist/main.js +0 -1989
  241. package/dist/client/assets/App-VAvoVlm2.js +0 -186
  242. package/dist/client/assets/App-VAvoVlm2.js.br +0 -0
  243. package/dist/client/assets/App-VAvoVlm2.js.gz +0 -0
  244. package/dist/client/assets/ArchitecturePanel-BIlIOGx7.js.br +0 -0
  245. package/dist/client/assets/ArchitecturePanel-BIlIOGx7.js.gz +0 -0
  246. package/dist/client/assets/ChangeWalkthroughPanel-BtXqyUzD.js.br +0 -0
  247. package/dist/client/assets/ChangeWalkthroughPanel-BtXqyUzD.js.gz +0 -0
  248. package/dist/client/assets/CollaborationMainWorkspace-DUw3cqW-.js +0 -1
  249. package/dist/client/assets/CollaborationMainWorkspace-DUw3cqW-.js.br +0 -0
  250. package/dist/client/assets/CollaborationMainWorkspace-DUw3cqW-.js.gz +0 -0
  251. package/dist/client/assets/CollaborationTaskContent-C2sQQp6K.js +0 -2
  252. package/dist/client/assets/ComputerControlView-D81udDZO.js.br +0 -0
  253. package/dist/client/assets/ComputerControlView-D81udDZO.js.gz +0 -0
  254. package/dist/client/assets/DagPlayground-B3hTlIFu.js.br +0 -0
  255. package/dist/client/assets/DagPlayground-B3hTlIFu.js.gz +0 -0
  256. package/dist/client/assets/DiffLab-C5sDPAZ5.js.br +0 -0
  257. package/dist/client/assets/DiffLab-C5sDPAZ5.js.gz +0 -0
  258. package/dist/client/assets/DiffReview-DQFgOJPF.js.br +0 -0
  259. package/dist/client/assets/DiffReview-DQFgOJPF.js.gz +0 -0
  260. package/dist/client/assets/DiffReviewLab-CZvBmujD.js.br +0 -0
  261. package/dist/client/assets/DiffReviewLab-CZvBmujD.js.gz +0 -0
  262. package/dist/client/assets/DiffViewer-DOvGC9bh.js.br +0 -0
  263. package/dist/client/assets/DiffViewer-DOvGC9bh.js.gz +0 -0
  264. package/dist/client/assets/ModelPreview-ClKH4BQ7.js.br +0 -0
  265. package/dist/client/assets/ModelPreview-ClKH4BQ7.js.gz +0 -0
  266. package/dist/client/assets/RightSidebar-BeegDfBO.js.br +0 -0
  267. package/dist/client/assets/RightSidebar-BeegDfBO.js.gz +0 -0
  268. package/dist/client/assets/abnfDiagram-VCTEODGH-CHUZIHQo.js.br +0 -0
  269. package/dist/client/assets/abnfDiagram-VCTEODGH-CHUZIHQo.js.gz +0 -0
  270. package/dist/client/assets/app-Bj0N393t.js +0 -35
  271. package/dist/client/assets/app-Bj0N393t.js.br +0 -0
  272. package/dist/client/assets/app-Bj0N393t.js.gz +0 -0
  273. package/dist/client/assets/arc-CIJEXYV7.js.br +0 -0
  274. package/dist/client/assets/arc-CIJEXYV7.js.gz +0 -0
  275. package/dist/client/assets/architectureDiagram-5GKGNRK7-CcX1UBXG.js.br +0 -0
  276. package/dist/client/assets/architectureDiagram-5GKGNRK7-CcX1UBXG.js.gz +0 -0
  277. package/dist/client/assets/blockDiagram-I7D4REHJ-gDLrIBDk.js.br +0 -0
  278. package/dist/client/assets/blockDiagram-I7D4REHJ-gDLrIBDk.js.gz +0 -0
  279. package/dist/client/assets/c4Diagram-7LVT6UL2-BQA7WLEL.js.br +0 -0
  280. package/dist/client/assets/c4Diagram-7LVT6UL2-BQA7WLEL.js.gz +0 -0
  281. package/dist/client/assets/channel-OHMJip5O.js +0 -1
  282. package/dist/client/assets/chunk-F27PBJKO-3scxqZTK.js.br +0 -0
  283. package/dist/client/assets/chunk-F27PBJKO-3scxqZTK.js.gz +0 -0
  284. package/dist/client/assets/chunk-IMKFNOWR-BOCOE1VY.js.br +0 -0
  285. package/dist/client/assets/chunk-IMKFNOWR-BOCOE1VY.js.gz +0 -0
  286. package/dist/client/assets/chunk-SVP7TREG-DOKo3BNt.js.br +0 -0
  287. package/dist/client/assets/chunk-SVP7TREG-DOKo3BNt.js.gz +0 -0
  288. package/dist/client/assets/chunk-TICWLB2K-CPpFFmO9.js.br +0 -0
  289. package/dist/client/assets/chunk-TICWLB2K-CPpFFmO9.js.gz +0 -0
  290. package/dist/client/assets/classDiagram-ZZMXUADV-DwA5mGyC.js +0 -1
  291. package/dist/client/assets/classDiagram-v2-VYDZK3BY-DwA5mGyC.js +0 -1
  292. package/dist/client/assets/cose-bilkent-JH36ORCC-iYXdWZMG.js.br +0 -0
  293. package/dist/client/assets/cose-bilkent-JH36ORCC-iYXdWZMG.js.gz +0 -0
  294. package/dist/client/assets/cynefin-OW5HDTMX-CXRpxmcA.js.br +0 -0
  295. package/dist/client/assets/cynefin-OW5HDTMX-CXRpxmcA.js.gz +0 -0
  296. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CH1TQhgO.js.br +0 -0
  297. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CH1TQhgO.js.gz +0 -0
  298. package/dist/client/assets/dagre-GXQ25YYZ-BdshuKJr.js.br +0 -0
  299. package/dist/client/assets/dagre-GXQ25YYZ-BdshuKJr.js.gz +0 -0
  300. package/dist/client/assets/diagram-S7CK7UJ4-VbNBimIR.js.br +0 -0
  301. package/dist/client/assets/diagram-S7CK7UJ4-VbNBimIR.js.gz +0 -0
  302. package/dist/client/assets/diagram-UQ7AKVKN-D_NUFcq3.js.br +0 -0
  303. package/dist/client/assets/diagram-UQ7AKVKN-D_NUFcq3.js.gz +0 -0
  304. package/dist/client/assets/diagram-VSXAHHWV-CfYRQ4mq.js.br +0 -0
  305. package/dist/client/assets/diagram-VSXAHHWV-CfYRQ4mq.js.gz +0 -0
  306. package/dist/client/assets/diagram-VX7I27RA-YHy6vMjY.js.br +0 -0
  307. package/dist/client/assets/diagram-VX7I27RA-YHy6vMjY.js.gz +0 -0
  308. package/dist/client/assets/diagram-Z3DM3KII-DvHqYL0O.js.br +0 -0
  309. package/dist/client/assets/diagram-Z3DM3KII-DvHqYL0O.js.gz +0 -0
  310. package/dist/client/assets/ebnfDiagram-PWID7BFC-Bl9bDxAP.js.br +0 -0
  311. package/dist/client/assets/ebnfDiagram-PWID7BFC-Bl9bDxAP.js.gz +0 -0
  312. package/dist/client/assets/erDiagram-RLTQ6QDP-DauNoBZZ.js.br +0 -0
  313. package/dist/client/assets/erDiagram-RLTQ6QDP-DauNoBZZ.js.gz +0 -0
  314. package/dist/client/assets/flowDiagram-HODETNUW-D6eDWfJY.js.br +0 -0
  315. package/dist/client/assets/flowDiagram-HODETNUW-D6eDWfJY.js.gz +0 -0
  316. package/dist/client/assets/ganttDiagram-EL5Y4UJY-CWHSwTR6.js.br +0 -0
  317. package/dist/client/assets/ganttDiagram-EL5Y4UJY-CWHSwTR6.js.gz +0 -0
  318. package/dist/client/assets/gestureArbiter-nU4jhK3S.js.br +0 -0
  319. package/dist/client/assets/gestureArbiter-nU4jhK3S.js.gz +0 -0
  320. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BHYt5-_X.js.br +0 -0
  321. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BHYt5-_X.js.gz +0 -0
  322. package/dist/client/assets/index-B4bEMUyn.css +0 -1
  323. package/dist/client/assets/index-B4bEMUyn.css.br +0 -0
  324. package/dist/client/assets/ishikawaDiagram-5VMMS53U-DAn65XKZ.js.gz +0 -0
  325. package/dist/client/assets/journeyDiagram-3NMN7TZE-B2c5x9jb.js.br +0 -0
  326. package/dist/client/assets/journeyDiagram-3NMN7TZE-B2c5x9jb.js.gz +0 -0
  327. package/dist/client/assets/kanban-definition-UXKFOSKX-CMeEp_9r.js.br +0 -0
  328. package/dist/client/assets/kanban-definition-UXKFOSKX-CMeEp_9r.js.gz +0 -0
  329. package/dist/client/assets/layout-Db99ysGT.js.br +0 -0
  330. package/dist/client/assets/layout-Db99ysGT.js.gz +0 -0
  331. package/dist/client/assets/linear-B6mREmTG.js.br +0 -0
  332. package/dist/client/assets/linear-B6mREmTG.js.gz +0 -0
  333. package/dist/client/assets/mermaid.core-DndzUmju.js.br +0 -0
  334. package/dist/client/assets/mermaid.core-DndzUmju.js.gz +0 -0
  335. package/dist/client/assets/mindmap-definition-YA3MSWOX-qYAlDvc4.js.br +0 -0
  336. package/dist/client/assets/mindmap-definition-YA3MSWOX-qYAlDvc4.js.gz +0 -0
  337. package/dist/client/assets/passwordBootstrap-DaJXVcdB.js +0 -2
  338. package/dist/client/assets/passwordBootstrap-DaJXVcdB.js.br +0 -0
  339. package/dist/client/assets/passwordBootstrap-DaJXVcdB.js.gz +0 -0
  340. package/dist/client/assets/pegDiagram-XKGWAZYB-Dg5DCFIn.js.br +0 -0
  341. package/dist/client/assets/pegDiagram-XKGWAZYB-Dg5DCFIn.js.gz +0 -0
  342. package/dist/client/assets/pieDiagram-E7YTZNPT-dje1AAFI.js.br +0 -0
  343. package/dist/client/assets/pieDiagram-E7YTZNPT-dje1AAFI.js.gz +0 -0
  344. package/dist/client/assets/quadrantDiagram-AXDQQJYC-DLXI6hrS.js.br +0 -0
  345. package/dist/client/assets/quadrantDiagram-AXDQQJYC-DLXI6hrS.js.gz +0 -0
  346. package/dist/client/assets/railroadDiagram-O6MQD6OU-DcY-P8Q_.js.br +0 -0
  347. package/dist/client/assets/railroadDiagram-O6MQD6OU-DcY-P8Q_.js.gz +0 -0
  348. package/dist/client/assets/rdpSession-JkZuPKb3.js.br +0 -0
  349. package/dist/client/assets/rdpSession-JkZuPKb3.js.gz +0 -0
  350. package/dist/client/assets/referenceLongPress-CR3uo3V0.js.br +0 -0
  351. package/dist/client/assets/referenceLongPress-CR3uo3V0.js.gz +0 -0
  352. package/dist/client/assets/requirementDiagram-BXWQKSXE-B-GLzS7h.js.br +0 -0
  353. package/dist/client/assets/requirementDiagram-BXWQKSXE-B-GLzS7h.js.gz +0 -0
  354. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CINtGjgu.js.br +0 -0
  355. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CINtGjgu.js.gz +0 -0
  356. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-BRE-_raI.js.br +0 -0
  357. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-BRE-_raI.js.gz +0 -0
  358. package/dist/client/assets/sizeCapture-INFHLROL-v2bGYNk3.js.br +0 -0
  359. package/dist/client/assets/sizeCapture-INFHLROL-v2bGYNk3.js.gz +0 -0
  360. package/dist/client/assets/stateDiagram-D77RDMKH-CIQ1zGkb.js.br +0 -0
  361. package/dist/client/assets/stateDiagram-D77RDMKH-CIQ1zGkb.js.gz +0 -0
  362. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-DCGuhzdh.js +0 -1
  363. package/dist/client/assets/swimlanes-42K2YHIH-DEjGaJr6.js.br +0 -0
  364. package/dist/client/assets/swimlanes-42K2YHIH-DEjGaJr6.js.gz +0 -0
  365. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-Bj14fTzZ.js +0 -8
  366. package/dist/client/assets/timeline-definition-24CTP7MA-BPbZrudq.js.br +0 -0
  367. package/dist/client/assets/timeline-definition-24CTP7MA-BPbZrudq.js.gz +0 -0
  368. package/dist/client/assets/vennDiagram-4TSXK5OY-CAsKNSfN.js.br +0 -0
  369. package/dist/client/assets/vennDiagram-4TSXK5OY-CAsKNSfN.js.gz +0 -0
  370. package/dist/client/assets/videoCompression-CCOgxfhm.js.br +0 -0
  371. package/dist/client/assets/videoCompression-CCOgxfhm.js.gz +0 -0
  372. package/dist/client/assets/wardleyDiagram-VM6X3IG4-EeabO9yU.js.br +0 -0
  373. package/dist/client/assets/wardleyDiagram-VM6X3IG4-EeabO9yU.js.gz +0 -0
  374. package/dist/client/assets/xychartDiagram-S5SC5T6Z-MSUoQl2z.js.br +0 -0
  375. package/dist/client/assets/xychartDiagram-S5SC5T6Z-MSUoQl2z.js.gz +0 -0
@@ -1,3 +1,5 @@
1
+ import { copyTmuxSelection } from '../utils/tmuxCopySelection.js';
2
+ import { isConfirmedEmptyTmuxServer } from '../utils/tmuxEmptyServerProbe.js';
1
3
  import { collaborationSessionDisplayName } from '../utils/sessionDisplayName.js';
2
4
  import { integrationError } from '../agent/integrationStore.js';
3
5
  import { assertNativeResumeAvailable, collectNativeResumeOwnerCandidates } from '../agent/nativeResumeOwner.js';
@@ -14,6 +16,7 @@ import { ensureNodePty } from '../utils/ensureNodePty.js';
14
16
  import { PtySpawnBackoff, PtySpawnDeferredError } from '../utils/ptySpawnBackoff.js';
15
17
  import { collaborationGroupRoutes } from '../agent/collaborationGroupRoutes.js';
16
18
  import { TerminalClientAttachment } from '../utils/terminalClientAttachment.js';
19
+ import { TerminalPasteBuffer } from '../utils/terminalPasteBuffer.js';
17
20
  import { SharedSessionSampler, SharedSnapshotCache } from '../utils/sharedSampling.js';
18
21
  import { batchTmuxOptions, TmuxMetadataWriter } from '../utils/tmuxMetadataWriter.js';
19
22
  import { redrawTmuxClient } from '../utils/tmuxClientRedraw.js';
@@ -51,7 +54,8 @@ import { archiveTaskWorkspace, restoreTaskWorkspace, snapshotTaskWorkspace } fro
51
54
  import { isTmuxRecoveryCandidate } from '../utils/tmuxRecoveryCandidate.js';
52
55
  import { AutomationStore, normalizeAutomationSchedule } from '../agent/automationStore.js';
53
56
  import { writeBracketedPrompt, canDeliverPromptToAgent } from '../agent/promptDelivery.js';
54
- import { captureTerminalInputGuard, waitAndWriteTerminalInput, TerminalInputTargetChangedError } from '../agent/terminalInput.js';
57
+ import { captureTerminalInputGuard, captureRuntimeInputGuard, waitAndWriteTerminalInput } from '../agent/terminalInput.js';
58
+ import { mergeSessionLaunchState } from '../agent/sessionLaunchState.js';
55
59
  import { agentLaunchBlockReason, normalizeAgentLaunchCheck } from '../agent/agentLaunchCheck.js';
56
60
  import { prepareSupervisionEnable } from '../utils/enableSupervision.js';
57
61
  import { buildServerHealthState, dismissServerHealth } from '../utils/serverHealth.js';
@@ -1082,8 +1086,9 @@ async function withInventoryOpenLock(key, task) {
1082
1086
  inventoryOpenLocks.set(key, pending);
1083
1087
  return pending;
1084
1088
  }
1085
- function upsertGlobalSessionRecord(record) {
1086
- const normalized = normalizePersistedClientSession(record);
1089
+ function upsertGlobalSessionRecord(record, launchChange) {
1090
+ const current = globalSessionState.sessions.find(candidate => candidate.sessionId === record.sessionId);
1091
+ const normalized = normalizePersistedClientSession(mergeSessionLaunchState(record, current, launchChange));
1087
1092
  if (!normalized) {
1088
1093
  throw new Error('invalid session record');
1089
1094
  }
@@ -1462,8 +1467,16 @@ async function beginAgentLaunchCheck(frontendSessionId, agentSlug, nativeSession
1462
1467
  if (!record)
1463
1468
  throw new Error('SESSION_REMOVED');
1464
1469
  const id = randomUUID();
1465
- upsertGlobalSessionRecord({ ...record, agentLaunchGeneration: id, agentLaunchCheck: { id, agentSlug, nativeSessionId, deadline: Date.now() + 120_000 } });
1466
- await persistGlobalStateNow();
1470
+ const updated = upsertGlobalSessionRecord(record, { expectedGeneration: record.agentLaunchGeneration ?? null,
1471
+ expectedCheckId: record.agentLaunchCheck?.id ?? null, generation: id,
1472
+ check: { id, agentSlug, nativeSessionId, deadline: Date.now() + 120_000 } });
1473
+ // Capture the guard before persistence yields. The launch command must use
1474
+ // this exact generation, even if another launch occurs during an await.
1475
+ const assertCurrent = terminalInputGuard(updated);
1476
+ assertCurrent('guard_capture');
1477
+ await persistGlobalStateNow(true);
1478
+ assertCurrent('launch_persisted');
1479
+ return assertCurrent;
1467
1480
  }
1468
1481
  async function observeAgentLaunchCheck(record, observed) {
1469
1482
  const check = record.agentLaunchCheck;
@@ -1477,53 +1490,56 @@ async function observeAgentLaunchCheck(record, observed) {
1477
1490
  return { state: 'offline', reason: 'SESSION_REMOVED' };
1478
1491
  if (latest.agentLaunchCheck?.id !== check.id)
1479
1492
  return { state: 'recovering', reason: 'AGENT_LAUNCH_CHANGED' };
1480
- upsertGlobalSessionRecord({ ...latest, agentLaunchCheck: null });
1493
+ upsertGlobalSessionRecord(latest, { expectedGeneration: latest.agentLaunchGeneration ?? null,
1494
+ expectedCheckId: check.id, generation: latest.agentLaunchGeneration ?? null, check: null });
1481
1495
  await persistGlobalStateNow();
1482
1496
  return null;
1483
1497
  }
1484
1498
  function terminalInputGuard(record) {
1485
1499
  const frontendSessionId = record.sessionId;
1486
1500
  const backendSessionId = record.backendSessionId;
1487
- const launchId = record.agentLaunchGeneration ?? null;
1488
- const routeRevision = collaborationRouting.get(frontendSessionId)?.routeRevision ?? null;
1489
- const backend = backendSessionId ? terminalSessions.get(backendSessionId) : undefined;
1490
- return () => {
1501
+ const expected = { backendSessionId, launchId: record.agentLaunchGeneration ?? null,
1502
+ routeRevision: collaborationRouting.get(frontendSessionId)?.routeRevision ?? null,
1503
+ backendInstance: backendSessionId ? terminalSessions.get(backendSessionId) : undefined };
1504
+ return captureRuntimeInputGuard(() => {
1491
1505
  const latest = globalSessionState.sessions.find(candidate => candidate.sessionId === frontendSessionId);
1492
1506
  if (!latest)
1493
1507
  throw new Error('SESSION_REMOVED');
1494
- const instanceMatches = !backendSessionId || terminalSessions.get(backendSessionId) === backend;
1495
- if ((collaborationRouting.get(frontendSessionId)?.routeRevision ?? null) !== routeRevision
1496
- || (latest.agentLaunchGeneration ?? null) !== launchId || latest.backendSessionId !== backendSessionId || !instanceMatches) {
1497
- throw new TerminalInputTargetChangedError({ expected_backend_session_id: backendSessionId, current_backend_session_id: latest.backendSessionId,
1498
- expected_launch_id: launchId, current_launch_id: latest.agentLaunchGeneration ?? null, backend_instance_matches: instanceMatches });
1499
- }
1500
- };
1508
+ return { backendSessionId: latest.backendSessionId, launchId: latest.agentLaunchGeneration ?? null,
1509
+ routeRevision: collaborationRouting.get(frontendSessionId)?.routeRevision ?? null,
1510
+ backendInstance: latest.backendSessionId ? terminalSessions.get(latest.backendSessionId) : undefined };
1511
+ }, expected);
1501
1512
  }
1502
1513
  /** tmux input always uses the pane queue, including automation and launch commands. */
1503
1514
  async function automaticTerminalInput(record, assertCurrent = terminalInputGuard(record), progress) {
1504
- assertCurrent();
1515
+ progress?.('guard_captured');
1516
+ assertCurrent('runtime_resolve');
1517
+ progress?.('runtime_resolving');
1505
1518
  if (record.mode === 'tmux') {
1506
1519
  const binding = collaborationRouting.get(record.sessionId) ?? {
1507
1520
  sessionId: record.sessionId, backendSessionId: record.backendSessionId, mode: record.mode,
1508
1521
  tmuxSessionName: record.tmuxSessionName, agentSlug: null, nativeSessionId: null, pane: null,
1509
1522
  };
1510
1523
  const inspected = await inspectCollaborationTmux(binding, null, true);
1511
- assertCurrent();
1524
+ assertCurrent('runtime_resolved');
1512
1525
  if (inspected.state !== 'ready' || !inspected.pane)
1513
1526
  throw new Error(inspected.reason ?? 'TMUX_PANE_UNAVAILABLE');
1514
1527
  const pane = inspected.pane;
1528
+ progress?.('runtime_resolved');
1515
1529
  return (prompt) => writeCollaborationTmuxPane(runTmux, pane, prompt, runTmuxStdin, assertCurrent, progress);
1516
1530
  }
1517
1531
  const backend = record.backendSessionId ? terminalSessions.get(record.backendSessionId) : null;
1518
1532
  if (!backend)
1519
1533
  throw new Error('SHELL_BACKEND_NOT_RUNNING');
1534
+ assertCurrent('runtime_resolved');
1535
+ progress?.('runtime_resolved');
1520
1536
  return (prompt) => writeBracketedPrompt(backend.ptyProcess, prompt, assertCurrent, progress);
1521
1537
  }
1522
- async function writeAutomaticTerminalPrompt(frontendSessionId, prompt, progress) {
1538
+ async function writeAutomaticTerminalPrompt(frontendSessionId, prompt, progress, launchGuard) {
1523
1539
  const record = globalSessionState.sessions.find(candidate => candidate.sessionId === frontendSessionId);
1524
1540
  if (!record)
1525
1541
  throw new Error('SESSION_REMOVED');
1526
- const write = await automaticTerminalInput(record, terminalInputGuard(record), progress);
1542
+ const write = await automaticTerminalInput(record, launchGuard ?? terminalInputGuard(record), progress);
1527
1543
  await write(prompt);
1528
1544
  }
1529
1545
  async function deliverAutomationPromptWhenReady(backendSessionId, prompt) {
@@ -1580,9 +1596,8 @@ async function runAgentAutomation(automation, req) {
1580
1596
  throw new Error('自动任务会话创建失败');
1581
1597
  if (automation.command) {
1582
1598
  const agent = detectAgentFromCommand(automation.command, agentCustomCommands());
1583
- if (agent)
1584
- await beginAgentLaunchCheck(frontendSessionId, agent.slug);
1585
- await writeAutomaticTerminalPrompt(frontendSessionId, automation.command);
1599
+ const launchGuard = agent ? await beginAgentLaunchCheck(frontendSessionId, agent.slug) : undefined;
1600
+ await writeAutomaticTerminalPrompt(frontendSessionId, automation.command, undefined, launchGuard);
1586
1601
  }
1587
1602
  if (automation.prompt) {
1588
1603
  if (automation.command)
@@ -1970,7 +1985,7 @@ async function spawnCollaborationAgentSession(req, group, sourceSessionId, input
1970
1985
  const backend = terminalSessions.get(opened.terminalSession.sessionId);
1971
1986
  if (!backend)
1972
1987
  throw new HttpStatusError(500, 'Agent Session 创建失败', 'COLLAB_AGENT_SESSION_FAILED');
1973
- await beginAgentLaunchCheck(frontendSessionId, launcher.slug);
1988
+ const launchGuard = await beginAgentLaunchCheck(frontendSessionId, launcher.slug);
1974
1989
  const latestGroup = collaborationStore.getGroup(group.id);
1975
1990
  if (!latestGroup || latestGroup.deleted) {
1976
1991
  const created = globalSessionState.sessions.find(record => record.sessionId === frontendSessionId);
@@ -1993,7 +2008,7 @@ async function spawnCollaborationAgentSession(req, group, sourceSessionId, input
1993
2008
  collaborationStore.setRole({ groupId: group.id, sessionId: frontendSessionId, role: bootstrapRole, creationKey });
1994
2009
  if (profile)
1995
2010
  collaborationStore.setMemberLaunchProfile(group.id, frontendSessionId, profile);
1996
- await writeAutomaticTerminalPrompt(frontendSessionId, buildCollaborationSpawnCommand({ slug: launcher.slug, command: profile?.command ?? launcher.command }));
2011
+ await writeAutomaticTerminalPrompt(frontendSessionId, buildCollaborationSpawnCommand({ slug: launcher.slug, command: profile?.command ?? launcher.command }), undefined, launchGuard);
1997
2012
  const requestedTask = typeof input.task === 'string' ? input.task.trim().slice(0, 20_000) : '';
1998
2013
  collaborationStore.send({
1999
2014
  groupId: updatedGroup.id,
@@ -2423,8 +2438,8 @@ async function launchIntegrationTerminal(record, restoring, prepared, progress,
2423
2438
  backend.agent = null;
2424
2439
  backend.agentResumeRecovered = false;
2425
2440
  progress?.('launch_intent');
2426
- await beginAgentLaunchCheck(record.session_id, record.agent_slug, restoring ? record.agent_native_session_id : null);
2427
- await writeAutomaticTerminalPrompt(record.session_id, integrationLaunchCommand(record, restoring), progress);
2441
+ const launchGuard = await beginAgentLaunchCheck(record.session_id, record.agent_slug, restoring ? record.agent_native_session_id : null);
2442
+ await writeAutomaticTerminalPrompt(record.session_id, integrationLaunchCommand(record, restoring), progress, launchGuard);
2428
2443
  broadcastClientState();
2429
2444
  });
2430
2445
  }
@@ -2471,12 +2486,12 @@ export function prepareCollaborationTaskWorker(task, template, dependencies, ser
2471
2486
  throw error;
2472
2487
  }
2473
2488
  if (!currentAgent && (!launch || launch.backendId !== opened.terminalSession.sessionId)) {
2474
- await beginAgentLaunchCheck(record.sessionId, launcher.slug);
2489
+ const launchGuard = await beginAgentLaunchCheck(record.sessionId, launcher.slug);
2475
2490
  // Persist before typing: a retry must never type the launcher into a newly booted Agent's prompt.
2476
2491
  const temporary = `${launchFile}.${process.pid}.tmp`;
2477
2492
  await fs.promises.writeFile(temporary, JSON.stringify({ sessionId: record.sessionId, backendId: opened.terminalSession.sessionId }), { mode: 0o600 });
2478
2493
  await fs.promises.rename(temporary, launchFile);
2479
- await writeAutomaticTerminalPrompt(opened.session.sessionId, buildCollaborationSpawnCommand({ slug: launcher.slug, command: inheritedProfile?.command ?? launcher.command }));
2494
+ await writeAutomaticTerminalPrompt(opened.session.sessionId, buildCollaborationSpawnCommand({ slug: launcher.slug, command: inheritedProfile?.command ?? launcher.command }), undefined, launchGuard);
2480
2495
  }
2481
2496
  const group = collaborationStore.getGroup(task.groupId);
2482
2497
  if (!group || group.deleted)
@@ -2510,10 +2525,10 @@ function getTmuxBinary() {
2510
2525
  }
2511
2526
  return 'tmux'; // fallback to PATH
2512
2527
  }
2513
- async function runTmux(args) {
2528
+ async function runTmux(args, options) {
2514
2529
  const { stdout } = await execFileAsync(getTmuxBinary(), args, {
2515
2530
  timeout: 5000,
2516
- maxBuffer: 2 * 1024 * 1024,
2531
+ maxBuffer: options?.maxBuffer ?? 2 * 1024 * 1024,
2517
2532
  env: buildInteractiveColorEnvironment(process.env),
2518
2533
  });
2519
2534
  return stdout;
@@ -4672,19 +4687,26 @@ async function resolveTmuxClientTty(sessionName, preferredClientPid) {
4672
4687
  }
4673
4688
  async function ensureTmuxSessionExists(sessionName, cwd) {
4674
4689
  let serverWasMissing = false;
4690
+ let serverIsEmpty = false;
4691
+ let sessionExists = false;
4675
4692
  try {
4676
4693
  await runTmux(['has-session', '-t', sessionName]);
4677
- await ensureTmuxColorEnvironment(sessionName);
4678
- return;
4694
+ sessionExists = true;
4679
4695
  }
4680
4696
  catch (error) {
4681
4697
  const errorMessage = getErrorMessage(error);
4682
4698
  serverWasMissing = isTmuxServerMissingMessage(errorMessage);
4683
4699
  if (!isTmuxSessionMissingMessage(errorMessage)) {
4684
- throw error;
4700
+ serverIsEmpty = await isConfirmedEmptyTmuxServer(error, sessionName, runTmux);
4701
+ if (!serverIsEmpty)
4702
+ throw error;
4685
4703
  }
4686
4704
  }
4687
- if (!serverWasMissing) {
4705
+ if (sessionExists) {
4706
+ await ensureTmuxColorEnvironment(sessionName);
4707
+ return;
4708
+ }
4709
+ if (!serverWasMissing && !serverIsEmpty) {
4688
4710
  await ensureTmuxColorEnvironment();
4689
4711
  }
4690
4712
  const innerTerm = await resolveTmuxInnerTerm();
@@ -6144,8 +6166,8 @@ router.post('/tmux/recovery/restore-all', async (_req, res) => {
6144
6166
  const previous = collaborationRouting.get(frontendSessionId);
6145
6167
  if (previous)
6146
6168
  collaborationRouting.bind({ ...previous, pane: null });
6147
- await beginAgentLaunchCheck(frontendSessionId, agent.slug, target.nativeSessionId);
6148
- await writeAutomaticTerminalPrompt(frontendSessionId, command);
6169
+ const launchGuard = await beginAgentLaunchCheck(frontendSessionId, agent.slug, target.nativeSessionId);
6170
+ await writeAutomaticTerminalPrompt(frontendSessionId, command, undefined, launchGuard);
6149
6171
  }));
6150
6172
  outcomes.push({ sessionId: frontendSessionId, restored: true });
6151
6173
  }
@@ -7098,8 +7120,8 @@ router.post('/operations/execution-archives/:sessionId/restore', executionArchiv
7098
7120
  broadcastClientState();
7099
7121
  throw error;
7100
7122
  }
7101
- await beginAgentLaunchCheck(record.sessionId, target.slug, target.nativeSessionId);
7102
- await writeAutomaticTerminalPrompt(opened.session.sessionId, command);
7123
+ const launchGuard = await beginAgentLaunchCheck(record.sessionId, target.slug, target.nativeSessionId);
7124
+ await writeAutomaticTerminalPrompt(opened.session.sessionId, command, undefined, launchGuard);
7103
7125
  restoreArchivedMembership(entry, record.sessionId);
7104
7126
  await persistGlobalStateNow();
7105
7127
  broadcastClientState();
@@ -8294,7 +8316,10 @@ router.post('/:sessionId/input', express.text({ type: '*/*' }), (req, res) => {
8294
8316
  }
8295
8317
  const data = typeof req.body === 'string' ? req.body : '';
8296
8318
  try {
8297
- session.ptyProcess.write(data);
8319
+ const paste = new TerminalPasteBuffer(() => { });
8320
+ const parts = paste.complete(data);
8321
+ for (const part of parts)
8322
+ session.ptyProcess.write(part);
8298
8323
  session.lastActivity = Date.now();
8299
8324
  res.json({ success: true });
8300
8325
  }
@@ -8343,10 +8368,9 @@ router.post('/:sessionId/agent-resume', async (req, res) => {
8343
8368
  try {
8344
8369
  const frontend = globalSessionState.sessions.find(candidate => candidate.backendSessionId === sessionId);
8345
8370
  const launch = async () => {
8371
+ const launchGuard = frontend ? await beginAgentLaunchCheck(frontend.sessionId, target.slug, target.nativeSessionId) : undefined;
8346
8372
  if (frontend)
8347
- await beginAgentLaunchCheck(frontend.sessionId, target.slug, target.nativeSessionId);
8348
- if (frontend)
8349
- await writeAutomaticTerminalPrompt(frontend.sessionId, target.command);
8373
+ await writeAutomaticTerminalPrompt(frontend.sessionId, target.command, undefined, launchGuard);
8350
8374
  else
8351
8375
  await writeBracketedPrompt(session.ptyProcess, target.command, captureTerminalInputGuard(() => terminalSessions.get(sessionId), session));
8352
8376
  };
@@ -8464,7 +8488,7 @@ router.post('/:sessionId/tmux', async (req, res) => {
8464
8488
  broadcastEvent(sessionId, { type: 'tmux-layout', layout });
8465
8489
  return res.json({ success: true, layout });
8466
8490
  }
8467
- return res.json({ success: true });
8491
+ return res.json({ success: true, ...(result.selection ? { selection: result.selection } : {}) });
8468
8492
  }
8469
8493
  catch (error) {
8470
8494
  const errorMessage = getErrorMessage(error);
@@ -8559,6 +8583,10 @@ router.post('/force-kill', (req, res) => {
8559
8583
  async function executeTmuxAction(tmuxTarget, action, body, control) {
8560
8584
  let shouldBroadcastLayout = true;
8561
8585
  switch (action) {
8586
+ case 'copy-selection': {
8587
+ const selection = await copyTmuxSelection(tmuxTarget, runTmux);
8588
+ return { shouldBroadcastLayout: false, selection };
8589
+ }
8562
8590
  case 'select-pane': {
8563
8591
  const paneId = typeof body.paneId === 'string' ? body.paneId : '';
8564
8592
  if (!paneId)
@@ -8949,6 +8977,12 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}, i
8949
8977
  if (ws.readyState === ws.OPEN)
8950
8978
  ws.send(JSON.stringify(event));
8951
8979
  });
8980
+ const pasteInput = new TerminalPasteBuffer(error => {
8981
+ if (ws.readyState === ws.OPEN) {
8982
+ ws.send(JSON.stringify({ type: 'error', error }));
8983
+ ws.close(1008, 'Incomplete terminal paste');
8984
+ }
8985
+ });
8952
8986
  // Handle client → server messages
8953
8987
  ws.on('message', async (raw) => {
8954
8988
  const messageReceivedAt = performance.now();
@@ -8963,20 +8997,30 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}, i
8963
8997
  switch (msg.type) {
8964
8998
  case 'input': {
8965
8999
  if (typeof msg.data === 'string' && msg.data.length > 0) {
8966
- const data = msg.data;
8967
- if (attachment) {
8968
- session.lastActivity = Date.now();
8969
- attachment.write(data);
9000
+ let parts;
9001
+ try {
9002
+ parts = pasteInput.push(msg.data);
8970
9003
  }
8971
- else if (session.mode === 'tmux') {
8972
- await enqueueTmuxIo(session, async () => {
9004
+ catch (error) {
9005
+ ws.send(JSON.stringify({ type: 'error', error: getErrorMessage(error) }));
9006
+ ws.close(1008, 'Invalid terminal paste');
9007
+ return;
9008
+ }
9009
+ for (const data of parts) {
9010
+ if (attachment) {
9011
+ session.lastActivity = Date.now();
9012
+ attachment.write(data);
9013
+ }
9014
+ else if (session.mode === 'tmux') {
9015
+ await enqueueTmuxIo(session, async () => {
9016
+ session.lastActivity = Date.now();
9017
+ session.ptyProcess.write(data);
9018
+ });
9019
+ }
9020
+ else {
8973
9021
  session.lastActivity = Date.now();
8974
9022
  session.ptyProcess.write(data);
8975
- });
8976
- }
8977
- else {
8978
- session.lastActivity = Date.now();
8979
- session.ptyProcess.write(data);
9023
+ }
8980
9024
  }
8981
9025
  }
8982
9026
  break;
@@ -9044,8 +9088,14 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}, i
9044
9088
  }
9045
9089
  const result = await enqueueTmuxIo(session, async () => {
9046
9090
  return executeTmuxAction(session.tmuxSessionName, msg.action, msg, session.tmuxControl);
9091
+ }).catch((error) => {
9092
+ // A correlated copy failure must settle this socket's request, not
9093
+ // become an unrelated terminal error followed by a 30-second wait.
9094
+ if (msg.action !== 'copy-selection')
9095
+ throw error;
9096
+ return { shouldBroadcastLayout: false, error: getErrorMessage(error) || 'Tmux selection copy failed' };
9047
9097
  });
9048
- ws.send(JSON.stringify({ type: 'tmux-result', reqId, success: !result.error, error: result.error }));
9098
+ ws.send(JSON.stringify({ type: 'tmux-result', reqId, success: !result.error, error: result.error, ...(result.selection ? { selection: result.selection } : {}) }));
9049
9099
  if (result.shouldBroadcastLayout && session.tmuxSessionName) {
9050
9100
  try {
9051
9101
  const layout = await getTmuxLayout(session.tmuxSessionName);
@@ -9143,6 +9193,7 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}, i
9143
9193
  });
9144
9194
  // Cleanup on close
9145
9195
  ws.on('close', () => {
9196
+ pasteInput.clear();
9146
9197
  initialScreen?.cancel();
9147
9198
  initialScreen = null;
9148
9199
  attachment?.close();
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { compareVersions, updateTermdockFromOfficialRegistry, } from './npmUpdate.js';
3
+ import { compareVersions, verifyRunningTermdockInstallation, updateTermdockFromOfficialRegistry, } from './npmUpdate.js';
4
4
  export const AUTO_UPDATE_INITIAL_DELAY_MS = 15_000;
5
5
  export const AUTO_UPDATE_INTERVAL_MS = 6 * 60 * 60 * 1_000;
6
6
  function initialState(currentVersion) {
@@ -44,11 +44,11 @@ export class TermdockAutoUpdateManager {
44
44
  return;
45
45
  this.initialTimer = setTimeout(() => {
46
46
  this.initialTimer = null;
47
- void this.checkNow();
47
+ void this.checkNow(false);
48
48
  }, AUTO_UPDATE_INITIAL_DELAY_MS);
49
49
  this.initialTimer.unref?.();
50
50
  this.intervalTimer = setInterval(() => {
51
- void this.checkNow();
51
+ void this.checkNow(false);
52
52
  }, AUTO_UPDATE_INTERVAL_MS);
53
53
  this.intervalTimer.unref?.();
54
54
  }
@@ -60,12 +60,24 @@ export class TermdockAutoUpdateManager {
60
60
  this.initialTimer = null;
61
61
  this.intervalTimer = null;
62
62
  }
63
- checkNow() {
63
+ checkNow(explicit = true) {
64
+ // Failed installation validation requires a user-requested check, not a timer retry.
65
+ if (!explicit && this.state.status === 'error' && hasPendingTermdockUpdate(this.state))
66
+ return Promise.resolve(this.getState());
64
67
  // Once an installed update is waiting for explicit confirmation, periodic
65
68
  // checks must never turn any external state change into implicit consent.
66
69
  // Keep the reminder until the user confirms or restarts manually.
67
70
  if (this.state.status === 'ready' && hasPendingTermdockUpdate(this.state)) {
68
- return Promise.resolve(this.getState());
71
+ try {
72
+ this.verifyInstalled(this.state.latestVersion);
73
+ return Promise.resolve(this.getState());
74
+ }
75
+ catch (error) {
76
+ this.installationError(error);
77
+ if (!explicit)
78
+ return Promise.resolve(this.getState());
79
+ }
80
+ // Only the explicit check repairs an invalid pending installation; never restart here.
69
81
  }
70
82
  if (this.checkPromise)
71
83
  return this.checkPromise;
@@ -78,10 +90,33 @@ export class TermdockAutoUpdateManager {
78
90
  if (this.state.status !== 'ready' || !hasPendingTermdockUpdate(this.state)) {
79
91
  throw new Error('No installed Termdock update is waiting for restart.');
80
92
  }
93
+ try {
94
+ this.verifyInstalled(this.state.latestVersion);
95
+ if (process.env.TERMDOCK_SUPERVISED !== '1' || !process.connected)
96
+ throw new Error('Automatic restart requires the verified supervised Termdock entry; restart manually.');
97
+ this.dependencies.verifyRestartEntry?.();
98
+ }
99
+ catch (error) {
100
+ this.installationError(error);
101
+ throw error;
102
+ }
81
103
  this.setState({ ...this.state, status: 'restarting', error: null });
82
- this.dependencies.requestRestart();
104
+ try {
105
+ this.dependencies.requestRestart();
106
+ }
107
+ catch (error) {
108
+ this.installationError(error);
109
+ throw error;
110
+ }
83
111
  return this.getState();
84
112
  }
113
+ verifyInstalled(version) {
114
+ (this.dependencies.verifyInstalled ?? verifyRunningTermdockInstallation)(version);
115
+ }
116
+ installationError(error) {
117
+ const detail = error instanceof Error ? error.message : String(error);
118
+ this.setState({ ...this.state, status: 'error', error: detail });
119
+ }
85
120
  async runCheck() {
86
121
  this.setState({ ...this.state, status: 'checking', checkedAt: Date.now(), error: null });
87
122
  try {
@@ -110,6 +145,7 @@ export class TermdockAutoUpdateManager {
110
145
  });
111
146
  return this.getState();
112
147
  }
148
+ this.verifyInstalled(result.latestVersion);
113
149
  this.setState({
114
150
  status: 'ready',
115
151
  currentVersion: result.currentVersion,
@@ -145,13 +181,24 @@ export class TermdockAutoUpdateManager {
145
181
  return fallback;
146
182
  if (value.status !== 'ready' && value.status !== 'restarting' && value.status !== 'error')
147
183
  return fallback;
184
+ let restoredStatus = value.status === 'restarting' ? 'ready' : value.status;
185
+ let restoredError = typeof value.error === 'string' ? value.error : null;
186
+ if (restoredStatus === 'ready') {
187
+ try {
188
+ this.verifyInstalled(value.latestVersion);
189
+ }
190
+ catch (error) {
191
+ restoredStatus = 'error';
192
+ restoredError = error instanceof Error ? error.message : String(error);
193
+ }
194
+ }
148
195
  return {
149
- status: value.status === 'restarting' ? 'ready' : value.status,
196
+ status: restoredStatus,
150
197
  currentVersion: this.dependencies.currentVersion,
151
198
  latestVersion: value.latestVersion,
152
199
  source: value.source === 'configured' ? 'configured' : 'official',
153
200
  checkedAt: typeof value.checkedAt === 'number' ? value.checkedAt : null,
154
- error: typeof value.error === 'string' ? value.error : null,
201
+ error: restoredError,
155
202
  };
156
203
  }
157
204
  catch {
@@ -1,5 +1,8 @@
1
1
  import { execFile, spawn } from 'node:child_process';
2
2
  import { promisify } from 'node:util';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
3
6
  const execFileAsync = promisify(execFile);
4
7
  export const OFFICIAL_NPM_REGISTRY = 'https://registry.npmjs.org';
5
8
  const TERMDOCK_PACKAGE = 'termdock';
@@ -41,7 +44,7 @@ export function buildNpmViewArgs(registry = OFFICIAL_NPM_REGISTRY) {
41
44
  args.push('--registry', registry);
42
45
  return args;
43
46
  }
44
- export function buildNpmInstallArgs(version, registry = OFFICIAL_NPM_REGISTRY) {
47
+ export function buildNpmInstallArgs(version, registry = OFFICIAL_NPM_REGISTRY, prefix) {
45
48
  if (!parseVersion(version))
46
49
  throw new Error(`Invalid Termdock version from npm: ${version}`);
47
50
  const args = [
@@ -49,11 +52,56 @@ export function buildNpmInstallArgs(version, registry = OFFICIAL_NPM_REGISTRY) {
49
52
  '--global',
50
53
  `${TERMDOCK_PACKAGE}@${version}`,
51
54
  ];
55
+ if (prefix)
56
+ args.push('--prefix', prefix);
52
57
  if (registry)
53
58
  args.push('--registry', registry);
54
59
  args.push('--foreground-scripts');
55
60
  return args;
56
61
  }
62
+ function installedVersion(installation) {
63
+ // Fresh filesystem reads: npm replaces this package while this process keeps
64
+ // running old JS. Neither require/import caches nor TERMDOCK_VERSION attest it.
65
+ if (fs.realpathSync(installation.packageRoot) !== installation.packageRoot) {
66
+ throw new Error('Running Termdock installation changed location; check for updates again.');
67
+ }
68
+ const value = JSON.parse(fs.readFileSync(path.join(installation.packageRoot, 'package.json'), 'utf8'));
69
+ if (!value || typeof value !== 'object' || !('name' in value) || value.name !== TERMDOCK_PACKAGE
70
+ || !('version' in value) || typeof value.version !== 'string' || !parseVersion(value.version)) {
71
+ throw new Error('Running Termdock installation has invalid package metadata.');
72
+ }
73
+ return value.version;
74
+ }
75
+ /** Resolve the module which is actually running, never PATH's unrelated npm root. */
76
+ export function resolveRunningTermdockInstallation(moduleUrl = import.meta.url, runningEntry = process.argv[1]) {
77
+ const moduleFile = fs.realpathSync(fileURLToPath(moduleUrl));
78
+ const packageRoot = path.resolve(path.dirname(moduleFile), '../../..');
79
+ const nodeModules = path.dirname(packageRoot);
80
+ if (path.basename(packageRoot) !== TERMDOCK_PACKAGE || path.basename(nodeModules) !== 'node_modules') {
81
+ throw new Error('Automatic updates require a supported global Termdock installation.');
82
+ }
83
+ const parent = path.dirname(nodeModules);
84
+ let prefix;
85
+ if (process.platform === 'win32')
86
+ prefix = parent;
87
+ else if (path.basename(parent) === 'lib')
88
+ prefix = path.dirname(parent);
89
+ else
90
+ throw new Error('Automatic updates require a supported global Termdock installation.');
91
+ const installation = { packageRoot, prefix };
92
+ // supervisor resolves and reuses this child's argv entry. A module loaded
93
+ // from another installation must never approve that different restart root.
94
+ if (!runningEntry || fs.realpathSync(runningEntry) !== path.join(packageRoot, 'dist/server/cli.js')) {
95
+ throw new Error('Running Termdock entry does not match its update installation.');
96
+ }
97
+ installedVersion(installation);
98
+ return installation;
99
+ }
100
+ export function verifyRunningTermdockInstallation(version, installation = resolveRunningTermdockInstallation()) {
101
+ if (compareVersions(installedVersion(installation), version) < 0) {
102
+ throw new Error('Running Termdock installation has not completed this update; check for updates again.');
103
+ }
104
+ }
57
105
  export function parseNpmVersionOutput(output) {
58
106
  let value;
59
107
  try {
@@ -67,6 +115,26 @@ export function parseNpmVersionOutput(output) {
67
115
  }
68
116
  return value;
69
117
  }
118
+ export function npmRuntimeEnvironment(execPath = process.execPath, env = process.env, platform = process.platform) {
119
+ const systemBins = platform === 'darwin' ? ['/opt/homebrew/bin', '/usr/local/bin'] : [];
120
+ return { ...env, PATH: [path.dirname(execPath), ...systemBins, env.PATH].filter(Boolean).join(path.delimiter) };
121
+ }
122
+ async function installEnvironment() {
123
+ const env = npmRuntimeEnvironment();
124
+ if (process.platform === 'darwin') {
125
+ // New CLT releases can leave node-gyp's implicit libc++ search path stale.
126
+ // Use the SDK selected by xcrun without changing the user's global setup.
127
+ const { stdout } = await execFileAsync('/usr/bin/xcrun', ['--show-sdk-path'], { timeout: 5000, env });
128
+ const sdk = stdout.trim();
129
+ const headers = path.join(sdk, 'usr/include/c++/v1');
130
+ if (!path.isAbsolute(sdk) || !fs.existsSync(path.join(headers, 'functional'))) {
131
+ throw new Error('macOS C++ SDK headers are unavailable. Install or repair Command Line Tools, then retry.');
132
+ }
133
+ env.SDKROOT = sdk;
134
+ env.CPLUS_INCLUDE_PATH = [headers, env.CPLUS_INCLUDE_PATH].filter(Boolean).join(path.delimiter);
135
+ }
136
+ return env;
137
+ }
70
138
  function npmExecutable() {
71
139
  return process.platform === 'win32' ? 'npm.cmd' : 'npm';
72
140
  }
@@ -76,7 +144,7 @@ async function fetchLatestVersion(registry) {
76
144
  const result = await execFileAsync(npmExecutable(), buildNpmViewArgs(registry), {
77
145
  timeout: NPM_QUERY_TIMEOUT_MS,
78
146
  maxBuffer: 256 * 1024,
79
- env: process.env,
147
+ env: npmRuntimeEnvironment(),
80
148
  });
81
149
  stdout = result.stdout;
82
150
  }
@@ -87,11 +155,15 @@ async function fetchLatestVersion(registry) {
87
155
  }
88
156
  return parseNpmVersionOutput(stdout);
89
157
  }
90
- function installVersion(version, registry) {
91
- return new Promise((resolve, reject) => {
92
- const child = spawn(npmExecutable(), buildNpmInstallArgs(version, registry), {
158
+ export async function installTermdockVersion(version, registry, installation, executable = npmExecutable()) {
159
+ if (compareVersions(installedVersion(installation), version) > 0) {
160
+ throw new Error('Running Termdock location already contains a newer version; restart that installation manually.');
161
+ }
162
+ const env = await installEnvironment();
163
+ await new Promise((resolve, reject) => {
164
+ const child = spawn(executable, buildNpmInstallArgs(version, registry, installation.prefix), {
93
165
  stdio: 'inherit',
94
- env: process.env,
166
+ env,
95
167
  });
96
168
  child.once('error', reject);
97
169
  child.once('exit', (code, signal) => {
@@ -103,6 +175,9 @@ function installVersion(version, registry) {
103
175
  reject(new Error(`npm failed to install Termdock (${reason}).`));
104
176
  });
105
177
  });
178
+ if (installedVersion(installation) !== version) {
179
+ throw new Error('npm did not install the requested version at the running Termdock location.');
180
+ }
106
181
  }
107
182
  export async function updateTermdockFromOfficialRegistry(currentVersion, onFallback, onLatest) {
108
183
  if (!parseVersion(currentVersion))
@@ -124,8 +199,9 @@ export async function updateTermdockFromOfficialRegistry(currentVersion, onFallb
124
199
  return { status: 'current', currentVersion, latestVersion, source };
125
200
  if (comparison > 0)
126
201
  return { status: 'newer-than-registry', currentVersion, latestVersion, source };
202
+ const installation = resolveRunningTermdockInstallation();
127
203
  try {
128
- await installVersion(latestVersion, source === 'official' ? OFFICIAL_NPM_REGISTRY : null);
204
+ await installTermdockVersion(latestVersion, source === 'official' ? OFFICIAL_NPM_REGISTRY : null, installation);
129
205
  }
130
206
  catch (error) {
131
207
  if (source === 'configured')
@@ -133,7 +209,7 @@ export async function updateTermdockFromOfficialRegistry(currentVersion, onFallb
133
209
  const cause = error instanceof Error ? error : new Error(String(error));
134
210
  onFallback?.('install', cause);
135
211
  source = 'configured';
136
- await installVersion(latestVersion, null);
212
+ await installTermdockVersion(latestVersion, null, installation);
137
213
  }
138
214
  return { status: 'updated', currentVersion, latestVersion, source };
139
215
  }