termdock 1.4.168 → 1.4.169

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 (514) hide show
  1. package/dist/client/assets/ChangeWalkthroughPanel-u9y3e-pI.js +2 -0
  2. package/dist/client/assets/ChangeWalkthroughPanel-u9y3e-pI.js.br +0 -0
  3. package/dist/client/assets/ChangeWalkthroughPanel-u9y3e-pI.js.gz +0 -0
  4. package/dist/client/assets/DagPlayground-BLUwaOMM.js +1 -0
  5. package/dist/client/assets/DagPlayground-BLUwaOMM.js.br +0 -0
  6. package/dist/client/assets/DagPlayground-BLUwaOMM.js.gz +0 -0
  7. package/dist/client/assets/DiffLab-ThgXydJA.js +370 -0
  8. package/dist/client/assets/DiffLab-ThgXydJA.js.br +0 -0
  9. package/dist/client/assets/DiffLab-ThgXydJA.js.gz +0 -0
  10. package/dist/client/assets/DiffReview-DNkXOQ2y.js +1 -0
  11. package/dist/client/assets/DiffReview-DNkXOQ2y.js.br +0 -0
  12. package/dist/client/assets/DiffReview-DNkXOQ2y.js.gz +0 -0
  13. package/dist/client/assets/DiffReviewLab-CHyV1WMR.js +2 -0
  14. package/dist/client/assets/DiffReviewLab-CHyV1WMR.js.br +0 -0
  15. package/dist/client/assets/DiffReviewLab-CHyV1WMR.js.gz +0 -0
  16. package/dist/client/assets/DiffViewer-CxxOpsVz.js +35 -0
  17. package/dist/client/assets/DiffViewer-CxxOpsVz.js.br +0 -0
  18. package/dist/client/assets/DiffViewer-CxxOpsVz.js.gz +0 -0
  19. package/dist/client/assets/DiffViewer-T3uj2-aP.css +1 -0
  20. package/dist/client/assets/DiffViewer-T3uj2-aP.css.br +0 -0
  21. package/dist/client/assets/DiffViewer-T3uj2-aP.css.gz +0 -0
  22. package/dist/client/assets/ModelPreview-DZzx3Tzo.js +4112 -0
  23. package/dist/client/assets/ModelPreview-DZzx3Tzo.js.br +0 -0
  24. package/dist/client/assets/ModelPreview-DZzx3Tzo.js.gz +0 -0
  25. package/dist/client/assets/RightSidebar-Bv8Y6hqx.js +55 -0
  26. package/dist/client/assets/RightSidebar-Bv8Y6hqx.js.br +0 -0
  27. package/dist/client/assets/RightSidebar-Bv8Y6hqx.js.gz +0 -0
  28. package/dist/client/assets/RightSidebar-DW-JEgm2.css +1 -0
  29. package/dist/client/assets/{abnfDiagram-VRR7QNED-BPFn9m09.js → abnfDiagram-VCTEODGH-DKmZLRlf.js} +1 -1
  30. package/dist/client/assets/abnfDiagram-VCTEODGH-DKmZLRlf.js.br +0 -0
  31. package/dist/client/assets/abnfDiagram-VCTEODGH-DKmZLRlf.js.gz +0 -0
  32. package/dist/client/assets/app-tT08GaCs.js +175 -0
  33. package/dist/client/assets/app-tT08GaCs.js.br +0 -0
  34. package/dist/client/assets/app-tT08GaCs.js.gz +0 -0
  35. package/dist/client/assets/arc-CjmHoRed.js +1 -0
  36. package/dist/client/assets/arc-CjmHoRed.js.br +0 -0
  37. package/dist/client/assets/arc-CjmHoRed.js.gz +0 -0
  38. package/dist/client/assets/architectureDiagram-5GKGNRK7-B0EDOwYH.js +36 -0
  39. package/dist/client/assets/architectureDiagram-5GKGNRK7-B0EDOwYH.js.br +0 -0
  40. package/dist/client/assets/architectureDiagram-5GKGNRK7-B0EDOwYH.js.gz +0 -0
  41. package/dist/client/assets/blockDiagram-I7D4REHJ-CW-AaouZ.js +129 -0
  42. package/dist/client/assets/blockDiagram-I7D4REHJ-CW-AaouZ.js.br +0 -0
  43. package/dist/client/assets/blockDiagram-I7D4REHJ-CW-AaouZ.js.gz +0 -0
  44. package/dist/client/assets/c4Diagram-7LVT6UL2-aE7hFKfo.js +38 -0
  45. package/dist/client/assets/c4Diagram-7LVT6UL2-aE7hFKfo.js.br +0 -0
  46. package/dist/client/assets/c4Diagram-7LVT6UL2-aE7hFKfo.js.gz +0 -0
  47. package/dist/client/assets/channel-DhsPQnwY.js +1 -0
  48. package/dist/client/assets/{chunk-2Q5K7J3B-CXqAcWtO.js → chunk-2Q5K7J3B-FAEL5P17.js} +1 -1
  49. package/dist/client/assets/{chunk-5VM5RSS4-B2ewCivF.js → chunk-5VM5RSS4-BQJAvucM.js} +1 -1
  50. package/dist/client/assets/chunk-F27PBJKO-DEkt187T.js +1 -0
  51. package/dist/client/assets/chunk-F27PBJKO-DEkt187T.js.br +0 -0
  52. package/dist/client/assets/chunk-F27PBJKO-DEkt187T.js.gz +0 -0
  53. package/dist/client/assets/{chunk-EX3LRPZG-DcpNYccw.js → chunk-IMKFNOWR-BfOJ-x_l.js} +5 -5
  54. package/dist/client/assets/chunk-IMKFNOWR-BfOJ-x_l.js.br +0 -0
  55. package/dist/client/assets/chunk-IMKFNOWR-BfOJ-x_l.js.gz +0 -0
  56. package/dist/client/assets/{chunk-JWPE2WC7-DJGW22NC.js → chunk-JWPE2WC7-BN6q6jKH.js} +1 -1
  57. package/dist/client/assets/chunk-POPQ4Y6H-BrhQRNCn.js +1 -0
  58. package/dist/client/assets/{chunk-MOJQB5TN-CI12TXOM.js → chunk-SVP7TREG-CjZOC5Dj.js} +4 -4
  59. package/dist/client/assets/chunk-SVP7TREG-CjZOC5Dj.js.br +0 -0
  60. package/dist/client/assets/chunk-SVP7TREG-CjZOC5Dj.js.gz +0 -0
  61. package/dist/client/assets/{chunk-V7JOEXUC-D2J88tQk.js → chunk-TICWLB2K-Wshj9ws7.js} +3 -3
  62. package/dist/client/assets/chunk-TICWLB2K-Wshj9ws7.js.br +0 -0
  63. package/dist/client/assets/chunk-TICWLB2K-Wshj9ws7.js.gz +0 -0
  64. package/dist/client/assets/{chunk-XXDRQBXY-DFycwWDp.js → chunk-XXDRQBXY-BPPghuc3.js} +1 -1
  65. package/dist/client/assets/classDiagram-ZZMXUADV-2OomHNTG.js +1 -0
  66. package/dist/client/assets/classDiagram-v2-VYDZK3BY-2OomHNTG.js +1 -0
  67. package/dist/client/assets/{cose-bilkent-JH36ORCC-D8eG4PZe.js → cose-bilkent-JH36ORCC-BjxJYQH8.js} +1 -1
  68. package/dist/client/assets/cose-bilkent-JH36ORCC-BjxJYQH8.js.br +0 -0
  69. package/dist/client/assets/cose-bilkent-JH36ORCC-BjxJYQH8.js.gz +0 -0
  70. package/dist/client/assets/{cynefin-VYW2F7L2-B9Z9SAtQ.js → cynefin-OW5HDTMX-QmUTVmd_.js} +38 -38
  71. package/dist/client/assets/cynefin-OW5HDTMX-QmUTVmd_.js.br +0 -0
  72. package/dist/client/assets/cynefin-OW5HDTMX-QmUTVmd_.js.gz +0 -0
  73. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CBJtWB9m.js +62 -0
  74. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CBJtWB9m.js.br +0 -0
  75. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CBJtWB9m.js.gz +0 -0
  76. package/dist/client/assets/cytoscape.esm-D3_iZ_3b.js.br +0 -0
  77. package/dist/client/assets/cytoscape.esm-D3_iZ_3b.js.gz +0 -0
  78. package/dist/client/assets/dagre-GXQ25YYZ-CJFctjtR.js +4 -0
  79. package/dist/client/assets/dagre-GXQ25YYZ-CJFctjtR.js.br +0 -0
  80. package/dist/client/assets/dagre-GXQ25YYZ-CJFctjtR.js.gz +0 -0
  81. package/dist/client/assets/defaultLocale-CrowFXzY.js.br +0 -0
  82. package/dist/client/assets/defaultLocale-CrowFXzY.js.gz +0 -0
  83. package/dist/client/assets/diagram-S7CK7UJ4-e7Jn-RGH.js +30 -0
  84. package/dist/client/assets/diagram-S7CK7UJ4-e7Jn-RGH.js.br +0 -0
  85. package/dist/client/assets/diagram-S7CK7UJ4-e7Jn-RGH.js.gz +0 -0
  86. package/dist/client/assets/diagram-UQ7AKVKN-B1G-uMf2.js +41 -0
  87. package/dist/client/assets/diagram-UQ7AKVKN-B1G-uMf2.js.br +0 -0
  88. package/dist/client/assets/diagram-UQ7AKVKN-B1G-uMf2.js.gz +0 -0
  89. package/dist/client/assets/{diagram-FQU43EPY-BSU4bMc7.js → diagram-VSXAHHWV-cp7u53yF.js} +3 -3
  90. package/dist/client/assets/diagram-VSXAHHWV-cp7u53yF.js.br +0 -0
  91. package/dist/client/assets/diagram-VSXAHHWV-cp7u53yF.js.gz +0 -0
  92. package/dist/client/assets/diagram-VX7I27RA-DJWrVfMd.js +24 -0
  93. package/dist/client/assets/diagram-VX7I27RA-DJWrVfMd.js.br +0 -0
  94. package/dist/client/assets/diagram-VX7I27RA-DJWrVfMd.js.gz +0 -0
  95. package/dist/client/assets/diagram-Z3DM3KII-B-IZbqzJ.js +24 -0
  96. package/dist/client/assets/diagram-Z3DM3KII-B-IZbqzJ.js.br +0 -0
  97. package/dist/client/assets/diagram-Z3DM3KII-B-IZbqzJ.js.gz +0 -0
  98. package/dist/client/assets/diffWorker-CAzvFFr7.js +27 -0
  99. package/dist/client/assets/diffWorker-CAzvFFr7.js.br +0 -0
  100. package/dist/client/assets/diffWorker-CAzvFFr7.js.gz +0 -0
  101. package/dist/client/assets/{ebnfDiagram-CCIWWBDH-N_k0E7sQ.js → ebnfDiagram-PWID7BFC-Bt4zDbpn.js} +1 -1
  102. package/dist/client/assets/ebnfDiagram-PWID7BFC-Bt4zDbpn.js.br +0 -0
  103. package/dist/client/assets/ebnfDiagram-PWID7BFC-Bt4zDbpn.js.gz +0 -0
  104. package/dist/client/assets/erDiagram-RLTQ6QDP-DUPOkndO.js +99 -0
  105. package/dist/client/assets/erDiagram-RLTQ6QDP-DUPOkndO.js.br +0 -0
  106. package/dist/client/assets/erDiagram-RLTQ6QDP-DUPOkndO.js.gz +0 -0
  107. package/dist/client/assets/flowDiagram-HODETNUW-CBSvTIxa.js +168 -0
  108. package/dist/client/assets/flowDiagram-HODETNUW-CBSvTIxa.js.br +0 -0
  109. package/dist/client/assets/flowDiagram-HODETNUW-CBSvTIxa.js.gz +0 -0
  110. package/dist/client/assets/ganttDiagram-EL5Y4UJY-C7BvkSc8.js +292 -0
  111. package/dist/client/assets/ganttDiagram-EL5Y4UJY-C7BvkSc8.js.br +0 -0
  112. package/dist/client/assets/ganttDiagram-EL5Y4UJY-C7BvkSc8.js.gz +0 -0
  113. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-C4v6Do2L.js +106 -0
  114. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-C4v6Do2L.js.br +0 -0
  115. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-C4v6Do2L.js.gz +0 -0
  116. package/dist/client/assets/index-BaBARzax.css +1 -0
  117. package/dist/client/assets/index-BaBARzax.css.br +0 -0
  118. package/dist/client/assets/index-BaBARzax.css.gz +0 -0
  119. package/dist/client/assets/{index-Ca-rq7yX.js → index-UqXCGE5m.js} +4 -4
  120. package/dist/client/assets/index-UqXCGE5m.js.br +0 -0
  121. package/dist/client/assets/index-UqXCGE5m.js.gz +0 -0
  122. package/dist/client/assets/infoDiagram-27XIBGKW-CVQtEdgb.js +2 -0
  123. package/dist/client/assets/{ishikawaDiagram-FXEZZL3T-Ew07ODU5.js → ishikawaDiagram-5VMMS53U-Cf7tUoyW.js} +5 -5
  124. package/dist/client/assets/ishikawaDiagram-5VMMS53U-Cf7tUoyW.js.br +0 -0
  125. package/dist/client/assets/ishikawaDiagram-5VMMS53U-Cf7tUoyW.js.gz +0 -0
  126. package/dist/client/assets/{journeyDiagram-5HDEW3XC-BUjwylu4.js → journeyDiagram-3NMN7TZE-B-9CWrlr.js} +5 -5
  127. package/dist/client/assets/journeyDiagram-3NMN7TZE-B-9CWrlr.js.br +0 -0
  128. package/dist/client/assets/journeyDiagram-3NMN7TZE-B-9CWrlr.js.gz +0 -0
  129. package/dist/client/assets/{kanban-definition-HUTT4EX6-Cjv8zokk.js → kanban-definition-UXKFOSKX-LDN2IZeo.js} +7 -7
  130. package/dist/client/assets/kanban-definition-UXKFOSKX-LDN2IZeo.js.br +0 -0
  131. package/dist/client/assets/kanban-definition-UXKFOSKX-LDN2IZeo.js.gz +0 -0
  132. package/dist/client/assets/katex-55ZPZeOF.css.br +0 -0
  133. package/dist/client/assets/katex-55ZPZeOF.css.gz +0 -0
  134. package/dist/client/assets/katex-DnlPpQZa.js.br +0 -0
  135. package/dist/client/assets/katex-DnlPpQZa.js.gz +0 -0
  136. package/dist/client/assets/katex-HP8lGamR.js.br +0 -0
  137. package/dist/client/assets/katex-HP8lGamR.js.gz +0 -0
  138. package/dist/client/assets/layout-DvqSuFgF.js +1 -0
  139. package/dist/client/assets/layout-DvqSuFgF.js.br +0 -0
  140. package/dist/client/assets/layout-DvqSuFgF.js.gz +0 -0
  141. package/dist/client/assets/{linear-C6Z8ZZfN.js → linear-D43LQnis.js} +1 -1
  142. package/dist/client/assets/linear-D43LQnis.js.br +0 -0
  143. package/dist/client/assets/linear-D43LQnis.js.gz +0 -0
  144. package/dist/client/assets/mermaid.core-DiblHLKe.js +308 -0
  145. package/dist/client/assets/mermaid.core-DiblHLKe.js.br +0 -0
  146. package/dist/client/assets/mermaid.core-DiblHLKe.js.gz +0 -0
  147. package/dist/client/assets/{mindmap-definition-LN4V7U3C-DACHJUhw.js → mindmap-definition-YA3MSWOX-k3f4uWuu.js} +3 -3
  148. package/dist/client/assets/mindmap-definition-YA3MSWOX-k3f4uWuu.js.br +0 -0
  149. package/dist/client/assets/mindmap-definition-YA3MSWOX-k3f4uWuu.js.gz +0 -0
  150. package/dist/client/assets/ordinal-Cboi1Yqb.js.br +0 -0
  151. package/dist/client/assets/ordinal-Cboi1Yqb.js.gz +0 -0
  152. package/dist/client/assets/{pegDiagram-2B236MQR-C6YRG4Sp.js → pegDiagram-XKGWAZYB-Dj32Fl3j.js} +1 -1
  153. package/dist/client/assets/pegDiagram-XKGWAZYB-Dj32Fl3j.js.br +0 -0
  154. package/dist/client/assets/pegDiagram-XKGWAZYB-Dj32Fl3j.js.gz +0 -0
  155. package/dist/client/assets/pieDiagram-E7YTZNPT-DWGSixfl.js +39 -0
  156. package/dist/client/assets/pieDiagram-E7YTZNPT-DWGSixfl.js.br +0 -0
  157. package/dist/client/assets/pieDiagram-E7YTZNPT-DWGSixfl.js.gz +0 -0
  158. package/dist/client/assets/purify.es-4eNOHKSq.js +3 -0
  159. package/dist/client/assets/purify.es-4eNOHKSq.js.br +0 -0
  160. package/dist/client/assets/purify.es-4eNOHKSq.js.gz +0 -0
  161. package/dist/client/assets/{quadrantDiagram-ABIIQ3AL-DugxSPrH.js → quadrantDiagram-AXDQQJYC-BPScfZWR.js} +1 -1
  162. package/dist/client/assets/quadrantDiagram-AXDQQJYC-BPScfZWR.js.br +0 -0
  163. package/dist/client/assets/quadrantDiagram-AXDQQJYC-BPScfZWR.js.gz +0 -0
  164. package/dist/client/assets/railroadDiagram-O6MQD6OU-CL00HIC2.js +1 -0
  165. package/dist/client/assets/railroadDiagram-O6MQD6OU-CL00HIC2.js.br +0 -0
  166. package/dist/client/assets/railroadDiagram-O6MQD6OU-CL00HIC2.js.gz +0 -0
  167. package/dist/client/assets/react-XDCjal2T.js.br +0 -0
  168. package/dist/client/assets/react-XDCjal2T.js.gz +0 -0
  169. package/dist/client/assets/{requirementDiagram-TGXJPOKE-BzaF87gc.js → requirementDiagram-BXWQKSXE-CosES4L6.js} +12 -12
  170. package/dist/client/assets/requirementDiagram-BXWQKSXE-CosES4L6.js.br +0 -0
  171. package/dist/client/assets/requirementDiagram-BXWQKSXE-CosES4L6.js.gz +0 -0
  172. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CjM8CYFn.js +40 -0
  173. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CjM8CYFn.js.br +0 -0
  174. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CjM8CYFn.js.gz +0 -0
  175. package/dist/client/assets/{sequenceDiagram-DBY2YBRQ-B1gfbBUX.js → sequenceDiagram-WJ2MYXX4-3RKv_35o.js} +1 -1
  176. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-3RKv_35o.js.br +0 -0
  177. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-3RKv_35o.js.gz +0 -0
  178. package/dist/client/assets/{sizeCapture-X5ZJPWSS-Cx3c55P-.js → sizeCapture-INFHLROL-BrVkA4VD.js} +1 -1
  179. package/dist/client/assets/sizeCapture-INFHLROL-BrVkA4VD.js.br +0 -0
  180. package/dist/client/assets/sizeCapture-INFHLROL-BrVkA4VD.js.gz +0 -0
  181. package/dist/client/assets/sparkles-B3pwUd8-.js +1 -0
  182. package/dist/client/assets/stateDiagram-D77RDMKH-DeWhyAVC.js +1 -0
  183. package/dist/client/assets/stateDiagram-D77RDMKH-DeWhyAVC.js.br +0 -0
  184. package/dist/client/assets/stateDiagram-D77RDMKH-DeWhyAVC.js.gz +0 -0
  185. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-DvdrGmTm.js +1 -0
  186. package/dist/client/assets/swimlanes-42K2YHIH-i2m0Wmhn.js +1 -0
  187. package/dist/client/assets/swimlanes-42K2YHIH-i2m0Wmhn.js.br +0 -0
  188. package/dist/client/assets/swimlanes-42K2YHIH-i2m0Wmhn.js.gz +0 -0
  189. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DIzij9pB.js +8 -0
  190. package/dist/client/assets/terminal-C7X98Amf.js.br +0 -0
  191. package/dist/client/assets/terminal-C7X98Amf.js.gz +0 -0
  192. package/dist/client/assets/{timeline-definition-FHXFAJF6-Dmjeiy4n.js → timeline-definition-24CTP7MA-BImN0AS_.js} +1 -1
  193. package/dist/client/assets/timeline-definition-24CTP7MA-BImN0AS_.js.br +0 -0
  194. package/dist/client/assets/timeline-definition-24CTP7MA-BImN0AS_.js.gz +0 -0
  195. package/dist/client/assets/vennDiagram-4TSXK5OY-DVUHKmvC.js +34 -0
  196. package/dist/client/assets/vennDiagram-4TSXK5OY-DVUHKmvC.js.br +0 -0
  197. package/dist/client/assets/vennDiagram-4TSXK5OY-DVUHKmvC.js.gz +0 -0
  198. package/dist/client/assets/{wardleyDiagram-EHGQE667-C0Qt8nhi.js → wardleyDiagram-VM6X3IG4-B9qi-hc7.js} +4 -4
  199. package/dist/client/assets/wardleyDiagram-VM6X3IG4-B9qi-hc7.js.br +0 -0
  200. package/dist/client/assets/wardleyDiagram-VM6X3IG4-B9qi-hc7.js.gz +0 -0
  201. package/dist/client/assets/xychartDiagram-S5SC5T6Z-3jgBcYVl.js +7 -0
  202. package/dist/client/assets/xychartDiagram-S5SC5T6Z-3jgBcYVl.js.br +0 -0
  203. package/dist/client/assets/xychartDiagram-S5SC5T6Z-3jgBcYVl.js.gz +0 -0
  204. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-38-022d7c89c800.woff2 +0 -0
  205. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-39-63f8fa5b3eba.woff2 +0 -0
  206. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3a-2d8d46cc4dca.woff2 +0 -0
  207. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3b-e75aed5d3969.woff2 +0 -0
  208. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c-ac2534aae681.woff2 +0 -0
  209. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c0-8c49a98e75c4.woff2 +0 -0
  210. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c1-971c5e7a86ce.woff2 +0 -0
  211. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c2-e5c4893acfb9.woff2 +0 -0
  212. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c3-156f2560c871.woff2 +0 -0
  213. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c4-49f0d18a7492.woff2 +0 -0
  214. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c5-33d81ad28c5c.woff2 +0 -0
  215. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c6-5c301879d053.woff2 +0 -0
  216. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3d-52c90894de44.woff2 +0 -0
  217. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-text-9e8d9df2dd02.woff2 +0 -0
  218. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-38-7942d3c93afb.woff2 +0 -0
  219. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-39-19989a2be535.woff2 +0 -0
  220. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3a-7786ff4a4dd9.woff2 +0 -0
  221. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3b-a759fd623d7e.woff2 +0 -0
  222. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c-2a1178076740.woff2 +0 -0
  223. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c0-6f2c7518f354.woff2 +0 -0
  224. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c1-4bf64cae9dd2.woff2 +0 -0
  225. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c2-7f26d4c7240b.woff2 +0 -0
  226. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c3-fc8e5a85d620.woff2 +0 -0
  227. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c4-91819b7977d3.woff2 +0 -0
  228. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c5-26933eec54e2.woff2 +0 -0
  229. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c6-af186404c8af.woff2 +0 -0
  230. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3d-b004d85f5642.woff2 +0 -0
  231. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-text-da002b4e56d3.woff2 +0 -0
  232. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-38-b3e69191d92f.woff2 +0 -0
  233. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-39-c4d8d66882cb.woff2 +0 -0
  234. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3a-27609324e8a3.woff2 +0 -0
  235. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3b-5e73d85d7506.woff2 +0 -0
  236. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c-7e535d65bbdb.woff2 +0 -0
  237. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c0-6465060a06a1.woff2 +0 -0
  238. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c1-9fd72ccd9350.woff2 +0 -0
  239. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c2-ea7dd77de270.woff2 +0 -0
  240. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c3-12808f88907a.woff2 +0 -0
  241. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c4-14b598e5e739.woff2 +0 -0
  242. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c5-3d40530ce6c2.woff2 +0 -0
  243. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c6-7020aec0d9e1.woff2 +0 -0
  244. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3d-19831897003a.woff2 +0 -0
  245. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-text-b7a9c776b048.woff2 +0 -0
  246. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-38-a637901140d8.woff2 +0 -0
  247. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-39-838726e8eeca.woff2 +0 -0
  248. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3a-ec149087d0b9.woff2 +0 -0
  249. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3b-db8e5a24d580.woff2 +0 -0
  250. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c-2290d2ad4621.woff2 +0 -0
  251. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c0-3b9edaf85d65.woff2 +0 -0
  252. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c1-5e7fb0696bbc.woff2 +0 -0
  253. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c2-cfad2884adf5.woff2 +0 -0
  254. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c3-d641de88278b.woff2 +0 -0
  255. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c4-3b0227356b3b.woff2 +0 -0
  256. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c5-9dc67c4d20b4.woff2 +0 -0
  257. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c6-c5b444110c62.woff2 +0 -0
  258. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3d-2b19b65bb43a.woff2 +0 -0
  259. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-text-d7b9316fdf4f.woff2 +0 -0
  260. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-4e-46bdca5c323f.woff2 +0 -0
  261. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-4f-17200dc0dd0d.woff2 +0 -0
  262. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-50-370e36250c30.woff2 +0 -0
  263. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-51-66352f738581.woff2 +0 -0
  264. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-52-191f4025d2b5.woff2 +0 -0
  265. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-53-fb0a637c39bf.woff2 +0 -0
  266. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-54-66f2e72c9ca0.woff2 +0 -0
  267. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-55-54b538fd4fd8.woff2 +0 -0
  268. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-56-88f45aeb2030.woff2 +0 -0
  269. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-57-154d4324f0ce.woff2 +0 -0
  270. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-58-1660c86b8a05.woff2 +0 -0
  271. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-59-31a4c5afa3aa.woff2 +0 -0
  272. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-5a-fa1d1941710e.woff2 +0 -0
  273. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-5b-031a2b2ebeb7.woff2 +0 -0
  274. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-5c-065b634c07b3.woff2 +0 -0
  275. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-5d-71f6cd3ed180.woff2 +0 -0
  276. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-5e-f59de7a6e5c5.woff2 +0 -0
  277. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-5f-8cbe737b6011.woff2 +0 -0
  278. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-60-22913526da09.woff2 +0 -0
  279. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-61-c810c1d1a3a3.woff2 +0 -0
  280. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-62-9464d5d87d65.woff2 +0 -0
  281. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-63-79564d99f5da.woff2 +0 -0
  282. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-64-4b7cff1dae6f.woff2 +0 -0
  283. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-65-8dd48db5e297.woff2 +0 -0
  284. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-66-a808e22a3d14.woff2 +0 -0
  285. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-67-ae5f61af3f79.woff2 +0 -0
  286. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-68-a46bf47bd9ba.woff2 +0 -0
  287. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-69-28210414eafb.woff2 +0 -0
  288. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-6a-6bfb1f5e4fb7.woff2 +0 -0
  289. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-6b-39be890e04e4.woff2 +0 -0
  290. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-6c-79a4ff740d98.woff2 +0 -0
  291. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-6d-2de5a763980e.woff2 +0 -0
  292. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-6e-8e55b339244d.woff2 +0 -0
  293. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-6f-a56caf9fc7fc.woff2 +0 -0
  294. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-70-d70c6ee8e03c.woff2 +0 -0
  295. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-71-ac6f5f86dfef.woff2 +0 -0
  296. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-72-db3d346ecc61.woff2 +0 -0
  297. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-73-e7371bd71f0b.woff2 +0 -0
  298. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-74-43946d9b2f0b.woff2 +0 -0
  299. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-75-ea7cf53e31fa.woff2 +0 -0
  300. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-76-04c7fa4e0ebf.woff2 +0 -0
  301. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-77-24d70898f6b8.woff2 +0 -0
  302. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-78-c6a5d7135296.woff2 +0 -0
  303. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-79-7812cb6432aa.woff2 +0 -0
  304. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-7a-6e123be5cd36.woff2 +0 -0
  305. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-7b-a183ddc6890f.woff2 +0 -0
  306. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-7c-0895291ece9c.woff2 +0 -0
  307. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-7d-1d44252384cf.woff2 +0 -0
  308. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-7e-7be4dc6f056e.woff2 +0 -0
  309. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-7f-0d8e987db151.woff2 +0 -0
  310. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-80-c0c154bb8be0.woff2 +0 -0
  311. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-81-5343baca5ce7.woff2 +0 -0
  312. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-82-6d89af9614ce.woff2 +0 -0
  313. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-83-fa17ef529c5b.woff2 +0 -0
  314. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-84-287ecb493fad.woff2 +0 -0
  315. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-85-fea695c48165.woff2 +0 -0
  316. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-86-8bb35373cb82.woff2 +0 -0
  317. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-87-f83e9f70a6cc.woff2 +0 -0
  318. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-88-894cd19292c1.woff2 +0 -0
  319. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-89-2903a6eaf546.woff2 +0 -0
  320. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-8a-3ce275bfcf96.woff2 +0 -0
  321. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-8b-3aaeb26309a6.woff2 +0 -0
  322. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-8c-719b6608b746.woff2 +0 -0
  323. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-8d-a7f1ccd0dfb7.woff2 +0 -0
  324. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-8e-d503ad5c4958.woff2 +0 -0
  325. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-8f-18c6d04746c8.woff2 +0 -0
  326. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-90-e9d94d915dfe.woff2 +0 -0
  327. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-91-c258b07ec626.woff2 +0 -0
  328. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-92-e4833a556b60.woff2 +0 -0
  329. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-94-0889f5b84499.woff2 +0 -0
  330. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-95-7ef116efe7ee.woff2 +0 -0
  331. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-96-afbc0d2cacda.woff2 +0 -0
  332. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-97-df3903d86f65.woff2 +0 -0
  333. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-98-0f21094931ee.woff2 +0 -0
  334. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-99-eb95f4bead58.woff2 +0 -0
  335. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-9a-764e8b8723ec.woff2 +0 -0
  336. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-9b-33a540b9196a.woff2 +0 -0
  337. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-9c-60d6040aa049.woff2 +0 -0
  338. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-9e-4a64c65bf44d.woff2 +0 -0
  339. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-9f-4d84fba11345.woff2 +0 -0
  340. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-punctuation-f1b7708e797a.woff2 +0 -0
  341. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-4e-bb1ec5541ecc.woff2 +0 -0
  342. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-4f-d6e8daa67360.woff2 +0 -0
  343. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-50-63c2ae7f85e8.woff2 +0 -0
  344. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-51-41b6e0624888.woff2 +0 -0
  345. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-52-57de15003b8d.woff2 +0 -0
  346. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-53-94382657e2bc.woff2 +0 -0
  347. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-54-177141086f32.woff2 +0 -0
  348. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-55-5ec6fae9813a.woff2 +0 -0
  349. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-56-720aa493b429.woff2 +0 -0
  350. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-57-a8884711a286.woff2 +0 -0
  351. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-58-42a3e7e1fe9a.woff2 +0 -0
  352. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-59-887ee4253daa.woff2 +0 -0
  353. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-5a-c45806889e3c.woff2 +0 -0
  354. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-5b-da142b99dca9.woff2 +0 -0
  355. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-5c-2bb495e5b511.woff2 +0 -0
  356. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-5d-9da87d6061f2.woff2 +0 -0
  357. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-5e-e4010764e593.woff2 +0 -0
  358. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-5f-a9c9021f6e01.woff2 +0 -0
  359. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-60-306f229a68e0.woff2 +0 -0
  360. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-61-6e4546c5f52a.woff2 +0 -0
  361. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-62-a73e47933059.woff2 +0 -0
  362. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-63-e8f49f472799.woff2 +0 -0
  363. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-64-37b54957eadc.woff2 +0 -0
  364. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-65-2742b20127ad.woff2 +0 -0
  365. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-66-239656e7fe56.woff2 +0 -0
  366. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-67-5dfa72b26c3f.woff2 +0 -0
  367. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-68-fe3d1fc05aae.woff2 +0 -0
  368. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-69-22535dbbd090.woff2 +0 -0
  369. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-6a-c4117cd520aa.woff2 +0 -0
  370. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-6b-895d3349f7de.woff2 +0 -0
  371. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-6c-56a0c71eb1b4.woff2 +0 -0
  372. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-6d-9ec807661604.woff2 +0 -0
  373. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-6e-3b633363cd57.woff2 +0 -0
  374. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-6f-91a1f1c31b75.woff2 +0 -0
  375. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-70-3a904a2a2371.woff2 +0 -0
  376. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-71-e8efb60879b0.woff2 +0 -0
  377. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-72-591318b99498.woff2 +0 -0
  378. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-73-d8f444050aa7.woff2 +0 -0
  379. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-74-55a832a12d7e.woff2 +0 -0
  380. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-75-660977996a4c.woff2 +0 -0
  381. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-76-441a04df9fb5.woff2 +0 -0
  382. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-77-5915143c4398.woff2 +0 -0
  383. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-78-242fbc33c745.woff2 +0 -0
  384. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-79-24d13953150a.woff2 +0 -0
  385. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-7a-41973af74017.woff2 +0 -0
  386. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-7b-f9661fdaf003.woff2 +0 -0
  387. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-7c-ef5167770bf7.woff2 +0 -0
  388. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-7d-d84ad5d95f37.woff2 +0 -0
  389. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-7e-66841a1c6381.woff2 +0 -0
  390. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-7f-5090e017351a.woff2 +0 -0
  391. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-80-9ad74a67c2b9.woff2 +0 -0
  392. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-81-423a60a6dcf1.woff2 +0 -0
  393. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-82-aad812217807.woff2 +0 -0
  394. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-83-3dc74dbac89c.woff2 +0 -0
  395. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-84-68db7802ffe8.woff2 +0 -0
  396. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-85-fa235a7160e4.woff2 +0 -0
  397. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-86-75a6a33d0db2.woff2 +0 -0
  398. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-87-7d98ea8ce063.woff2 +0 -0
  399. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-88-363fa8f178aa.woff2 +0 -0
  400. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-89-f2d185e8721f.woff2 +0 -0
  401. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-8a-e372253a07f5.woff2 +0 -0
  402. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-8b-0af53db9bdc1.woff2 +0 -0
  403. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-8c-6a43d3643480.woff2 +0 -0
  404. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-8d-09c4b5345b99.woff2 +0 -0
  405. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-8e-122a752954a6.woff2 +0 -0
  406. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-8f-c651bbfffeb3.woff2 +0 -0
  407. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-90-ab0a5fef3083.woff2 +0 -0
  408. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-91-e07b5cbe4792.woff2 +0 -0
  409. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-92-cba0a8ee6758.woff2 +0 -0
  410. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-94-e7a6bd14e248.woff2 +0 -0
  411. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-95-420f721d52ba.woff2 +0 -0
  412. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-96-90fd476b83f2.woff2 +0 -0
  413. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-97-34036fc287f7.woff2 +0 -0
  414. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-98-5c3cdd76911e.woff2 +0 -0
  415. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-99-73e6090fd7c8.woff2 +0 -0
  416. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-9a-673ebaebe683.woff2 +0 -0
  417. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-9b-90a5a3ee22d6.woff2 +0 -0
  418. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-9c-116d201c978b.woff2 +0 -0
  419. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-9e-78db36865caa.woff2 +0 -0
  420. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-9f-27e8d16243d5.woff2 +0 -0
  421. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-punctuation-a4288065ed29.woff2 +0 -0
  422. package/dist/client/fonts/terminal/manifest.json +1349 -0
  423. package/dist/client/fonts/terminal/manifest.json.br +0 -0
  424. package/dist/client/fonts/terminal/manifest.json.gz +0 -0
  425. package/dist/client/icons/agents/claude.svg.br +0 -0
  426. package/dist/client/icons/agents/claude.svg.gz +0 -0
  427. package/dist/client/icons/agents/codex.svg.br +0 -0
  428. package/dist/client/icons/agents/codex.svg.gz +0 -0
  429. package/dist/client/icons/agents/copilot.svg.br +0 -0
  430. package/dist/client/icons/agents/copilot.svg.gz +0 -0
  431. package/dist/client/icons/agents/droid.svg.br +0 -0
  432. package/dist/client/icons/agents/droid.svg.gz +0 -0
  433. package/dist/client/icons/agents/gemini.svg.br +0 -0
  434. package/dist/client/icons/agents/gemini.svg.gz +0 -0
  435. package/dist/client/icons/agents/goose.svg.br +0 -0
  436. package/dist/client/icons/agents/goose.svg.gz +0 -0
  437. package/dist/client/index.html +7 -52
  438. package/dist/client/index.html.br +0 -0
  439. package/dist/client/index.html.gz +0 -0
  440. package/dist/client/sw-notifications.js.br +0 -0
  441. package/dist/client/sw-notifications.js.gz +0 -0
  442. package/dist/client/sw.js +1 -1
  443. package/dist/client/sw.js.br +0 -0
  444. package/dist/client/sw.js.gz +0 -0
  445. package/dist/client/workbox-9845bf53.js.br +0 -0
  446. package/dist/client/workbox-9845bf53.js.gz +0 -0
  447. package/dist/server/agent/installers.js +47 -27
  448. package/dist/server/cli.js +4 -4
  449. package/dist/server/entry.js +57 -145
  450. package/dist/server/routes/auth.js +9 -3
  451. package/dist/server/routes/filesystem.js +39 -9
  452. package/dist/server/routes/local.js +3 -2
  453. package/dist/server/routes/terminal.js +337 -225
  454. package/dist/server/utils/apiAccess.js +27 -0
  455. package/dist/server/utils/apiCachePolicy.js +10 -0
  456. package/dist/server/utils/authProtection.js +140 -38
  457. package/dist/server/utils/cookieSecurity.js +3 -2
  458. package/dist/server/utils/csrfProtection.js +2 -6
  459. package/dist/server/utils/previewValidation.js +16 -0
  460. package/dist/server/utils/publicSecurity.js +44 -0
  461. package/dist/server/utils/requestDeadline.js +2 -0
  462. package/dist/server/utils/requestSecurity.js +23 -28
  463. package/dist/server/utils/staticAssets.js +97 -0
  464. package/dist/server/utils/terminalClientAttachment.js +61 -0
  465. package/dist/server/utils/terminalHandshakeDimensions.js +9 -0
  466. package/dist/server/utils/terminalOutputDelivery.js +90 -0
  467. package/dist/server/utils/tmuxClientRedraw.js +16 -0
  468. package/dist/server/utils/tmuxInitialScreen.js +50 -0
  469. package/dist/server/utils/tmuxResizeReady.js +56 -0
  470. package/dist/server/utils/webSocketSecurity.js +28 -0
  471. package/package.json +7 -4
  472. package/runtime-manifest.json +4 -4
  473. package/scripts/generate-font-subsets.py +88 -0
  474. package/scripts/precompress-client.mjs +28 -0
  475. package/dist/client/assets/ModelPreview-BVdIA5hh.js +0 -4108
  476. package/dist/client/assets/app-uayLhfKS.js +0 -632
  477. package/dist/client/assets/arc-BrdWVufU.js +0 -1
  478. package/dist/client/assets/architectureDiagram-ZJ3FMSHR-M74Mohos.js +0 -36
  479. package/dist/client/assets/blockDiagram-677ZJIJ3-D6OG5gyC.js +0 -132
  480. package/dist/client/assets/c4Diagram-LMCZKHZV-C2w-_Jc4.js +0 -10
  481. package/dist/client/assets/channel-B3PaW8my.js +0 -1
  482. package/dist/client/assets/chunk-32BRIVSS-CEtSQTtD.js +0 -1
  483. package/dist/client/assets/chunk-RYQCIY6F-DS5ufo5c.js +0 -1
  484. package/dist/client/assets/chunk-VR4S4FIN-0lqTHFzc.js +0 -1
  485. package/dist/client/assets/classDiagram-OUVF2IWQ-CLK6o5ur.js +0 -1
  486. package/dist/client/assets/classDiagram-v2-EOCWNBFH-CLK6o5ur.js +0 -1
  487. package/dist/client/assets/cynefinDiagram-TSTJHNR4-DLfD0XDP.js +0 -62
  488. package/dist/client/assets/dagre-VKFMJZFB-BVcVxS_K.js +0 -4
  489. package/dist/client/assets/diagram-G47NLZAW-U4SDLU5l.js +0 -24
  490. package/dist/client/assets/diagram-NH7WQ7WH-DzUUOLaX.js +0 -24
  491. package/dist/client/assets/diagram-OA4YK3LP-CkCRYrYh.js +0 -30
  492. package/dist/client/assets/diagram-WEI45ONY-D5_8zUCk.js +0 -41
  493. package/dist/client/assets/diffWorker-Bg2YXCD-.js +0 -27
  494. package/dist/client/assets/erDiagram-Q63AITRT-CaBjWdJp.js +0 -85
  495. package/dist/client/assets/flowDiagram-23GEKE2U-CVOqw7CA.js +0 -156
  496. package/dist/client/assets/ganttDiagram-NO4QXBWP-DI8IFeJE.js +0 -292
  497. package/dist/client/assets/gitGraphDiagram-IHSO6WYX-CnpSm3yq.js +0 -106
  498. package/dist/client/assets/graph-D2o_JWn5.js +0 -1
  499. package/dist/client/assets/index-C13NrW5y.css +0 -1
  500. package/dist/client/assets/infoDiagram-FWYZ7A6U-C-dKF4KW.js +0 -2
  501. package/dist/client/assets/layout-1eBIAoSl.js +0 -1
  502. package/dist/client/assets/map-BdqsVdb3.js +0 -1
  503. package/dist/client/assets/mermaid.core-B13cUj_d.js +0 -306
  504. package/dist/client/assets/pieDiagram-ENE6RG2P-7cfuhoAx.js +0 -39
  505. package/dist/client/assets/purify.es-CC4Brkr_.js +0 -3
  506. package/dist/client/assets/railroadDiagram-RFXS5EU6-BhRp2Kow.js +0 -1
  507. package/dist/client/assets/sankeyDiagram-HTMAVEWB-4yvODBzh.js +0 -40
  508. package/dist/client/assets/stateDiagram-2N3HPSRC-CyZ_X_VK.js +0 -1
  509. package/dist/client/assets/stateDiagram-v2-6OUMAXLB-9hsqTyV0.js +0 -1
  510. package/dist/client/assets/swimlanes-5IMT3BWC-BZPAGrt1.js +0 -2
  511. package/dist/client/assets/swimlanesDiagram-G3AALYLV-DYvi0MbZ.js +0 -8
  512. package/dist/client/assets/vennDiagram-L72KCM5P-BC2FrHDP.js +0 -34
  513. package/dist/client/assets/xychartDiagram-FW5EYKEG-cQNpjzG4.js +0 -7
  514. package/dist/client/registerSW.js +0 -1
@@ -1,3 +1,7 @@
1
+ import { TerminalClientAttachment } from '../utils/terminalClientAttachment.js';
2
+ import { redrawTmuxClient } from '../utils/tmuxClientRedraw.js';
3
+ import { TmuxInitialScreen } from '../utils/tmuxInitialScreen.js';
4
+ import { TerminalOutputDelivery, resolveTerminalReplayCursor } from '../utils/terminalOutputDelivery.js';
1
5
  import express from 'express';
2
6
  import fs from 'fs';
3
7
  import os from 'os';
@@ -111,6 +115,10 @@ const TERMDOCK_GUI_DETACHED_AT_OPTION = '@termdock-gui-detached-at';
111
115
  const TERMDOCK_FRONTEND_SESSION_ID_OPTION = '@termdock-frontend-session-id';
112
116
  // WebSocket clients per session (separate from SSE clients).
113
117
  const wsClients = new Map();
118
+ const outputDeliveries = new WeakMap();
119
+ const independentTmuxClients = new WeakSet();
120
+ const independentTmuxReplays = new WeakMap();
121
+ const TERMINAL_STREAM_EPOCH = crypto.randomUUID();
114
122
  // Sessions where copy-mode -e just auto-exited at the bottom.
115
123
  // Prevents immediate re-entry on subsequent scroll-down commands.
116
124
  const exitedAtBottom = new Set();
@@ -780,7 +788,10 @@ function getHistorySince(sessionId, sinceSeq) {
780
788
  : history.chunks.slice();
781
789
  return { chunks, lastSeq, outOfWindow: false };
782
790
  }
783
- if (sinceSeq >= lastSeq) {
791
+ if (sinceSeq > lastSeq) {
792
+ return { chunks: history.chunks.slice(), lastSeq, outOfWindow: true };
793
+ }
794
+ if (sinceSeq === lastSeq) {
784
795
  return { chunks: [], lastSeq, outOfWindow: false };
785
796
  }
786
797
  const oldestSeq = history.chunks.length > 0 ? history.chunks[0].seq : history.nextSeq;
@@ -2215,89 +2226,6 @@ function enqueueTmuxIo(session, operation) {
2215
2226
  session.tmuxIoChain = result.then(() => undefined, () => undefined);
2216
2227
  return result;
2217
2228
  }
2218
- function markTmuxClientsForScreenSync(sessionId, session) {
2219
- if (session.mode !== 'tmux')
2220
- return;
2221
- const clients = wsClients.get(sessionId);
2222
- if (!clients || clients.size === 0)
2223
- return;
2224
- const pending = session.tmuxScreenSyncClients ?? new Set();
2225
- for (const clientId of clients.keys())
2226
- pending.add(clientId);
2227
- session.tmuxScreenSyncClients = pending;
2228
- session.tmuxResizeGeneration = (session.tmuxResizeGeneration ?? 0) + 1;
2229
- }
2230
- function markTmuxClientForScreenSync(session, clientId) {
2231
- if (session.mode !== 'tmux')
2232
- return;
2233
- const pending = session.tmuxScreenSyncClients ?? new Set();
2234
- pending.add(clientId);
2235
- session.tmuxScreenSyncClients = pending;
2236
- session.tmuxResizeGeneration = (session.tmuxResizeGeneration ?? 0) + 1;
2237
- }
2238
- const TMUX_RESIZE_SCREEN_SYNC_DELAY_MS = 180;
2239
- function clearTmuxScreenSyncTimer(session, clientId) {
2240
- const timer = session.tmuxScreenSyncTimers?.get(clientId);
2241
- if (timer)
2242
- clearTimeout(timer);
2243
- session.tmuxScreenSyncTimers?.delete(clientId);
2244
- if (session.tmuxScreenSyncTimers?.size === 0) {
2245
- session.tmuxScreenSyncTimers = undefined;
2246
- }
2247
- }
2248
- function scheduleTmuxScreenSyncAfterResize(sessionId, session, clientId) {
2249
- if (session.mode !== 'tmux' || !session.tmuxSessionName)
2250
- return;
2251
- clearTmuxScreenSyncTimer(session, clientId);
2252
- const timers = session.tmuxScreenSyncTimers ?? new Map();
2253
- const timer = setTimeout(() => {
2254
- clearTmuxScreenSyncTimer(session, clientId);
2255
- const ws = wsClients.get(sessionId)?.get(clientId);
2256
- if (!ws || ws.readyState !== ws.OPEN)
2257
- return;
2258
- void enqueueTmuxIo(session, () => syncTmuxScreenBeforeScroll(sessionId, clientId, session, ws));
2259
- }, TMUX_RESIZE_SCREEN_SYNC_DELAY_MS);
2260
- timer.unref?.();
2261
- timers.set(clientId, timer);
2262
- session.tmuxScreenSyncTimers = timers;
2263
- }
2264
- function isTmuxWheelInput(data) {
2265
- return /^(?:\u001b\[<6[45];\d+;\d+[Mm])+$/.test(data);
2266
- }
2267
- async function syncTmuxScreenBeforeScroll(sessionId, clientId, session, ws) {
2268
- clearTmuxScreenSyncTimer(session, clientId);
2269
- if (session.mode !== 'tmux'
2270
- || !session.tmuxSessionName
2271
- || !session.tmuxScreenSyncClients?.has(clientId)) {
2272
- return;
2273
- }
2274
- const generation = session.tmuxResizeGeneration ?? 0;
2275
- try {
2276
- // capture-pane itself enters tmux's command queue after the tty resize.
2277
- // Do not call refresh-client here: that emits another incremental repaint
2278
- // through node-pty which can arrive after this authoritative snapshot and
2279
- // be applied twice (for example, duplicate Codex "Working" rows).
2280
- const snapshot = await captureTmuxPane(session.tmuxSessionName);
2281
- if (ws.readyState === ws.OPEN) {
2282
- ws.send(JSON.stringify({
2283
- type: 'tmux-screen-sync',
2284
- chunks: buildTmuxScreenSnapshot(snapshot),
2285
- cols: session.cols,
2286
- rows: session.rows,
2287
- generation,
2288
- }));
2289
- session.tmuxScreenSyncClients.delete(clientId);
2290
- if (session.tmuxScreenSyncClients.size === 0) {
2291
- session.tmuxScreenSyncClients = undefined;
2292
- }
2293
- }
2294
- }
2295
- catch (error) {
2296
- // Keep the client marked dirty. Its next wheel event retries the exact
2297
- // synchronization instead of permanently accepting a partial screen.
2298
- console.warn(`[tmux-screen-sync] failed session=${sessionId} client=${clientId}: ${getErrorMessage(error)}`);
2299
- }
2300
- }
2301
2229
  async function isTmuxPaneInMode(target, control) {
2302
2230
  const paneInModeRaw = (await sendTmuxCommand(target, control, [
2303
2231
  'display-message',
@@ -3576,9 +3504,7 @@ async function resolveTmuxClientTty(sessionName, preferredClientPid) {
3576
3504
  }
3577
3505
  if (preferredClientPid !== null) {
3578
3506
  const matched = rows.find(([clientPid]) => clientPid === String(preferredClientPid));
3579
- if (matched?.[1]) {
3580
- return matched[1];
3581
- }
3507
+ return matched?.[1] || null;
3582
3508
  }
3583
3509
  return rows[0][1] || null;
3584
3510
  }
@@ -4088,10 +4014,6 @@ function cleanupSession(sessionId, options) {
4088
4014
  }
4089
4015
  session.flowPausedClientTimers.clear();
4090
4016
  session.flowPausedClients.clear();
4091
- for (const timer of session.tmuxScreenSyncTimers?.values() ?? []) {
4092
- clearTimeout(timer);
4093
- }
4094
- session.tmuxScreenSyncTimers = undefined;
4095
4017
  if (session.ptyPausedForFlowControl) {
4096
4018
  applyPtyFlowControl(sessionId, session, false, 'session-cleanup');
4097
4019
  }
@@ -4138,7 +4060,7 @@ function cleanupSession(sessionId, options) {
4138
4060
  }
4139
4061
  }
4140
4062
  }
4141
- function broadcastToWs(sessionId, data, excludeClientId) {
4063
+ function broadcastToWs(sessionId, data, excludeClientId, output, eventType) {
4142
4064
  const clients = wsClients.get(sessionId);
4143
4065
  const session = terminalSessions.get(sessionId);
4144
4066
  if (!clients)
@@ -4146,8 +4068,20 @@ function broadcastToWs(sessionId, data, excludeClientId) {
4146
4068
  for (const [clientId, ws] of clients.entries()) {
4147
4069
  if (excludeClientId && clientId === excludeClientId)
4148
4070
  continue;
4071
+ if (independentTmuxClients.has(ws) && (output || eventType === 'pty-size'))
4072
+ continue;
4149
4073
  try {
4150
- ws.send(data);
4074
+ if (ws.readyState !== ws.OPEN)
4075
+ continue;
4076
+ if (ws.bufferedAmount > 1024 * 1024) {
4077
+ ws.close(1013, 'Output transport is congested');
4078
+ continue;
4079
+ }
4080
+ const delivery = outputDeliveries.get(ws);
4081
+ if (output && delivery)
4082
+ delivery.enqueue(output);
4083
+ else
4084
+ ws.send(data);
4151
4085
  }
4152
4086
  catch {
4153
4087
  clients.delete(clientId);
@@ -4157,7 +4091,8 @@ function broadcastToWs(sessionId, data, excludeClientId) {
4157
4091
  }
4158
4092
  }
4159
4093
  function broadcastJsonWs(sessionId, payload, excludeClientId) {
4160
- broadcastToWs(sessionId, JSON.stringify(payload), excludeClientId);
4094
+ const output = payload?.type === 'data' ? payload : undefined;
4095
+ broadcastToWs(sessionId, JSON.stringify(payload), excludeClientId, output, payload?.type);
4161
4096
  }
4162
4097
  // 统一的 pty resize 入口:调用 ptyProcess.resize 改变 pty size 之后,把
4163
4098
  // 真实尺寸广播给除发起方之外的所有 ws client。多端场景下,B 端把 pty
@@ -4183,11 +4118,7 @@ function applyPtyResize(sessionId, session, cols, rows, source, originClientId)
4183
4118
  session.autoTitleTerminal.resize(cleanCols, cleanRows);
4184
4119
  session.lastActivity = Date.now();
4185
4120
  if (changed) {
4186
- markTmuxClientsForScreenSync(sessionId, session);
4187
4121
  broadcastJsonWs(sessionId, { type: 'pty-size', cols: cleanCols, rows: cleanRows, source }, originClientId);
4188
- if (originClientId) {
4189
- scheduleTmuxScreenSyncAfterResize(sessionId, session, originClientId);
4190
- }
4191
4122
  }
4192
4123
  return true;
4193
4124
  }
@@ -4497,7 +4428,9 @@ async function spawnTerminalSession(req, input) {
4497
4428
  ? getTmuxBinary()
4498
4429
  : (process.platform === 'win32' ? 'powershell.exe' : resolveShellCandidates()[0]);
4499
4430
  const args = mode === 'tmux' && tmuxSessionName
4500
- ? ['attach-session', '-t', tmuxSessionName]
4431
+ // xterm supports DEC 2026. Declare it on this attached client so tmux
4432
+ // emits real synchronized-output boundaries around its redraw batches.
4433
+ ? ['-T', 'RGB,sync', 'attach-session', '-t', tmuxSessionName]
4501
4434
  : (process.platform === 'win32' ? buildPowerShellCwdHookArgs() : []);
4502
4435
  const envPath = buildAugmentedPath();
4503
4436
  const resolvedEnv = buildInteractiveColorEnvironment({
@@ -6759,6 +6692,27 @@ router.post('/:sessionId/resize', async (req, res) => {
6759
6692
  res.status(500).json({ error: errorMessage || 'Failed to resize terminal' });
6760
6693
  }
6761
6694
  });
6695
+ async function switchTmuxBackendSession(sessionId, session, target) {
6696
+ if (!target)
6697
+ throw new Error('tmuxSessionName is required');
6698
+ const clientTty = await resolveTmuxClientTty(session.tmuxSessionName, getPtyProcessPid(session.ptyProcess));
6699
+ if (!clientTty)
6700
+ throw new Error('No tmux client available for current session');
6701
+ await prepareManagedTmuxSession(target, session.cwd);
6702
+ await sendTmuxCommand(session.tmuxSessionName, session.tmuxControl, ['switch-client', '-c', clientTty, '-t', target]);
6703
+ session.tmuxSessionName = target;
6704
+ session.lastActivity = Date.now();
6705
+ if (updateGlobalBindingForBackendSession(sessionId, {
6706
+ mode: 'tmux', tmuxSessionName: target, cwd: session.cwd, lastActivity: session.lastActivity,
6707
+ }))
6708
+ persistAndBroadcastGlobalState();
6709
+ // Each display must attach to the newly selected task and initialize its
6710
+ // own parser stream; the metadata client's bytes are never a replacement.
6711
+ await Promise.all([...wsClients.get(sessionId)?.values() ?? []].map(ws => independentTmuxReplays.get(ws)?.()));
6712
+ const layout = await getTmuxLayout(target);
6713
+ broadcastEvent(sessionId, { type: 'tmux-layout', layout });
6714
+ return layout;
6715
+ }
6762
6716
  router.post('/:sessionId/tmux', async (req, res) => {
6763
6717
  const { sessionId } = req.params;
6764
6718
  const session = terminalSessions.get(sessionId);
@@ -6779,25 +6733,7 @@ router.post('/:sessionId/tmux', async (req, res) => {
6779
6733
  if (!targetSessionName) {
6780
6734
  return res.status(400).json({ error: 'tmuxSessionName is required' });
6781
6735
  }
6782
- const preferredClientPid = getPtyProcessPid(session.ptyProcess);
6783
- const clientTty = await resolveTmuxClientTty(tmuxTarget, preferredClientPid);
6784
- if (!clientTty) {
6785
- return res.status(500).json({ error: 'No tmux client available for current session' });
6786
- }
6787
- await prepareManagedTmuxSession(targetSessionName, session.cwd);
6788
- await sendTmuxCommand(tmuxTarget, session.tmuxControl, ['switch-client', '-c', clientTty, '-t', targetSessionName]);
6789
- session.tmuxSessionName = targetSessionName;
6790
- session.lastActivity = Date.now();
6791
- if (updateGlobalBindingForBackendSession(sessionId, {
6792
- mode: 'tmux',
6793
- tmuxSessionName: targetSessionName,
6794
- cwd: session.cwd,
6795
- lastActivity: session.lastActivity,
6796
- })) {
6797
- persistAndBroadcastGlobalState();
6798
- }
6799
- const layout = await getTmuxLayout(targetSessionName);
6800
- broadcastEvent(sessionId, { type: 'tmux-layout', layout });
6736
+ const layout = await switchTmuxBackendSession(sessionId, session, targetSessionName);
6801
6737
  return res.json({ success: true, layout });
6802
6738
  }
6803
6739
  // All other actions: delegate to shared executeTmuxAction
@@ -7048,13 +6984,65 @@ async function executeTmuxAction(tmuxTarget, action, body, control) {
7048
6984
  }
7049
6985
  return { shouldBroadcastLayout };
7050
6986
  }
7051
- export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}) {
6987
+ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}, initialDimensions) {
7052
6988
  const session = terminalSessions.get(sessionId);
7053
6989
  if (!session) {
7054
6990
  ws.close(4001, 'Session not found');
7055
6991
  return;
7056
6992
  }
7057
- const sinceSeq = options.sinceSeq ?? 0;
6993
+ const initialSince = options.sinceSeq ?? 0;
6994
+ const delivery = new TerminalOutputDelivery((frame) => {
6995
+ if (ws.readyState === ws.OPEN)
6996
+ ws.send(JSON.stringify(frame));
6997
+ }, options.flowControl === true, 128 * 1024, 512 * 1024, () => {
6998
+ // No ACK may be outstanding (e.g. a single oversized frame). Reconnect
6999
+ // against authoritative history instead of leaving this observer stalled.
7000
+ if (ws.readyState === ws.OPEN)
7001
+ ws.close(1013, 'Output observer exceeded budget');
7002
+ });
7003
+ outputDeliveries.set(ws, delivery);
7004
+ let outputWanted = options.outputActive !== false;
7005
+ let clientPaused = false;
7006
+ let replayRequest = null;
7007
+ let clientCols = session.cols;
7008
+ let clientRows = session.rows;
7009
+ let initialAttachmentResize = true;
7010
+ let initialScreen = null;
7011
+ if (initialDimensions && options.independentTmux) {
7012
+ clientCols = initialDimensions.cols;
7013
+ clientRows = initialDimensions.rows;
7014
+ }
7015
+ const ownTmux = session.mode === 'tmux' && options.independentTmux === true;
7016
+ if (ownTmux)
7017
+ independentTmuxClients.add(ws);
7018
+ const attachment = ownTmux ? new TerminalClientAttachment(async (cols, rows) => {
7019
+ const provider = await getPtyProvider();
7020
+ // The metadata observer must not choose the pane size while a browser
7021
+ // owns an attached client. Resolve by exact PID, never another client.
7022
+ const raw = await runTmux(['list-clients', '-t', session.tmuxSessionName, '-F', '#{client_pid} #{client_tty}']);
7023
+ const metadata = raw.split('\n').map(line => line.trim().split(/\s+/))
7024
+ .find(([pid]) => pid === String(session.ptyProcess.pid));
7025
+ if (metadata?.[1])
7026
+ await runTmux(['refresh-client', '-t', metadata[1], '-f', 'ignore-size']);
7027
+ const env = buildInteractiveColorEnvironment({ ...process.env, PATH: buildAugmentedPath() });
7028
+ delete env.TMUX;
7029
+ delete env.TMUX_PANE;
7030
+ return provider.spawn(getTmuxBinary(), ['-T', 'RGB,sync', 'attach-session', '-t', session.tmuxSessionName], {
7031
+ name: 'xterm-256color', cols, rows, cwd: session.cwd || os.homedir(),
7032
+ env: { ...env, TERM: 'xterm-256color', COLORTERM: 'truecolor' },
7033
+ });
7034
+ }, (data) => {
7035
+ if (ws.readyState !== ws.OPEN)
7036
+ return;
7037
+ if (ws.bufferedAmount > 1024 * 1024) {
7038
+ ws.close(1013, 'Output transport is congested');
7039
+ return;
7040
+ }
7041
+ const liveData = initialScreen ? initialScreen.push(data) : data;
7042
+ if (liveData)
7043
+ delivery.enqueue({ type: 'data', data: liveData });
7044
+ }, () => { if (ws.readyState === ws.OPEN)
7045
+ ws.close(1012, 'Tmux display client detached'); }) : null;
7058
7046
  // Register client
7059
7047
  let clients = wsClients.get(sessionId);
7060
7048
  if (!clients) {
@@ -7067,86 +7055,153 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}) {
7067
7055
  if (updateGlobalBindingForBackendSession(sessionId, { cwd: session.cwd, lastActivity: session.lastActivity })) {
7068
7056
  persistAndBroadcastGlobalState();
7069
7057
  }
7070
- void (async () => {
7071
- // 连接时立即检测一次 activeProgram,避免前端首次显示闪烁
7072
- try {
7073
- if (session.mode === 'shell') {
7074
- const ap = await detectShellActiveProgram(session);
7075
- if (ap)
7076
- session.activeProgram = ap;
7058
+ const sendReplay = (requestedSince = initialSince, clientEpoch = options.streamEpoch) => {
7059
+ if (replayRequest)
7060
+ return replayRequest;
7061
+ const sinceSeq = resolveTerminalReplayCursor(requestedSince, clientEpoch, TERMINAL_STREAM_EPOCH);
7062
+ delivery.replaying = true;
7063
+ if (attachment) {
7064
+ attachment.close();
7065
+ initialScreen?.cancel();
7066
+ initialScreen = null;
7067
+ initialAttachmentResize = true;
7068
+ delivery.setActive(false); // Discard only this observer's obsolete stream.
7069
+ }
7070
+ replayRequest = (async () => {
7071
+ // 连接时立即检测一次 activeProgram,避免前端首次显示闪烁
7072
+ try {
7073
+ if (session.mode === 'shell') {
7074
+ const ap = await detectShellActiveProgram(session);
7075
+ if (ap)
7076
+ session.activeProgram = ap;
7077
+ }
7078
+ else if (session.mode === 'tmux' && session.tmuxSessionName) {
7079
+ const layout = await getCachedTmuxLayout(session.tmuxSessionName);
7080
+ const ap = getActiveProgramFromTmuxLayout(layout);
7081
+ if (ap)
7082
+ session.activeProgram = ap;
7083
+ }
7077
7084
  }
7078
- else if (session.mode === 'tmux' && session.tmuxSessionName) {
7079
- const layout = await getCachedTmuxLayout(session.tmuxSessionName);
7080
- const ap = getActiveProgramFromTmuxLayout(layout);
7081
- if (ap)
7082
- session.activeProgram = ap;
7085
+ catch { /* ignore */ }
7086
+ // 计算重连补帧:
7087
+ // - sinceSeq > 0:短线重连,shell 模式按 seq 补增量;超出窗口则发 outOfWindow + 全量。
7088
+ // - sinceSeq == 0:首次连接(包括手机 PWA 冷启动)。以前这里只回 lastSeq、不带数据,
7089
+ // 靠客户端单独走 HTTP /attach 拿 scrollback;但那条路径会阻塞 MultiTerminalView 的
7090
+ // "Restoring sessions..." 全屏 loading(蜂窝 RTT 1-3 秒)。现在直接把 restore history
7091
+ // 塞进 'connected' 事件,省掉一次 HTTP 往返,前端 UI 可以立刻渲染、scrollback 随 WS
7092
+ // 到达即填充。tmux 模式发 capture-pane 输出(带 clear-screen 前缀,避免与 xterm 默认
7093
+ // 内容拼接),shell 模式发 ring buffer 内容(最多 100KB)。
7094
+ //
7095
+ // replayOutOfWindow=true 的语义在 sinceSeq=0 时是"你没有基线,请清空已有内容
7096
+ // 再应用 replayChunks"。这正好覆盖客户端"localStorage hydrate 出来的缓存 buffer"
7097
+ // 场景:缓存内容会被服务端权威版本干净地替换,不会出现重复或顺序错位。
7098
+ let replayChunks = [];
7099
+ let replayLastSeq = 0;
7100
+ let replayOutOfWindow = false;
7101
+ if (attachment) {
7102
+ if (ws.readyState !== ws.OPEN)
7103
+ return;
7104
+ delivery.setActive(outputWanted && !clientPaused);
7105
+ if (delivery.active) {
7106
+ const screen = new TmuxInitialScreen();
7107
+ initialScreen = screen;
7108
+ if (!await attachment.open(clientCols, clientRows)) {
7109
+ screen.cancel();
7110
+ return;
7111
+ }
7112
+ const first = await screen.ready;
7113
+ if (initialScreen === screen)
7114
+ initialScreen = null;
7115
+ if (first.status === 'cancelled' || ws.readyState !== ws.OPEN)
7116
+ return;
7117
+ if (first.status === 'overflow')
7118
+ throw new Error('Initial tmux screen exceeded output budget');
7119
+ // Bootstrap with the actual first PTY redraw, not a standalone empty
7120
+ // reset followed by the screen in a second client write. Subsequent
7121
+ // bytes already wait in delivery and retain their original ordering.
7122
+ replayChunks = first.data ? [first.data] : ['\x1bc'];
7123
+ }
7124
+ else {
7125
+ replayChunks = ['\x1bc'];
7126
+ }
7127
+ replayOutOfWindow = true;
7083
7128
  }
7084
- }
7085
- catch { /* ignore */ }
7086
- // 计算重连补帧:
7087
- // - sinceSeq > 0:短线重连,shell 模式按 seq 补增量;超出窗口则发 outOfWindow + 全量。
7088
- // - sinceSeq == 0:首次连接(包括手机 PWA 冷启动)。以前这里只回 lastSeq、不带数据,
7089
- // 靠客户端单独走 HTTP /attach 拿 scrollback;但那条路径会阻塞 MultiTerminalView 的
7090
- // "Restoring sessions..." 全屏 loading(蜂窝 RTT 1-3 秒)。现在直接把 restore history
7091
- // 塞进 'connected' 事件,省掉一次 HTTP 往返,前端 UI 可以立刻渲染、scrollback 随 WS
7092
- // 到达即填充。tmux 模式发 capture-pane 输出(带 clear-screen 前缀,避免与 xterm 默认
7093
- // 内容拼接),shell 模式发 ring buffer 内容(最多 100KB)。
7094
- //
7095
- // replayOutOfWindow=true 的语义在 sinceSeq=0 时是"你没有基线,请清空已有内容
7096
- // 再应用 replayChunks"。这正好覆盖客户端"localStorage hydrate 出来的缓存 buffer"
7097
- // 场景:缓存内容会被服务端权威版本干净地替换,不会出现重复或顺序错位。
7098
- let replayChunks = [];
7099
- let replayLastSeq = 0;
7100
- let replayOutOfWindow = false;
7101
- if (sinceSeq > 0 && session.mode === 'shell') {
7102
- const since = getHistorySince(sessionId, sinceSeq);
7103
- replayChunks = since.chunks.map((c) => c.data);
7104
- replayLastSeq = since.lastSeq;
7105
- replayOutOfWindow = since.outOfWindow;
7106
- }
7107
- else {
7108
- // 首次连接:直接补全量 scrollback,并强制让客户端清空已有内容(处理缓存 hydrate)
7109
- try {
7110
- replayChunks = await getRestoreHistory(sessionId, session);
7129
+ else if (sinceSeq > 0 && session.mode === 'shell') {
7130
+ const since = getHistorySince(sessionId, sinceSeq);
7131
+ replayChunks = since.chunks.map((c) => c.data);
7132
+ replayLastSeq = since.lastSeq;
7133
+ replayOutOfWindow = since.outOfWindow;
7111
7134
  }
7112
- catch (error) {
7113
- console.warn(`[ws] getRestoreHistory failed for ${sessionId}: ${getErrorMessage(error)}`);
7114
- replayChunks = [];
7135
+ else {
7136
+ // 首次连接:直接补全量 scrollback,并强制让客户端清空已有内容(处理缓存 hydrate)
7137
+ try {
7138
+ replayChunks = session.mode === 'shell' ? getReconnectionHistory(sessionId) : await getRestoreHistory(sessionId, session);
7139
+ }
7140
+ catch (error) {
7141
+ console.warn(`[ws] getRestoreHistory failed for ${sessionId}: ${getErrorMessage(error)}`);
7142
+ replayChunks = [];
7143
+ }
7144
+ replayLastSeq = session.mode === 'shell' ? getHistoryLastSeq(sessionId) : 0;
7145
+ replayOutOfWindow = replayChunks.length > 0;
7115
7146
  }
7116
- replayLastSeq = session.mode === 'shell' ? getHistoryLastSeq(sessionId) : 0;
7117
- replayOutOfWindow = replayChunks.length > 0;
7118
- }
7119
- // Send connected event (after initial detection)
7120
- const runtime = globalThis.Bun ? 'bun' : 'node';
7121
- ws.send(JSON.stringify({
7122
- type: 'connected',
7123
- runtime,
7124
- ptyBackend: session.ptyBackend || 'unknown',
7125
- mode: session.mode,
7126
- tmuxSessionName: session.tmuxSessionName,
7127
- cwd: session.cwd ?? null,
7128
- activeProgram: session.activeProgram?.command ?? getPersistedActiveProgramForBackend(sessionId),
7129
- activeProgramRaw: session.activeProgram?.rawArgs ?? null,
7130
- activeProgramSource: session.activeProgram?.source ?? null,
7131
- tuiProgress: session.tuiProgress,
7132
- shellTitle: session.lastOscTitle,
7133
- promptState: session.lastPromptState,
7134
- focusTrackingRequested: session.focusTrackingRequested,
7135
- // 短线重连补帧:
7136
- // replayChunks 为补发数据;replayLastSeq 是客户端应记录的新基线;
7137
- // replayOutOfWindow 表示客户端基线已被服务端淘汰,前端可以选择清屏后再回放。
7138
- replayChunks,
7139
- replayLastSeq,
7140
- replayOutOfWindow,
7141
- }));
7142
- // Rich agent state rides its own message (see the SSE path above).
7143
- if (session.agent || session.agentSession || session.agentResumeRecovered) {
7144
- ws.send(JSON.stringify(buildAgentStatusPayload(sessionId, session)));
7145
- }
7146
- if (session.gitStatus) {
7147
- ws.send(JSON.stringify({ type: 'git-status', gitStatus: session.gitStatus }));
7148
- }
7149
- })();
7147
+ if (ws.readyState !== ws.OPEN)
7148
+ return;
7149
+ // Empty authoritative histories still need to clear an obsolete baseline.
7150
+ if (sinceSeq === 0 && replayChunks.length === 0) {
7151
+ replayChunks = ['\x1bc'];
7152
+ replayOutOfWindow = true;
7153
+ }
7154
+ // Send connected event (after initial detection)
7155
+ const runtime = globalThis.Bun ? 'bun' : 'node';
7156
+ ws.send(JSON.stringify({
7157
+ type: 'connected',
7158
+ streamEpoch: TERMINAL_STREAM_EPOCH,
7159
+ outputProtocol: options.flowControl ? 2 : undefined,
7160
+ runtime,
7161
+ ptyBackend: session.ptyBackend || 'unknown',
7162
+ mode: session.mode,
7163
+ tmuxSessionName: session.tmuxSessionName,
7164
+ cwd: session.cwd ?? null,
7165
+ activeProgram: session.activeProgram?.command ?? getPersistedActiveProgramForBackend(sessionId),
7166
+ activeProgramRaw: session.activeProgram?.rawArgs ?? null,
7167
+ activeProgramSource: session.activeProgram?.source ?? null,
7168
+ tuiProgress: session.tuiProgress,
7169
+ shellTitle: session.lastOscTitle,
7170
+ promptState: session.lastPromptState,
7171
+ focusTrackingRequested: session.focusTrackingRequested,
7172
+ // 短线重连补帧:
7173
+ // replayChunks 为补发数据;replayLastSeq 是客户端应记录的新基线;
7174
+ // replayOutOfWindow 表示客户端基线已被服务端淘汰,前端可以选择清屏后再回放。
7175
+ replayChunks,
7176
+ replayLastSeq,
7177
+ replayOutOfWindow,
7178
+ }));
7179
+ delivery.finishReplay(replayLastSeq);
7180
+ // Rich agent state rides its own message (see the SSE path above).
7181
+ if (session.agent || session.agentSession || session.agentResumeRecovered) {
7182
+ ws.send(JSON.stringify(buildAgentStatusPayload(sessionId, session)));
7183
+ }
7184
+ if (session.gitStatus) {
7185
+ ws.send(JSON.stringify({ type: 'git-status', gitStatus: session.gitStatus }));
7186
+ }
7187
+ })().catch((error) => {
7188
+ initialScreen?.cancel();
7189
+ initialScreen = null;
7190
+ console.warn(`[ws] replay failed session=${sessionId}: ${getErrorMessage(error)}`);
7191
+ if (ws.readyState === ws.OPEN)
7192
+ ws.close(1011, 'Replay unavailable');
7193
+ }).finally(() => { replayRequest = null; });
7194
+ return replayRequest;
7195
+ };
7196
+ if (attachment)
7197
+ independentTmuxReplays.set(ws, async () => {
7198
+ attachment.close();
7199
+ initialScreen?.cancel();
7200
+ await replayRequest;
7201
+ if (ws.readyState === ws.OPEN)
7202
+ await sendReplay(0);
7203
+ });
7204
+ void sendReplay();
7150
7205
  // Tmux layout polling (per-client, like the SSE stream does)
7151
7206
  let tmuxInterval = null;
7152
7207
  let activeProgramInterval = null;
@@ -7284,11 +7339,12 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}) {
7284
7339
  case 'input': {
7285
7340
  if (typeof msg.data === 'string' && msg.data.length > 0) {
7286
7341
  const data = msg.data;
7287
- if (session.mode === 'tmux') {
7342
+ if (attachment) {
7343
+ session.lastActivity = Date.now();
7344
+ attachment.write(data);
7345
+ }
7346
+ else if (session.mode === 'tmux') {
7288
7347
  await enqueueTmuxIo(session, async () => {
7289
- if (isTmuxWheelInput(data)) {
7290
- await syncTmuxScreenBeforeScroll(sessionId, clientId, session, ws);
7291
- }
7292
7348
  session.lastActivity = Date.now();
7293
7349
  session.ptyProcess.write(data);
7294
7350
  });
@@ -7303,34 +7359,47 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}) {
7303
7359
  case 'resize': {
7304
7360
  const cols = Number(msg.cols);
7305
7361
  const rows = Number(msg.rows);
7306
- if (cols > 0 && rows > 0) {
7307
- const screenSyncGenerationBefore = session.tmuxResizeGeneration ?? 0;
7362
+ if (Number.isFinite(cols) && Number.isFinite(rows) && cols > 0 && rows > 0) {
7363
+ if (attachment) {
7364
+ const cleanCols = Math.floor(cols), cleanRows = Math.floor(rows);
7365
+ const sameSize = clientCols === cleanCols && clientRows === cleanRows;
7366
+ const ok = sameSize ? attachment.attached : attachment.resize(cleanCols, cleanRows);
7367
+ if (ok) {
7368
+ // The first resize confirms the grid supplied at attachment.
7369
+ // Its PTY is already drawing that grid; forcing refresh-client
7370
+ // here repeats the initial clear/full redraw. Later same-size
7371
+ // requests remain explicit display recovery requests.
7372
+ const needsRedraw = sameSize && !initialAttachmentResize;
7373
+ initialAttachmentResize = false;
7374
+ clientCols = cleanCols;
7375
+ clientRows = cleanRows;
7376
+ session.lastActivity = Date.now();
7377
+ if (needsRedraw)
7378
+ await redrawTmuxClient(runTmux, session.tmuxSessionName, attachment.pid);
7379
+ }
7380
+ if (ws.readyState === ws.OPEN)
7381
+ ws.send(JSON.stringify({
7382
+ type: 'resize-ack', seq: typeof msg.seq === 'number' ? msg.seq : undefined,
7383
+ ok, cols: clientCols, rows: clientRows, screenSyncPending: false,
7384
+ }));
7385
+ break;
7386
+ }
7387
+ const sameSize = session.cols === Math.floor(cols) && session.rows === Math.floor(rows);
7308
7388
  const ok = session.mode === 'tmux'
7309
7389
  ? await enqueueTmuxIo(session, () => applyPtyResize(sessionId, session, cols, rows, `ws-resize:${clientId}`, clientId))
7310
7390
  : applyPtyResize(sessionId, session, cols, rows, `ws-resize:${clientId}`, clientId);
7311
- // A forced same-size resize is the client's explicit redraw
7312
- // request. There is no geometry change for applyPtyResize to mark,
7313
- // but the client still needs an authoritative grid (including the
7314
- // cursor position) rather than waiting for the TUI to emit output.
7315
- if (ok
7316
- && session.mode === 'tmux'
7317
- && (session.tmuxResizeGeneration ?? 0) === screenSyncGenerationBefore) {
7318
- markTmuxClientForScreenSync(session, clientId);
7319
- scheduleTmuxScreenSyncAfterResize(sessionId, session, clientId);
7391
+ // Same-size requests explicitly recover the display; actual geometry
7392
+ // changes already cause tmux to redraw its attached client.
7393
+ if (ok && session.mode === 'tmux' && sameSize) {
7394
+ await enqueueTmuxIo(session, () => redrawTmuxClient(runTmux, session.tmuxSessionName, session.ptyProcess.pid));
7320
7395
  }
7321
- const screenSyncGeneration = session.tmuxResizeGeneration ?? 0;
7322
- const screenSyncPending = ok
7323
- && session.mode === 'tmux'
7324
- && screenSyncGeneration > screenSyncGenerationBefore
7325
- && session.tmuxScreenSyncClients?.has(clientId) === true;
7326
7396
  ws.send(JSON.stringify({
7327
7397
  type: 'resize-ack',
7328
7398
  seq: typeof msg.seq === 'number' ? msg.seq : undefined,
7329
7399
  ok,
7330
7400
  cols: session.cols,
7331
7401
  rows: session.rows,
7332
- screenSyncPending,
7333
- screenSyncGeneration: screenSyncPending ? screenSyncGeneration : undefined,
7402
+ screenSyncPending: false,
7334
7403
  }));
7335
7404
  }
7336
7405
  break;
@@ -7341,10 +7410,14 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}) {
7341
7410
  ws.send(JSON.stringify({ type: 'tmux-result', reqId, success: false, error: 'Not in tmux mode' }));
7342
7411
  break;
7343
7412
  }
7413
+ if (msg.action === 'switch-session') {
7414
+ const target = typeof msg.tmuxSessionName === 'string' ? msg.tmuxSessionName.trim() : '';
7415
+ await enqueueTmuxIo(session, () => switchTmuxBackendSession(sessionId, session, target));
7416
+ if (ws.readyState === ws.OPEN)
7417
+ ws.send(JSON.stringify({ type: 'tmux-result', reqId, success: true }));
7418
+ break;
7419
+ }
7344
7420
  const result = await enqueueTmuxIo(session, async () => {
7345
- if (msg.action === 'scroll') {
7346
- await syncTmuxScreenBeforeScroll(sessionId, clientId, session, ws);
7347
- }
7348
7421
  return executeTmuxAction(session.tmuxSessionName, msg.action, msg, session.tmuxControl);
7349
7422
  });
7350
7423
  ws.send(JSON.stringify({ type: 'tmux-result', reqId, success: !result.error, error: result.error }));
@@ -7360,7 +7433,12 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}) {
7360
7433
  case 'focus': {
7361
7434
  const focused = msg.focused === true;
7362
7435
  const reason = typeof msg.reason === 'string' ? msg.reason : 'client-focus';
7363
- updateClientFocusState(sessionId, session, clientId, focused, reason);
7436
+ if (attachment) {
7437
+ if (session.focusTrackingRequested)
7438
+ attachment.write(getFocusSequence(focused));
7439
+ }
7440
+ else
7441
+ updateClientFocusState(sessionId, session, clientId, focused, reason);
7364
7442
  break;
7365
7443
  }
7366
7444
  case 'viewing': {
@@ -7375,10 +7453,41 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}) {
7375
7453
  }
7376
7454
  break;
7377
7455
  }
7456
+ case 'output-subscription': {
7457
+ if (!options.flowControl || typeof msg.active !== 'boolean')
7458
+ break;
7459
+ outputWanted = msg.active;
7460
+ const resumed = delivery.setActive(outputWanted && !clientPaused);
7461
+ if (!delivery.active)
7462
+ attachment?.close();
7463
+ if (resumed && delivery.active) {
7464
+ void sendReplay(typeof msg.since === 'number' ? msg.since : 0, typeof msg.epoch === 'string' ? msg.epoch : undefined);
7465
+ }
7466
+ break;
7467
+ }
7468
+ case 'output-ack': {
7469
+ if (!options.flowControl || typeof msg.flowSeq !== 'number')
7470
+ break;
7471
+ delivery.acknowledge(msg.flowSeq);
7472
+ if (delivery.needsReplay && delivery.active) {
7473
+ void sendReplay(typeof msg.since === 'number' ? msg.since : 0, typeof msg.epoch === 'string' ? msg.epoch : undefined);
7474
+ }
7475
+ break;
7476
+ }
7378
7477
  case 'flow-control': {
7379
7478
  if (typeof msg.paused === 'boolean') {
7380
7479
  const reason = typeof msg.reason === 'string' ? msg.reason : 'client-flow-control';
7381
- setClientFlowPaused(sessionId, session, clientId, msg.paused, reason);
7480
+ if (options.flowControl) {
7481
+ const wasPaused = clientPaused;
7482
+ clientPaused = msg.paused;
7483
+ delivery.setActive(outputWanted && !clientPaused);
7484
+ if (!delivery.active)
7485
+ attachment?.close();
7486
+ if (wasPaused && delivery.active)
7487
+ void sendReplay(0);
7488
+ }
7489
+ else
7490
+ setClientFlowPaused(sessionId, session, clientId, msg.paused, reason);
7382
7491
  }
7383
7492
  break;
7384
7493
  }
@@ -7412,6 +7521,9 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}) {
7412
7521
  });
7413
7522
  // Cleanup on close
7414
7523
  ws.on('close', () => {
7524
+ initialScreen?.cancel();
7525
+ initialScreen = null;
7526
+ attachment?.close();
7415
7527
  if (tmuxInterval)
7416
7528
  clearInterval(tmuxInterval);
7417
7529
  if (activeProgramInterval)
@@ -7423,8 +7535,8 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}) {
7423
7535
  wsClients.delete(sessionId);
7424
7536
  }
7425
7537
  }
7426
- removeClientFocus(sessionId, session, clientId);
7427
- clearTmuxScreenSyncTimer(session, clientId);
7538
+ if (!attachment)
7539
+ removeClientFocus(sessionId, session, clientId);
7428
7540
  if (options.pushClientId) {
7429
7541
  setClientViewingSession(options.pushClientId, sessionId, false);
7430
7542
  }