termdock 1.4.312 → 1.4.314

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 (351) hide show
  1. package/dist/client/assets/{App-ChS2-lkz.js → App-BCTGnwU1.js} +53 -53
  2. package/dist/client/assets/App-BCTGnwU1.js.br +0 -0
  3. package/dist/client/assets/App-BCTGnwU1.js.gz +0 -0
  4. package/dist/client/assets/{ArchitecturePanel-JtjyyJoW.js → ArchitecturePanel-CVTIYbyj.js} +6 -6
  5. package/dist/client/assets/ArchitecturePanel-CVTIYbyj.js.br +0 -0
  6. package/dist/client/assets/ArchitecturePanel-CVTIYbyj.js.gz +0 -0
  7. package/dist/client/assets/{ChangeWalkthroughPanel-BlQ5-VPp.js → ChangeWalkthroughPanel-BKsuofw6.js} +2 -2
  8. package/dist/client/assets/ChangeWalkthroughPanel-BKsuofw6.js.br +0 -0
  9. package/dist/client/assets/ChangeWalkthroughPanel-BKsuofw6.js.gz +0 -0
  10. package/dist/client/assets/{CollaborationMainWorkspace-aFLAMqDr.js → CollaborationMainWorkspace-DZ0qwLUz.js} +1 -1
  11. package/dist/client/assets/CollaborationMainWorkspace-DZ0qwLUz.js.br +0 -0
  12. package/dist/client/assets/CollaborationMainWorkspace-DZ0qwLUz.js.gz +0 -0
  13. package/dist/client/assets/CollaborationTaskContent-BLQNknOq.js +2 -0
  14. package/dist/client/assets/{ComputerControlView-TAKDbBUl.js → ComputerControlView-DN6cXOnb.js} +2 -2
  15. package/dist/client/assets/ComputerControlView-DN6cXOnb.js.br +0 -0
  16. package/dist/client/assets/ComputerControlView-DN6cXOnb.js.gz +0 -0
  17. package/dist/client/assets/{DagPlayground-CR4uDFOx.js → DagPlayground-ZgszT1TH.js} +1 -1
  18. package/dist/client/assets/DagPlayground-ZgszT1TH.js.br +0 -0
  19. package/dist/client/assets/DagPlayground-ZgszT1TH.js.gz +0 -0
  20. package/dist/client/assets/{DiffLab-BqeHMDOy.js → DiffLab-D_9U-zfZ.js} +1 -1
  21. package/dist/client/assets/DiffLab-D_9U-zfZ.js.br +0 -0
  22. package/dist/client/assets/DiffLab-D_9U-zfZ.js.gz +0 -0
  23. package/dist/client/assets/{DiffReview-DqrOcRfP.js → DiffReview-8Pfe_BNO.js} +1 -1
  24. package/dist/client/assets/DiffReview-8Pfe_BNO.js.br +0 -0
  25. package/dist/client/assets/DiffReview-8Pfe_BNO.js.gz +0 -0
  26. package/dist/client/assets/{DiffReviewLab-CEYpbrL6.js → DiffReviewLab-p3ZSl0P2.js} +1 -1
  27. package/dist/client/assets/DiffReviewLab-p3ZSl0P2.js.br +0 -0
  28. package/dist/client/assets/DiffReviewLab-p3ZSl0P2.js.gz +0 -0
  29. package/dist/client/assets/{DiffViewer-F-uQSmhG.js → DiffViewer-Cz64sLJT.js} +8 -8
  30. package/dist/client/assets/DiffViewer-Cz64sLJT.js.br +0 -0
  31. package/dist/client/assets/DiffViewer-Cz64sLJT.js.gz +0 -0
  32. package/dist/client/assets/{ModelPreview-KmXFkgij.js → ModelPreview-B28x060d.js} +1 -1
  33. package/dist/client/assets/ModelPreview-B28x060d.js.br +0 -0
  34. package/dist/client/assets/ModelPreview-B28x060d.js.gz +0 -0
  35. package/dist/client/assets/{RightSidebar-VMdXpo4h.js → RightSidebar-SIqDjggD.js} +3 -3
  36. package/dist/client/assets/RightSidebar-SIqDjggD.js.br +0 -0
  37. package/dist/client/assets/RightSidebar-SIqDjggD.js.gz +0 -0
  38. package/dist/client/assets/{abnfDiagram-VCTEODGH-CAMk1C0N.js → abnfDiagram-VCTEODGH--t0bQKCQ.js} +1 -1
  39. package/dist/client/assets/abnfDiagram-VCTEODGH--t0bQKCQ.js.br +0 -0
  40. package/dist/client/assets/abnfDiagram-VCTEODGH--t0bQKCQ.js.gz +0 -0
  41. package/dist/client/assets/{app-CHxLSuGQ.js → app-DWidKLU2.js} +13 -13
  42. package/dist/client/assets/app-DWidKLU2.js.br +0 -0
  43. package/dist/client/assets/app-DWidKLU2.js.gz +0 -0
  44. package/dist/client/assets/{arc-CYG_-1vC.js → arc-DMWsmL7t.js} +1 -1
  45. package/dist/client/assets/arc-DMWsmL7t.js.br +0 -0
  46. package/dist/client/assets/arc-DMWsmL7t.js.gz +0 -0
  47. package/dist/client/assets/{architectureDiagram-5GKGNRK7-BqHzezLR.js → architectureDiagram-5GKGNRK7-BYkvSKnR.js} +1 -1
  48. package/dist/client/assets/architectureDiagram-5GKGNRK7-BYkvSKnR.js.br +0 -0
  49. package/dist/client/assets/architectureDiagram-5GKGNRK7-BYkvSKnR.js.gz +0 -0
  50. package/dist/client/assets/{blockDiagram-I7D4REHJ-D6GWRO_Z.js → blockDiagram-I7D4REHJ-B574d9TS.js} +1 -1
  51. package/dist/client/assets/blockDiagram-I7D4REHJ-B574d9TS.js.br +0 -0
  52. package/dist/client/assets/blockDiagram-I7D4REHJ-B574d9TS.js.gz +0 -0
  53. package/dist/client/assets/{c4Diagram-7LVT6UL2-CutmGIGb.js → c4Diagram-7LVT6UL2-D__CwUct.js} +1 -1
  54. package/dist/client/assets/c4Diagram-7LVT6UL2-D__CwUct.js.br +0 -0
  55. package/dist/client/assets/c4Diagram-7LVT6UL2-D__CwUct.js.gz +0 -0
  56. package/dist/client/assets/channel-BonXK9tr.js +1 -0
  57. package/dist/client/assets/{chunk-2Q5K7J3B-DwiUpGFu.js → chunk-2Q5K7J3B-BvwmL72I.js} +1 -1
  58. package/dist/client/assets/{chunk-5VM5RSS4-C35gLPSH.js → chunk-5VM5RSS4-BktO-a5l.js} +1 -1
  59. package/dist/client/assets/{chunk-F27PBJKO-CNptP19P.js → chunk-F27PBJKO-DeClqFBe.js} +1 -1
  60. package/dist/client/assets/chunk-F27PBJKO-DeClqFBe.js.br +0 -0
  61. package/dist/client/assets/chunk-F27PBJKO-DeClqFBe.js.gz +0 -0
  62. package/dist/client/assets/{chunk-IMKFNOWR-DHdpB9A0.js → chunk-IMKFNOWR-DBRCslkn.js} +1 -1
  63. package/dist/client/assets/chunk-IMKFNOWR-DBRCslkn.js.br +0 -0
  64. package/dist/client/assets/chunk-IMKFNOWR-DBRCslkn.js.gz +0 -0
  65. package/dist/client/assets/{chunk-JWPE2WC7-CrKSOzdE.js → chunk-JWPE2WC7-BfpbqgrR.js} +1 -1
  66. package/dist/client/assets/{chunk-POPQ4Y6H-CiZGLRSk.js → chunk-POPQ4Y6H-Bw-dqneu.js} +1 -1
  67. package/dist/client/assets/{chunk-SVP7TREG-B70pX8OB.js → chunk-SVP7TREG-BdxOWBjP.js} +1 -1
  68. package/dist/client/assets/chunk-SVP7TREG-BdxOWBjP.js.br +0 -0
  69. package/dist/client/assets/chunk-SVP7TREG-BdxOWBjP.js.gz +0 -0
  70. package/dist/client/assets/{chunk-TICWLB2K-Ba1mI99F.js → chunk-TICWLB2K-BtNXehgz.js} +1 -1
  71. package/dist/client/assets/chunk-TICWLB2K-BtNXehgz.js.br +0 -0
  72. package/dist/client/assets/chunk-TICWLB2K-BtNXehgz.js.gz +0 -0
  73. package/dist/client/assets/{chunk-XXDRQBXY-DmKIl18h.js → chunk-XXDRQBXY-CUxGdImw.js} +1 -1
  74. package/dist/client/assets/classDiagram-ZZMXUADV-CXO_pgVP.js +1 -0
  75. package/dist/client/assets/classDiagram-v2-VYDZK3BY-CXO_pgVP.js +1 -0
  76. package/dist/client/assets/{cose-bilkent-JH36ORCC-C-NMDUHW.js → cose-bilkent-JH36ORCC-Buod2YZ0.js} +1 -1
  77. package/dist/client/assets/cose-bilkent-JH36ORCC-Buod2YZ0.js.br +0 -0
  78. package/dist/client/assets/cose-bilkent-JH36ORCC-Buod2YZ0.js.gz +0 -0
  79. package/dist/client/assets/{cynefin-OW5HDTMX-CZgEc1ab.js → cynefin-OW5HDTMX-i2eiybdj.js} +1 -1
  80. package/dist/client/assets/cynefin-OW5HDTMX-i2eiybdj.js.br +0 -0
  81. package/dist/client/assets/cynefin-OW5HDTMX-i2eiybdj.js.gz +0 -0
  82. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-CHQeSNm2.js → cynefinDiagram-5FMLGOSQ-D_YF2Yi3.js} +1 -1
  83. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-D_YF2Yi3.js.br +0 -0
  84. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-D_YF2Yi3.js.gz +0 -0
  85. package/dist/client/assets/{dagre-GXQ25YYZ-B_jkMdPS.js → dagre-GXQ25YYZ-CfLEvt7Z.js} +1 -1
  86. package/dist/client/assets/dagre-GXQ25YYZ-CfLEvt7Z.js.br +0 -0
  87. package/dist/client/assets/dagre-GXQ25YYZ-CfLEvt7Z.js.gz +0 -0
  88. package/dist/client/assets/{diagram-S7CK7UJ4-nv6Lnsrp.js → diagram-S7CK7UJ4-BV0Wackt.js} +1 -1
  89. package/dist/client/assets/diagram-S7CK7UJ4-BV0Wackt.js.br +0 -0
  90. package/dist/client/assets/diagram-S7CK7UJ4-BV0Wackt.js.gz +0 -0
  91. package/dist/client/assets/{diagram-UQ7AKVKN-BZf2fzaA.js → diagram-UQ7AKVKN-jwaoLY_P.js} +1 -1
  92. package/dist/client/assets/diagram-UQ7AKVKN-jwaoLY_P.js.br +0 -0
  93. package/dist/client/assets/diagram-UQ7AKVKN-jwaoLY_P.js.gz +0 -0
  94. package/dist/client/assets/{diagram-VSXAHHWV-CxL0_BH8.js → diagram-VSXAHHWV-CuAFyl0n.js} +1 -1
  95. package/dist/client/assets/diagram-VSXAHHWV-CuAFyl0n.js.br +0 -0
  96. package/dist/client/assets/diagram-VSXAHHWV-CuAFyl0n.js.gz +0 -0
  97. package/dist/client/assets/{diagram-VX7I27RA-Dm9MqpIE.js → diagram-VX7I27RA-bbmA7rRk.js} +1 -1
  98. package/dist/client/assets/diagram-VX7I27RA-bbmA7rRk.js.br +0 -0
  99. package/dist/client/assets/diagram-VX7I27RA-bbmA7rRk.js.gz +0 -0
  100. package/dist/client/assets/{diagram-Z3DM3KII-BIfTa7P5.js → diagram-Z3DM3KII-CX3-Mxwo.js} +1 -1
  101. package/dist/client/assets/diagram-Z3DM3KII-CX3-Mxwo.js.br +0 -0
  102. package/dist/client/assets/diagram-Z3DM3KII-CX3-Mxwo.js.gz +0 -0
  103. package/dist/client/assets/{ebnfDiagram-PWID7BFC-D4XhCDFS.js → ebnfDiagram-PWID7BFC-Pkq6omzy.js} +1 -1
  104. package/dist/client/assets/ebnfDiagram-PWID7BFC-Pkq6omzy.js.br +0 -0
  105. package/dist/client/assets/ebnfDiagram-PWID7BFC-Pkq6omzy.js.gz +0 -0
  106. package/dist/client/assets/{erDiagram-RLTQ6QDP-Dxd48dXC.js → erDiagram-RLTQ6QDP-CjdD0JCI.js} +1 -1
  107. package/dist/client/assets/erDiagram-RLTQ6QDP-CjdD0JCI.js.br +0 -0
  108. package/dist/client/assets/erDiagram-RLTQ6QDP-CjdD0JCI.js.gz +0 -0
  109. package/dist/client/assets/{flowDiagram-HODETNUW-BXBMsEmE.js → flowDiagram-HODETNUW-DKECYHVY.js} +1 -1
  110. package/dist/client/assets/flowDiagram-HODETNUW-DKECYHVY.js.br +0 -0
  111. package/dist/client/assets/flowDiagram-HODETNUW-DKECYHVY.js.gz +0 -0
  112. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-CBfDd-KZ.js → ganttDiagram-EL5Y4UJY-BPCGT0Kd.js} +1 -1
  113. package/dist/client/assets/ganttDiagram-EL5Y4UJY-BPCGT0Kd.js.br +0 -0
  114. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-CBfDd-KZ.js.gz → ganttDiagram-EL5Y4UJY-BPCGT0Kd.js.gz} +0 -0
  115. package/dist/client/assets/{gestureArbiter-DXLmNGli.js → gestureArbiter-DVPPQnKq.js} +1 -1
  116. package/dist/client/assets/{gestureArbiter-DXLmNGli.js.br → gestureArbiter-DVPPQnKq.js.br} +0 -0
  117. package/dist/client/assets/gestureArbiter-DVPPQnKq.js.gz +0 -0
  118. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-DtLM68fN.js → gitGraphDiagram-WWUBYQGX-DFCvVJ6L.js} +1 -1
  119. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DFCvVJ6L.js.br +0 -0
  120. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DFCvVJ6L.js.gz +0 -0
  121. package/dist/client/assets/{index-KuPaZyuZ.css → index-CSp4mPGE.css} +1 -1
  122. package/dist/client/assets/index-CSp4mPGE.css.br +0 -0
  123. package/dist/client/assets/{index-KuPaZyuZ.css.gz → index-CSp4mPGE.css.gz} +0 -0
  124. package/dist/client/assets/{infoDiagram-27XIBGKW-FRhqdJvW.js → infoDiagram-27XIBGKW-BTL8-sSN.js} +1 -1
  125. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-DAHBvAZ-.js → ishikawaDiagram-5VMMS53U-Xtc0AfGK.js} +1 -1
  126. package/dist/client/assets/ishikawaDiagram-5VMMS53U-Xtc0AfGK.js.br +0 -0
  127. package/dist/client/assets/ishikawaDiagram-5VMMS53U-Xtc0AfGK.js.gz +0 -0
  128. package/dist/client/assets/{journeyDiagram-3NMN7TZE-CVuWuL3Z.js → journeyDiagram-3NMN7TZE-BLtTDKtV.js} +1 -1
  129. package/dist/client/assets/journeyDiagram-3NMN7TZE-BLtTDKtV.js.br +0 -0
  130. package/dist/client/assets/journeyDiagram-3NMN7TZE-BLtTDKtV.js.gz +0 -0
  131. package/dist/client/assets/{kanban-definition-UXKFOSKX-ByQSUVJV.js → kanban-definition-UXKFOSKX-C65azoTU.js} +1 -1
  132. package/dist/client/assets/kanban-definition-UXKFOSKX-C65azoTU.js.br +0 -0
  133. package/dist/client/assets/kanban-definition-UXKFOSKX-C65azoTU.js.gz +0 -0
  134. package/dist/client/assets/{layout-Bb3Nb1c4.js → layout-TEicKqeV.js} +1 -1
  135. package/dist/client/assets/layout-TEicKqeV.js.br +0 -0
  136. package/dist/client/assets/layout-TEicKqeV.js.gz +0 -0
  137. package/dist/client/assets/{linear-DHMMQlOo.js → linear-DQSikGMo.js} +1 -1
  138. package/dist/client/assets/{linear-DHMMQlOo.js.br → linear-DQSikGMo.js.br} +0 -0
  139. package/dist/client/assets/linear-DQSikGMo.js.gz +0 -0
  140. package/dist/client/assets/{mermaid.core-BYfniK0H.js → mermaid.core-vZB1UnWX.js} +5 -5
  141. package/dist/client/assets/mermaid.core-vZB1UnWX.js.br +0 -0
  142. package/dist/client/assets/mermaid.core-vZB1UnWX.js.gz +0 -0
  143. package/dist/client/assets/{mindmap-definition-YA3MSWOX-EDLD5AyH.js → mindmap-definition-YA3MSWOX-B-coBapV.js} +1 -1
  144. package/dist/client/assets/mindmap-definition-YA3MSWOX-B-coBapV.js.br +0 -0
  145. package/dist/client/assets/mindmap-definition-YA3MSWOX-B-coBapV.js.gz +0 -0
  146. package/dist/client/assets/{passwordBootstrap-DCrtirwT.js → passwordBootstrap-LSQpoVpD.js} +1 -1
  147. package/dist/client/assets/passwordBootstrap-LSQpoVpD.js.br +0 -0
  148. package/dist/client/assets/passwordBootstrap-LSQpoVpD.js.gz +0 -0
  149. package/dist/client/assets/{pegDiagram-XKGWAZYB-BHYhkqJN.js → pegDiagram-XKGWAZYB--jWB5n1V.js} +1 -1
  150. package/dist/client/assets/pegDiagram-XKGWAZYB--jWB5n1V.js.br +0 -0
  151. package/dist/client/assets/pegDiagram-XKGWAZYB--jWB5n1V.js.gz +0 -0
  152. package/dist/client/assets/{pieDiagram-E7YTZNPT-BUIJlswC.js → pieDiagram-E7YTZNPT-DmAqsAUK.js} +1 -1
  153. package/dist/client/assets/pieDiagram-E7YTZNPT-DmAqsAUK.js.br +0 -0
  154. package/dist/client/assets/pieDiagram-E7YTZNPT-DmAqsAUK.js.gz +0 -0
  155. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-D8Im-7yC.js → quadrantDiagram-AXDQQJYC-CqsfUApA.js} +1 -1
  156. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CqsfUApA.js.br +0 -0
  157. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CqsfUApA.js.gz +0 -0
  158. package/dist/client/assets/{railroadDiagram-O6MQD6OU-D7n6z2G1.js → railroadDiagram-O6MQD6OU-CzvYijD5.js} +1 -1
  159. package/dist/client/assets/railroadDiagram-O6MQD6OU-CzvYijD5.js.br +0 -0
  160. package/dist/client/assets/railroadDiagram-O6MQD6OU-CzvYijD5.js.gz +0 -0
  161. package/dist/client/assets/{rdpSession-DJlNIbVk.js → rdpSession-DGvDRc95.js} +1 -1
  162. package/dist/client/assets/rdpSession-DGvDRc95.js.br +0 -0
  163. package/dist/client/assets/rdpSession-DGvDRc95.js.gz +0 -0
  164. package/dist/client/assets/{referenceLongPress-DFSrssSr.js → referenceLongPress-BwP_B3l2.js} +1 -1
  165. package/dist/client/assets/referenceLongPress-BwP_B3l2.js.br +0 -0
  166. package/dist/client/assets/referenceLongPress-BwP_B3l2.js.gz +0 -0
  167. package/dist/client/assets/{requirementDiagram-BXWQKSXE-Ki0rR-F7.js → requirementDiagram-BXWQKSXE-E2FSO_hc.js} +1 -1
  168. package/dist/client/assets/requirementDiagram-BXWQKSXE-E2FSO_hc.js.br +0 -0
  169. package/dist/client/assets/requirementDiagram-BXWQKSXE-E2FSO_hc.js.gz +0 -0
  170. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-36NmMqsW.js → sankeyDiagram-P5KCCOFB-uSCR6gDg.js} +1 -1
  171. package/dist/client/assets/sankeyDiagram-P5KCCOFB-uSCR6gDg.js.br +0 -0
  172. package/dist/client/assets/sankeyDiagram-P5KCCOFB-uSCR6gDg.js.gz +0 -0
  173. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-5vsPuFyO.js → sequenceDiagram-WJ2MYXX4-BqxdP03l.js} +1 -1
  174. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-BqxdP03l.js.br +0 -0
  175. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-BqxdP03l.js.gz +0 -0
  176. package/dist/client/assets/{sizeCapture-INFHLROL-DbAulwBg.js → sizeCapture-INFHLROL-B7GSZxIt.js} +1 -1
  177. package/dist/client/assets/sizeCapture-INFHLROL-B7GSZxIt.js.br +0 -0
  178. package/dist/client/assets/sizeCapture-INFHLROL-B7GSZxIt.js.gz +0 -0
  179. package/dist/client/assets/{sparkles-CapLTKAs.js → sparkles-DBVpVoIl.js} +1 -1
  180. package/dist/client/assets/{stateDiagram-D77RDMKH-Bgwe0g5S.js → stateDiagram-D77RDMKH-DJ9UpQL9.js} +1 -1
  181. package/dist/client/assets/stateDiagram-D77RDMKH-DJ9UpQL9.js.br +0 -0
  182. package/dist/client/assets/stateDiagram-D77RDMKH-DJ9UpQL9.js.gz +0 -0
  183. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-P9vVPNJW.js +1 -0
  184. package/dist/client/assets/{swimlanes-42K2YHIH-COGAWe-g.js → swimlanes-42K2YHIH-B6f_z8xv.js} +1 -1
  185. package/dist/client/assets/swimlanes-42K2YHIH-B6f_z8xv.js.br +0 -0
  186. package/dist/client/assets/swimlanes-42K2YHIH-B6f_z8xv.js.gz +0 -0
  187. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-Deucv-sT.js +8 -0
  188. package/dist/client/assets/{timeline-definition-24CTP7MA-C4gt5z68.js → timeline-definition-24CTP7MA-CMNs0nui.js} +1 -1
  189. package/dist/client/assets/timeline-definition-24CTP7MA-CMNs0nui.js.br +0 -0
  190. package/dist/client/assets/timeline-definition-24CTP7MA-CMNs0nui.js.gz +0 -0
  191. package/dist/client/assets/{triangle-alert-xPHw25jD.js → triangle-alert-CN3m1g76.js} +1 -1
  192. package/dist/client/assets/{vennDiagram-4TSXK5OY-CIEXh9oD.js → vennDiagram-4TSXK5OY-B2glpBlo.js} +1 -1
  193. package/dist/client/assets/vennDiagram-4TSXK5OY-B2glpBlo.js.br +0 -0
  194. package/dist/client/assets/vennDiagram-4TSXK5OY-B2glpBlo.js.gz +0 -0
  195. package/dist/client/assets/{videoCompression-CUkCS2-q.js → videoCompression-DwronsgA.js} +1 -1
  196. package/dist/client/assets/videoCompression-DwronsgA.js.br +0 -0
  197. package/dist/client/assets/videoCompression-DwronsgA.js.gz +0 -0
  198. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-gQhcW1vd.js → wardleyDiagram-VM6X3IG4-DyMNl-ZC.js} +1 -1
  199. package/dist/client/assets/wardleyDiagram-VM6X3IG4-DyMNl-ZC.js.br +0 -0
  200. package/dist/client/assets/wardleyDiagram-VM6X3IG4-DyMNl-ZC.js.gz +0 -0
  201. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-BmIcdejz.js → xychartDiagram-S5SC5T6Z-DhZFXjY5.js} +1 -1
  202. package/dist/client/assets/xychartDiagram-S5SC5T6Z-DhZFXjY5.js.br +0 -0
  203. package/dist/client/assets/xychartDiagram-S5SC5T6Z-DhZFXjY5.js.gz +0 -0
  204. package/dist/client/index.html +3 -2
  205. package/dist/client/index.html.br +0 -0
  206. package/dist/client/index.html.gz +0 -0
  207. package/dist/client/ipad-status-bar.js +12 -0
  208. package/dist/client/sw.js +1 -1
  209. package/dist/client/sw.js.br +0 -0
  210. package/dist/client/sw.js.gz +0 -0
  211. package/dist/server/agent/collaborationCli.js +21 -5
  212. package/dist/server/agent/collaborationStore.js +25 -2
  213. package/dist/server/agent/collaborationTmuxDelivery.js +32 -19
  214. package/dist/server/agent/integrationCli.js +8 -3
  215. package/dist/server/agent/integrationServer.js +5 -1
  216. package/dist/server/agent/integrationSessions.js +147 -13
  217. package/dist/server/agent/promptDelivery.js +12 -8
  218. package/dist/server/agent/sessionLaunchDiagnostics.js +26 -0
  219. package/dist/server/agent/terminalInput.js +44 -0
  220. package/dist/server/routes/terminal.js +140 -53
  221. package/docs/integrations.md +110 -0
  222. package/package.json +1 -1
  223. package/runtime-manifest.json +3 -3
  224. package/dist/client/assets/App-ChS2-lkz.js.br +0 -0
  225. package/dist/client/assets/App-ChS2-lkz.js.gz +0 -0
  226. package/dist/client/assets/ArchitecturePanel-JtjyyJoW.js.br +0 -0
  227. package/dist/client/assets/ArchitecturePanel-JtjyyJoW.js.gz +0 -0
  228. package/dist/client/assets/ChangeWalkthroughPanel-BlQ5-VPp.js.br +0 -0
  229. package/dist/client/assets/ChangeWalkthroughPanel-BlQ5-VPp.js.gz +0 -0
  230. package/dist/client/assets/CollaborationMainWorkspace-aFLAMqDr.js.br +0 -0
  231. package/dist/client/assets/CollaborationMainWorkspace-aFLAMqDr.js.gz +0 -0
  232. package/dist/client/assets/CollaborationTaskContent-BDQMRhU9.js +0 -2
  233. package/dist/client/assets/ComputerControlView-TAKDbBUl.js.br +0 -0
  234. package/dist/client/assets/ComputerControlView-TAKDbBUl.js.gz +0 -0
  235. package/dist/client/assets/DagPlayground-CR4uDFOx.js.br +0 -0
  236. package/dist/client/assets/DagPlayground-CR4uDFOx.js.gz +0 -0
  237. package/dist/client/assets/DiffLab-BqeHMDOy.js.br +0 -0
  238. package/dist/client/assets/DiffLab-BqeHMDOy.js.gz +0 -0
  239. package/dist/client/assets/DiffReview-DqrOcRfP.js.br +0 -0
  240. package/dist/client/assets/DiffReview-DqrOcRfP.js.gz +0 -0
  241. package/dist/client/assets/DiffReviewLab-CEYpbrL6.js.br +0 -0
  242. package/dist/client/assets/DiffReviewLab-CEYpbrL6.js.gz +0 -0
  243. package/dist/client/assets/DiffViewer-F-uQSmhG.js.br +0 -0
  244. package/dist/client/assets/DiffViewer-F-uQSmhG.js.gz +0 -0
  245. package/dist/client/assets/ModelPreview-KmXFkgij.js.br +0 -0
  246. package/dist/client/assets/ModelPreview-KmXFkgij.js.gz +0 -0
  247. package/dist/client/assets/RightSidebar-VMdXpo4h.js.br +0 -0
  248. package/dist/client/assets/RightSidebar-VMdXpo4h.js.gz +0 -0
  249. package/dist/client/assets/abnfDiagram-VCTEODGH-CAMk1C0N.js.br +0 -0
  250. package/dist/client/assets/abnfDiagram-VCTEODGH-CAMk1C0N.js.gz +0 -0
  251. package/dist/client/assets/app-CHxLSuGQ.js.br +0 -0
  252. package/dist/client/assets/app-CHxLSuGQ.js.gz +0 -0
  253. package/dist/client/assets/arc-CYG_-1vC.js.br +0 -0
  254. package/dist/client/assets/arc-CYG_-1vC.js.gz +0 -0
  255. package/dist/client/assets/architectureDiagram-5GKGNRK7-BqHzezLR.js.br +0 -0
  256. package/dist/client/assets/architectureDiagram-5GKGNRK7-BqHzezLR.js.gz +0 -0
  257. package/dist/client/assets/blockDiagram-I7D4REHJ-D6GWRO_Z.js.br +0 -0
  258. package/dist/client/assets/blockDiagram-I7D4REHJ-D6GWRO_Z.js.gz +0 -0
  259. package/dist/client/assets/c4Diagram-7LVT6UL2-CutmGIGb.js.br +0 -0
  260. package/dist/client/assets/c4Diagram-7LVT6UL2-CutmGIGb.js.gz +0 -0
  261. package/dist/client/assets/channel-B3BKM2gg.js +0 -1
  262. package/dist/client/assets/chunk-F27PBJKO-CNptP19P.js.br +0 -0
  263. package/dist/client/assets/chunk-F27PBJKO-CNptP19P.js.gz +0 -0
  264. package/dist/client/assets/chunk-IMKFNOWR-DHdpB9A0.js.br +0 -0
  265. package/dist/client/assets/chunk-IMKFNOWR-DHdpB9A0.js.gz +0 -0
  266. package/dist/client/assets/chunk-SVP7TREG-B70pX8OB.js.br +0 -0
  267. package/dist/client/assets/chunk-SVP7TREG-B70pX8OB.js.gz +0 -0
  268. package/dist/client/assets/chunk-TICWLB2K-Ba1mI99F.js.br +0 -0
  269. package/dist/client/assets/chunk-TICWLB2K-Ba1mI99F.js.gz +0 -0
  270. package/dist/client/assets/classDiagram-ZZMXUADV-CS4V_MQS.js +0 -1
  271. package/dist/client/assets/classDiagram-v2-VYDZK3BY-CS4V_MQS.js +0 -1
  272. package/dist/client/assets/cose-bilkent-JH36ORCC-C-NMDUHW.js.br +0 -0
  273. package/dist/client/assets/cose-bilkent-JH36ORCC-C-NMDUHW.js.gz +0 -0
  274. package/dist/client/assets/cynefin-OW5HDTMX-CZgEc1ab.js.br +0 -0
  275. package/dist/client/assets/cynefin-OW5HDTMX-CZgEc1ab.js.gz +0 -0
  276. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CHQeSNm2.js.br +0 -0
  277. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CHQeSNm2.js.gz +0 -0
  278. package/dist/client/assets/dagre-GXQ25YYZ-B_jkMdPS.js.br +0 -0
  279. package/dist/client/assets/dagre-GXQ25YYZ-B_jkMdPS.js.gz +0 -0
  280. package/dist/client/assets/diagram-S7CK7UJ4-nv6Lnsrp.js.br +0 -0
  281. package/dist/client/assets/diagram-S7CK7UJ4-nv6Lnsrp.js.gz +0 -0
  282. package/dist/client/assets/diagram-UQ7AKVKN-BZf2fzaA.js.br +0 -0
  283. package/dist/client/assets/diagram-UQ7AKVKN-BZf2fzaA.js.gz +0 -0
  284. package/dist/client/assets/diagram-VSXAHHWV-CxL0_BH8.js.br +0 -0
  285. package/dist/client/assets/diagram-VSXAHHWV-CxL0_BH8.js.gz +0 -0
  286. package/dist/client/assets/diagram-VX7I27RA-Dm9MqpIE.js.br +0 -0
  287. package/dist/client/assets/diagram-VX7I27RA-Dm9MqpIE.js.gz +0 -0
  288. package/dist/client/assets/diagram-Z3DM3KII-BIfTa7P5.js.br +0 -0
  289. package/dist/client/assets/diagram-Z3DM3KII-BIfTa7P5.js.gz +0 -0
  290. package/dist/client/assets/ebnfDiagram-PWID7BFC-D4XhCDFS.js.br +0 -0
  291. package/dist/client/assets/ebnfDiagram-PWID7BFC-D4XhCDFS.js.gz +0 -0
  292. package/dist/client/assets/erDiagram-RLTQ6QDP-Dxd48dXC.js.br +0 -0
  293. package/dist/client/assets/erDiagram-RLTQ6QDP-Dxd48dXC.js.gz +0 -0
  294. package/dist/client/assets/flowDiagram-HODETNUW-BXBMsEmE.js.br +0 -0
  295. package/dist/client/assets/flowDiagram-HODETNUW-BXBMsEmE.js.gz +0 -0
  296. package/dist/client/assets/ganttDiagram-EL5Y4UJY-CBfDd-KZ.js.br +0 -0
  297. package/dist/client/assets/gestureArbiter-DXLmNGli.js.gz +0 -0
  298. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DtLM68fN.js.br +0 -0
  299. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DtLM68fN.js.gz +0 -0
  300. package/dist/client/assets/index-KuPaZyuZ.css.br +0 -0
  301. package/dist/client/assets/ishikawaDiagram-5VMMS53U-DAHBvAZ-.js.br +0 -0
  302. package/dist/client/assets/ishikawaDiagram-5VMMS53U-DAHBvAZ-.js.gz +0 -0
  303. package/dist/client/assets/journeyDiagram-3NMN7TZE-CVuWuL3Z.js.br +0 -0
  304. package/dist/client/assets/journeyDiagram-3NMN7TZE-CVuWuL3Z.js.gz +0 -0
  305. package/dist/client/assets/kanban-definition-UXKFOSKX-ByQSUVJV.js.br +0 -0
  306. package/dist/client/assets/kanban-definition-UXKFOSKX-ByQSUVJV.js.gz +0 -0
  307. package/dist/client/assets/layout-Bb3Nb1c4.js.br +0 -0
  308. package/dist/client/assets/layout-Bb3Nb1c4.js.gz +0 -0
  309. package/dist/client/assets/linear-DHMMQlOo.js.gz +0 -0
  310. package/dist/client/assets/mermaid.core-BYfniK0H.js.br +0 -0
  311. package/dist/client/assets/mermaid.core-BYfniK0H.js.gz +0 -0
  312. package/dist/client/assets/mindmap-definition-YA3MSWOX-EDLD5AyH.js.br +0 -0
  313. package/dist/client/assets/mindmap-definition-YA3MSWOX-EDLD5AyH.js.gz +0 -0
  314. package/dist/client/assets/passwordBootstrap-DCrtirwT.js.br +0 -0
  315. package/dist/client/assets/passwordBootstrap-DCrtirwT.js.gz +0 -0
  316. package/dist/client/assets/pegDiagram-XKGWAZYB-BHYhkqJN.js.br +0 -0
  317. package/dist/client/assets/pegDiagram-XKGWAZYB-BHYhkqJN.js.gz +0 -0
  318. package/dist/client/assets/pieDiagram-E7YTZNPT-BUIJlswC.js.br +0 -0
  319. package/dist/client/assets/pieDiagram-E7YTZNPT-BUIJlswC.js.gz +0 -0
  320. package/dist/client/assets/quadrantDiagram-AXDQQJYC-D8Im-7yC.js.br +0 -0
  321. package/dist/client/assets/quadrantDiagram-AXDQQJYC-D8Im-7yC.js.gz +0 -0
  322. package/dist/client/assets/railroadDiagram-O6MQD6OU-D7n6z2G1.js.br +0 -0
  323. package/dist/client/assets/railroadDiagram-O6MQD6OU-D7n6z2G1.js.gz +0 -0
  324. package/dist/client/assets/rdpSession-DJlNIbVk.js.br +0 -0
  325. package/dist/client/assets/rdpSession-DJlNIbVk.js.gz +0 -0
  326. package/dist/client/assets/referenceLongPress-DFSrssSr.js.br +0 -0
  327. package/dist/client/assets/referenceLongPress-DFSrssSr.js.gz +0 -0
  328. package/dist/client/assets/requirementDiagram-BXWQKSXE-Ki0rR-F7.js.br +0 -0
  329. package/dist/client/assets/requirementDiagram-BXWQKSXE-Ki0rR-F7.js.gz +0 -0
  330. package/dist/client/assets/sankeyDiagram-P5KCCOFB-36NmMqsW.js.br +0 -0
  331. package/dist/client/assets/sankeyDiagram-P5KCCOFB-36NmMqsW.js.gz +0 -0
  332. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-5vsPuFyO.js.br +0 -0
  333. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-5vsPuFyO.js.gz +0 -0
  334. package/dist/client/assets/sizeCapture-INFHLROL-DbAulwBg.js.br +0 -0
  335. package/dist/client/assets/sizeCapture-INFHLROL-DbAulwBg.js.gz +0 -0
  336. package/dist/client/assets/stateDiagram-D77RDMKH-Bgwe0g5S.js.br +0 -0
  337. package/dist/client/assets/stateDiagram-D77RDMKH-Bgwe0g5S.js.gz +0 -0
  338. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-Bg6S3Zm0.js +0 -1
  339. package/dist/client/assets/swimlanes-42K2YHIH-COGAWe-g.js.br +0 -0
  340. package/dist/client/assets/swimlanes-42K2YHIH-COGAWe-g.js.gz +0 -0
  341. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DwBBOocG.js +0 -8
  342. package/dist/client/assets/timeline-definition-24CTP7MA-C4gt5z68.js.br +0 -0
  343. package/dist/client/assets/timeline-definition-24CTP7MA-C4gt5z68.js.gz +0 -0
  344. package/dist/client/assets/vennDiagram-4TSXK5OY-CIEXh9oD.js.br +0 -0
  345. package/dist/client/assets/vennDiagram-4TSXK5OY-CIEXh9oD.js.gz +0 -0
  346. package/dist/client/assets/videoCompression-CUkCS2-q.js.br +0 -0
  347. package/dist/client/assets/videoCompression-CUkCS2-q.js.gz +0 -0
  348. package/dist/client/assets/wardleyDiagram-VM6X3IG4-gQhcW1vd.js.br +0 -0
  349. package/dist/client/assets/wardleyDiagram-VM6X3IG4-gQhcW1vd.js.gz +0 -0
  350. package/dist/client/assets/xychartDiagram-S5SC5T6Z-BmIcdejz.js.br +0 -0
  351. package/dist/client/assets/xychartDiagram-S5SC5T6Z-BmIcdejz.js.gz +0 -0
@@ -1,5 +1,6 @@
1
1
  import { plainCollaborationSnapshot } from './collaborationText.js';
2
2
  import { normalizePromptForPaste, waitForPromptSubmit } from './promptDelivery.js';
3
+ import { serializeTerminalInput } from './terminalInput.js';
3
4
  const TMUX_KEY_NAMES = {
4
5
  enter: 'Enter', escape: 'Escape', space: 'Space', left: 'Left', right: 'Right', up: 'Up', down: 'Down',
5
6
  };
@@ -31,21 +32,22 @@ async function assertSamePane(run, pane) {
31
32
  /** Unique-per-process buffer name so concurrent deliveries to different panes
32
33
  * never share (or clobber) a buffer. */
33
34
  let bufferSequence = 0;
34
- const paneWrites = new Map();
35
+ function paneInputKey(pane) {
36
+ return `${pane.serverPid}:${pane.sessionId}:${pane.paneId}:${pane.panePid}`;
37
+ }
35
38
  /** Serialize TD paste/submit pairs for this exact runtime pane. */
36
- export function writeCollaborationTmuxPane(run, pane, prompt, stdin) {
37
- const key = `${pane.serverPid}:${pane.sessionId}:${pane.paneId}:${pane.panePid}`;
38
- const previous = paneWrites.get(key) ?? Promise.resolve();
39
- const operation = previous.catch(() => undefined).then(() => writeTmuxPrompt(run, pane, prompt, stdin))
40
- .finally(() => { if (paneWrites.get(key) === operation)
41
- paneWrites.delete(key); });
42
- paneWrites.set(key, operation);
43
- return operation;
39
+ export function writeCollaborationTmuxPane(run, pane, prompt, stdin, assertCurrent, progress) {
40
+ progress?.('queue_wait');
41
+ return serializeTerminalInput(paneInputKey(pane), () => {
42
+ progress?.('queue_acquired');
43
+ return writeTmuxPrompt(run, pane, prompt, stdin, assertCurrent, progress);
44
+ });
44
45
  }
45
46
  async function writeTmuxPrompt(run, pane, prompt,
46
47
  /** Body travels on stdin so tmux cannot parse its semicolons/backslashes. */
47
- stdin) {
48
+ stdin, assertCurrent, progress) {
48
49
  await assertSamePane(run, pane);
50
+ assertCurrent?.();
49
51
  // A fixed pane target is independent of the current window, keyboard focus
50
52
  // and browser presence. Delivery goes through a named tmux buffer rather
51
53
  // than `send-keys -l`: while a pane is in copy-mode, literal bytes are
@@ -66,6 +68,7 @@ stdin) {
66
68
  try {
67
69
  // Paste once, then send one unbracketed CR after 50ms. No screen parsing,
68
70
  // Agent-specific recovery, consumption confirmation or additional Enter.
71
+ progress?.('paste_attempted');
69
72
  await stdin([
70
73
  // The body arrives on stdin, not argv: it is user content, and in a
71
74
  // `\;` chain argv is a language where `;` and `\` mean something.
@@ -75,8 +78,11 @@ stdin) {
75
78
  // for it to rewrite — the flag is insurance, not the mechanism.
76
79
  'paste-buffer', '-p', '-r', '-d', '-b', buffer, '-t', pane.paneId,
77
80
  ], normalizePromptForPaste(prompt));
81
+ progress?.('paste_written');
78
82
  await waitForPromptSubmit();
79
83
  await assertSamePane(run, pane);
84
+ assertCurrent?.();
85
+ progress?.('submit_attempted');
80
86
  await run([
81
87
  // The submit key rides outside the paste block: inside it, an editor
82
88
  // inserts a pasted CR as text instead of acting on it. Pasting the bare
@@ -84,6 +90,7 @@ stdin) {
84
90
  'set-buffer', '-b', buffer, '--', '\r', ';',
85
91
  'paste-buffer', '-d', '-b', buffer, '-t', pane.paneId,
86
92
  ]);
93
+ progress?.('submit_written');
87
94
  }
88
95
  finally {
89
96
  // -d consumed the buffer on the happy path; this sweeps up after a failed
@@ -100,10 +107,14 @@ export async function paneInMode(run, pane) {
100
107
  * unchanged. Named keys only — no freeform keystroke passthrough. Refuses
101
108
  * while the pane is in a mode: there the key would be taken by the mode
102
109
  * handler (Enter in copy-mode exits the user's scroll) rather than the app. */
103
- export async function sendTmuxPaneKey(run, pane, key) {
110
+ export function sendTmuxPaneKey(run, pane, key, assertCurrent) {
111
+ return serializeTerminalInput(paneInputKey(pane), () => sendTmuxPaneKeyUnlocked(run, pane, key, assertCurrent));
112
+ }
113
+ async function sendTmuxPaneKeyUnlocked(run, pane, key, assertCurrent) {
104
114
  await assertSamePane(run, pane);
105
115
  if (await paneInMode(run, pane))
106
116
  throw new Error('TMUX_PANE_IN_MODE');
117
+ assertCurrent?.();
107
118
  await run(['send-keys', '-t', pane.paneId, TMUX_KEY_NAMES[key]]);
108
119
  }
109
120
  /** Current pane screen text (viewport), identity-checked. */
@@ -116,14 +127,16 @@ export async function captureTmuxPaneText(run, pane, rawOutput = false) {
116
127
  * Enter (the highlighted option). Refuses unless the screen actually shows
117
128
  * an approval prompt: driving a dialog that isn't there would only inject
118
129
  * a stray keystroke into the agent's work. Returns false when no dialog. */
119
- export async function approveCollaborationDialog(run, pane) {
120
- const content = await captureTmuxPaneText(run, pane);
121
- if (!detectApprovalDialog(content))
122
- return false;
123
- // sendTmuxPaneKey refuses in-mode panes, so a dialog-looking screen behind a
124
- // user's scroll never turns Enter into copy-mode navigation.
125
- await sendTmuxPaneKey(run, pane, 'enter');
126
- return true;
130
+ export function approveCollaborationDialog(run, pane, assertCurrent) {
131
+ return serializeTerminalInput(paneInputKey(pane), async () => {
132
+ assertCurrent?.();
133
+ const content = await captureTmuxPaneText(run, pane);
134
+ if (!detectApprovalDialog(content))
135
+ return false;
136
+ // The same input queue covers both the observation and requested key.
137
+ await sendTmuxPaneKeyUnlocked(run, pane, 'enter', assertCurrent);
138
+ return true;
139
+ });
127
140
  }
128
141
  /** History-inclusive terminal observation, without inferring consumption. */
129
142
  export async function captureTmuxPaneHistory(run, pane, lines = 800, rawOutput = false) {
@@ -28,7 +28,10 @@ export const INTEGRATION_HELP = `td integration — local scoped integration adm
28
28
  Minimum CLI/running service 1.4.309; capabilities.session_resume_configuration=true.
29
29
  Errors: RESUME_CONFIGURATION_CHANGED, EXACT_RESUME_UNSUPPORTED,
30
30
  SESSION_GENERATION_MISMATCH, SESSION_OPERATION_IN_PROGRESS, LAUNCHER_UNAVAILABLE.
31
- diagnostics <TD-session-id> (read the last restore check; administrator only)
31
+ diagnostics <TD-session-id> (read stored launch/restore diagnostics; administrator only)
32
+ 1.4.314 adds phase/timestamps, paste/submit write facts and target-change
33
+ evidence; no argv/environment/credentials or application readiness claim.
34
+ Prior versions cannot reconstruct missing launch evidence retroactively.
32
35
  create --file <policy.json> --credential-file <private-output.json>
33
36
  update --file <policy.json> (same identity/group; preserves the credential)
34
37
  revoke <principal-id>
@@ -217,11 +220,13 @@ export async function runIntegrationCollab(command, port, io) {
217
220
  return subscribe(socketPath, `/events?${params}`, credential, command.options.timeout ? duration(String(command.options.timeout)) : undefined, io.write);
218
221
  }
219
222
  if (command.action === 'session') {
223
+ if (command.operation === 'retry-cold' && capability.session_cold_retry !== true)
224
+ throw new CollaborationError('SESSION_COLD_RETRY_UNSUPPORTED', 'CLI and running service must support explicit cold retry (minimum 1.4.314)', 409);
220
225
  if (command.operation === 'release' && (capability.session_runtime_release !== true || capability.session_lifecycle_generation !== true || capability.stable_session_identity !== true))
221
226
  throw new CollaborationError('SESSION_RELEASE_UNSUPPORTED', 'CLI and running service must support the lifecycle contract (minimum 1.4.309)', 409);
222
- const route = command.operation === 'create' ? '/sessions' : `/sessions/${encodeURIComponent(command.target)}${['restore', 'release'].includes(command.operation) ? `/${command.operation}` : ''}`;
227
+ const route = command.operation === 'create' ? '/sessions' : `/sessions/${encodeURIComponent(command.target)}${['restore', 'release', 'retry-cold'].includes(command.operation) ? `/${command.operation}` : ''}`;
223
228
  const body = command.operation === 'create' ? { group_id: command.options.group, launch_profile: command.options['launch-profile'], cwd: command.options.cwd, idempotency_key: command.options['idempotency-key'] }
224
- : ['restore', 'release'].includes(command.operation) ? { ...(command.operation === 'release' ? { generation: Number(command.options.generation) } : {}), idempotency_key: command.options['idempotency-key'] } : undefined;
229
+ : ['restore', 'release', 'retry-cold'].includes(command.operation) ? { ...(['release', 'retry-cold'].includes(command.operation) ? { generation: Number(command.options.generation) } : {}), idempotency_key: command.options['idempotency-key'] } : undefined;
225
230
  io.write(JSON.stringify(parsed(await request(socketPath, command.operation === 'get' ? 'GET' : 'POST', route, body, headers(credential)))));
226
231
  return 0;
227
232
  }
@@ -70,7 +70,7 @@ export class IntegrationRuntime {
70
70
  };
71
71
  app.get('/admin/groups', run(req => { admin(req); return { groups: options.messages.list().filter(g => !g.federated).map(g => ({ id: g.id, name: g.name })) }; }));
72
72
  app.get('/admin/capabilities', run(req => { admin(req); return this.capabilities(); }));
73
- app.get('/admin/sessions/:id/restore-diagnostics', run(req => { admin(req); return this.sessions.restoreDiagnostics(req.params.id); }));
73
+ app.get('/admin/sessions/:id/restore-diagnostics', run(req => { admin(req); return { ...this.sessions.restoreDiagnostics(req.params.id), ...this.sessions.launchDiagnostics(req.params.id) }; }));
74
74
  app.get('/admin/sessions/:id/resume-configuration', run(async (req) => { admin(req); return this.sessions.resumeConfiguration(req.params.id); }));
75
75
  app.post('/admin/sessions/:id/resume-configuration', run(async (req) => { admin(req); return { session: publicIntegrationSession(await this.sessions.confirmResumeConfiguration(req.params.id, req.body?.generation, req.body?.fingerprint)) }; }));
76
76
  app.post('/admin/sessions/:id/startup-input/clear', run(async (req) => {
@@ -197,6 +197,7 @@ export class IntegrationRuntime {
197
197
  }));
198
198
  app.get('/sessions/:id', run(async (req) => { const p = principal(req); this.authorize(p, 'session.read'); return { session: publicIntegrationSession(await this.sessions.get(p, req.params.id)) }; }));
199
199
  app.post('/sessions/:id/restore', run(async (req) => { const p = principal(req); this.authorize(p, 'session.restore'); const session = await this.sessions.restore(p, req.params.id, req.body?.idempotency_key); this.sync(); return { session: publicIntegrationSession(session) }; }));
200
+ app.post('/sessions/:id/retry-cold', run(async (req) => { const p = principal(req); this.authorize(p, 'session.create'); const session = await this.sessions.retryCold(p, req.params.id, req.body?.generation, req.body?.idempotency_key); this.sync(); return { session: publicIntegrationSession(session) }; }));
200
201
  app.post('/sessions/:id/release', run(async (req) => { const p = principal(req); this.authorize(p, 'session.release'); const session = await this.sessions.release(p, req.params.id, req.body?.generation, req.body?.idempotency_key); this.sync(); return { session: publicIntegrationSession(session) }; }));
201
202
  app.get('/events', run((req, res) => {
202
203
  const p = principal(req);
@@ -225,6 +226,9 @@ export class IntegrationRuntime {
225
226
  session_resume_configuration: true, session_lifecycle_min_version: '1.4.309',
226
227
  session_startup_input_clear: true, session_startup_input_clear_min_version: '1.4.310',
227
228
  agent_launch_process_check: true, agent_launch_process_check_min_version: '1.4.312',
229
+ terminal_input_runtime_fence: true, terminal_input_runtime_fence_min_version: '1.4.313',
230
+ session_launch_diagnostics: true, session_launch_diagnostics_min_version: '1.4.314',
231
+ session_cold_retry: true, session_cold_retry_min_version: '1.4.314',
228
232
  integration_policy_update: true,
229
233
  session_restore_diagnostics: true,
230
234
  native_identity_linux_flock_owner: process.platform === 'linux',
@@ -5,6 +5,8 @@ import { atomicJson, integrationError } from './integrationStore.js';
5
5
  import { SessionLifecycleCoordinator, assertMessageRuntime, assertReleaseFacts, assertReleaseGeneration } from './sessionLifecycle.js';
6
6
  import { resumeConfigurationFingerprint } from './sessionResumeConfiguration.js';
7
7
  import { NativeResumeOwnerError } from './nativeResumeOwner.js';
8
+ import { CollaborationError } from './collaborationProtocol.js';
9
+ import { beginLaunchDiagnostics, launchFailure, launchProgress } from './sessionLaunchDiagnostics.js';
8
10
  /** Quote each configured argument as literal shell data, including paths. */
9
11
  export function integrationLaunchCommand(record, restore) {
10
12
  const launchArgs = record.profile.argv.map(arg => arg === '{cwd}' ? record.cwd : arg);
@@ -20,8 +22,9 @@ function startupInput(record, now) {
20
22
  return condition ? { state: 'pending', deadline: now + (condition.timeoutMs ?? 120000), matched_since: null, observed_at: null } : undefined;
21
23
  }
22
24
  export function publicIntegrationSession(record) {
23
- const { profile: _, deadline: _deadline, launch_submitted: _submitted, startup_condition: _condition, restore_diagnostics: diagnostics, ...publicRecord } = record;
24
- return { ...publicRecord, ...(diagnostics ? { restore_diagnostics_available: true } : {}) };
25
+ const { profile: _, deadline: _deadline, launch_submitted: _submitted, startup_condition: _condition, restore_diagnostics: diagnostics, launch_diagnostics: launchDiagnostics, launch_diagnostics_history: _history, message_history_seen: _messages, ...publicRecord } = record;
26
+ return { ...publicRecord, ...(diagnostics ? { restore_diagnostics_available: true } : {}),
27
+ ...(launchDiagnostics ? { launch_diagnostics_available: true } : {}) };
25
28
  }
26
29
  export function permittedCwd(profile, cwd) {
27
30
  if (typeof cwd !== 'string' || !path.isAbsolute(cwd) || /[\x00-\x1f\x7f]/.test(cwd))
@@ -56,6 +59,7 @@ export class IntegrationSessions {
56
59
  listeners = new Set();
57
60
  lifecycle = new SessionLifecycleCoordinator();
58
61
  mutations = new Map();
62
+ coldRetries = new Set();
59
63
  timers = new Set();
60
64
  stopObservation;
61
65
  stopDeliveryGuard;
@@ -111,7 +115,9 @@ export class IntegrationSessions {
111
115
  }
112
116
  saveRecord(record) {
113
117
  const before = this.doc.sessions;
114
- this.doc.sessions = [...before.filter(s => s.session_id !== record.session_id), structuredClone(record)];
118
+ const seen = before.find(s => s.session_id === record.session_id)?.message_history_seen;
119
+ this.doc.sessions = [...before.filter(s => s.session_id !== record.session_id), structuredClone({ ...record,
120
+ ...(seen ? { message_history_seen: true } : {}) })];
115
121
  try {
116
122
  this.save();
117
123
  }
@@ -154,7 +160,8 @@ export class IntegrationSessions {
154
160
  const now = Date.now(), record = { operation_id: randomUUID(), session_id: randomBytes(6).toString('hex'),
155
161
  group_id: principal.groupId, principal_id: principal.id, agent_slug: profile.agentSlug, agent_native_session_id: null,
156
162
  state: 'starting', generation: 1, runtime_present: null, error_code: null, cwd, launch_profile: profile.id, profile: structuredClone(profile),
157
- created_at: now, updated_at: now, deadline: now + this.bindingTimeout, launch_submitted: false };
163
+ created_at: now, updated_at: now, deadline: now + this.bindingTimeout, launch_submitted: false, message_history_seen: false };
164
+ record.launch_diagnostics = beginLaunchDiagnostics(record.operation_id, 1, 'cold_start');
158
165
  record.startup_input = startupInput(record, now);
159
166
  this.doc.requests[request.scoped] = { hash: request.hash, sessionId: record.session_id };
160
167
  try {
@@ -166,7 +173,7 @@ export class IntegrationSessions {
166
173
  }
167
174
  return this.launch(record, false);
168
175
  }
169
- launch(record, restoring) {
176
+ launch(record, restoring, retryCold = false) {
170
177
  const promise = (async () => {
171
178
  try {
172
179
  // Store intent before launching. A failed persistence cannot execute.
@@ -181,17 +188,29 @@ export class IntegrationSessions {
181
188
  catch (error) {
182
189
  // Existing creation supports plugins without an exact resume path.
183
190
  // They remain launchable, but cannot gain a releasable descriptor.
184
- if (restoring || error.code !== 'EXACT_RESUME_UNSUPPORTED')
191
+ if (restoring || retryCold || error.code !== 'EXACT_RESUME_UNSUPPORTED')
185
192
  throw error;
186
193
  }
187
194
  }
188
195
  record.launch_submitted = true;
189
196
  this.saveRecord(record);
197
+ const progress = (phase) => {
198
+ const latest = this.doc.sessions.find(s => s.session_id === record.session_id);
199
+ if (latest.operation_id !== record.operation_id || latest.generation !== record.generation)
200
+ integrationError('SESSION_GENERATION_MISMATCH', 'Launch operation changed during progress recording', 409);
201
+ if (latest.launch_diagnostics) {
202
+ record.launch_diagnostics = launchProgress(latest.launch_diagnostics, phase);
203
+ this.saveRecord({ ...latest, launch_diagnostics: record.launch_diagnostics });
204
+ }
205
+ };
190
206
  const prepared = (binding) => { record.terminal_binding = binding; this.saveRecord(record); };
191
- if (restoring)
192
- await this.adapter.restore(record, prepared);
207
+ if (retryCold)
208
+ await this.adapter.retryCold(record, prepared, progress);
209
+ else if (restoring)
210
+ await this.adapter.restore(record, prepared, progress);
193
211
  else
194
- await this.adapter.create(record, prepared);
212
+ await this.adapter.create(record, prepared, progress);
213
+ progress('binding_observe');
195
214
  await this.refresh(record.session_id);
196
215
  this.scheduleRefresh(record);
197
216
  }
@@ -199,6 +218,7 @@ export class IntegrationSessions {
199
218
  const current = this.doc.sessions.find(s => s.session_id === record.session_id);
200
219
  const code = error.code;
201
220
  this.saveRecord({ ...current, state: 'failed', error_code: typeof code === 'string' ? code : 'SESSION_LAUNCH_FAILED',
221
+ launch_diagnostics: current.launch_diagnostics ? launchFailure(current.launch_diagnostics, error, typeof code === 'string' ? code : 'SESSION_LAUNCH_FAILED') : undefined,
202
222
  restore_diagnostics: error instanceof NativeResumeOwnerError ? { ...structuredClone(error.diagnostics), operation_id: current.operation_id } : undefined,
203
223
  updated_at: Date.now() });
204
224
  }
@@ -216,10 +236,27 @@ export class IntegrationSessions {
216
236
  return structuredClone({ session_id: record.session_id, operation_id: record.operation_id,
217
237
  state: record.state, error_code: record.error_code, diagnostics: record.restore_diagnostics ?? null });
218
238
  }
219
- assertRuntimeMessage(id) { assertMessageRuntime(this.doc.sessions.find(s => s.session_id === id)); }
239
+ launchDiagnostics(id) {
240
+ const record = this.doc.sessions.find(s => s.session_id === id);
241
+ if (!record)
242
+ return integrationError('INTEGRATION_SESSION_NOT_FOUND', 'Integration session does not exist', 404);
243
+ return structuredClone({ launch_diagnostics: record.launch_diagnostics ?? null,
244
+ launch_diagnostics_history: record.launch_diagnostics_history ?? [] });
245
+ }
246
+ assertRuntimeMessage(id) {
247
+ const record = this.doc.sessions.find(s => s.session_id === id);
248
+ if (this.coldRetries.has(id) || record?.cold_retry_pending)
249
+ integrationError('SESSION_OPERATION_IN_PROGRESS', 'Cold retry must finish or be reconciled before sending', 409);
250
+ assertMessageRuntime(record);
251
+ // Durable, conservative latch before admission; even a later enqueue
252
+ // failure cannot make a previously attempted business request disappear.
253
+ if (record && !record.message_history_seen)
254
+ this.saveRecord({ ...record, message_history_seen: true });
255
+ }
220
256
  assertMessageTarget(principal, id) {
221
257
  const record = this.doc.sessions.find(s => s.session_id === id && s.group_id === principal.groupId);
222
- assertMessageRuntime(record);
258
+ if (record)
259
+ this.assertRuntimeMessage(id);
223
260
  }
224
261
  async mutate(principal, key, input, action) {
225
262
  const request = this.request(principal, key, input);
@@ -259,6 +296,74 @@ export class IntegrationSessions {
259
296
  async restore(principal, id, key) {
260
297
  return this.mutate(principal, key, ['restore', id], () => this.lifecycle.run(id, () => this.restoreOnce(principal, id, key)));
261
298
  }
299
+ async retryCold(principal, id, generation, key) {
300
+ return this.mutate(principal, key, ['retry-cold', id, generation], () => this.lifecycle.run(id, async () => {
301
+ const request = this.request(principal, key, ['retry-cold', id, generation]);
302
+ if (request.previous)
303
+ return this.replayRequest(principal, id, request.previous);
304
+ if (!this.adapter.retryCold || !this.adapter.messageHistory)
305
+ integrationError('SESSION_COLD_RETRY_UNSUPPORTED', 'Runtime adapter does not support verified cold retry', 409);
306
+ if (this.pending.has(id))
307
+ integrationError('SESSION_OPERATION_IN_PROGRESS', 'Launch is in progress', 409);
308
+ this.coldRetries.add(id);
309
+ try {
310
+ const record = await this.get(principal, id);
311
+ assertReleaseGeneration(record, generation);
312
+ if (record.cold_retry_pending || record.operation_uncertain)
313
+ integrationError('OPERATION_OUTCOME_UNCONFIRMED', 'Reconcile prior lifecycle outcome before cold retry', 409);
314
+ if (record.agent_native_session_id)
315
+ integrationError('SESSION_COLD_RETRY_NATIVE_BOUND', 'Use exact native restore for a bound session', 409);
316
+ if (record.state !== 'failed')
317
+ integrationError('SESSION_COLD_RETRY_NOT_FAILED', 'Only failed unbound cold starts can be retried', 409);
318
+ const history = this.adapter.messageHistory(id);
319
+ if (history === null)
320
+ integrationError('SESSION_MESSAGE_HISTORY_UNCONFIRMED', 'Message history cannot be verified', 409);
321
+ if (record.message_history_seen || history || this.adapter.pendingMessages?.(id))
322
+ integrationError('SESSION_MESSAGE_HISTORY_PRESENT', 'Cold retry refuses any TD business message history or attempted admission', 409);
323
+ const authorized = principal.launchProfiles.find(p => p.id === record.launch_profile);
324
+ if (!authorized)
325
+ integrationError('LAUNCH_PROFILE_DENIED', 'Original launch profile is no longer authorized', 403);
326
+ permittedCwd(authorized, record.cwd);
327
+ permittedCwd(record.profile, record.cwd);
328
+ if (!record.resume_configuration_fingerprint)
329
+ integrationError('RESUME_CONFIGURATION_UNCONFIRMED', 'Administrator must confirm the launcher/plugin fingerprint', 409);
330
+ if (record.resume_configuration_fingerprint !== await resumeConfigurationFingerprint(record, this.adapter))
331
+ integrationError('RESUME_CONFIGURATION_CHANGED', 'Launcher/plugin configuration changed', 409);
332
+ const observed = await this.adapter.inspect(record);
333
+ if (!record.terminal_binding || !observed.exists || observed.running || !observed.shell || observed.nativeId)
334
+ integrationError('SESSION_COLD_RETRY_RUNTIME_UNCONFIRMED', 'Retry requires the exact original, exited foreground shell', 409);
335
+ record.launch_diagnostics_history = [...(record.launch_diagnostics_history ?? []), ...(record.launch_diagnostics ? [record.launch_diagnostics] : [])].slice(-16);
336
+ record.generation = generation + 1;
337
+ record.operation_id = randomUUID();
338
+ record.state = 'starting';
339
+ record.error_code = null;
340
+ record.cold_retry_pending = true;
341
+ record.cold_retry_count = (record.cold_retry_count ?? 0) + 1;
342
+ record.runtime_present = true;
343
+ record.launch_submitted = false;
344
+ record.updated_at = Date.now();
345
+ record.deadline = Date.now() + this.bindingTimeout;
346
+ record.restore_diagnostics = undefined;
347
+ record.startup_input = startupInput(record, Date.now());
348
+ record.launch_diagnostics = beginLaunchDiagnostics(record.operation_id, record.generation, 'cold_retry');
349
+ this.doc.requests[request.scoped] = { hash: request.hash, sessionId: id, operationId: record.operation_id, generation: record.generation };
350
+ try {
351
+ this.saveRecord(record);
352
+ }
353
+ catch (error) {
354
+ delete this.doc.requests[request.scoped];
355
+ throw error;
356
+ }
357
+ const result = await this.launch(record, false, true);
358
+ result.cold_retry_pending = false;
359
+ this.saveRecord(result);
360
+ return result;
361
+ }
362
+ finally {
363
+ this.coldRetries.delete(id);
364
+ }
365
+ }));
366
+ }
262
367
  async restoreOnce(principal, id, idempotencyKey) {
263
368
  const request = this.request(principal, idempotencyKey, ['restore', id]);
264
369
  if (request.previous)
@@ -268,6 +373,8 @@ export class IntegrationSessions {
268
373
  let releaseNative;
269
374
  try {
270
375
  const record = await this.get(principal, id);
376
+ if (record.cold_retry_pending)
377
+ integrationError('OPERATION_OUTCOME_UNCONFIRMED', 'Reconcile the cold retry before native restore', 409);
271
378
  if (!record.agent_native_session_id)
272
379
  integrationError('NATIVE_SESSION_ID_MISSING', 'An exact native session binding is required', 409);
273
380
  // Recheck the current grant and actual directories; restore uses the
@@ -310,6 +417,8 @@ export class IntegrationSessions {
310
417
  record.deadline = Date.now() + this.bindingTimeout;
311
418
  record.updated_at = Date.now();
312
419
  record.restore_diagnostics = undefined;
420
+ record.launch_diagnostics_history = [...(record.launch_diagnostics_history ?? []), ...(record.launch_diagnostics ? [record.launch_diagnostics] : [])].slice(-16);
421
+ record.launch_diagnostics = beginLaunchDiagnostics(record.operation_id, record.generation, 'native_restore');
313
422
  if (!record.startup_input_disabled && !record.profile.startupInput && !record.startup_condition)
314
423
  record.startup_condition = structuredClone(principal.launchProfiles.find(profile => profile.id === record.launch_profile)?.startupInput);
315
424
  record.startup_input = startupInput(record, Date.now());
@@ -443,6 +552,8 @@ export class IntegrationSessions {
443
552
  const record = structuredClone(this.doc.sessions.find(s => s.session_id === id));
444
553
  if (!record)
445
554
  return;
555
+ if (record.cold_retry_pending && (this.lifecycle.active(id) || this.pending.has(id)))
556
+ return;
446
557
  if (record.state === 'released' || record.state === 'releasing' || record.operation_uncertain) {
447
558
  if (this.lifecycle.active(id))
448
559
  return;
@@ -483,8 +594,10 @@ export class IntegrationSessions {
483
594
  if (JSON.stringify(current) !== JSON.stringify(record))
484
595
  return;
485
596
  const code = error.code;
486
- if (record.state !== 'failed' || record.error_code !== code)
487
- this.saveRecord({ ...record, state: 'failed', error_code: typeof code === 'string' ? code : 'SESSION_OBSERVATION_FAILED', updated_at: Date.now() });
597
+ const errorCode = typeof code === 'string' ? code : 'SESSION_OBSERVATION_FAILED';
598
+ if (record.state !== 'failed' || record.error_code !== errorCode)
599
+ this.saveRecord({ ...record, state: 'failed', error_code: errorCode,
600
+ launch_diagnostics: record.launch_diagnostics ? launchFailure(record.launch_diagnostics, error, errorCode) : undefined, updated_at: Date.now() });
488
601
  return;
489
602
  }
490
603
  const next = { ...record, runtime_present: this.adapter.runtimePresent ? await this.adapter.runtimePresent(record) : observed.exists };
@@ -521,6 +634,27 @@ export class IntegrationSessions {
521
634
  next.state = 'failed';
522
635
  next.error_code = 'SESSION_BINDING_TIMEOUT';
523
636
  }
637
+ if (record.cold_retry_pending) {
638
+ if (next.state === 'ready')
639
+ next.cold_retry_pending = false;
640
+ else if (record.terminal_binding && observed.exists && !observed.running && observed.shell && !observed.nativeId) {
641
+ next.state = 'failed';
642
+ next.error_code = 'SESSION_COLD_RETRY_INTERRUPTED';
643
+ next.cold_retry_pending = false;
644
+ if (next.launch_diagnostics)
645
+ next.launch_diagnostics = launchProgress(next.launch_diagnostics, 'reconciled_shell');
646
+ }
647
+ else if (!observed.exists) {
648
+ next.state = 'failed';
649
+ next.error_code = 'SESSION_COLD_RETRY_RUNTIME_UNCONFIRMED';
650
+ }
651
+ }
652
+ if (next.launch_diagnostics) {
653
+ next.launch_diagnostics = { ...next.launch_diagnostics, runtime_exists: observed.exists };
654
+ if (next.state === 'failed' && next.error_code && (record.state !== 'failed' || record.error_code !== next.error_code)) {
655
+ next.launch_diagnostics = launchFailure(next.launch_diagnostics, new CollaborationError(next.error_code, '', 409), next.error_code);
656
+ }
657
+ }
524
658
  if (next.startup_input && next.startup_input.state !== 'observed') {
525
659
  const condition = next.startup_condition ?? next.profile.startupInput;
526
660
  let matched = false;
@@ -1,3 +1,4 @@
1
+ import { serializeTerminalInput } from './terminalInput.js';
1
2
  /**
2
3
  * Fold a prompt into the single-channel form both tmux and agent TUIs expect:
3
4
  * every line break becomes one CR (commits a line inside the editor, and is
@@ -16,18 +17,21 @@ export function waitForPromptSubmit() {
16
17
  export function buildBracketedPasteBytes(prompt) {
17
18
  return `\x1b[200~${normalizePromptForPaste(prompt)}\x1b[201~`;
18
19
  }
19
- const promptWrites = new WeakMap();
20
20
  /** Serialize TD prompt pairs per PTY. Success only records terminal writes. */
21
- export function writeBracketedPrompt(target, prompt) {
22
- const previous = promptWrites.get(target) ?? Promise.resolve();
23
- const operation = previous.catch(() => undefined).then(async () => {
21
+ export function writeBracketedPrompt(target, prompt, assertCurrent, progress) {
22
+ progress?.('queue_wait');
23
+ return serializeTerminalInput(target, async () => {
24
+ progress?.('queue_acquired');
25
+ assertCurrent?.();
26
+ progress?.('paste_attempted');
24
27
  target.write(buildBracketedPasteBytes(prompt));
28
+ progress?.('paste_written');
25
29
  await waitForPromptSubmit();
30
+ assertCurrent?.();
31
+ progress?.('submit_attempted');
26
32
  target.write('\r');
27
- }).finally(() => { if (promptWrites.get(target) === operation)
28
- promptWrites.delete(target); });
29
- promptWrites.set(target, operation);
30
- return operation;
33
+ progress?.('submit_written');
34
+ });
31
35
  }
32
36
  /**
33
37
  * Process detection and hook events are independent Agent signals. A target is
@@ -0,0 +1,26 @@
1
+ import { CollaborationError } from './collaborationProtocol.js';
2
+ import { TerminalInputTargetChangedError } from './terminalInput.js';
3
+ export function beginLaunchDiagnostics(operation_id, generation, kind) {
4
+ const now = Date.now();
5
+ return { operation_id, generation, kind, phase: 'configuration', updated_at: now,
6
+ error_code: null, reason_code: null, paste: 'not_attempted', submit: 'not_attempted',
7
+ runtime_exists: null, steps: [{ phase: 'configuration', at: now }] };
8
+ }
9
+ export function launchProgress(current, phase) {
10
+ const now = Date.now();
11
+ return { ...current, phase, updated_at: now, steps: [...current.steps, { phase, at: now }].slice(-24),
12
+ paste: phase === 'paste_attempted' ? 'attempted' : phase === 'paste_written' ? 'write_returned' : current.paste,
13
+ submit: phase === 'submit_attempted' ? 'attempted' : phase === 'submit_written' ? 'write_returned' : current.submit };
14
+ }
15
+ /** Error text/stdout/argv are never copied into durable diagnostics. */
16
+ export function launchFailure(current, error, error_code) {
17
+ const value = error;
18
+ const standard = new Set(['ENOENT', 'EACCES', 'EPERM', 'EIO', 'ETIMEDOUT', 'EPIPE', 'ECONNRESET',
19
+ 'TMUX_PANE_CHANGED', 'TMUX_PANE_IN_MODE', 'SESSION_REMOVED', 'SHELL_BACKEND_CHANGED']);
20
+ const reason_code = error instanceof TerminalInputTargetChangedError ? error.code
21
+ : error instanceof CollaborationError && /^[A-Z][A-Z0-9_]{0,79}$/.test(error.code) ? error.code
22
+ : typeof value?.code === 'string' && standard.has(value.code) ? value.code
23
+ : typeof value?.message === 'string' && standard.has(value.message) ? value.message : 'UNCLASSIFIED_LAUNCH_ERROR';
24
+ return { ...current, updated_at: Date.now(), error_code, reason_code,
25
+ ...(error instanceof TerminalInputTargetChangedError ? { target_change: error.evidence } : {}) };
26
+ }
@@ -0,0 +1,44 @@
1
+ /** One TD input operation per actual transport, independent of application state. */
2
+ const objectInputs = new WeakMap();
3
+ const namedInputs = new Map();
4
+ export function serializeTerminalInput(target, action) {
5
+ return typeof target === 'string' ? serializeInQueue(namedInputs, target, action)
6
+ : serializeInQueue(objectInputs, target, action);
7
+ }
8
+ function serializeInQueue(store, target, action) {
9
+ const previous = store.get(target) ?? Promise.resolve();
10
+ const operation = previous.catch(() => undefined).then(action).finally(() => {
11
+ if (store.get(target) === operation)
12
+ store.delete(target);
13
+ });
14
+ store.set(target, operation);
15
+ return operation;
16
+ }
17
+ export class TerminalInputTargetChangedError extends Error {
18
+ evidence;
19
+ code = 'TERMINAL_INPUT_TARGET_CHANGED';
20
+ constructor(evidence) {
21
+ super('TERMINAL_INPUT_TARGET_CHANGED');
22
+ this.evidence = evidence;
23
+ }
24
+ }
25
+ /** Clearing a one-time launch check does not change the runtime generation. */
26
+ export function captureTerminalInputGuard(current, expected = current()) {
27
+ return () => {
28
+ if (current() !== expected)
29
+ throw new TerminalInputTargetChangedError();
30
+ };
31
+ }
32
+ /** Await the actual write instead of leaving detached timers after reporting success. */
33
+ export async function waitAndWriteTerminalInput(input) {
34
+ for (let attempt = 0;; attempt++) {
35
+ input.assertCurrent();
36
+ const ready = await input.ready(attempt);
37
+ input.assertCurrent();
38
+ if (ready) {
39
+ await input.write();
40
+ return;
41
+ }
42
+ await new Promise(resolve => setTimeout(resolve, 250));
43
+ }
44
+ }