termdock 1.4.326 → 1.4.328

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 (350) hide show
  1. package/dist/client/assets/{App-DrnLToMO.js → App-xr2R4dST.js} +6 -6
  2. package/dist/client/assets/App-xr2R4dST.js.br +0 -0
  3. package/dist/client/assets/App-xr2R4dST.js.gz +0 -0
  4. package/dist/client/assets/{ArchitecturePanel-CGjioSu0.js → ArchitecturePanel-XprzcGMT.js} +2 -2
  5. package/dist/client/assets/ArchitecturePanel-XprzcGMT.js.br +0 -0
  6. package/dist/client/assets/ArchitecturePanel-XprzcGMT.js.gz +0 -0
  7. package/dist/client/assets/{ChangeWalkthroughPanel-BsG5tR4F.js → ChangeWalkthroughPanel-g83lCwJi.js} +1 -1
  8. package/dist/client/assets/ChangeWalkthroughPanel-g83lCwJi.js.br +0 -0
  9. package/dist/client/assets/ChangeWalkthroughPanel-g83lCwJi.js.gz +0 -0
  10. package/dist/client/assets/{CollaborationMainWorkspace-KMTTUtsp.js → CollaborationMainWorkspace-BbkFTnw1.js} +1 -1
  11. package/dist/client/assets/CollaborationMainWorkspace-BbkFTnw1.js.br +0 -0
  12. package/dist/client/assets/CollaborationMainWorkspace-BbkFTnw1.js.gz +0 -0
  13. package/dist/client/assets/CollaborationTaskContent-C8Nrrlcz.js +2 -0
  14. package/dist/client/assets/ComputerControlView-yBUQcmwF.js +6 -0
  15. package/dist/client/assets/ComputerControlView-yBUQcmwF.js.br +0 -0
  16. package/dist/client/assets/ComputerControlView-yBUQcmwF.js.gz +0 -0
  17. package/dist/client/assets/{DagPlayground-761ejCr8.js → DagPlayground--KDWJkVL.js} +1 -1
  18. package/dist/client/assets/DagPlayground--KDWJkVL.js.br +0 -0
  19. package/dist/client/assets/DagPlayground--KDWJkVL.js.gz +0 -0
  20. package/dist/client/assets/{DiffLab-yWG9ju3P.js → DiffLab-BAyGlKKp.js} +1 -1
  21. package/dist/client/assets/DiffLab-BAyGlKKp.js.br +0 -0
  22. package/dist/client/assets/DiffLab-BAyGlKKp.js.gz +0 -0
  23. package/dist/client/assets/{DiffReview-02640ofg.js → DiffReview-CLKpyDPZ.js} +1 -1
  24. package/dist/client/assets/DiffReview-CLKpyDPZ.js.br +0 -0
  25. package/dist/client/assets/DiffReview-CLKpyDPZ.js.gz +0 -0
  26. package/dist/client/assets/{DiffReviewLab-D0W0SEIG.js → DiffReviewLab-BoFElesI.js} +1 -1
  27. package/dist/client/assets/DiffReviewLab-BoFElesI.js.br +0 -0
  28. package/dist/client/assets/DiffReviewLab-BoFElesI.js.gz +0 -0
  29. package/dist/client/assets/{DiffViewer-CLjrE1oE.js → DiffViewer-DDiASWHf.js} +1 -1
  30. package/dist/client/assets/DiffViewer-DDiASWHf.js.br +0 -0
  31. package/dist/client/assets/{DiffViewer-CLjrE1oE.js.gz → DiffViewer-DDiASWHf.js.gz} +0 -0
  32. package/dist/client/assets/{ModelPreview-BnIvn0Fn.js → ModelPreview-PJWJT35T.js} +1 -1
  33. package/dist/client/assets/ModelPreview-PJWJT35T.js.br +0 -0
  34. package/dist/client/assets/{ModelPreview-BnIvn0Fn.js.gz → ModelPreview-PJWJT35T.js.gz} +0 -0
  35. package/dist/client/assets/{RightSidebar-Dx4Jf94o.js → RightSidebar-CfOJHcXO.js} +3 -3
  36. package/dist/client/assets/RightSidebar-CfOJHcXO.js.br +0 -0
  37. package/dist/client/assets/RightSidebar-CfOJHcXO.js.gz +0 -0
  38. package/dist/client/assets/{abnfDiagram-VCTEODGH-C-k_lOuF.js → abnfDiagram-VCTEODGH-CwEvSK80.js} +1 -1
  39. package/dist/client/assets/abnfDiagram-VCTEODGH-CwEvSK80.js.br +0 -0
  40. package/dist/client/assets/abnfDiagram-VCTEODGH-CwEvSK80.js.gz +0 -0
  41. package/dist/client/assets/{app-DNdmWYEJ.js → app-DNnVU3VK.js} +10 -10
  42. package/dist/client/assets/app-DNnVU3VK.js.br +0 -0
  43. package/dist/client/assets/app-DNnVU3VK.js.gz +0 -0
  44. package/dist/client/assets/{arc-DvBgO2ML.js → arc-Ctz1KMpY.js} +1 -1
  45. package/dist/client/assets/arc-Ctz1KMpY.js.br +0 -0
  46. package/dist/client/assets/arc-Ctz1KMpY.js.gz +0 -0
  47. package/dist/client/assets/{architectureDiagram-5GKGNRK7-BrZRHTn8.js → architectureDiagram-5GKGNRK7-DJSgVQQQ.js} +1 -1
  48. package/dist/client/assets/architectureDiagram-5GKGNRK7-DJSgVQQQ.js.br +0 -0
  49. package/dist/client/assets/architectureDiagram-5GKGNRK7-DJSgVQQQ.js.gz +0 -0
  50. package/dist/client/assets/{blockDiagram-I7D4REHJ-DuvUrrD4.js → blockDiagram-I7D4REHJ-N_yr-Q8w.js} +1 -1
  51. package/dist/client/assets/blockDiagram-I7D4REHJ-N_yr-Q8w.js.br +0 -0
  52. package/dist/client/assets/blockDiagram-I7D4REHJ-N_yr-Q8w.js.gz +0 -0
  53. package/dist/client/assets/{c4Diagram-7LVT6UL2-BHM4QTZx.js → c4Diagram-7LVT6UL2-DVQnawpY.js} +1 -1
  54. package/dist/client/assets/c4Diagram-7LVT6UL2-DVQnawpY.js.br +0 -0
  55. package/dist/client/assets/c4Diagram-7LVT6UL2-DVQnawpY.js.gz +0 -0
  56. package/dist/client/assets/channel-b8iCTsm_.js +1 -0
  57. package/dist/client/assets/{chunk-2Q5K7J3B-TnQro6-_.js → chunk-2Q5K7J3B-BXZwjzSA.js} +1 -1
  58. package/dist/client/assets/{chunk-5VM5RSS4-Vl8qqZf_.js → chunk-5VM5RSS4-mKa-FMDa.js} +1 -1
  59. package/dist/client/assets/{chunk-F27PBJKO-DH6GfEdY.js → chunk-F27PBJKO-BW5JuQIW.js} +1 -1
  60. package/dist/client/assets/chunk-F27PBJKO-BW5JuQIW.js.br +0 -0
  61. package/dist/client/assets/chunk-F27PBJKO-BW5JuQIW.js.gz +0 -0
  62. package/dist/client/assets/{chunk-IMKFNOWR-DpKvDckf.js → chunk-IMKFNOWR-CDGBumC-.js} +1 -1
  63. package/dist/client/assets/chunk-IMKFNOWR-CDGBumC-.js.br +0 -0
  64. package/dist/client/assets/chunk-IMKFNOWR-CDGBumC-.js.gz +0 -0
  65. package/dist/client/assets/{chunk-JWPE2WC7-DP773yal.js → chunk-JWPE2WC7-CGx9O6IX.js} +1 -1
  66. package/dist/client/assets/{chunk-POPQ4Y6H-BoR9GKji.js → chunk-POPQ4Y6H-BkWYxDSy.js} +1 -1
  67. package/dist/client/assets/{chunk-SVP7TREG-DFbN0Uvp.js → chunk-SVP7TREG-BGwkXakv.js} +1 -1
  68. package/dist/client/assets/chunk-SVP7TREG-BGwkXakv.js.br +0 -0
  69. package/dist/client/assets/chunk-SVP7TREG-BGwkXakv.js.gz +0 -0
  70. package/dist/client/assets/{chunk-TICWLB2K-BCoshST2.js → chunk-TICWLB2K-CMxjLRcv.js} +1 -1
  71. package/dist/client/assets/chunk-TICWLB2K-CMxjLRcv.js.br +0 -0
  72. package/dist/client/assets/chunk-TICWLB2K-CMxjLRcv.js.gz +0 -0
  73. package/dist/client/assets/{chunk-XXDRQBXY-DMAOtV4y.js → chunk-XXDRQBXY-DCIQ1i4z.js} +1 -1
  74. package/dist/client/assets/classDiagram-ZZMXUADV-DrGmXJ_R.js +1 -0
  75. package/dist/client/assets/classDiagram-v2-VYDZK3BY-DrGmXJ_R.js +1 -0
  76. package/dist/client/assets/{cose-bilkent-JH36ORCC-BlsyBXEx.js → cose-bilkent-JH36ORCC-Des2am0k.js} +1 -1
  77. package/dist/client/assets/cose-bilkent-JH36ORCC-Des2am0k.js.br +0 -0
  78. package/dist/client/assets/cose-bilkent-JH36ORCC-Des2am0k.js.gz +0 -0
  79. package/dist/client/assets/{cynefin-OW5HDTMX-Btg93pC8.js → cynefin-OW5HDTMX-BOJs6wCD.js} +1 -1
  80. package/dist/client/assets/cynefin-OW5HDTMX-BOJs6wCD.js.br +0 -0
  81. package/dist/client/assets/{cynefin-OW5HDTMX-Btg93pC8.js.gz → cynefin-OW5HDTMX-BOJs6wCD.js.gz} +0 -0
  82. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-TenkE0c6.js → cynefinDiagram-5FMLGOSQ-DVLqWiJ6.js} +1 -1
  83. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-DVLqWiJ6.js.br +0 -0
  84. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-DVLqWiJ6.js.gz +0 -0
  85. package/dist/client/assets/{dagre-GXQ25YYZ-BPYSZagf.js → dagre-GXQ25YYZ-e7mtFW8V.js} +1 -1
  86. package/dist/client/assets/dagre-GXQ25YYZ-e7mtFW8V.js.br +0 -0
  87. package/dist/client/assets/dagre-GXQ25YYZ-e7mtFW8V.js.gz +0 -0
  88. package/dist/client/assets/{diagram-S7CK7UJ4-BrJ04LYZ.js → diagram-S7CK7UJ4-B9P-CEm4.js} +1 -1
  89. package/dist/client/assets/diagram-S7CK7UJ4-B9P-CEm4.js.br +0 -0
  90. package/dist/client/assets/diagram-S7CK7UJ4-B9P-CEm4.js.gz +0 -0
  91. package/dist/client/assets/{diagram-UQ7AKVKN-DFHufHof.js → diagram-UQ7AKVKN-DvTmtjeC.js} +1 -1
  92. package/dist/client/assets/diagram-UQ7AKVKN-DvTmtjeC.js.br +0 -0
  93. package/dist/client/assets/diagram-UQ7AKVKN-DvTmtjeC.js.gz +0 -0
  94. package/dist/client/assets/{diagram-VSXAHHWV-CFidKRGl.js → diagram-VSXAHHWV-BmwhsB8_.js} +1 -1
  95. package/dist/client/assets/diagram-VSXAHHWV-BmwhsB8_.js.br +0 -0
  96. package/dist/client/assets/diagram-VSXAHHWV-BmwhsB8_.js.gz +0 -0
  97. package/dist/client/assets/{diagram-VX7I27RA-C8arbI7W.js → diagram-VX7I27RA-CvV9NUzM.js} +1 -1
  98. package/dist/client/assets/diagram-VX7I27RA-CvV9NUzM.js.br +0 -0
  99. package/dist/client/assets/diagram-VX7I27RA-CvV9NUzM.js.gz +0 -0
  100. package/dist/client/assets/{diagram-Z3DM3KII-fMLMbGcS.js → diagram-Z3DM3KII-DT1POaEF.js} +1 -1
  101. package/dist/client/assets/diagram-Z3DM3KII-DT1POaEF.js.br +0 -0
  102. package/dist/client/assets/diagram-Z3DM3KII-DT1POaEF.js.gz +0 -0
  103. package/dist/client/assets/{ebnfDiagram-PWID7BFC-BjBUR2zi.js → ebnfDiagram-PWID7BFC-QZNS7lcr.js} +1 -1
  104. package/dist/client/assets/ebnfDiagram-PWID7BFC-QZNS7lcr.js.br +0 -0
  105. package/dist/client/assets/ebnfDiagram-PWID7BFC-QZNS7lcr.js.gz +0 -0
  106. package/dist/client/assets/{erDiagram-RLTQ6QDP-BVDyIbY-.js → erDiagram-RLTQ6QDP-C9KhKBAJ.js} +1 -1
  107. package/dist/client/assets/erDiagram-RLTQ6QDP-C9KhKBAJ.js.br +0 -0
  108. package/dist/client/assets/erDiagram-RLTQ6QDP-C9KhKBAJ.js.gz +0 -0
  109. package/dist/client/assets/{flowDiagram-HODETNUW-Dej14Ugo.js → flowDiagram-HODETNUW-Du-YKajw.js} +1 -1
  110. package/dist/client/assets/flowDiagram-HODETNUW-Du-YKajw.js.br +0 -0
  111. package/dist/client/assets/flowDiagram-HODETNUW-Du-YKajw.js.gz +0 -0
  112. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-4q8Cv5Jl.js → ganttDiagram-EL5Y4UJY-I9ibR23C.js} +1 -1
  113. package/dist/client/assets/ganttDiagram-EL5Y4UJY-I9ibR23C.js.br +0 -0
  114. package/dist/client/assets/ganttDiagram-EL5Y4UJY-I9ibR23C.js.gz +0 -0
  115. package/dist/client/assets/{gestureArbiter-q3jASYgN.js → gestureArbiter-BE8k_FL7.js} +1 -1
  116. package/dist/client/assets/gestureArbiter-BE8k_FL7.js.br +0 -0
  117. package/dist/client/assets/gestureArbiter-BE8k_FL7.js.gz +0 -0
  118. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-DnE330VW.js → gitGraphDiagram-WWUBYQGX-BK6myYCK.js} +1 -1
  119. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BK6myYCK.js.br +0 -0
  120. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BK6myYCK.js.gz +0 -0
  121. package/dist/client/assets/{index-Dd_3ISCb.css → index-C6xPtOPw.css} +1 -1
  122. package/dist/client/assets/index-C6xPtOPw.css.br +0 -0
  123. package/dist/client/assets/{index-Dd_3ISCb.css.gz → index-C6xPtOPw.css.gz} +0 -0
  124. package/dist/client/assets/{infoDiagram-27XIBGKW-BJyKPHsP.js → infoDiagram-27XIBGKW-D1tExNKF.js} +1 -1
  125. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-CJV8ONjw.js → ishikawaDiagram-5VMMS53U-CwY6cf7s.js} +1 -1
  126. package/dist/client/assets/ishikawaDiagram-5VMMS53U-CwY6cf7s.js.br +0 -0
  127. package/dist/client/assets/ishikawaDiagram-5VMMS53U-CwY6cf7s.js.gz +0 -0
  128. package/dist/client/assets/{journeyDiagram-3NMN7TZE-C_dzPksa.js → journeyDiagram-3NMN7TZE-Cqy1TbUI.js} +1 -1
  129. package/dist/client/assets/journeyDiagram-3NMN7TZE-Cqy1TbUI.js.br +0 -0
  130. package/dist/client/assets/journeyDiagram-3NMN7TZE-Cqy1TbUI.js.gz +0 -0
  131. package/dist/client/assets/{kanban-definition-UXKFOSKX-05lEbrKo.js → kanban-definition-UXKFOSKX-SXzevtXv.js} +1 -1
  132. package/dist/client/assets/kanban-definition-UXKFOSKX-SXzevtXv.js.br +0 -0
  133. package/dist/client/assets/kanban-definition-UXKFOSKX-SXzevtXv.js.gz +0 -0
  134. package/dist/client/assets/{layout-CV4xlefz.js → layout-CFH4KsMu.js} +1 -1
  135. package/dist/client/assets/layout-CFH4KsMu.js.br +0 -0
  136. package/dist/client/assets/layout-CFH4KsMu.js.gz +0 -0
  137. package/dist/client/assets/{linear-Ne3ggM1q.js → linear-DSGS6T8F.js} +1 -1
  138. package/dist/client/assets/linear-DSGS6T8F.js.br +0 -0
  139. package/dist/client/assets/linear-DSGS6T8F.js.gz +0 -0
  140. package/dist/client/assets/{mermaid.core-CAOB7F_V.js → mermaid.core-BpDQIw7m.js} +5 -5
  141. package/dist/client/assets/mermaid.core-BpDQIw7m.js.br +0 -0
  142. package/dist/client/assets/mermaid.core-BpDQIw7m.js.gz +0 -0
  143. package/dist/client/assets/{mindmap-definition-YA3MSWOX-BWwXAlmP.js → mindmap-definition-YA3MSWOX-D7H6k38f.js} +1 -1
  144. package/dist/client/assets/mindmap-definition-YA3MSWOX-D7H6k38f.js.br +0 -0
  145. package/dist/client/assets/mindmap-definition-YA3MSWOX-D7H6k38f.js.gz +0 -0
  146. package/dist/client/assets/{passwordBootstrap-Cm1ye6eX.js → passwordBootstrap-B4SLDWeK.js} +1 -1
  147. package/dist/client/assets/passwordBootstrap-B4SLDWeK.js.br +0 -0
  148. package/dist/client/assets/passwordBootstrap-B4SLDWeK.js.gz +0 -0
  149. package/dist/client/assets/{pegDiagram-XKGWAZYB-DKhyr6CD.js → pegDiagram-XKGWAZYB-DT21hoef.js} +1 -1
  150. package/dist/client/assets/pegDiagram-XKGWAZYB-DT21hoef.js.br +0 -0
  151. package/dist/client/assets/pegDiagram-XKGWAZYB-DT21hoef.js.gz +0 -0
  152. package/dist/client/assets/{pieDiagram-E7YTZNPT-h2Q03QIh.js → pieDiagram-E7YTZNPT-CP_7qBRV.js} +1 -1
  153. package/dist/client/assets/pieDiagram-E7YTZNPT-CP_7qBRV.js.br +0 -0
  154. package/dist/client/assets/pieDiagram-E7YTZNPT-CP_7qBRV.js.gz +0 -0
  155. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-CWxDTEGF.js → quadrantDiagram-AXDQQJYC-CLBVrI3n.js} +1 -1
  156. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CLBVrI3n.js.br +0 -0
  157. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CLBVrI3n.js.gz +0 -0
  158. package/dist/client/assets/{railroadDiagram-O6MQD6OU-BY5sm6Td.js → railroadDiagram-O6MQD6OU-DJoM5WtF.js} +1 -1
  159. package/dist/client/assets/railroadDiagram-O6MQD6OU-DJoM5WtF.js.br +0 -0
  160. package/dist/client/assets/railroadDiagram-O6MQD6OU-DJoM5WtF.js.gz +0 -0
  161. package/dist/client/assets/rdpSession-C0jVZfFV.js +1 -0
  162. package/dist/client/assets/rdpSession-C0jVZfFV.js.br +0 -0
  163. package/dist/client/assets/rdpSession-C0jVZfFV.js.gz +0 -0
  164. package/dist/client/assets/{referenceLongPress-5uMCEptL.js → referenceLongPress-LCYPFdN8.js} +1 -1
  165. package/dist/client/assets/referenceLongPress-LCYPFdN8.js.br +0 -0
  166. package/dist/client/assets/referenceLongPress-LCYPFdN8.js.gz +0 -0
  167. package/dist/client/assets/{requirementDiagram-BXWQKSXE-D8IK92YE.js → requirementDiagram-BXWQKSXE-BHLyxBdU.js} +1 -1
  168. package/dist/client/assets/requirementDiagram-BXWQKSXE-BHLyxBdU.js.br +0 -0
  169. package/dist/client/assets/requirementDiagram-BXWQKSXE-BHLyxBdU.js.gz +0 -0
  170. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-NkH3NrGx.js → sankeyDiagram-P5KCCOFB-CUgEsLUw.js} +1 -1
  171. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CUgEsLUw.js.br +0 -0
  172. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CUgEsLUw.js.gz +0 -0
  173. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-DieLFBCA.js → sequenceDiagram-WJ2MYXX4-qEb89gHp.js} +1 -1
  174. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-qEb89gHp.js.br +0 -0
  175. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-qEb89gHp.js.gz +0 -0
  176. package/dist/client/assets/{sizeCapture-INFHLROL-C-rwOQvA.js → sizeCapture-INFHLROL-BUOHBGK2.js} +1 -1
  177. package/dist/client/assets/sizeCapture-INFHLROL-BUOHBGK2.js.br +0 -0
  178. package/dist/client/assets/sizeCapture-INFHLROL-BUOHBGK2.js.gz +0 -0
  179. package/dist/client/assets/{sparkles-Cku-tzxx.js → sparkles-Cm9xs8pz.js} +1 -1
  180. package/dist/client/assets/{stateDiagram-D77RDMKH-C7mgOyy6.js → stateDiagram-D77RDMKH-Dx0afnU6.js} +1 -1
  181. package/dist/client/assets/stateDiagram-D77RDMKH-Dx0afnU6.js.br +0 -0
  182. package/dist/client/assets/stateDiagram-D77RDMKH-Dx0afnU6.js.gz +0 -0
  183. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-CzHE6VoX.js +1 -0
  184. package/dist/client/assets/{swimlanes-42K2YHIH-C4aAuzlE.js → swimlanes-42K2YHIH-DeG8X6CN.js} +1 -1
  185. package/dist/client/assets/swimlanes-42K2YHIH-DeG8X6CN.js.br +0 -0
  186. package/dist/client/assets/swimlanes-42K2YHIH-DeG8X6CN.js.gz +0 -0
  187. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-B4wu-iuA.js +8 -0
  188. package/dist/client/assets/{timeline-definition-24CTP7MA-CKntrnOJ.js → timeline-definition-24CTP7MA-Bkts868I.js} +1 -1
  189. package/dist/client/assets/timeline-definition-24CTP7MA-Bkts868I.js.br +0 -0
  190. package/dist/client/assets/timeline-definition-24CTP7MA-Bkts868I.js.gz +0 -0
  191. package/dist/client/assets/{triangle-alert-DPNiOY7C.js → triangle-alert-D1VnXjVL.js} +1 -1
  192. package/dist/client/assets/{vennDiagram-4TSXK5OY-W9jedFfD.js → vennDiagram-4TSXK5OY-BOoHxntl.js} +1 -1
  193. package/dist/client/assets/vennDiagram-4TSXK5OY-BOoHxntl.js.br +0 -0
  194. package/dist/client/assets/vennDiagram-4TSXK5OY-BOoHxntl.js.gz +0 -0
  195. package/dist/client/assets/{videoCompression-BYHN4Eba.js → videoCompression-BONtNnBl.js} +1 -1
  196. package/dist/client/assets/videoCompression-BONtNnBl.js.br +0 -0
  197. package/dist/client/assets/videoCompression-BONtNnBl.js.gz +0 -0
  198. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-CzvXMjBC.js → wardleyDiagram-VM6X3IG4-BAuuRkvt.js} +1 -1
  199. package/dist/client/assets/wardleyDiagram-VM6X3IG4-BAuuRkvt.js.br +0 -0
  200. package/dist/client/assets/wardleyDiagram-VM6X3IG4-BAuuRkvt.js.gz +0 -0
  201. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-VD8CKhIU.js → xychartDiagram-S5SC5T6Z-DvJOw2Ss.js} +1 -1
  202. package/dist/client/assets/xychartDiagram-S5SC5T6Z-DvJOw2Ss.js.br +0 -0
  203. package/dist/client/assets/xychartDiagram-S5SC5T6Z-DvJOw2Ss.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.js +1 -1
  208. package/dist/client/sw.js.br +0 -0
  209. package/dist/client/sw.js.gz +0 -0
  210. package/dist/server/agent/collaborationCli.js +3 -0
  211. package/dist/server/agent/integrationRecoveryBinding.js +34 -0
  212. package/dist/server/agent/integrationServer.js +1 -0
  213. package/dist/server/agent/integrationSessions.js +79 -3
  214. package/dist/server/entry.js +4 -0
  215. package/dist/server/routes/terminal.js +90 -0
  216. package/docs/integrations.md +27 -0
  217. package/docs/systemd.md +35 -0
  218. package/package.json +3 -1
  219. package/packaging/systemd/termdock.service.d/10-preserve-tmux.conf +5 -0
  220. package/runtime-manifest.json +3 -3
  221. package/dist/client/assets/App-DrnLToMO.js.br +0 -0
  222. package/dist/client/assets/App-DrnLToMO.js.gz +0 -0
  223. package/dist/client/assets/ArchitecturePanel-CGjioSu0.js.br +0 -0
  224. package/dist/client/assets/ArchitecturePanel-CGjioSu0.js.gz +0 -0
  225. package/dist/client/assets/ChangeWalkthroughPanel-BsG5tR4F.js.br +0 -0
  226. package/dist/client/assets/ChangeWalkthroughPanel-BsG5tR4F.js.gz +0 -0
  227. package/dist/client/assets/CollaborationMainWorkspace-KMTTUtsp.js.br +0 -0
  228. package/dist/client/assets/CollaborationMainWorkspace-KMTTUtsp.js.gz +0 -0
  229. package/dist/client/assets/CollaborationTaskContent-D-qPRh4f.js +0 -2
  230. package/dist/client/assets/ComputerControlView-Bh3aWVA-.js +0 -5
  231. package/dist/client/assets/ComputerControlView-Bh3aWVA-.js.br +0 -0
  232. package/dist/client/assets/ComputerControlView-Bh3aWVA-.js.gz +0 -0
  233. package/dist/client/assets/DagPlayground-761ejCr8.js.br +0 -0
  234. package/dist/client/assets/DagPlayground-761ejCr8.js.gz +0 -0
  235. package/dist/client/assets/DiffLab-yWG9ju3P.js.br +0 -0
  236. package/dist/client/assets/DiffLab-yWG9ju3P.js.gz +0 -0
  237. package/dist/client/assets/DiffReview-02640ofg.js.br +0 -0
  238. package/dist/client/assets/DiffReview-02640ofg.js.gz +0 -0
  239. package/dist/client/assets/DiffReviewLab-D0W0SEIG.js.br +0 -0
  240. package/dist/client/assets/DiffReviewLab-D0W0SEIG.js.gz +0 -0
  241. package/dist/client/assets/DiffViewer-CLjrE1oE.js.br +0 -0
  242. package/dist/client/assets/ModelPreview-BnIvn0Fn.js.br +0 -0
  243. package/dist/client/assets/RightSidebar-Dx4Jf94o.js.br +0 -0
  244. package/dist/client/assets/RightSidebar-Dx4Jf94o.js.gz +0 -0
  245. package/dist/client/assets/abnfDiagram-VCTEODGH-C-k_lOuF.js.br +0 -0
  246. package/dist/client/assets/abnfDiagram-VCTEODGH-C-k_lOuF.js.gz +0 -0
  247. package/dist/client/assets/app-DNdmWYEJ.js.br +0 -0
  248. package/dist/client/assets/app-DNdmWYEJ.js.gz +0 -0
  249. package/dist/client/assets/arc-DvBgO2ML.js.br +0 -0
  250. package/dist/client/assets/arc-DvBgO2ML.js.gz +0 -0
  251. package/dist/client/assets/architectureDiagram-5GKGNRK7-BrZRHTn8.js.br +0 -0
  252. package/dist/client/assets/architectureDiagram-5GKGNRK7-BrZRHTn8.js.gz +0 -0
  253. package/dist/client/assets/blockDiagram-I7D4REHJ-DuvUrrD4.js.br +0 -0
  254. package/dist/client/assets/blockDiagram-I7D4REHJ-DuvUrrD4.js.gz +0 -0
  255. package/dist/client/assets/c4Diagram-7LVT6UL2-BHM4QTZx.js.br +0 -0
  256. package/dist/client/assets/c4Diagram-7LVT6UL2-BHM4QTZx.js.gz +0 -0
  257. package/dist/client/assets/channel-BqA2i16W.js +0 -1
  258. package/dist/client/assets/chunk-F27PBJKO-DH6GfEdY.js.br +0 -0
  259. package/dist/client/assets/chunk-F27PBJKO-DH6GfEdY.js.gz +0 -0
  260. package/dist/client/assets/chunk-IMKFNOWR-DpKvDckf.js.br +0 -0
  261. package/dist/client/assets/chunk-IMKFNOWR-DpKvDckf.js.gz +0 -0
  262. package/dist/client/assets/chunk-SVP7TREG-DFbN0Uvp.js.br +0 -0
  263. package/dist/client/assets/chunk-SVP7TREG-DFbN0Uvp.js.gz +0 -0
  264. package/dist/client/assets/chunk-TICWLB2K-BCoshST2.js.br +0 -0
  265. package/dist/client/assets/chunk-TICWLB2K-BCoshST2.js.gz +0 -0
  266. package/dist/client/assets/classDiagram-ZZMXUADV-ChnKE-K2.js +0 -1
  267. package/dist/client/assets/classDiagram-v2-VYDZK3BY-ChnKE-K2.js +0 -1
  268. package/dist/client/assets/cose-bilkent-JH36ORCC-BlsyBXEx.js.br +0 -0
  269. package/dist/client/assets/cose-bilkent-JH36ORCC-BlsyBXEx.js.gz +0 -0
  270. package/dist/client/assets/cynefin-OW5HDTMX-Btg93pC8.js.br +0 -0
  271. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-TenkE0c6.js.br +0 -0
  272. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-TenkE0c6.js.gz +0 -0
  273. package/dist/client/assets/dagre-GXQ25YYZ-BPYSZagf.js.br +0 -0
  274. package/dist/client/assets/dagre-GXQ25YYZ-BPYSZagf.js.gz +0 -0
  275. package/dist/client/assets/diagram-S7CK7UJ4-BrJ04LYZ.js.br +0 -0
  276. package/dist/client/assets/diagram-S7CK7UJ4-BrJ04LYZ.js.gz +0 -0
  277. package/dist/client/assets/diagram-UQ7AKVKN-DFHufHof.js.br +0 -0
  278. package/dist/client/assets/diagram-UQ7AKVKN-DFHufHof.js.gz +0 -0
  279. package/dist/client/assets/diagram-VSXAHHWV-CFidKRGl.js.br +0 -0
  280. package/dist/client/assets/diagram-VSXAHHWV-CFidKRGl.js.gz +0 -0
  281. package/dist/client/assets/diagram-VX7I27RA-C8arbI7W.js.br +0 -0
  282. package/dist/client/assets/diagram-VX7I27RA-C8arbI7W.js.gz +0 -0
  283. package/dist/client/assets/diagram-Z3DM3KII-fMLMbGcS.js.br +0 -0
  284. package/dist/client/assets/diagram-Z3DM3KII-fMLMbGcS.js.gz +0 -0
  285. package/dist/client/assets/ebnfDiagram-PWID7BFC-BjBUR2zi.js.br +0 -0
  286. package/dist/client/assets/ebnfDiagram-PWID7BFC-BjBUR2zi.js.gz +0 -0
  287. package/dist/client/assets/erDiagram-RLTQ6QDP-BVDyIbY-.js.br +0 -0
  288. package/dist/client/assets/erDiagram-RLTQ6QDP-BVDyIbY-.js.gz +0 -0
  289. package/dist/client/assets/flowDiagram-HODETNUW-Dej14Ugo.js.br +0 -0
  290. package/dist/client/assets/flowDiagram-HODETNUW-Dej14Ugo.js.gz +0 -0
  291. package/dist/client/assets/ganttDiagram-EL5Y4UJY-4q8Cv5Jl.js.br +0 -0
  292. package/dist/client/assets/ganttDiagram-EL5Y4UJY-4q8Cv5Jl.js.gz +0 -0
  293. package/dist/client/assets/gestureArbiter-q3jASYgN.js.br +0 -0
  294. package/dist/client/assets/gestureArbiter-q3jASYgN.js.gz +0 -0
  295. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DnE330VW.js.br +0 -0
  296. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DnE330VW.js.gz +0 -0
  297. package/dist/client/assets/index-Dd_3ISCb.css.br +0 -0
  298. package/dist/client/assets/ishikawaDiagram-5VMMS53U-CJV8ONjw.js.br +0 -0
  299. package/dist/client/assets/ishikawaDiagram-5VMMS53U-CJV8ONjw.js.gz +0 -0
  300. package/dist/client/assets/journeyDiagram-3NMN7TZE-C_dzPksa.js.br +0 -0
  301. package/dist/client/assets/journeyDiagram-3NMN7TZE-C_dzPksa.js.gz +0 -0
  302. package/dist/client/assets/kanban-definition-UXKFOSKX-05lEbrKo.js.br +0 -0
  303. package/dist/client/assets/kanban-definition-UXKFOSKX-05lEbrKo.js.gz +0 -0
  304. package/dist/client/assets/layout-CV4xlefz.js.br +0 -0
  305. package/dist/client/assets/layout-CV4xlefz.js.gz +0 -0
  306. package/dist/client/assets/linear-Ne3ggM1q.js.br +0 -0
  307. package/dist/client/assets/linear-Ne3ggM1q.js.gz +0 -0
  308. package/dist/client/assets/mermaid.core-CAOB7F_V.js.br +0 -0
  309. package/dist/client/assets/mermaid.core-CAOB7F_V.js.gz +0 -0
  310. package/dist/client/assets/mindmap-definition-YA3MSWOX-BWwXAlmP.js.br +0 -0
  311. package/dist/client/assets/mindmap-definition-YA3MSWOX-BWwXAlmP.js.gz +0 -0
  312. package/dist/client/assets/passwordBootstrap-Cm1ye6eX.js.br +0 -0
  313. package/dist/client/assets/passwordBootstrap-Cm1ye6eX.js.gz +0 -0
  314. package/dist/client/assets/pegDiagram-XKGWAZYB-DKhyr6CD.js.br +0 -0
  315. package/dist/client/assets/pegDiagram-XKGWAZYB-DKhyr6CD.js.gz +0 -0
  316. package/dist/client/assets/pieDiagram-E7YTZNPT-h2Q03QIh.js.br +0 -0
  317. package/dist/client/assets/pieDiagram-E7YTZNPT-h2Q03QIh.js.gz +0 -0
  318. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CWxDTEGF.js.br +0 -0
  319. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CWxDTEGF.js.gz +0 -0
  320. package/dist/client/assets/railroadDiagram-O6MQD6OU-BY5sm6Td.js.br +0 -0
  321. package/dist/client/assets/railroadDiagram-O6MQD6OU-BY5sm6Td.js.gz +0 -0
  322. package/dist/client/assets/rdpSession-CWvrHSd8.js +0 -1
  323. package/dist/client/assets/rdpSession-CWvrHSd8.js.br +0 -0
  324. package/dist/client/assets/rdpSession-CWvrHSd8.js.gz +0 -0
  325. package/dist/client/assets/referenceLongPress-5uMCEptL.js.br +0 -0
  326. package/dist/client/assets/referenceLongPress-5uMCEptL.js.gz +0 -0
  327. package/dist/client/assets/requirementDiagram-BXWQKSXE-D8IK92YE.js.br +0 -0
  328. package/dist/client/assets/requirementDiagram-BXWQKSXE-D8IK92YE.js.gz +0 -0
  329. package/dist/client/assets/sankeyDiagram-P5KCCOFB-NkH3NrGx.js.br +0 -0
  330. package/dist/client/assets/sankeyDiagram-P5KCCOFB-NkH3NrGx.js.gz +0 -0
  331. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DieLFBCA.js.br +0 -0
  332. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DieLFBCA.js.gz +0 -0
  333. package/dist/client/assets/sizeCapture-INFHLROL-C-rwOQvA.js.br +0 -0
  334. package/dist/client/assets/sizeCapture-INFHLROL-C-rwOQvA.js.gz +0 -0
  335. package/dist/client/assets/stateDiagram-D77RDMKH-C7mgOyy6.js.br +0 -0
  336. package/dist/client/assets/stateDiagram-D77RDMKH-C7mgOyy6.js.gz +0 -0
  337. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-BDWPsG19.js +0 -1
  338. package/dist/client/assets/swimlanes-42K2YHIH-C4aAuzlE.js.br +0 -0
  339. package/dist/client/assets/swimlanes-42K2YHIH-C4aAuzlE.js.gz +0 -0
  340. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DE8jpsjW.js +0 -8
  341. package/dist/client/assets/timeline-definition-24CTP7MA-CKntrnOJ.js.br +0 -0
  342. package/dist/client/assets/timeline-definition-24CTP7MA-CKntrnOJ.js.gz +0 -0
  343. package/dist/client/assets/vennDiagram-4TSXK5OY-W9jedFfD.js.br +0 -0
  344. package/dist/client/assets/vennDiagram-4TSXK5OY-W9jedFfD.js.gz +0 -0
  345. package/dist/client/assets/videoCompression-BYHN4Eba.js.br +0 -0
  346. package/dist/client/assets/videoCompression-BYHN4Eba.js.gz +0 -0
  347. package/dist/client/assets/wardleyDiagram-VM6X3IG4-CzvXMjBC.js.br +0 -0
  348. package/dist/client/assets/wardleyDiagram-VM6X3IG4-CzvXMjBC.js.gz +0 -0
  349. package/dist/client/assets/xychartDiagram-S5SC5T6Z-VD8CKhIU.js.br +0 -0
  350. package/dist/client/assets/xychartDiagram-S5SC5T6Z-VD8CKhIU.js.gz +0 -0
@@ -61,6 +61,7 @@ export class IntegrationSessions {
61
61
  lifecycle = new SessionLifecycleCoordinator();
62
62
  mutations = new Map();
63
63
  coldRetries = new Set();
64
+ reconcilingBindings = new Set();
64
65
  closingOperations = new Set();
65
66
  timers = new Set();
66
67
  stopObservation;
@@ -302,7 +303,13 @@ export class IntegrationSessions {
302
303
  return record;
303
304
  }
304
305
  async restore(principal, id, key) {
305
- return this.mutate(principal, key, ['restore', id], () => this.lifecycle.run(id, () => this.restoreOnce(principal, id, key)));
306
+ return this.mutate(principal, key, ['restore', id], async () => {
307
+ // A get can reconcile a proven tmux-recovery binding before restore takes
308
+ // the per-session lifecycle lock. restoreOnce then sees the exact live
309
+ // native owner and remains a no-op instead of launching a second Agent.
310
+ await this.get(principal, id);
311
+ return this.lifecycle.run(id, () => this.restoreOnce(principal, id, key));
312
+ });
306
313
  }
307
314
  async retryCold(principal, id, generation, key) {
308
315
  return this.mutate(principal, key, ['retry-cold', id, generation], () => this.lifecycle.run(id, async () => {
@@ -690,7 +697,7 @@ export class IntegrationSessions {
690
697
  return record;
691
698
  }));
692
699
  }
693
- async refresh(id) {
700
+ async refresh(id, allowBindingReconciliation = true) {
694
701
  const record = structuredClone(this.doc.sessions.find(s => s.session_id === id));
695
702
  if (!record)
696
703
  return;
@@ -781,8 +788,19 @@ export class IntegrationSessions {
781
788
  const current = this.doc.sessions.find(s => s.session_id === id);
782
789
  if (JSON.stringify(current) !== JSON.stringify(record))
783
790
  return;
791
+ if (this.lifecycle.active(id) || this.pending.has(id))
792
+ return;
784
793
  const code = error.code;
785
794
  const errorCode = typeof code === 'string' ? code : 'SESSION_OBSERVATION_FAILED';
795
+ if (allowBindingReconciliation && errorCode === 'SESSION_IDENTITY_MISMATCH' && this.adapter.reconcileRecoveryBinding
796
+ && ['ready', 'failed'].includes(record.state) && (record.runtime_present === true || record.state === 'failed')
797
+ && (!record.error_code || record.error_code === 'SESSION_IDENTITY_MISMATCH')
798
+ && record.agent_native_session_id && record.terminal_binding && !record.operation_uncertain
799
+ && !record.close_intent && !record.rename_pending && !record.cold_retry_pending
800
+ && !this.pending.has(id) && !this.lifecycle.active(id)) {
801
+ if (await this.reconcileRecoveredBinding(record))
802
+ return;
803
+ }
786
804
  if (record.state !== 'failed' || record.error_code !== errorCode)
787
805
  this.saveRecord({ ...record, state: 'failed', error_code: errorCode,
788
806
  launch_diagnostics: record.launch_diagnostics ? launchFailure(record.launch_diagnostics, error, errorCode) : undefined, updated_at: Date.now() });
@@ -871,11 +889,66 @@ export class IntegrationSessions {
871
889
  this.saveRecord(next);
872
890
  }
873
891
  }
892
+ async reconcileRecoveredBinding(expected) {
893
+ const id = expected.session_id;
894
+ const reconcile = this.adapter.reconcileRecoveryBinding;
895
+ if (!reconcile || this.lifecycle.active(id) || this.pending.has(id))
896
+ return false;
897
+ let committed = false;
898
+ try {
899
+ await this.lifecycle.run(id, async () => {
900
+ const current = this.doc.sessions.find(record => record.session_id === id);
901
+ if (!current || JSON.stringify(current) !== JSON.stringify(expected) || this.pending.has(id)
902
+ || !['ready', 'failed'].includes(current.state) || !(current.runtime_present === true || current.state === 'failed')
903
+ || (current.error_code && current.error_code !== 'SESSION_IDENTITY_MISMATCH')
904
+ || current.operation_uncertain || current.close_intent || current.rename_pending || current.cold_retry_pending
905
+ || !current.agent_native_session_id || !current.terminal_binding)
906
+ return;
907
+ this.reconcilingBindings.add(id);
908
+ let reconciled;
909
+ try {
910
+ reconciled = await reconcile.call(this.adapter, current);
911
+ }
912
+ catch {
913
+ return;
914
+ }
915
+ if (!reconciled || JSON.stringify(reconciled.binding) === JSON.stringify(current.terminal_binding))
916
+ return;
917
+ const latest = this.doc.sessions.find(record => record.session_id === id);
918
+ if (!latest || JSON.stringify(latest) !== JSON.stringify(current))
919
+ return;
920
+ const now = Date.now();
921
+ const next = { ...current, terminal_binding: structuredClone(reconciled.binding), state: 'ready',
922
+ runtime_present: true, error_code: null, operation_uncertain: false, generation: (current.generation ?? 1) + 1,
923
+ operation_id: randomUUID(), updated_at: now,
924
+ binding_reconciliation: { at: now, recovery_operation_id: reconciled.recoveryOperationId,
925
+ previous_binding: structuredClone(current.terminal_binding) },
926
+ startup_input: startupInput(current, now) };
927
+ this.saveRecord(next);
928
+ committed = true;
929
+ });
930
+ }
931
+ catch {
932
+ return false;
933
+ }
934
+ finally {
935
+ this.reconcilingBindings.delete(id);
936
+ }
937
+ if (committed) {
938
+ try {
939
+ this.adapter.recoveryBindingReconciled?.(id);
940
+ }
941
+ catch { /* The worker also retries on its normal tick. */ }
942
+ }
943
+ return committed;
944
+ }
874
945
  /** Only gates configured launches. Native UUID and Agent turn state are not input prerequisites. */
875
946
  async deliveryReadiness(id) {
876
947
  const existing = this.doc.sessions.find(record => record.session_id === id);
877
948
  if (!existing)
878
949
  return null;
950
+ if (this.reconcilingBindings.has(id))
951
+ return { allowed: false, reason: 'SESSION_BINDING_RECONCILIATION_PENDING' };
879
952
  if (this.closingOperations.has(id))
880
953
  return { allowed: false, reason: 'SESSION_OPERATION_IN_PROGRESS' };
881
954
  if (existing.state === 'closed')
@@ -886,7 +959,10 @@ export class IntegrationSessions {
886
959
  return { allowed: false, reason: existing.state === 'released' ? 'SESSION_RELEASED' : 'SESSION_OPERATION_IN_PROGRESS' };
887
960
  if (!existing.startup_input)
888
961
  return null;
889
- await this.refresh(id);
962
+ // This callback can run inside the delivery worker's own queue. Binding
963
+ // reconciliation must enter that queue from get/observation, never wait on
964
+ // the worker from within itself.
965
+ await this.refresh(id, false);
890
966
  const record = this.doc.sessions.find(record => record.session_id === id);
891
967
  if (record.error_code && record.error_code !== 'SESSION_BINDING_TIMEOUT')
892
968
  return { allowed: false, reason: record.error_code };
@@ -116,6 +116,10 @@ function shouldWriteClientLog(level, message) {
116
116
  clientLogSuppressedCount += 1;
117
117
  return false;
118
118
  }
119
+ // Motion trace records share a label but contain different ordered samples.
120
+ // Preserve every chunk while retaining the global rate limit above.
121
+ if (message === 'COMPUTER_MOTION_TRACE')
122
+ return true;
119
123
  const key = `${String(level ?? 'info')}\u0000${String(message ?? '')}`;
120
124
  const last = clientLogRecent.get(key);
121
125
  if (last && now - last < CLIENT_LOG_DEDUP_WINDOW_MS) {
@@ -73,6 +73,7 @@ import { NativeSessionSearch } from '../agent/nativeSessionSearch.js';
73
73
  import { CollaborationError } from '../agent/collaborationProtocol.js';
74
74
  import { resolveCollaborationBackend, resolveCollaborationSessionId } from '../agent/sessionBindingRecovery.js';
75
75
  import { CollaborationRoutingStore, selectCollaborationPane, selectDrivePane, assessCollaborationRouteIdentity } from '../agent/collaborationRouting.js';
76
+ import { selectRecoveredIntegrationBinding } from '../agent/integrationRecoveryBinding.js';
76
77
  import { CollaborationDeliveryWorker } from '../agent/collaborationDeliveryWorker.js';
77
78
  import { approveCollaborationDialog, captureTmuxPaneHistory, captureTmuxPaneText, sendTmuxPaneKey, writeCollaborationTmuxPane } from '../agent/collaborationTmuxDelivery.js';
78
79
  import { listAllHookAgents, refreshStaleHooksAtLaunch, installHooksForSlug, uninstallHooksForSlug, } from '../agent/installers.js';
@@ -2072,6 +2073,28 @@ function integrationTerminalRecord(record) {
2072
2073
  integrationError('SESSION_IDENTITY_MISMATCH', 'Owned TD terminal binding changed', 409);
2073
2074
  return terminal;
2074
2075
  }
2076
+ async function integrationRecoveryOwnership(record) {
2077
+ const root = `${TERMDOCK_DIR}/integration-state`;
2078
+ const directories = await fs.promises.readdir(root, { withFileTypes: true }).catch(() => []);
2079
+ const descriptorOwners = [];
2080
+ const principalOwners = [];
2081
+ for (const directory of directories) {
2082
+ if (!directory.isDirectory())
2083
+ continue;
2084
+ const directoryPath = path.join(root, directory.name);
2085
+ const sessions = await readJsonFileIfExists(path.join(directoryPath, 'integration-sessions.json'));
2086
+ for (const session of sessions?.sessions ?? [])
2087
+ if (session.session_id === record.session_id) {
2088
+ descriptorOwners.push({ sessionId: String(session.session_id), groupId: String(session.group_id ?? ''), principalId: String(session.principal_id ?? '') });
2089
+ }
2090
+ const integrations = await readJsonFileIfExists(path.join(directoryPath, 'integrations.json'));
2091
+ for (const principal of integrations?.principals ?? [])
2092
+ if (principal.id === record.principal_id) {
2093
+ principalOwners.push({ principalId: String(principal.id), groupId: String(principal.groupId ?? ''), revoked: principal.revoked === true });
2094
+ }
2095
+ }
2096
+ return { descriptorOwners, principalOwners };
2097
+ }
2075
2098
  async function integrationTmuxPresent(record) {
2076
2099
  try {
2077
2100
  await runTmux(['has-session', '-t', `=wt-integration-${record.session_id}`]);
@@ -2299,6 +2322,73 @@ export const integrationSessionAdapter = {
2299
2322
  collaborationRouting.bind({ ...route, nativeSessionId: nativeId, pane: { ...route.pane, nativeSessionId: nativeId } });
2300
2323
  return { exists: true, running: Boolean(pane.agentSlug), shell: await integrationPaneIsIdleShell(pane), agentSlug: pane.agentSlug || null, nativeId };
2301
2324
  },
2325
+ async reconcileRecoveryBinding(record) {
2326
+ if (process.platform !== 'linux' || !record.agent_native_session_id || !record.terminal_binding)
2327
+ return null;
2328
+ const expectedNativeSessionId = record.agent_native_session_id;
2329
+ let reconciled = null;
2330
+ const collect = async () => {
2331
+ const sessionName = `wt-integration-${record.session_id}`;
2332
+ const recoveryAfter = Math.max(record.created_at, record.binding_reconciliation?.at ?? 0);
2333
+ const matchingRecovery = tmuxRecoveryOperations.all().reverse().find(operation => operation.items.some(item => item.sessionId === record.session_id && item.state === 'succeeded'
2334
+ && Number.isSafeInteger(item.completedAt) && item.completedAt > recoveryAfter));
2335
+ const owners = await integrationRecoveryOwnership(record);
2336
+ const groupOwners = collaborationStore.list().filter(group => !group.deleted && group.sessionIds.includes(record.session_id)).map(group => group.id);
2337
+ const globalOwners = globalSessionState.sessions.filter(session => session.sessionId === record.session_id || session.tmuxSessionName === sessionName);
2338
+ const terminal = globalSessionState.sessions.find(session => session.sessionId === record.session_id);
2339
+ const backendMatches = [...terminalSessions].filter(([, backend]) => backend.mode === 'tmux' && backend.tmuxSessionName === sessionName);
2340
+ const backendOwnershipVerified = !!terminal && terminal.mode === 'tmux' && terminal.tmuxSessionName === sessionName
2341
+ && terminal.agentResume?.slug === record.agent_slug && terminal.agentResume.sessionId === expectedNativeSessionId
2342
+ && backendMatches.length === 1 && !globalSessionState.sessions.some(other => other.sessionId !== record.session_id
2343
+ && (other.tmuxSessionName === sessionName || other.backendSessionId === backendMatches[0]?.[0]))
2344
+ && [null, record.session_id].includes(collaborationRouting.ownerOfBackend(backendMatches[0]?.[0] ?? ''));
2345
+ let panes = [];
2346
+ if (backendOwnershipVerified && backendMatches.length === 1) {
2347
+ await runTmux(['has-session', '-t', `=${sessionName}`]);
2348
+ const layout = await getTmuxLayout(sessionName);
2349
+ if (layout.sessionName === sessionName && layout.windows.flatMap(window => window.panes).length === 1) {
2350
+ const [backendSessionId] = backendMatches[0];
2351
+ const unpinned = { sessionId: record.session_id, backendSessionId, mode: 'tmux',
2352
+ tmuxSessionName: sessionName, agentSlug: record.agent_slug, nativeSessionId: expectedNativeSessionId, pane: null };
2353
+ const inspected = await inspectCollaborationTmux(unpinned, null, false, true, true, true);
2354
+ panes = (inspected.candidates ?? []).map(pane => ({ tmuxSessionName: sessionName,
2355
+ agentSlug: pane.agentSlug, nativeSessionId: pane.nativeSessionId,
2356
+ nativeIdentitySource: pane.nativeIdentitySource ?? null, nativeIdentityVerified: pane.nativeIdentityVerified === true,
2357
+ binding: { serverPid: pane.serverPid, sessionId: pane.sessionId, paneId: pane.paneId, panePid: pane.panePid,
2358
+ agentSlug: pane.agentSlug, nativeSessionId: pane.nativeSessionId } }));
2359
+ }
2360
+ }
2361
+ const selected = selectRecoveredIntegrationBinding({ sessionId: record.session_id, groupId: record.group_id, principalId: record.principal_id,
2362
+ agentSlug: record.agent_slug, nativeSessionId: expectedNativeSessionId, tmuxSessionName: sessionName,
2363
+ descriptorOwners: owners.descriptorOwners, principalOwners: owners.principalOwners, groupOwners,
2364
+ terminalOwners: globalOwners.map(session => session.sessionId), backendOwnershipVerified,
2365
+ recoveryOperationId: matchingRecovery?.id ?? null, panes });
2366
+ return selected && backendMatches.length === 1 ? { ...selected, backendSessionId: backendMatches[0][0] } : null;
2367
+ };
2368
+ await collaborationDeliveryWorker.reconfigure(record.session_id, async () => {
2369
+ if (routeHasUnconfirmedWrite(record.session_id))
2370
+ throw Object.assign(new Error('A previous terminal write has an uncertain outcome'), { code: 'ROUTE_DELIVERY_OUTCOME_UNCONFIRMED' });
2371
+ const first = await collect();
2372
+ if (!first)
2373
+ throw Object.assign(new Error('Recovery binding evidence is incomplete, ambiguous, or does not match the exact native identity'), { code: 'SESSION_RECOVERY_BINDING_UNCONFIRMED' });
2374
+ const second = await collect();
2375
+ if (!second || first.recoveryOperationId !== second.recoveryOperationId || first.backendSessionId !== second.backendSessionId
2376
+ || JSON.stringify(first.binding) !== JSON.stringify(second.binding)) {
2377
+ throw Object.assign(new Error('Integration runtime changed while recovery binding was being verified'), { code: 'SESSION_RECOVERY_BINDING_CHANGED' });
2378
+ }
2379
+ if (routeHasUnconfirmedWrite(record.session_id) || collaborationRouting.hasOtherPaneOwner(record.session_id, second.binding)) {
2380
+ throw Object.assign(new Error('A previous write or another route owner prevents automatic binding reconciliation'), { code: 'ROUTE_DELIVERY_OUTCOME_UNCONFIRMED' });
2381
+ }
2382
+ const previous = collaborationRouting.get(record.session_id);
2383
+ collaborationRouting.bind({ sessionId: record.session_id, backendSessionId: second.backendSessionId,
2384
+ mode: 'tmux', tmuxSessionName: `wt-integration-${record.session_id}`, agentSlug: record.agent_slug,
2385
+ nativeSessionId: record.agent_native_session_id, pane: second.binding, routeRevision: crypto.randomUUID(),
2386
+ lastRecovery: { kind: 'native-identity', at: Date.now(), previousPane: previous?.pane ?? record.terminal_binding ?? null } });
2387
+ reconciled = { binding: second.binding, recoveryOperationId: second.recoveryOperationId };
2388
+ });
2389
+ return reconciled;
2390
+ },
2391
+ recoveryBindingReconciled(sessionId) { collaborationDeliveryWorker.wake(sessionId); },
2302
2392
  async create(record, prepared, progress) {
2303
2393
  await listDetectedAgentLaunchers();
2304
2394
  if (!agentBySlug(record.agent_slug))
@@ -1327,3 +1327,30 @@ TD/native session、运行承载、消息/reply、consumer 游标或历史;不
1327
1327
  `GROUP_ARCHIVE_STATE_UNCONFIRMED`,不会猜测或重建。只允许本机非 federated、未删除
1328
1328
  组;删除组、跨服务组和不确定的目标分别返回 `GROUP_NOT_FOUND`、`GROUP_NOT_LOCAL`、
1329
1329
  `GROUP_ARCHIVE_TARGET_UNAVAILABLE`。归档不延长消息历史保留期。
1330
+
1331
+ ## 1.4.328:IntegrationSession 对账 tmux recovery 的新承载
1332
+
1333
+ 最低 CLI / 实际服务 **1.4.328**,能力回读字段为
1334
+ `session_recovery_binding_reconcile=true` 与
1335
+ `session_recovery_binding_reconcile_min_version=1.4.328`。该自动对账目前只在 Linux
1336
+ 提供;其它平台返回 capability=false,因为没有同等的当前 writer-lock 身份证明。
1337
+
1338
+ 所属 principal 调用现有 `session get` 时,如果 IntegrationSession 因
1339
+ `SESSION_IDENTITY_MISMATCH` 指向旧 pane,而 TD 持久恢复 operation 已成功恢复该逻辑
1340
+ session,服务会尝试受限对账。它要求当前唯一受管终端名严格为
1341
+ `wt-integration-<session_id>`,IntegrationSession 与有效 principal/group 的持久归属唯一,
1342
+ 当前组和全局终端记录唯一,只有一个 tmux pane/backend,且该前台 Agent 的当前 Linux
1343
+ flock-owner 身份独立核验出原 agent slug 与原生 UUID。目标元组会连续采样确认未变,
1344
+ 并在现有投递 worker 屏障内更新绑定。
1345
+
1346
+ 成功后保留逻辑 `session_id`、group、principal、原生 UUID、消息与历史,只更新
1347
+ `terminal_binding`、状态和 `generation`,并在 `binding_reconciliation` 记录旧绑定及
1348
+ 对应 `recovery_operation_id`。不会启动或恢复第二个 Agent,也不创建 task、发送正文或
1349
+ 重放已写入的消息。此前写入结果不明时不会自动改绑;已写入的消息保持原 receipt,
1350
+ 尚未写入的 pending 消息由原 worker 继续处理。
1351
+
1352
+ 任一 owner 缺失/重复、tmux 名或 pane 不唯一、native UUID 不同、writer-lock 不可核验、
1353
+ 没有该 session 成功的恢复 operation,或绑定在双重采样间再次变化时,服务保持
1354
+ fail-closed,旧绑定与原消息保留,`session get` 仍报告身份错误;不会按 tmux 名称、PID
1355
+ 缓存、cwd、argv 中的 resume 参数或显示名猜测认领。此 capability 不新增权限;仅通过
1356
+ `session.read` 认证的所属 principal 可触发其自身记录的对账。
@@ -0,0 +1,35 @@
1
+ # Running Termdock under systemd
2
+
3
+ When a systemd unit starts `td --supervise`, set `KillMode=process` if its
4
+ Termdock-managed tmux sessions and Agents must survive a Termdock service or
5
+ supervisor restart. systemd's default `KillMode=control-group` sends the stop
6
+ signal to the entire unit cgroup; that includes tmux servers and Agent
7
+ processes started by Termdock. It can therefore turn a service restart into a
8
+ simultaneous shutdown of every managed Agent.
9
+
10
+ The repository ships
11
+ [`10-preserve-tmux.conf`](../packaging/systemd/termdock.service.d/10-preserve-tmux.conf)
12
+ as a drop-in fragment. Install it under the drop-in directory for the unit
13
+ that runs Termdock (the example path assumes `termdock.service`):
14
+
15
+ ```sh
16
+ sudo install -D -m 0644 packaging/systemd/termdock.service.d/10-preserve-tmux.conf \
17
+ /etc/systemd/system/termdock.service.d/10-preserve-tmux.conf
18
+ sudo systemctl daemon-reload
19
+ systemctl show termdock.service -p KillMode
20
+ ```
21
+
22
+ The final command should report `KillMode=process`. If the unit has a different
23
+ name, use its matching `/etc/systemd/system/<unit>.service.d/` directory and
24
+ verify that unit.
25
+
26
+ This setting intentionally leaves tmux workloads alive when systemd stops the
27
+ Termdock main process. Before permanently removing the service or host, close
28
+ or release managed sessions through Termdock's session lifecycle and verify
29
+ that the runtime inventory is empty. Do not use `systemctl kill` or restore
30
+ `KillMode=control-group` as a way to clean up Agent sessions; those actions can
31
+ terminate unrelated work in the unit.
32
+
33
+ This is a process-manager boundary, separate from recovery queue admission.
34
+ Termdock will not terminate non-Termdock processes to satisfy its memory or
35
+ resident-Agent budget.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "termdock",
3
- "version": "1.4.326",
3
+ "version": "1.4.328",
4
4
  "description": "A complete web-based terminal application with modern UI",
5
5
  "type": "module",
6
6
  "main": ".desktop-dist/main.js",
@@ -16,6 +16,8 @@
16
16
  "dist",
17
17
  "runtime-manifest.json",
18
18
  "README.md",
19
+ "docs/systemd.md",
20
+ "packaging/systemd/termdock.service.d/10-preserve-tmux.conf",
19
21
  "LICENSE",
20
22
  "scripts",
21
23
  "docs/integrations.md"
@@ -0,0 +1,5 @@
1
+ # Install as a drop-in for the unit that runs `td --supervise`.
2
+ # Termdock-managed tmux sessions are independent runtime workloads and must
3
+ # survive a supervisor/service process restart.
4
+ [Service]
5
+ KillMode=process
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "packageName": "termdock",
4
- "version": "1.4.326",
4
+ "version": "1.4.328",
5
5
  "runtimeProtocolVersion": 1,
6
6
  "minimumDesktopVersion": "1.4.46",
7
7
  "nodeMajor": 22,
8
8
  "dependencyHash": "sha256-oaGYi/P5ob8sd6VnNBOwshKozjhdV+hYiCmLAsn5x00=",
9
- "serverBundleHash": "sha256-8rbCJEWANeXtZp/cvJ7UT9tGunnkMMxL7mcvARckvLQ=",
10
- "clientBundleHash": "sha256-9MzxeyAxwRf4rg374l2f6wUzrybLPL+H5boh1/uodkQ=",
9
+ "serverBundleHash": "sha256-TbAZkctDrckV3heGqq3j/WuZeJSNx5/tTHYzQNmiahg=",
10
+ "clientBundleHash": "sha256-faF/1hpcDUHYr8eCLtTq/Xg23fWqv2gWgPNgHTsk1Zs=",
11
11
  "entrypoint": "dist/server/cli.js",
12
12
  "clientEntrypoint": "dist/client/index.html"
13
13
  }
@@ -1,2 +0,0 @@
1
- import{bA as r}from"./app-DNdmWYEJ.js";import{b as m}from"./dnd-BCFAPC0L.js";import{b as n}from"./RightSidebar-Dx4Jf94o.js";import"./react-XDCjal2T.js";import"./terminal-C7X98Amf.js";import"./App-DrnLToMO.js";import"./gestureArbiter-q3jASYgN.js";import"./triangle-alert-DPNiOY7C.js";import"./referenceLongPress-5uMCEptL.js";import"./DiffReview-02640ofg.js";import"./sparkles-Cku-tzxx.js";import"./DiffViewer-CLjrE1oE.js";import"./ChangeWalkthroughPanel-BsG5tR4F.js";function g({content:o}){const e=m.useMemo(()=>n(o.split(`
2
- `),null,null),[o]);return r.jsx("div",{className:"min-w-0 space-y-3 break-words text-sm leading-6 text-foreground [&_h1]:text-lg [&_h2]:text-base [&_h3]:text-sm [&_pre]:max-w-full [&_table]:text-xs",children:e.map((t,i)=>r.jsx("div",{className:"min-w-0",children:typeof t.content=="function"?t.content(null):t.content},i))})}export{g as default};
@@ -1,5 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/rdpSession-CWvrHSd8.js","assets/app-DNdmWYEJ.js","assets/react-XDCjal2T.js","assets/dnd-BCFAPC0L.js","assets/terminal-C7X98Amf.js","assets/index-Dd_3ISCb.css","assets/ChangeWalkthroughPanel-BsG5tR4F.js","assets/sparkles-Cku-tzxx.js","assets/triangle-alert-DPNiOY7C.js","assets/App-DrnLToMO.js","assets/gestureArbiter-q3jASYgN.js","assets/gestureArbiter-C2J0D0kV.css","assets/referenceLongPress-5uMCEptL.js"])))=>i.map(i=>d[i]);
2
- import{ah as De,cz as Lt,df as gt,bA as t,cw as Ie,bz as Ve,W as it,o as lt,l as Tt,X as At,_ as ut}from"./app-DNdmWYEJ.js";import{b as o,r as dt}from"./dnd-BCFAPC0L.js";import{a as Rt}from"./ChangeWalkthroughPanel-BsG5tR4F.js";import{s as mt,Y as pt,K as He,j as ft}from"./App-DrnLToMO.js";import{M as _t}from"./triangle-alert-DPNiOY7C.js";const Mt=[["path",{d:"M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z",key:"edeuup"}]],ht=De("mouse-pointer-2",Mt);const It=[["path",{d:"M14 17H5",key:"gfn3mx"}],["path",{d:"M19 7h-9",key:"6i9tg"}],["circle",{cx:"17",cy:"17",r:"3",key:"18b49y"}],["circle",{cx:"7",cy:"7",r:"3",key:"dfmy0x"}]],Pt=De("settings-2",It);const Dt=[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65",key:"13gj7c"}],["line",{x1:"11",x2:"11",y1:"8",y2:"14",key:"1vmskp"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11",key:"durymu"}]],zt=De("zoom-in",Dt);const Ot=[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65",key:"13gj7c"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11",key:"durymu"}]],Ft=De("zoom-out",Ot);function Ye(e){const c=e==="darwin"?"mac":e==="win32"?"windows":"linux",f={host:"127.0.0.1",platform:c,protocol:c==="mac"?"vnc":"rdp",port:"3389",username:"",domain:"",ignoreCert:!1,rememberLogin:!0};return{target:"local",local:f,remote:{...f,host:""},viewOnly:!1,fit:!0,autoConnect:!0}}function xt(e,c){const f=Ye(c);if(!e||typeof e!="object")return f;const u=e,p=(x,d)=>{const s=x&&typeof x=="object"?x:{},v=(g,P)=>typeof s[g]=="string"&&s[g].length<=P&&!/[\x00-\x1f]/.test(s[g])?s[g]:d[g];return{host:v("host",253),username:v("username",255),domain:v("domain",255),platform:["mac","linux","windows"].includes(String(s.platform))?s.platform:d.platform,protocol:s.protocol==="rdp"||s.protocol==="vnc"?s.protocol:d.protocol,port:typeof s.port=="string"&&/^\d{0,5}$/.test(s.port)&&Number(s.port)<=65535?s.port:d.port,ignoreCert:s.ignoreCert===!0,rememberLogin:s.rememberLogin!==!1}};return{target:u.target==="remote"?"remote":"local",local:{...p(u.local,f.local),host:"127.0.0.1"},remote:p(u.remote,f.remote),viewOnly:u.viewOnly===!0,fit:u.fit!==!1,autoConnect:u.autoConnect!==!1}}function bt(e){return JSON.stringify([e.host.trim().toLowerCase(),e.protocol,e.protocol==="vnc"?5900:Number(e.port),e.username.trim(),e.domain.trim()])}function $t(e){const[c,f]=o.useState(Ye),[u,p]=o.useState(!1),[x,d]=o.useState("loading"),[s,v]=o.useState(0),[g,P]=o.useState([]),[W,T]=o.useState("idle"),k=o.useRef(c),A=o.useRef(0),a=o.useRef(0),N=o.useRef(""),b=o.useRef(null),C=o.useRef(new Set),K=o.useCallback(w=>{k.current=w(k.current),A.current++,f(k.current),d("saving")},[]);o.useEffect(()=>{const w=++a.current;A.current=0,N.current="",b.current=null,k.current=Ye(),f(k.current),p(!1),d("loading"),P([]),T("idle");const D=new AbortController;return fetch("/api/computer/preferences",{signal:D.signal}).then(async h=>{if(!h.ok)throw new Error("PREFERENCES_LOAD_FAILED");return await h.json()}).then(h=>{if(w!==a.current||D.signal.aborted)return;let R=xt(h.preferences);const O=A.current>0;if(!h.configured&&!O)try{const E=localStorage.getItem(`termdock:computer-host:${e}`);if(E){const U=/^(127\.0\.0\.1|localhost|::1|\[::1\])$/i.test(E)?"local":"remote";R=xt({...R,target:U,[U]:{...R[U],host:E,platform:localStorage.getItem(`termdock:computer-platform:${e}`)||R[U].platform,protocol:localStorage.getItem(`termdock:computer-protocol:${e}`)||"vnc",port:localStorage.getItem(`termdock:computer-rdp-port:${e}`)||"3389"}}),A.current++}}catch{}O||(k.current=R),N.current=h.configured?JSON.stringify(R):"",f(k.current),p(!0),d(h.configured?"saved":"saving"),P(Array.isArray(h.credentialKeys)?h.credentialKeys.filter(E=>typeof E=="string"):[]),T(h.credentialError?"error":"idle")}).catch(()=>{!D.signal.aborted&&w===a.current&&d("error")}),()=>{++a.current,D.abort();for(const h of C.current)h.abort();C.current.clear()}},[e,s]);const H=o.useCallback(()=>{if(b.current)return b.current;if(!u)return Promise.resolve(!1);const w=a.current,D=(async()=>{for(;N.current!==JSON.stringify(k.current);){const h=JSON.stringify(k.current),R=new AbortController;C.current.add(R),d("saving");try{if(!(await fetch("/api/computer/preferences",{method:"PUT",headers:{"Content-Type":"application/json"},body:h,signal:R.signal})).ok)throw new Error("PREFERENCES_SAVE_FAILED");if(w!==a.current)return!1;N.current=h}catch{return w===a.current&&d("error"),!1}finally{C.current.delete(R)}}return w===a.current&&d("saved"),!0})();return b.current=D,D.finally(()=>{b.current===D&&(b.current=null)}),D},[u]);o.useEffect(()=>{if(!u||N.current===JSON.stringify(c))return;const w=setTimeout(()=>{H()},300);return()=>clearTimeout(w)},[u,c,H]);const Z=o.useCallback(async(w,D,h)=>{const R=a.current,O=new AbortController;w!=="use"&&T("saving");try{if(!await H()||R!==a.current)throw new Error("COMPUTER_CREDENTIALS_FAILED");C.current.add(O);const E=await fetch(`/api/computer/credentials/${w}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({profile:D,...w==="save"?{password:h}:{}}),signal:O.signal});if(R!==a.current)throw new Error("COMPUTER_CREDENTIALS_FAILED");if(!E.ok)throw new Error(w==="use"&&E.status===404?"COMPUTER_CREDENTIALS_MISSING":"COMPUTER_CREDENTIALS_FAILED");const ne=await E.json();if(R!==a.current)throw new Error("COMPUTER_CREDENTIALS_FAILED");const U=bt(D);if(w==="save"&&P(ae=>[...new Set([...ae,U])]),w==="forget"&&P(ae=>ae.filter(pe=>pe!==U)),w==="use"&&(typeof ne.password!="string"||!ne.password))throw new Error("COMPUTER_CREDENTIALS_MISSING");return T("idle"),ne.password}catch(E){throw R===a.current&&!O.signal.aborted&&T("error"),E}finally{C.current.delete(O)}},[H]);return{preferences:c,change:K,loaded:u,saveState:x,flush:H,credentialKeys:g,loginState:W,credentialRequest:Z,retry:()=>u?void H():v(w=>w+1)}}class Ut{binaryType="arraybuffer";protocol="";CONNECTING=0;OPEN=1;CLOSING=2;CLOSED=3;onopen=null;onmessage=null;onerror=null;onclose=null;socket;get readyState(){return this.socket.readyState}constructor(c,f){this.socket=Lt(`/api/computer/ws?host=${encodeURIComponent(c)}`),this.socket.onopen=u=>this.onopen?.(u),this.socket.onerror=u=>this.onerror?.(u),this.socket.onclose=u=>{(u.code!==1e3||u.reason)&&f(u.reason||"COMPUTER_DISCONNECTED"),this.onclose?.(u)},this.socket.onmessage=u=>{try{const p=JSON.parse(u.data);if(p.type!=="data"||typeof p.data!="string"||!Number.isSafeInteger(p.seq))throw new Error("Invalid VNC record");const x=Uint8Array.from(atob(p.data),d=>d.charCodeAt(0));this.onmessage?.(new MessageEvent("message",{data:x.buffer})),this.socket.readyState===1&&this.socket.send(JSON.stringify({type:"ack",seq:p.seq}))}catch{f("COMPUTER_INVALID_MESSAGE"),this.close(),this.onclose?.(new CloseEvent("close",{code:4400}))}}}send(c){const f=ArrayBuffer.isView(c)?new Uint8Array(c.buffer,c.byteOffset,c.byteLength):new Uint8Array(c);for(let u=0;u<f.length;u+=32*1024){const p=f.subarray(u,u+32768);let x="";for(const d of p)x+=String.fromCharCode(d);this.socket.send(JSON.stringify({type:"data",data:btoa(x)}))}}close(){this.socket.close()}}function Vt(e){return e==="mac"||e==="linux"||e==="windows"}function Ht(e){const c=e==="mac"?[65513,"MetaLeft"]:[65507,"ControlLeft"],f=e==="mac"?c:[65515,"MetaLeft"];return{escape:[[65307,"Escape"]],enter:[[65293,"Enter"]],backspace:[[65288,"Backspace"]],tab:[e==="mac"?c:[65513,"AltLeft"],[65289,"Tab"]],search:e==="mac"?[f,[32,"Space"]]:[f],copy:[c,[99,"KeyC"]],paste:[c,[118,"KeyV"]],up:[[65362,"ArrowUp"]],down:[[65364,"ArrowDown"]],left:[[65361,"ArrowLeft"]],right:[[65363,"ArrowRight"]]}}function Bt(e){const c=e;return{size:()=>({width:c._fbWidth,height:c._fbHeight}),surface:()=>c._canvas,send:(f,u,p)=>{const x=c._display.scale,d=(f-c._display.absX(0))*x,s=(u-c._display.absY(0))*x;c._mousePos={x:d,y:s},c._mouseMoveTimer!==null&&clearTimeout(c._mouseMoveTimer),c._mouseMoveTimer=null,c._mouseButtonMask=p,c._mouseLastMoveTime=Date.now(),c._sendMouse(d,s,p)}}}const yt="termdock:computer-touch-mode:v1";function Kt(){try{const e=localStorage.getItem(yt);if(e==="trackpad"||e==="direct")return e}catch{}return navigator.maxTouchPoints>0&&window.matchMedia("(any-pointer: coarse)").matches?"trackpad":"direct"}function Yt(e){try{localStorage.setItem(yt,e)}catch{}}const Xt=8,Wt=300,qt=450,Be=18,Ce=(e,c)=>Math.max(0,Math.min(e,Math.max(0,c-1)));function Zt(e,c,f,u,p={}){const x=new AbortController,d=new Map;let s=0,v=0,g=!1,P=!1,W=!1,T=!1,k=0,A=1,a=0,N=0,b,C=!1,K=!0,H=!0,Z,w=!1;const D=()=>{const n=c.size(),l=u.current??={x:n.width/2,y:n.height/2};return l.x=Ce(l.x,n.width),l.y=Ce(l.y,n.height),l};let h;const R=()=>{const n=c.size();if((!h||h.width!==n.width||h.height!==n.height)&&(H=!0),!H&&h)return h;const l=c.surface(),S=e.getBoundingClientRect(),m=l.getBoundingClientRect(),y=[];for(let L=l.parentElement;L&&L!==e;L=L.parentElement){const j=getComputedStyle(L),$=/auto|scroll/.test(j.overflowX)?Math.max(0,L.scrollWidth-L.clientWidth):0,Re=/auto|scroll/.test(j.overflowY)?Math.max(0,L.scrollHeight-L.clientHeight):0;if(!$&&!Re)continue;const xe=L.getBoundingClientRect();y.push({element:L,left:xe.left-S.left,top:xe.top-S.top,right:xe.right-S.left,bottom:xe.bottom-S.top,maxX:$,maxY:Re})}return h={...n,left:m.left-S.left,top:m.top-S.top,scaleX:n.width&&m.width?m.width/n.width:1,scaleY:n.height&&m.height?m.height/n.height:1,viewportWidth:S.width,viewportHeight:S.height,clientLeft:S.left,clientTop:S.top,scrollers:y},H=!1,h},O=()=>{const n=R(),l=D();if(!n.width||!n.height||!K||T||p.mode==="direct"||p.viewOnly){f.hidden=!0;return}let S=n.left+l.x*n.scaleX,m=n.top+l.y*n.scaleY;for(const y of n.scrollers){if(y.maxX){const L=y.element.scrollLeft,j=S<y.left+20?S-y.left-20:S>y.right-20?S-y.right+20:0,$=Math.max(0,Math.min(y.maxX,L+j));L!==$&&(y.element.scrollLeft=$,S-=$-L,n.left-=$-L)}if(y.maxY){const L=y.element.scrollTop,j=m<y.top+20?m-y.top-20:m>y.bottom-20?m-y.bottom+20:0,$=Math.max(0,Math.min(y.maxY,L+j));L!==$&&(y.element.scrollTop=$,m-=$-L,n.top-=$-L)}}f.hidden=S<0||m<0||S>=n.viewportWidth||m>=n.viewportHeight,f.style.transform=`translate3d(${S}px, ${m}px, 0)`},E=(n=N)=>{if(p.viewOnly)return;const l=D();c.send(Math.round(l.x),Math.round(l.y),n)},ne=()=>{b=void 0,O(),C&&(C=!1,E());let n=0;for(;Math.abs(a)>=Be&&n++<8;){const l=a>0?16:8;E(l),E(0),a-=Math.sign(a)*Be}},U=()=>{w||(b??=requestAnimationFrame(ne))},ae=()=>{b!==void 0&&(cancelAnimationFrame(b),ne())},pe=()=>{clearTimeout(Z),ae(),N&&(N=0,E())},fe=n=>{n.cancelable&&n.preventDefault(),n.stopImmediatePropagation()},je=()=>[...d.values()].reduce((n,l)=>n+l.y,0)/d.size,he=()=>{const[n,l]=[...d.values()];return{distance:Math.hypot(n.x-l.x,n.y-l.y),x:(n.x+l.x)/2,y:(n.y+l.y)/2}},G=n=>{const l=R();u.current={x:Ce((n.clientX-l.clientLeft-l.left)/l.scaleX,l.width),y:Ce((n.clientY-l.clientTop-l.top)/l.scaleY,l.height)}},ke=n=>{if(!(n.pointerType!=="touch"&&n.pointerType!=="pen")){fe(n),K=!0,U(),d.size||(s=performance.now(),v=0,g=!1,P=!1,W=!1,T=!1,a=0,p.mode==="direct"&&G(n)),d.set(n.pointerId,{x:n.clientX,y:n.clientY,startX:n.clientX,startY:n.clientY}),v=Math.max(v,d.size);try{e.setPointerCapture(n.pointerId)}catch{}clearTimeout(Z),d.size===1&&v===1?Z=setTimeout(()=>{!w&&d.size===1&&!g&&!P&&(N=1,E())},qt):(pe(),W=!0,d.size===2&&(k=he().distance,A=p.zoom?.get()??1))}},ie=n=>{if(n.pointerType==="mouse"){const j=R();u.current={x:Ce((n.clientX-j.clientLeft-j.left)/j.scaleX,j.width),y:Ce((n.clientY-j.clientTop-j.top)/j.scaleY,j.height)},K=!1,f.hidden=!0;return}const l=d.get(n.pointerId);if(!l)return;fe(n);const S=je(),m=d.size===2?he():void 0,y=n.clientX-l.x,L=n.clientY-l.y;if(l.x=n.clientX,l.y=n.clientY,Math.hypot(l.x-l.startX,l.y-l.startY)>Xt&&(g=!0,clearTimeout(Z)),d.size===2&&!P){const j=he();if(p.zoom&&k>0&&(T||Math.abs(j.distance/k-1)>.06)){T=!0,g=!0,a=0,p.zoom.set(A*j.distance/k,j),H=!0,m&&p.zoom.pan(j.x-m.x,j.y-m.y),U();return}if(p.mode==="direct"&&p.zoom&&p.zoom.get()>1&&m){g=!0,p.zoom.pan(j.x-m.x,j.y-m.y),H=!0,U();return}a+=S-je(),Math.abs(a)>=Be&&(g=!0,U())}else if(d.size===1&&!W&&!P){if(p.mode==="direct"){G(n),g&&(N=1),C=!0,U();return}const j=D(),$=R();j.x+=y/$.scaleX,j.y+=L/$.scaleY,D(),C=!0,U()}},Y=n=>{if(!d.has(n.pointerId))return;fe(n);const l=N!==0;n.type!=="pointerup"&&(P=!0),pe(),d.delete(n.pointerId);try{e.hasPointerCapture(n.pointerId)&&e.releasePointerCapture(n.pointerId)}catch{}d.size||(a=0,!P&&!l&&!g&&v<=2&&performance.now()-s<=Wt&&(p.mode!=="direct"||v===1)&&(E(v===2?4:1),E(0)))},_=()=>{P=!0,pe();const n=[...d.keys()];d.clear(),a=0;for(const l of n)try{e.hasPointerCapture(l)&&e.releasePointerCapture(l)}catch{}},B={capture:!0,passive:!1,signal:x.signal};e.addEventListener("pointerdown",ke,B),e.addEventListener("pointermove",ie,B),e.addEventListener("pointerup",Y,B),e.addEventListener("pointercancel",Y,B),e.addEventListener("lostpointercapture",Y,B);for(const n of["touchstart","touchmove","touchend","touchcancel","contextmenu"])e.addEventListener(n,fe,B);const J=()=>{H=!0,U()};e.addEventListener("scroll",J,{capture:!0,signal:x.signal}),window.addEventListener("blur",_,{signal:x.signal});const Q=()=>{document.hidden&&_()};document.addEventListener("visibilitychange",Q,{signal:x.signal});const Ne=new ResizeObserver(J);return Ne.observe(e),Ne.observe(c.surface()),O(),()=>{w||(w=!0,x.abort(),_(),Ne.disconnect(),f.hidden=!0)}}function Gt(e,c){e=Math.max(1,e||1280),c=Math.max(1,c||800);const f=Math.max(1,640/e,480/c);return{width:Math.max(640,Math.min(2560,Math.round(e*f))),height:Math.max(480,Math.min(1600,Math.round(c*f)))}}const Ke="​",Jt={Enter:"enter",Backspace:"backspace",Delete:"delete",Tab:"tab",ArrowUp:"up",ArrowDown:"down",ArrowLeft:"left",ArrowRight:"right"};function Qt({sendText:e,sendKey:c,inputRef:f,onFocusChange:u}){const{t:p}=gt(),x=o.useRef(null),d=o.useRef(!1),s=o.useRef(null),v=f??x,g=o.useRef({sendText:e,sendKey:c});g.current={sendText:e,sendKey:c};const[P,W]=o.useState(!1),T=()=>{v.current&&(v.current.value=Ke,v.current.setSelectionRange(1,1)),W(!1)},k=()=>{const a=(v.current?.value||"").replace(/^\u200b/,"");a&&g.current.sendText(a),T()},A=()=>{s.current!==null&&(cancelAnimationFrame(s.current),s.current=null),k()};return o.useLayoutEffect(()=>{const a=v.current;a.value=Ke,a.setSelectionRange(1,1),a.focus({preventScroll:!0});const N=b=>{if(d.current||b.isComposing)return;const C=b.inputType==="deleteContentBackward"?"backspace":b.inputType==="deleteContentForward"?"delete":["insertLineBreak","insertParagraph"].includes(b.inputType)?"enter":null;if(!C)return;b.preventDefault();const K=C==="enter"&&s.current!==null;A(),K||g.current.sendKey(C)};return a.addEventListener("beforeinput",N),()=>{a.removeEventListener("beforeinput",N),s.current!==null&&cancelAnimationFrame(s.current)}},[]),t.jsxs("div",{className:"relative shrink-0 border-t border-border bg-surface px-3 py-2",children:[!P&&t.jsx("span",{"aria-hidden":"true",className:"pointer-events-none absolute inset-y-2 left-6 flex items-center text-sm text-muted-foreground",children:p("computer.keyboardPlaceholder")}),t.jsx("input",{ref:v,className:"min-h-11 w-full rounded-md border border-border bg-background px-3 text-base outline-none focus:border-primary","aria-label":p("computer.keyboardInput"),autoCapitalize:"none",autoCorrect:"off",autoComplete:"off",spellCheck:!1,inputMode:"text",enterKeyHint:"enter",maxLength:1025,defaultValue:Ke,onChange:a=>{if(W(!!a.target.value.replace(/^\u200b/,"")),d.current||a.nativeEvent.isComposing||s.current!==null)return;a.nativeEvent.inputType==="deleteContentBackward"&&!a.target.value?(g.current.sendKey("backspace"),T()):k()},onCompositionStart:()=>{s.current!==null&&A(),d.current=!0},onCompositionEnd:()=>{d.current=!1,s.current!==null&&cancelAnimationFrame(s.current),s.current=requestAnimationFrame(()=>{s.current=null,k()})},onFocus:()=>u?.(!0),onBlur:()=>{!d.current&&s.current!==null&&A(),u?.(!1)},onKeyDown:a=>{if(d.current||a.nativeEvent.isComposing||a.keyCode===229)return;const N=Jt[a.key];N&&(a.preventDefault(),A(),g.current.sendKey(N))}})]})}function er(e){let c=[],f=null;const u=new Map,p=()=>{f=null,c.splice(0,32).forEach(x=>{e(x),x[2]?u.set(x[0],x):u.delete(x[0])}),c.length&&(f=requestAnimationFrame(p))};return{send(x){c.push(...x),f===null&&p()},clear(){f!==null&&cancelAnimationFrame(f),f=null,c=[];const x=[...u.values()].reverse();u.clear();for(const[d,s]of x)try{e([d,s,!1])}catch{}}}}const tr=e=>Math.max(1,Math.min(8,Number.isFinite(e)?e:1));function rr(e,c){let f=1;const u="viewportZoom"in e,p=e,x=()=>u?e.pointerTarget.surface():p._canvas,d=()=>u?e.viewportScroller:p._screen,s=u?void 0:p._updateScale;return s&&(p._updateScale=function(){s.call(p),p._display.scale*=f}),{get:()=>f,set(v,g){const P=tr(v),W=x(),T=d(),k=W.getBoundingClientRect(),A=T.getBoundingClientRect(),a=g??{x:A.left+A.width/2,y:A.top+A.height/2},N={x:(a.x-k.left)/(k.width||1),y:(a.y-k.top)/(k.height||1)};f=P,u?e.viewportZoom=f:p._updateScale();const b=W.getBoundingClientRect();T.scrollLeft+=b.left+N.x*b.width-a.x,T.scrollTop+=b.top+N.y*b.height-a.y,f===1&&(T.scrollLeft=0,T.scrollTop=0),c(f)},pan(v,g){const P=d();P.scrollLeft-=v,P.scrollTop-=g},dispose(){s&&(p._updateScale=s)}}}const ce="inline-flex min-h-9 items-center justify-center gap-1.5 rounded-md border border-border px-2.5 text-xs hover:bg-surface-2 disabled:opacity-40",me="min-h-11 w-full rounded-md border border-border bg-background px-2 text-sm outline-none focus:border-primary";function Pe(e){return/API_NOT_ALLOWED|AUTHORIZATION|revoked|PAIRING/.test(e)?"computer.permission":e.includes("RDP_BACKEND_UNAVAILABLE")?"computer.rdpBackendUnavailable":e.includes("RDP_CERTIFICATE")?"computer.rdpCertificate":e.includes("CREDENTIALS_MISSING")?"computer.loginExpired":e.includes("CREDENTIALS_FAILED")?"computer.loginSaveFailed":e.includes("AUTH_FAILED")?"computer.authFailed":e.includes("RDP_FAILED")?"computer.rdpFailed":e.includes("SCREEN_SHARING_OFF")?"computer.sharingOff":e.includes("PRIVATE_HOST_ONLY")?"computer.privateOnly":e.includes("INVALID_HOST")?"computer.invalidHost":e.includes("TIMEOUT")?"computer.timeout":e.includes("UNREACHABLE")?"computer.unreachable":e.includes("DISCONNECTED")?"computer.disconnected":"computer.failed"}function nr(){const{t:e}=gt(),[c,f]=o.useState(()=>Ie()?.targetPeerId??""),[u,p]=o.useState(null),{preferences:x,change:d,loaded:s,saveState:v,flush:g,retry:P,credentialKeys:W,loginState:T,credentialRequest:k}=$t(c),A=x.target==="local",a=x[x.target],{host:N,platform:b,protocol:C,port:K,domain:H,ignoreCert:Z,username:w}=a,D=C==="rdp"&&u?.rdpAvailable===!1,{viewOnly:h,fit:R}=x,O=a.rememberLogin&&W.includes(bt(a)),E=r=>d(i=>({...i,[i.target]:{...i[i.target],...r}})),ne=r=>E({username:r}),U=r=>E({domain:r}),ae=r=>{E({ignoreCert:r}),g()},pe=r=>E({port:r}),fe=r=>{r&&(le.current(),Le.clear(),y(null)),d(i=>({...i,viewOnly:r})),g()},[je,he]=o.useState(!1),G=Ht(b),ke=b==="mac"?"⌘V":"Ctrl+V",[ie,Y]=o.useState(""),[_,B]=o.useState("idle"),[J,Q]=o.useState(null),[Ne,n]=o.useState(""),[l,S]=o.useState(!1),[m,y]=o.useState(null),L=o.useRef(null),[j,$]=o.useState(!1),[Re,xe]=o.useState(!1),Xe=o.useRef(0),[q,vt]=o.useState(()=>navigator.maxTouchPoints>0||window.innerWidth<=640);o.useEffect(()=>{const r=()=>vt(navigator.maxTouchPoints>0||window.innerWidth<=640);return window.addEventListener("resize",r),()=>window.removeEventListener("resize",r)},[]);const _e=m==="keyboard"&&j&&(!q||!window.visualViewport||Re),[Ee,We]=o.useState(1),ee=o.useRef(null),ze=o.useRef(null),[Me,qe]=o.useState(""),[wt,Se]=o.useState(!1),[Ct,jt]=o.useState(!1),[oe,kt]=o.useState(Kt),Ze=o.useRef(null),Ge=o.useRef(null),le=o.useRef(()=>{}),[Je,Nt]=o.useState(Ve),ve=o.useRef(!1),ue=o.useRef(""),Qe=o.useRef(()=>{}),et=o.useRef(null),Oe=o.useRef(null),ge=o.useMemo(()=>{const r=document.createElement("div");return r.className="h-full w-full min-h-0 overflow-hidden",r},[]),F=o.useRef(null),Le=o.useMemo(()=>er(([r,i,I])=>F.current?.sendKey(r,i,I)),[]),Fe=o.useRef(null),se=o.useRef(0),$e=o.useRef(void 0),te=o.useCallback(()=>{le.current(),ee.current?.dispose(),ee.current=null,Le.clear(),Ge.current=null,se.current++,clearTimeout($e.current);const r=F.current;F.current=null,r?.disconnect(),Fe.current?.close(),Fe.current=null,ge.replaceChildren()},[ge,Le]);o.useLayoutEffect(()=>(Oe.current?.appendChild(ge),()=>{ge.remove()}),[ge,l]),o.useEffect(()=>()=>te(),[te]),o.useEffect(()=>{const r=()=>{const i=Ve();Nt(i),!i&&(ve.current=!1,ue.current="",te(),B("idle"),Y(""),S(!1),y(null))};return window.addEventListener(it,r),()=>window.removeEventListener(it,r)},[te]),o.useEffect(()=>{const r=()=>f(Ie()?.targetPeerId??"");return window.addEventListener(lt,r),()=>window.removeEventListener(lt,r)},[]),o.useEffect(()=>{te(),ve.current=!1,ue.current="",B("idle"),Q(null),Y(""),p(null),S(!1),y(null),he(!1),n(""),qe(""),Se(!1);const r=new AbortController;return fetch("/api/computer/status",{signal:r.signal}).then(async i=>{if(!i.ok)throw new Error(i.status===403?"API_NOT_ALLOWED":"COMPUTER_FAILED");return await i.json()}).then(i=>{r.signal.aborted||p(i)}).catch(i=>{r.signal.aborted||Q(Pe(String(i)))}),()=>{r.abort(),te()}},[c,te]),o.useEffect(()=>{F.current&&(F.current.viewOnly=h)},[h]),o.useEffect(()=>{F.current&&(F.current.scaleViewport=R)},[R]),o.useEffect(()=>{F.current&&"pauseResize"in F.current&&(F.current.pauseResize=!!m)},[m]),o.useEffect(()=>{const r=F.current;r&&("keyboardActive"in r?r.keyboardActive=m==="keyboard":r.focusOnClick=m!=="keyboard")},[m]);const tt=r=>{r===A||X||!s||(Y(""),Q(null),d(i=>({...i,target:r?"local":"remote"})),g())},rt=()=>{ve.current=!0,ue.current="",te(),B("idle"),Y(""),S(!1),y(null),Se(!1)},nt=async r=>{if(r?.preventDefault(),D)return;if(ve.current=!0,_==="credentials"&&F.current&&"sendCredentials"in F.current){ue.current=ie,F.current.sendCredentials({username:w,password:ie}),B("connecting");return}if(!Ve()||!s||!ie&&!O)return;g(),te(),Q(null),n(""),B("connecting"),Se(!1);const i=se.current,I=z=>{i===se.current&&(te(),B("error"),Q(z),y(null),ue.current="",(z==="computer.authFailed"||z==="computer.permission"||z==="computer.loginExpired")&&Y(""),O&&(z==="computer.authFailed"||z==="computer.loginExpired")&&k("forget",a).catch(()=>{}))};$e.current=setTimeout(()=>I("computer.timeout"),6e4);try{let z=ie||await k("use",a);if(i!==se.current)return;ue.current=z||"";let V;if(C==="rdp"){const{RdpSession:re}=await ut(async()=>{const{RdpSession:Ue}=await import("./rdpSession-CWvrHSd8.js");return{RdpSession:Ue}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12]));if(i!==se.current)return;const ye=window.innerWidth<=640,de=ze.current?.getBoundingClientRect(),Ae=Gt(ye?window.innerWidth:de?.width||1280,Math.max(1,(ye?window.innerHeight:de?.height||800)-100));V=new re(ge,{host:N.trim(),port:Number(K),username:w.trim(),password:z||"",domain:H.trim(),ignoreCert:Z,...Ae},Ue=>I(Pe(Ue)))}else{const{default:re}=await ut(async()=>{const{default:Ae}=await import("./rfb-CxsXsMUX.js");return{default:Ae}},[]);if(i!==se.current)return;const ye=new Ut(N.trim(),Ae=>I(Pe(Ae)));Fe.current=ye;const de=new re(ge,ye,{shared:!0,credentials:{username:w.trim()||void 0,password:z}});de.background="var(--chrome-bg)",de.resizeSession=!1,de.qualityLevel=6,de.compressionLevel=2,V=de}z=void 0,F.current=V,V.scaleViewport=R,V.viewOnly=h,V.addEventListener("connect",()=>{if(i!==se.current)return;clearTimeout($e.current),B("connected"),Y(""),window.innerWidth<=640&&(document.activeElement?.blur?.(),S(!0));const re=ue.current;ue.current="",a.rememberLogin&&re&&k("save",a,re).catch(()=>{})}),V.addEventListener("credentialsrequired",re=>{if(i!==se.current)return;const ye=re.detail.types;jt(ye.includes("username")),B("credentials")}),V.addEventListener("securityfailure",()=>I("computer.authFailed")),V.addEventListener("disconnect",()=>I("computer.disconnected")),V.addEventListener("desktopname",re=>{i===se.current&&n(re.detail.name)})}catch(z){I(Pe(String(z)))}},be=r=>{!F.current||_!=="connected"||h||Le.send([...r.map(([I,z])=>[I,z,!0]),...[...r].reverse().map(([I,z])=>[I,z,!1])])},M=_==="connected",X=_==="connecting"||_==="credentials";o.useEffect(()=>{const r=F.current;if(!M||!r||!("viewportZoom"in r)&&!("_display"in r))return;const i=rr(r,We);return ee.current=i,We(1),()=>{i.dispose(),ee.current===i&&(ee.current=null)}},[M]),o.useEffect(()=>{const r=F.current,i=Oe.current,I=Ze.current;if(!M||m&&m!=="keyboard"||oe!=="trackpad"&&!(navigator.maxTouchPoints>0)||!r||!i||!I)return;const z="pointerTarget"in r?r.pointerTarget:Bt(r),V=Zt(i,z,I,Ge,{mode:oe,zoom:ee.current??void 0,viewOnly:h});return le.current=V,()=>{V(),le.current===V&&(le.current=()=>{})}},[M,h,oe,l,m]);const ot=r=>{r!==oe&&(le.current(),kt(r),Yt(r))};Qe.current=()=>{nt()},o.useEffect(()=>{Je&&s&&u&&!D&&x.autoConnect&&O&&_==="idle"&&!ve.current&&Qe.current()},[Je,s,u,D,x.autoConnect,O,_]);const st=()=>{ve.current=!0,k("forget",a).catch(()=>{})},we=r=>{if(r==="keyboard"){if(m==="keyboard"&&!_e){L.current?.blur(),L.current?.focus({preventScroll:!0});return}le.current(),Xe.current=window.visualViewport?.height??window.innerHeight,dt.flushSync(()=>{$(!1),xe(!1),y(i=>i===r?null:r)})}else le.current(),y(i=>i===r?null:r)},Et=()=>{ee.current?.set(1),d(r=>({...r,fit:!0})),g()},St=r=>{if(!F.current||h)return;const i=[];for(const I of r){const z=I.codePointAt(0),V=I===`
3
- `?65293:I===" "?65289:z<256?z:16777216|z;i.push([V,null,!0],[V,null,!1])}Le.send(i)};o.useEffect(()=>{if(!M||m!=="keyboard"&&m!=="clipboard"||!window.visualViewport)return;const r=window.visualViewport,i=ze.current,I=()=>{m==="keyboard"&&xe(j&&Xe.current-r.height>100),l&&i&&r.height>=160&&(i.style.height=`${r.height}px`,i.style.top=`${r.offsetTop}px`)};return I(),r.addEventListener("resize",I),r.addEventListener("scroll",I),()=>{r.removeEventListener("resize",I),r.removeEventListener("scroll",I),i&&(i.style.height="",i.style.top="")}},[M,m,l,j]);const ct=t.jsxs("div",{className:"flex shrink-0 items-center text-xs",role:"group","aria-label":e("computer.desktopZoom"),title:q?e("computer.pinchHint"):void 0,children:[t.jsx("button",{type:"button",className:"flex min-h-11 min-w-11 items-center justify-center","aria-label":e("computer.zoomOut"),disabled:Ee<=1,onPointerDown:r=>r.preventDefault(),onClick:()=>ee.current?.set(Ee/1.25),children:t.jsx(Ft,{size:16})}),t.jsxs("button",{type:"button",className:"min-h-11 min-w-11","aria-label":e("computer.resetZoom"),onPointerDown:r=>r.preventDefault(),onClick:Et,children:[Math.round(Ee*100),"%"]}),t.jsx("button",{type:"button",className:"flex min-h-11 min-w-11 items-center justify-center","aria-label":e("computer.zoomIn"),disabled:Ee>=8,onPointerDown:r=>r.preventDefault(),onClick:()=>ee.current?.set(Ee*1.25),children:t.jsx(zt,{size:16})}),q&&t.jsx("span",{className:"hidden pr-2 text-[10px] text-muted-foreground sm:inline",children:e("computer.pinchHint")})]}),Te=`flex shrink-0 items-center justify-center rounded-md hover:bg-surface-2 focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary ${q?"min-h-11 min-w-11":"h-8 min-w-8"}`,at=t.jsxs("div",{ref:ze,className:`flex min-h-0 flex-col bg-surface text-foreground ${l?"fixed inset-0 z-modal-panel h-dvh pb-[env(safe-area-inset-bottom)] pt-[env(safe-area-inset-top)]":"relative h-full"}`,role:l?"dialog":void 0,"aria-modal":l||void 0,"aria-label":e("computer.title"),onKeyDown:r=>{r.stopPropagation(),r.key==="Escape"&&!r.nativeEvent.isComposing&&m&&(r.preventDefault(),y(null))},onKeyUp:r=>r.stopPropagation(),children:[t.jsxs("div",{className:`relative z-30 flex shrink-0 items-center gap-2 border-b border-border bg-surface px-2 ${q?"min-h-12":"min-h-8"}`,children:[l&&t.jsx("button",{type:"button",className:Te,onClick:()=>{S(!1),y(null)},"aria-label":e("computer.exitFullscreen"),children:t.jsx(Rt,{size:20})}),t.jsx(Tt,{size:16,className:"shrink-0 text-muted-foreground"}),t.jsx("span",{className:"min-w-0 flex-1 truncate text-xs font-medium",children:M&&(Ne||(A?u?.hostname||Ie()?.serviceName:N))||e("computer.title")}),M&&t.jsx("span",{className:"text-[11px] text-primary",children:e("computer.connected")}),M&&T==="error"&&t.jsx("span",{role:"alert",className:"text-[11px] text-destructive",children:e("computer.loginSaveFailed")}),M&&v==="saving"&&t.jsx("span",{role:"status","aria-label":e("computer.settingsSaving"),title:e("computer.settingsSaving"),children:t.jsx(mt,{size:12,className:"animate-spin text-muted-foreground"})}),M&&v==="error"&&t.jsxs("button",{type:"button",className:ce,title:e("computer.settingsSaveFailed"),"aria-label":e("computer.settingsSaveFailed"),onClick:P,children:["! ",e("computer.retry")]}),X&&t.jsxs("button",{type:"button",className:ce,onClick:rt,children:[t.jsx(pt,{size:14}),e("computer.cancel")]}),M&&!q&&m==="keyboard"&&t.jsx("button",{type:"button",className:Te,onClick:()=>we("keyboard"),"aria-label":e("computer.keyboard"),"aria-pressed":_e,children:t.jsx(He,{size:18})}),M&&!q&&t.jsx("button",{type:"button",className:`${Te} ${m==="clipboard"?"bg-surface-2 text-primary":""}`,disabled:h,onClick:()=>we("clipboard"),"aria-label":e("computer.clipboardTool"),title:e("computer.clipboardTool"),"aria-pressed":m==="clipboard",children:t.jsx(ft,{size:18})}),M&&!l&&t.jsxs("button",{type:"button",className:`${Te} gap-1 px-1 text-xs`,onClick:()=>S(!0),"aria-label":e("computer.fullscreen"),children:[t.jsx(_t,{size:16}),e("computer.expand")]}),M&&t.jsx("button",{type:"button",className:Te,onClick:()=>we("tools"),"aria-label":e("computer.tools"),"aria-expanded":m==="tools",children:t.jsx(Pt,{size:18})})]}),!M&&t.jsx("div",{className:"min-h-0 flex-1 overflow-y-auto p-4 sm:p-6",children:t.jsxs("div",{className:"mx-auto w-full max-w-md",children:[t.jsxs("form",{className:"space-y-3",onSubmit:r=>{nt(r)},"aria-busy":_==="connecting",children:[t.jsxs("div",{className:"grid grid-cols-2 gap-1 rounded-lg bg-background p-1",role:"group","aria-label":e("computer.target"),children:[t.jsx("button",{type:"button",className:`min-h-11 rounded-md px-3 text-sm font-medium ${A?"bg-surface-2 text-foreground":"text-muted-foreground hover:bg-surface"}`,"aria-pressed":A,disabled:X||!u||!s,onClick:()=>tt(!0),children:e("computer.thisComputer")}),t.jsx("button",{type:"button",className:`min-h-11 rounded-md px-3 text-sm font-medium ${A?"text-muted-foreground hover:bg-surface":"bg-surface-2 text-foreground"}`,"aria-pressed":!A,disabled:X||!s,onClick:()=>tt(!1),children:e("computer.otherComputer")})]}),A?t.jsx("p",{className:"text-xs leading-relaxed text-muted-foreground",role:"status",children:u?e("computer.localService",{name:Ie()?.serviceName||u.hostname}):e("computer.loading")}):t.jsxs("label",{className:"block space-y-1 text-xs",children:[t.jsx("span",{children:e("computer.host")}),t.jsx("input",{className:me,value:N,disabled:X||!s,onChange:r=>{E({host:r.target.value,domain:"",ignoreCert:!1}),Y(""),Q(null)},placeholder:e("computer.hostPlaceholder"),onBlur:()=>{g()},autoCapitalize:"none",autoCorrect:"off",spellCheck:!1,required:!0,maxLength:253})]}),t.jsxs("p",{className:"text-xs text-muted-foreground",children:[b==="mac"?"macOS":b==="linux"?"Ubuntu / Linux":"Windows"," · ",C.toUpperCase()," · ",C==="rdp"?K||"3389":"5900",h?` · ${e("computer.viewOnly")}`:""]}),t.jsxs("label",{className:"block space-y-1 text-xs",children:[t.jsx("span",{children:e(C==="rdp"?"computer.rdpUsername":"computer.username")}),t.jsx("input",{className:me,value:w,disabled:_==="connecting"||!s,onChange:r=>ne(r.target.value),onBlur:()=>{g()},autoCapitalize:"none",autoCorrect:"off",autoComplete:"off",required:C==="rdp"||_==="credentials"&&Ct,maxLength:255})]}),t.jsxs("label",{className:"block space-y-1 text-xs",children:[t.jsx("span",{children:e("computer.password")}),t.jsx("input",{className:me,type:"password",value:ie,disabled:_==="connecting"||!s,onChange:r=>Y(r.target.value),placeholder:O&&_!=="credentials"?e("computer.savedPassword"):void 0,autoComplete:"new-password",required:!O||_==="credentials",maxLength:1024})]}),t.jsx("p",{className:"text-[11px] leading-relaxed text-muted-foreground",children:e(C==="rdp"?"computer.rdpLoginHint":"computer.vncLoginHint")}),t.jsxs("div",{className:"flex min-h-11 items-center justify-between gap-2 text-xs",children:[t.jsxs("label",{className:"flex min-h-11 items-center gap-2",children:[t.jsx("input",{type:"checkbox",checked:a.rememberLogin,disabled:X||!s||T==="saving",onChange:r=>{const i=r.target.checked;E({rememberLogin:i}),!i&&O?k("forget",{...a,rememberLogin:i}).catch(()=>{}):g()}}),e("computer.rememberLogin")]}),O&&t.jsx("button",{type:"button",className:"min-h-11 text-muted-foreground underline",disabled:X||T==="saving",onClick:st,children:e("computer.forgetLogin")})]}),T==="error"&&!J&&t.jsx("p",{role:"alert",className:"text-xs text-destructive",children:e("computer.loginSaveFailed")}),D&&t.jsxs("div",{role:"status",className:"space-y-1 text-xs leading-relaxed text-muted-foreground",children:[t.jsx("p",{children:e("computer.rdpBackendUnavailable")}),t.jsx("p",{children:e("computer.rdpBackendRecovery")})]}),_==="credentials"&&t.jsx("p",{className:"text-xs text-primary",children:e("computer.credentials")}),J&&t.jsxs("div",{role:"alert",className:"rounded-md bg-surface-2 p-3 text-xs leading-relaxed text-destructive",children:[e(J),J==="computer.rdpCertificate"&&t.jsxs("label",{className:"mt-1 flex min-h-11 items-center gap-2 text-foreground",children:[t.jsx("input",{type:"checkbox",checked:Z,onChange:r=>ae(r.target.checked)}),e("computer.trustCertificateHere")]}),_==="error"&&J!=="computer.rdpCertificate"&&t.jsx("button",{type:"button",className:"mt-1 block min-h-9 text-foreground underline",onClick:()=>{he(!0),requestAnimationFrame(()=>et.current?.scrollIntoView?.({block:"nearest",behavior:"smooth"}))},children:e("computer.checkSettings")})]}),t.jsxs("button",{type:"submit",className:"inline-flex min-h-11 w-full items-center justify-center gap-2 rounded-md bg-primary px-3 text-sm font-medium text-primary-foreground disabled:opacity-40",disabled:!s||D||_==="connecting"||T==="saving"||A&&!u||!N.trim()||!ie&&(!O||_==="credentials")||C==="rdp"&&(!w.trim()||!Number.isInteger(Number(K))||Number(K)<1||Number(K)>65535),children:[_==="connecting"&&t.jsx(mt,{size:16,className:"animate-spin"}),e(_==="connecting"?"computer.connecting":_==="credentials"?"computer.authenticate":_==="error"?"computer.retryConnect":"computer.connect")]}),t.jsxs("details",{ref:et,className:"border-b border-border text-xs",open:je,onToggle:r=>he(r.currentTarget.open),children:[t.jsxs("summary",{className:"flex min-h-11 cursor-pointer list-none items-center justify-between text-muted-foreground",children:[t.jsx("span",{children:e("computer.advanced")}),t.jsx("span",{"aria-hidden":"true",children:je?"−":"+"})]}),t.jsxs("div",{className:"space-y-3 pb-4",children:[t.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[t.jsxs("label",{className:"block space-y-1",children:[t.jsx("span",{children:e("computer.platform")}),t.jsxs("select",{className:me,value:b,disabled:X||!s,onChange:r=>{Vt(r.target.value)&&E({platform:r.target.value,protocol:r.target.value==="mac"?"vnc":"rdp",ignoreCert:!1}),Y(""),g()},children:[t.jsx("option",{value:"mac",children:"macOS"}),t.jsx("option",{value:"linux",children:"Ubuntu / Linux"}),t.jsx("option",{value:"windows",children:"Windows"})]})]}),t.jsxs("label",{className:"block space-y-1",children:[t.jsx("span",{children:e("computer.protocol")}),t.jsxs("select",{className:me,value:C,disabled:X||!s,onChange:r=>{E({protocol:r.target.value==="rdp"?"rdp":"vnc"}),Y(""),Q(null),g()},children:[t.jsx("option",{value:"rdp",children:"RDP"}),t.jsx("option",{value:"vnc",children:"VNC"})]})]})]}),C==="rdp"&&t.jsxs(t.Fragment,{children:[t.jsxs("label",{className:"block space-y-1",children:[t.jsx("span",{children:e("computer.port")}),t.jsx("input",{className:me,type:"number",min:1,max:65535,step:1,value:K,disabled:X||!s,onBlur:()=>{g()},onChange:r=>pe(r.target.value)})]}),t.jsxs("label",{className:"block space-y-1",children:[t.jsx("span",{children:e("computer.domain")}),t.jsx("input",{className:me,value:H,disabled:X||!s,onBlur:()=>{g()},onChange:r=>U(r.target.value),autoComplete:"off",maxLength:255})]}),t.jsxs("label",{className:"flex min-h-11 items-center gap-2",children:[t.jsx("input",{type:"checkbox",checked:Z,disabled:X||!s,onChange:r=>ae(r.target.checked)}),e("computer.trustCertificate")]})]}),t.jsxs("label",{className:"flex min-h-11 items-center gap-2",children:[t.jsx("input",{type:"checkbox",checked:h,disabled:X||!s,onChange:r=>fe(r.target.checked)}),e("computer.viewOnly")]}),t.jsxs("label",{className:"flex min-h-11 items-center gap-2",children:[t.jsx("input",{type:"checkbox",checked:x.autoConnect,disabled:X||!s,onChange:r=>{d(i=>({...i,autoConnect:r.target.checked})),g()}}),e("computer.autoConnect")]})]})]})]}),t.jsxs("p",{role:"status",className:"mt-2 text-[11px] leading-relaxed text-muted-foreground",children:[e(v==="saved"?"computer.settingsSaved":v==="error"?s?"computer.settingsSaveFailed":"computer.settingsLoadFailed":v==="loading"?"computer.settingsLoading":"computer.settingsSaving"),v==="error"&&t.jsx("button",{type:"button",className:"ml-2 min-h-9 text-primary underline",onClick:P,children:e("computer.retry")})]}),t.jsxs("details",{className:"text-xs",children:[t.jsx("summary",{className:"flex min-h-11 cursor-pointer items-center text-muted-foreground",children:e("computer.setup")}),t.jsxs("ol",{className:"ml-4 list-decimal space-y-2 pt-2 leading-relaxed text-muted-foreground",children:[t.jsx("li",{children:e(C==="rdp"?b==="linux"?"computer.rdpLinuxStep1":"computer.rdpStep1":b==="mac"?"computer.step1":b==="linux"?"computer.linuxStep1":"computer.windowsStep1")}),t.jsx("li",{children:e(C==="rdp"?"computer.rdpStep2":b==="mac"?"computer.step2":b==="linux"?"computer.linuxStep2":"computer.windowsStep2")}),t.jsx("li",{children:e("computer.step3")})]}),C==="vnc"&&b==="linux"&&t.jsxs(t.Fragment,{children:[t.jsx("p",{className:"mt-3 leading-relaxed text-muted-foreground",children:e("computer.linuxCommandHint")}),t.jsx("pre",{className:"mt-2 overflow-x-auto rounded-md bg-background p-2 text-[11px]",children:t.jsx("code",{children:`sudo apt install x11vnc
4
- x11vnc -storepasswd
5
- x11vnc -display "$DISPLAY" -auth guess -localhost -usepw -forever -shared -rfbport 5900`})}),t.jsx("p",{className:"mt-2 leading-relaxed text-muted-foreground",children:e("computer.linuxProtocolHint")})]}),t.jsx("p",{className:"mt-3 leading-relaxed text-muted-foreground",children:e(C==="rdp"?"computer.rdpNetworkHint":"computer.networkHint")})]})]})}),M&&m==="tools"&&t.jsx("button",{type:"button",className:`absolute inset-x-0 ${q?"bottom-14 top-12":"bottom-0 top-8"} z-20 bg-background/40`,"aria-label":e("computer.returnToDesktop"),onClick:()=>y(null)}),M&&t.jsxs("div",{hidden:m!=="tools",className:`${m==="tools"?"flex":"hidden"} absolute inset-x-3 ${q?"top-14":"top-10"} z-30 max-h-[calc(100%-7rem)] flex-wrap items-center gap-3 overflow-y-auto rounded-lg border border-border bg-surface px-4 py-3 text-xs shadow-lg [&_button]:min-h-11 [&_select]:min-h-11 [&_label]:min-h-11`,role:"region","aria-label":e("computer.tools"),children:[t.jsxs("div",{className:"flex w-full items-center justify-between",children:[t.jsx("span",{className:"font-medium",children:e("computer.tools")}),t.jsx("button",{type:"button",className:"flex min-w-11 items-center justify-center","aria-label":e("computer.closeTools"),onClick:()=>y(null),children:t.jsx(At,{size:18})})]}),q&&t.jsx("div",{className:"flex w-full items-center gap-2",children:t.jsx("div",{className:"inline-flex rounded-md bg-background p-0.5",role:"group","aria-label":e("computer.touchMode"),children:["trackpad","direct"].map(r=>t.jsx("button",{type:"button",className:`min-h-9 rounded px-3 text-xs ${oe===r?"bg-surface-2 text-foreground":"text-muted-foreground hover:bg-surface"}`,"aria-pressed":oe===r,onClick:()=>ot(r),children:e(r==="trackpad"?"computer.trackpadMode":"computer.directTouchMode")},r))})}),!q&&t.jsxs(t.Fragment,{children:[ct,t.jsxs("button",{type:"button",className:ce,disabled:h,onClick:()=>we("keyboard"),children:[t.jsx(He,{size:14}),e("computer.keyboard")]})]}),t.jsxs("label",{className:"flex min-h-9 items-center gap-1.5",children:[t.jsx("input",{type:"checkbox",checked:h,onChange:r=>fe(r.target.checked)}),e("computer.viewOnly")]}),t.jsx("button",{type:"button",className:ce,onClick:()=>{ee.current?.set(1),d(r=>({...r,fit:!r.fit})),g()},children:e(R?"computer.actualSize":"computer.fit")}),t.jsxs("select",{className:`${ce} min-w-0 bg-surface`,"aria-label":e("computer.shortcuts"),value:"",disabled:h,onChange:r=>{be(G[r.target.value]??[])},children:[t.jsx("option",{value:"",disabled:!0,children:e("computer.shortcuts")}),t.jsxs("option",{value:"tab",children:[b==="mac"?"⌘ Tab":"Alt+Tab"," · ",e("computer.switchApps")]}),t.jsxs("option",{value:"search",children:[b==="mac"?"⌘ Space":"Super / Win"," · ",e(b==="mac"?"computer.spotlight":"computer.systemSearch")]}),t.jsx("option",{value:"copy",children:b==="mac"?"⌘C":"Ctrl+C"}),t.jsx("option",{value:"paste",children:ke}),t.jsx("option",{value:"escape",children:"Esc"}),t.jsx("option",{value:"enter",children:"Enter"}),t.jsx("option",{value:"backspace",children:"⌫"}),t.jsx("option",{value:"up",children:"↑"}),t.jsx("option",{value:"down",children:"↓"}),t.jsx("option",{value:"left",children:"←"}),t.jsx("option",{value:"right",children:"→"})]}),t.jsxs("div",{className:"flex w-full items-center justify-between border-t border-border pt-2",children:[O&&t.jsx("button",{type:"button",className:ce,disabled:T==="saving",onClick:st,children:e("computer.forgetLogin")}),t.jsxs("button",{type:"button",className:`${ce} ml-auto text-destructive`,onClick:rt,children:[t.jsx(pt,{size:14}),e("computer.disconnect")]})]})]}),t.jsx("div",{ref:Oe,"data-sidebar-gesture-ignore":"",className:`relative z-10 min-h-0 flex-1 overflow-hidden bg-[var(--chrome-bg)] ${M?"":"hidden"}`,onMouseDownCapture:r=>{m==="keyboard"&&r.preventDefault()},style:{touchAction:M?"none":void 0},"aria-label":e("computer.remoteTitle"),children:M&&t.jsx("div",{ref:Ze,hidden:!0,"aria-hidden":"true",className:"pointer-events-none absolute left-0 top-0 z-20 h-5 w-5 will-change-transform",children:t.jsx(ht,{size:20,strokeWidth:2,className:"fill-background text-primary drop-shadow"})})}),t.jsx("div",{hidden:m!=="tools",children:M&&q&&!h&&t.jsx("p",{className:"shrink-0 border-t border-border px-2 py-1 text-[10px] leading-relaxed text-muted-foreground",children:e(oe==="trackpad"?"computer.trackpadHint":"computer.directTouchHint")})}),M&&m==="keyboard"&&!h&&t.jsxs(t.Fragment,{children:[t.jsx(Qt,{inputRef:L,onFocusChange:$,sendText:St,sendKey:r=>be(r==="tab"?[[65289,"Tab"]]:r==="delete"?[[65535,"Delete"]]:G[r])}),t.jsx("div",{className:"grid shrink-0 grid-cols-6 gap-1 bg-surface px-1",role:"group","aria-label":e("computer.keyboardNavigation"),children:["escape","left","down","up","right","selectAll"].map(r=>t.jsx("button",{type:"button",className:"min-h-11 rounded-md text-sm hover:bg-surface-2","aria-label":e(`computer.key${r[0].toUpperCase()}${r.slice(1)}`),onPointerDown:i=>i.preventDefault(),onClick:()=>be(r==="selectAll"?[...G.copy.slice(0,1),[97,"KeyA"]]:G[r]),children:{escape:"Esc",left:"←",down:"↓",up:"↑",right:"→",selectAll:b==="mac"?"⌘A":"Ctrl+A"}[r]},r))})]}),M&&m==="clipboard"&&!h&&t.jsxs("form",{className:"shrink-0 space-y-2 border-t border-border p-3",onSubmit:r=>{if(r.preventDefault(),!(!Me||!F.current))try{F.current.clipboardPasteFrom(Me),Se(!0)}catch{Q("computer.clipboardFailed")}},children:[t.jsx("textarea",{className:`${me} min-w-0 resize-none py-2 text-base`,rows:2,"aria-label":e("computer.clipboard"),placeholder:e("computer.clipboardPlaceholder"),value:Me,onChange:r=>{qe(r.target.value),Se(!1)},maxLength:16384}),t.jsxs("div",{className:"flex gap-2",children:[t.jsx("button",{type:"submit",className:`${ce} min-h-11 flex-1`,disabled:!Me,children:e("computer.clipboard")}),t.jsx("button",{type:"button",className:`${ce} min-h-11`,onClick:()=>be(G.paste),children:ke})]}),t.jsx("p",{role:"status",className:"text-[10px] leading-relaxed text-muted-foreground",children:wt?e("computer.clipboardSent"):e("computer.clipboardHint",{shortcut:ke})}),J&&t.jsx("p",{role:"alert",className:"text-xs text-destructive",children:e(J)})]}),M&&q&&t.jsxs("div",{className:"relative z-30 flex shrink-0 items-center border-t border-border bg-surface px-1 py-1 text-[11px]",children:[t.jsxs("div",{className:`grid min-w-0 flex-1 ${m==="keyboard"?"grid-cols-5":"grid-cols-3"}`,children:[t.jsxs("button",{type:"button",className:`flex min-h-11 flex-col items-center justify-center gap-0.5 rounded-md ${_e?"bg-surface-2 text-primary":""}`,disabled:h,onClick:()=>we("keyboard"),"aria-pressed":_e,children:[t.jsx(He,{size:18}),e("computer.keyboard")]}),t.jsxs("button",{type:"button",className:`flex min-h-11 flex-col items-center justify-center gap-0.5 rounded-md ${m==="clipboard"?"bg-surface-2 text-primary":""}`,disabled:h,onClick:()=>we("clipboard"),"aria-pressed":m==="clipboard",children:[t.jsx(ft,{size:18}),e("computer.clipboardTool")]}),m==="keyboard"?t.jsxs(t.Fragment,{children:[t.jsx("button",{type:"button",className:"min-h-11 rounded-md text-sm",onPointerDown:r=>r.preventDefault(),onClick:()=>be([[65289,"Tab"]]),children:"Tab"}),t.jsx("button",{type:"button",className:"min-h-11 rounded-md text-lg",onPointerDown:r=>r.preventDefault(),onClick:()=>be(G.backspace),children:"⌫"}),t.jsx("button",{type:"button",className:"min-h-11 rounded-md text-lg",onPointerDown:r=>r.preventDefault(),onClick:()=>be(G.enter),children:"↵"})]}):t.jsx(t.Fragment,{children:t.jsxs("button",{type:"button",className:"flex min-h-11 flex-col items-center justify-center gap-0.5 rounded-md",disabled:h,onClick:()=>ot(oe==="trackpad"?"direct":"trackpad"),"aria-label":e("computer.switchTouchMode"),children:[t.jsx(ht,{size:18}),e(oe==="trackpad"?"computer.trackpadMode":"computer.directTouchMode")]})})]}),ct]})]});return l?dt.createPortal(at,document.body):at}const lr=Object.freeze(Object.defineProperty({__proto__:null,default:nr},Symbol.toStringTag,{value:"Module"}));export{lr as C,Gt as c};
@@ -1 +0,0 @@
1
- import{c as a,C as n}from"./mermaid.core-CAOB7F_V.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};