termdock 1.4.313 → 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 +17 -5
  212. package/dist/server/agent/collaborationStore.js +25 -2
  213. package/dist/server/agent/collaborationTmuxDelivery.js +11 -3
  214. package/dist/server/agent/integrationCli.js +8 -3
  215. package/dist/server/agent/integrationServer.js +4 -1
  216. package/dist/server/agent/integrationSessions.js +147 -13
  217. package/dist/server/agent/promptDelivery.js +7 -1
  218. package/dist/server/agent/sessionLaunchDiagnostics.js +26 -0
  219. package/dist/server/agent/terminalInput.js +9 -1
  220. package/dist/server/routes/terminal.js +48 -19
  221. package/docs/integrations.md +98 -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
@@ -36,12 +36,16 @@ function paneInputKey(pane) {
36
36
  return `${pane.serverPid}:${pane.sessionId}:${pane.paneId}:${pane.panePid}`;
37
37
  }
38
38
  /** Serialize TD paste/submit pairs for this exact runtime pane. */
39
- export function writeCollaborationTmuxPane(run, pane, prompt, stdin, assertCurrent) {
40
- return serializeTerminalInput(paneInputKey(pane), () => writeTmuxPrompt(run, pane, prompt, stdin, assertCurrent));
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
+ });
41
45
  }
42
46
  async function writeTmuxPrompt(run, pane, prompt,
43
47
  /** Body travels on stdin so tmux cannot parse its semicolons/backslashes. */
44
- stdin, assertCurrent) {
48
+ stdin, assertCurrent, progress) {
45
49
  await assertSamePane(run, pane);
46
50
  assertCurrent?.();
47
51
  // A fixed pane target is independent of the current window, keyboard focus
@@ -64,6 +68,7 @@ stdin, assertCurrent) {
64
68
  try {
65
69
  // Paste once, then send one unbracketed CR after 50ms. No screen parsing,
66
70
  // Agent-specific recovery, consumption confirmation or additional Enter.
71
+ progress?.('paste_attempted');
67
72
  await stdin([
68
73
  // The body arrives on stdin, not argv: it is user content, and in a
69
74
  // `\;` chain argv is a language where `;` and `\` mean something.
@@ -73,9 +78,11 @@ stdin, assertCurrent) {
73
78
  // for it to rewrite — the flag is insurance, not the mechanism.
74
79
  'paste-buffer', '-p', '-r', '-d', '-b', buffer, '-t', pane.paneId,
75
80
  ], normalizePromptForPaste(prompt));
81
+ progress?.('paste_written');
76
82
  await waitForPromptSubmit();
77
83
  await assertSamePane(run, pane);
78
84
  assertCurrent?.();
85
+ progress?.('submit_attempted');
79
86
  await run([
80
87
  // The submit key rides outside the paste block: inside it, an editor
81
88
  // inserts a pasted CR as text instead of acting on it. Pasting the bare
@@ -83,6 +90,7 @@ stdin, assertCurrent) {
83
90
  'set-buffer', '-b', buffer, '--', '\r', ';',
84
91
  'paste-buffer', '-d', '-b', buffer, '-t', pane.paneId,
85
92
  ]);
93
+ progress?.('submit_written');
86
94
  }
87
95
  finally {
88
96
  // -d consumed the buffer on the happy path; this sweeps up after a failed
@@ -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);
@@ -226,6 +227,8 @@ export class IntegrationRuntime {
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',
228
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',
229
232
  integration_policy_update: true,
230
233
  session_restore_diagnostics: true,
231
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;
@@ -18,13 +18,19 @@ export function buildBracketedPasteBytes(prompt) {
18
18
  return `\x1b[200~${normalizePromptForPaste(prompt)}\x1b[201~`;
19
19
  }
20
20
  /** Serialize TD prompt pairs per PTY. Success only records terminal writes. */
21
- export function writeBracketedPrompt(target, prompt, assertCurrent) {
21
+ export function writeBracketedPrompt(target, prompt, assertCurrent, progress) {
22
+ progress?.('queue_wait');
22
23
  return serializeTerminalInput(target, async () => {
24
+ progress?.('queue_acquired');
23
25
  assertCurrent?.();
26
+ progress?.('paste_attempted');
24
27
  target.write(buildBracketedPasteBytes(prompt));
28
+ progress?.('paste_written');
25
29
  await waitForPromptSubmit();
26
30
  assertCurrent?.();
31
+ progress?.('submit_attempted');
27
32
  target.write('\r');
33
+ progress?.('submit_written');
28
34
  });
29
35
  }
30
36
  /**
@@ -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
+ }
@@ -14,11 +14,19 @@ function serializeInQueue(store, target, action) {
14
14
  store.set(target, operation);
15
15
  return operation;
16
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
+ }
17
25
  /** Clearing a one-time launch check does not change the runtime generation. */
18
26
  export function captureTerminalInputGuard(current, expected = current()) {
19
27
  return () => {
20
28
  if (current() !== expected)
21
- throw new Error('TERMINAL_INPUT_TARGET_CHANGED');
29
+ throw new TerminalInputTargetChangedError();
22
30
  };
23
31
  }
24
32
  /** Await the actual write instead of leaving detached timers after reporting success. */
@@ -50,7 +50,7 @@ import { archiveTaskWorkspace, restoreTaskWorkspace, snapshotTaskWorkspace } fro
50
50
  import { isTmuxRecoveryCandidate } from '../utils/tmuxRecoveryCandidate.js';
51
51
  import { AutomationStore, normalizeAutomationSchedule } from '../agent/automationStore.js';
52
52
  import { writeBracketedPrompt, canDeliverPromptToAgent } from '../agent/promptDelivery.js';
53
- import { captureTerminalInputGuard, waitAndWriteTerminalInput } from '../agent/terminalInput.js';
53
+ import { captureTerminalInputGuard, waitAndWriteTerminalInput, TerminalInputTargetChangedError } from '../agent/terminalInput.js';
54
54
  import { agentLaunchBlockReason, normalizeAgentLaunchCheck } from '../agent/agentLaunchCheck.js';
55
55
  import { prepareSupervisionEnable } from '../utils/enableSupervision.js';
56
56
  import { buildServerHealthState, dismissServerHealth } from '../utils/serverHealth.js';
@@ -1479,21 +1479,21 @@ async function observeAgentLaunchCheck(record, observed) {
1479
1479
  function terminalInputGuard(record) {
1480
1480
  const frontendSessionId = record.sessionId;
1481
1481
  const backendSessionId = record.backendSessionId;
1482
- const generation = captureTerminalInputGuard(() => globalSessionState.sessions
1483
- .find(candidate => candidate.sessionId === frontendSessionId)?.agentLaunchGeneration ?? null, record.agentLaunchGeneration ?? null);
1482
+ const launchId = record.agentLaunchGeneration ?? null;
1484
1483
  const backend = backendSessionId ? terminalSessions.get(backendSessionId) : undefined;
1485
1484
  return () => {
1486
1485
  const latest = globalSessionState.sessions.find(candidate => candidate.sessionId === frontendSessionId);
1487
1486
  if (!latest)
1488
1487
  throw new Error('SESSION_REMOVED');
1489
- generation();
1490
- if (latest.backendSessionId !== backendSessionId
1491
- || backendSessionId && terminalSessions.get(backendSessionId) !== backend)
1492
- throw new Error('TERMINAL_INPUT_TARGET_CHANGED');
1488
+ const instanceMatches = !backendSessionId || terminalSessions.get(backendSessionId) === backend;
1489
+ if ((latest.agentLaunchGeneration ?? null) !== launchId || latest.backendSessionId !== backendSessionId || !instanceMatches) {
1490
+ throw new TerminalInputTargetChangedError({ expected_backend_session_id: backendSessionId, current_backend_session_id: latest.backendSessionId,
1491
+ expected_launch_id: launchId, current_launch_id: latest.agentLaunchGeneration ?? null, backend_instance_matches: instanceMatches });
1492
+ }
1493
1493
  };
1494
1494
  }
1495
1495
  /** tmux input always uses the pane queue, including automation and launch commands. */
1496
- async function automaticTerminalInput(record, assertCurrent = terminalInputGuard(record)) {
1496
+ async function automaticTerminalInput(record, assertCurrent = terminalInputGuard(record), progress) {
1497
1497
  assertCurrent();
1498
1498
  if (record.mode === 'tmux') {
1499
1499
  const binding = collaborationRouting.get(record.sessionId) ?? {
@@ -1505,18 +1505,18 @@ async function automaticTerminalInput(record, assertCurrent = terminalInputGuard
1505
1505
  if (inspected.state !== 'ready' || !inspected.pane)
1506
1506
  throw new Error(inspected.reason ?? 'TMUX_PANE_UNAVAILABLE');
1507
1507
  const pane = inspected.pane;
1508
- return (prompt) => writeCollaborationTmuxPane(runTmux, pane, prompt, runTmuxStdin, assertCurrent);
1508
+ return (prompt) => writeCollaborationTmuxPane(runTmux, pane, prompt, runTmuxStdin, assertCurrent, progress);
1509
1509
  }
1510
1510
  const backend = record.backendSessionId ? terminalSessions.get(record.backendSessionId) : null;
1511
1511
  if (!backend)
1512
1512
  throw new Error('SHELL_BACKEND_NOT_RUNNING');
1513
- return (prompt) => writeBracketedPrompt(backend.ptyProcess, prompt, assertCurrent);
1513
+ return (prompt) => writeBracketedPrompt(backend.ptyProcess, prompt, assertCurrent, progress);
1514
1514
  }
1515
- async function writeAutomaticTerminalPrompt(frontendSessionId, prompt) {
1515
+ async function writeAutomaticTerminalPrompt(frontendSessionId, prompt, progress) {
1516
1516
  const record = globalSessionState.sessions.find(candidate => candidate.sessionId === frontendSessionId);
1517
1517
  if (!record)
1518
1518
  throw new Error('SESSION_REMOVED');
1519
- const write = await automaticTerminalInput(record);
1519
+ const write = await automaticTerminalInput(record, terminalInputGuard(record), progress);
1520
1520
  await write(prompt);
1521
1521
  }
1522
1522
  async function deliverAutomationPromptWhenReady(backendSessionId, prompt) {
@@ -1985,6 +1985,7 @@ export const integrationSessionAdapter = {
1985
1985
  registerDeliveryGuard(guard) { integrationDeliveryGuard = guard; return () => { if (integrationDeliveryGuard === guard)
1986
1986
  integrationDeliveryGuard = undefined; }; },
1987
1987
  pendingMessages(id) { return collaborationStore.pendingCount(id); },
1988
+ messageHistory(id) { return collaborationStore.hasTerminalMessageHistory(id); },
1988
1989
  async prepareRelease(record) {
1989
1990
  if (collaborationStore.groupsForSession(record.session_id).some(group => group.id !== record.group_id))
1990
1991
  integrationError('SESSION_SCOPE_CONFLICT', 'Runtime belongs to another collaboration group; administrator must resolve its membership first', 409);
@@ -2076,21 +2077,28 @@ export const integrationSessionAdapter = {
2076
2077
  collaborationRouting.bind({ ...route, nativeSessionId: nativeId, pane: { ...route.pane, nativeSessionId: nativeId } });
2077
2078
  return { exists: true, running: Boolean(pane.agentSlug), shell: await integrationPaneIsIdleShell(pane), agentSlug: pane.agentSlug || null, nativeId };
2078
2079
  },
2079
- async create(record, prepared) {
2080
+ async create(record, prepared, progress) {
2080
2081
  await listDetectedAgentLaunchers();
2081
2082
  if (!agentBySlug(record.agent_slug))
2082
2083
  integrationError('COLLAB_AGENT_UNAVAILABLE', 'Configured agent plugin is not installed');
2083
2084
  if (integrationTerminalRecord(record))
2084
2085
  integrationError('SESSION_CREATE_OUTCOME_UNKNOWN', 'Creation intent already has a terminal; inspect it instead of relaunching', 409);
2085
- await launchIntegrationTerminal(record, false, prepared);
2086
+ await launchIntegrationTerminal(record, false, prepared, progress);
2086
2087
  },
2087
- async restore(record, prepared) {
2088
+ async restore(record, prepared, progress) {
2088
2089
  await listDetectedAgentLaunchers();
2089
2090
  const agent = agentBySlug(record.agent_slug);
2090
2091
  if (!record.agent_native_session_id || !agent || !buildResumeCommand(agent, record.agent_native_session_id, null))
2091
2092
  integrationError('EXACT_RESUME_UNSUPPORTED', 'Agent plugin must support exact native resume');
2093
+ progress?.('native_owner_check');
2092
2094
  await assertIntegrationNativeResumeAvailable(record);
2093
- await launchIntegrationTerminal(record, true, prepared);
2095
+ await launchIntegrationTerminal(record, true, prepared, progress);
2096
+ },
2097
+ async retryCold(record, prepared, progress) {
2098
+ await listDetectedAgentLaunchers();
2099
+ if (!agentBySlug(record.agent_slug))
2100
+ integrationError('COLLAB_AGENT_UNAVAILABLE', 'Configured agent plugin is not installed');
2101
+ await launchIntegrationTerminal(record, false, prepared, progress, true);
2094
2102
  },
2095
2103
  };
2096
2104
  async function assertIntegrationNativeResumeAvailable(record) {
@@ -2141,12 +2149,28 @@ async function assertIntegrationNativeResumeAvailable(record) {
2141
2149
  program: program?.command ?? null, processSource: program?.source, argumentsObserved: !!program?.rawArgs }];
2142
2150
  });
2143
2151
  }
2144
- async function launchIntegrationTerminal(record, restoring, prepared) {
2152
+ async function launchIntegrationTerminal(record, restoring, prepared, progress, retryCold = false) {
2145
2153
  await collaborationDeliveryWorker.reconfigure(record.session_id, async () => {
2154
+ progress?.('runtime_prepare');
2146
2155
  const group = collaborationStore.getGroup(record.group_id);
2147
2156
  if (!group || group.deleted)
2148
2157
  integrationError('TASK_GROUP_NOT_FOUND', 'Integration group no longer exists', 404);
2149
2158
  const original = await integrationSessionAdapter.inspect(record);
2159
+ if (retryCold) {
2160
+ await integrationSessionAdapter.prepareRelease(record);
2161
+ const owned = integrationTerminalRecord(record);
2162
+ if (!owned || globalSessionState.sessions.some(other => other.sessionId !== record.session_id
2163
+ && (other.tmuxSessionName === owned.tmuxSessionName || owned.backendSessionId && other.backendSessionId === owned.backendSessionId))) {
2164
+ integrationError('SESSION_IDENTITY_MISMATCH', 'Cold retry runtime lacks unique logical ownership', 409);
2165
+ }
2166
+ const history = collaborationStore.hasTerminalMessageHistory(record.session_id);
2167
+ if (history === null)
2168
+ integrationError('SESSION_MESSAGE_HISTORY_UNCONFIRMED', 'Message history cannot be verified', 409);
2169
+ if (history || collaborationStore.pendingCount(record.session_id))
2170
+ integrationError('SESSION_MESSAGE_HISTORY_PRESENT', 'TD message history appeared before retry', 409);
2171
+ if (!record.terminal_binding || !original.exists || original.running || !original.shell || original.nativeId)
2172
+ integrationError('SESSION_COLD_RETRY_RUNTIME_UNCONFIRMED', 'Original shell could not be confirmed before retry', 409);
2173
+ }
2150
2174
  if (!original.exists) {
2151
2175
  let tmuxExists = false;
2152
2176
  try {
@@ -2178,6 +2202,7 @@ async function launchIntegrationTerminal(record, restoring, prepared) {
2178
2202
  const pane = inspected.pane;
2179
2203
  const pinned = { serverPid: pane.serverPid, sessionId: pane.sessionId,
2180
2204
  paneId: pane.paneId, panePid: pane.panePid, agentSlug: record.agent_slug, nativeSessionId: record.agent_native_session_id };
2205
+ progress?.('binding_persist');
2181
2206
  prepared(pinned); // Must persist before the command enters the terminal.
2182
2207
  collaborationRouting.bind({ sessionId: record.session_id, backendSessionId: opened.terminalSession.sessionId,
2183
2208
  mode: 'tmux', tmuxSessionName: terminal.tmuxSessionName, agentSlug: record.agent_slug, nativeSessionId: record.agent_native_session_id, pane: pinned });
@@ -2195,8 +2220,11 @@ async function launchIntegrationTerminal(record, restoring, prepared) {
2195
2220
  // use an active-pane target which might have changed during preparation.
2196
2221
  if (record.resume_configuration_fingerprint && record.resume_configuration_fingerprint !== await resumeConfigurationFingerprint(record, integrationSessionAdapter))
2197
2222
  integrationError('RESUME_CONFIGURATION_CHANGED', 'Recovery configuration changed before terminal input', 409);
2198
- if (restoring)
2223
+ if (restoring) {
2224
+ progress?.('native_owner_check');
2199
2225
  await assertIntegrationNativeResumeAvailable(record);
2226
+ }
2227
+ progress?.('runtime_verify');
2200
2228
  const shell = await inspectCollaborationTmux({ sessionId: record.session_id, backendSessionId: opened.terminalSession.sessionId,
2201
2229
  mode: 'tmux', tmuxSessionName: terminal.tmuxSessionName, agentSlug: null, nativeSessionId: null, pane: pinned });
2202
2230
  if (shell.state !== 'ready' || !shell.pane || !await integrationPaneIsIdleShell(shell.pane))
@@ -2206,8 +2234,9 @@ async function launchIntegrationTerminal(record, restoring, prepared) {
2206
2234
  backend.agentSession = null;
2207
2235
  backend.agent = null;
2208
2236
  backend.agentResumeRecovered = false;
2237
+ progress?.('launch_intent');
2209
2238
  await beginAgentLaunchCheck(record.session_id, record.agent_slug, restoring ? record.agent_native_session_id : null);
2210
- await writeAutomaticTerminalPrompt(record.session_id, integrationLaunchCommand(record, restoring));
2239
+ await writeAutomaticTerminalPrompt(record.session_id, integrationLaunchCommand(record, restoring), progress);
2211
2240
  broadcastClientState();
2212
2241
  });
2213
2242
  }