termdock 1.4.313 → 1.4.315

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 (355) hide show
  1. package/dist/client/assets/{App-ChS2-lkz.js → App-B2SFV3qg.js} +53 -53
  2. package/dist/client/assets/App-B2SFV3qg.js.br +0 -0
  3. package/dist/client/assets/App-B2SFV3qg.js.gz +0 -0
  4. package/dist/client/assets/{ArchitecturePanel-JtjyyJoW.js → ArchitecturePanel-Cj7za6DZ.js} +6 -6
  5. package/dist/client/assets/ArchitecturePanel-Cj7za6DZ.js.br +0 -0
  6. package/dist/client/assets/ArchitecturePanel-Cj7za6DZ.js.gz +0 -0
  7. package/dist/client/assets/{ChangeWalkthroughPanel-BlQ5-VPp.js → ChangeWalkthroughPanel-BB52iLLC.js} +2 -2
  8. package/dist/client/assets/ChangeWalkthroughPanel-BB52iLLC.js.br +0 -0
  9. package/dist/client/assets/ChangeWalkthroughPanel-BB52iLLC.js.gz +0 -0
  10. package/dist/client/assets/{CollaborationMainWorkspace-aFLAMqDr.js → CollaborationMainWorkspace-D5WKV3rA.js} +1 -1
  11. package/dist/client/assets/CollaborationMainWorkspace-D5WKV3rA.js.br +0 -0
  12. package/dist/client/assets/CollaborationMainWorkspace-D5WKV3rA.js.gz +0 -0
  13. package/dist/client/assets/CollaborationTaskContent-MwUgcmG_.js +2 -0
  14. package/dist/client/assets/ComputerControlView-Dkc4R1IU.js +5 -0
  15. package/dist/client/assets/ComputerControlView-Dkc4R1IU.js.br +0 -0
  16. package/dist/client/assets/ComputerControlView-Dkc4R1IU.js.gz +0 -0
  17. package/dist/client/assets/{DagPlayground-CR4uDFOx.js → DagPlayground-BHY3l8UG.js} +1 -1
  18. package/dist/client/assets/DagPlayground-BHY3l8UG.js.br +0 -0
  19. package/dist/client/assets/DagPlayground-BHY3l8UG.js.gz +0 -0
  20. package/dist/client/assets/{DiffLab-BqeHMDOy.js → DiffLab-BSQiKfBJ.js} +1 -1
  21. package/dist/client/assets/DiffLab-BSQiKfBJ.js.br +0 -0
  22. package/dist/client/assets/DiffLab-BSQiKfBJ.js.gz +0 -0
  23. package/dist/client/assets/{DiffReview-DqrOcRfP.js → DiffReview-CYrBBq0V.js} +1 -1
  24. package/dist/client/assets/DiffReview-CYrBBq0V.js.br +0 -0
  25. package/dist/client/assets/DiffReview-CYrBBq0V.js.gz +0 -0
  26. package/dist/client/assets/{DiffReviewLab-CEYpbrL6.js → DiffReviewLab-VSIbEnxm.js} +1 -1
  27. package/dist/client/assets/DiffReviewLab-VSIbEnxm.js.br +0 -0
  28. package/dist/client/assets/DiffReviewLab-VSIbEnxm.js.gz +0 -0
  29. package/dist/client/assets/{DiffViewer-F-uQSmhG.js → DiffViewer-Cx5fyiMB.js} +8 -8
  30. package/dist/client/assets/DiffViewer-Cx5fyiMB.js.br +0 -0
  31. package/dist/client/assets/DiffViewer-Cx5fyiMB.js.gz +0 -0
  32. package/dist/client/assets/{ModelPreview-KmXFkgij.js → ModelPreview-B22odexG.js} +1 -1
  33. package/dist/client/assets/ModelPreview-B22odexG.js.br +0 -0
  34. package/dist/client/assets/ModelPreview-B22odexG.js.gz +0 -0
  35. package/dist/client/assets/{RightSidebar-VMdXpo4h.js → RightSidebar-DKA0jXPW.js} +3 -3
  36. package/dist/client/assets/RightSidebar-DKA0jXPW.js.br +0 -0
  37. package/dist/client/assets/RightSidebar-DKA0jXPW.js.gz +0 -0
  38. package/dist/client/assets/{abnfDiagram-VCTEODGH-CAMk1C0N.js → abnfDiagram-VCTEODGH-sbUSsiPn.js} +1 -1
  39. package/dist/client/assets/abnfDiagram-VCTEODGH-sbUSsiPn.js.br +0 -0
  40. package/dist/client/assets/abnfDiagram-VCTEODGH-sbUSsiPn.js.gz +0 -0
  41. package/dist/client/assets/app-CYOLJycb.js +35 -0
  42. package/dist/client/assets/app-CYOLJycb.js.br +0 -0
  43. package/dist/client/assets/app-CYOLJycb.js.gz +0 -0
  44. package/dist/client/assets/{arc-CYG_-1vC.js → arc-GhJ9aeQ3.js} +1 -1
  45. package/dist/client/assets/arc-GhJ9aeQ3.js.br +0 -0
  46. package/dist/client/assets/arc-GhJ9aeQ3.js.gz +0 -0
  47. package/dist/client/assets/{architectureDiagram-5GKGNRK7-BqHzezLR.js → architectureDiagram-5GKGNRK7-BYmAIJBx.js} +1 -1
  48. package/dist/client/assets/architectureDiagram-5GKGNRK7-BYmAIJBx.js.br +0 -0
  49. package/dist/client/assets/architectureDiagram-5GKGNRK7-BYmAIJBx.js.gz +0 -0
  50. package/dist/client/assets/{blockDiagram-I7D4REHJ-D6GWRO_Z.js → blockDiagram-I7D4REHJ-CZNZT_ez.js} +1 -1
  51. package/dist/client/assets/blockDiagram-I7D4REHJ-CZNZT_ez.js.br +0 -0
  52. package/dist/client/assets/blockDiagram-I7D4REHJ-CZNZT_ez.js.gz +0 -0
  53. package/dist/client/assets/{c4Diagram-7LVT6UL2-CutmGIGb.js → c4Diagram-7LVT6UL2-6xcSowLn.js} +1 -1
  54. package/dist/client/assets/c4Diagram-7LVT6UL2-6xcSowLn.js.br +0 -0
  55. package/dist/client/assets/c4Diagram-7LVT6UL2-6xcSowLn.js.gz +0 -0
  56. package/dist/client/assets/channel-C1FwyjiU.js +1 -0
  57. package/dist/client/assets/{chunk-2Q5K7J3B-DwiUpGFu.js → chunk-2Q5K7J3B-C06nkhUQ.js} +1 -1
  58. package/dist/client/assets/{chunk-5VM5RSS4-C35gLPSH.js → chunk-5VM5RSS4-BHY43hJO.js} +1 -1
  59. package/dist/client/assets/{chunk-F27PBJKO-CNptP19P.js → chunk-F27PBJKO-Dl8JYcZO.js} +1 -1
  60. package/dist/client/assets/chunk-F27PBJKO-Dl8JYcZO.js.br +0 -0
  61. package/dist/client/assets/chunk-F27PBJKO-Dl8JYcZO.js.gz +0 -0
  62. package/dist/client/assets/{chunk-IMKFNOWR-DHdpB9A0.js → chunk-IMKFNOWR-BALi4Q3g.js} +1 -1
  63. package/dist/client/assets/chunk-IMKFNOWR-BALi4Q3g.js.br +0 -0
  64. package/dist/client/assets/chunk-IMKFNOWR-BALi4Q3g.js.gz +0 -0
  65. package/dist/client/assets/{chunk-JWPE2WC7-CrKSOzdE.js → chunk-JWPE2WC7-BBD2d7j7.js} +1 -1
  66. package/dist/client/assets/{chunk-POPQ4Y6H-CiZGLRSk.js → chunk-POPQ4Y6H-CZN0_ndj.js} +1 -1
  67. package/dist/client/assets/{chunk-SVP7TREG-B70pX8OB.js → chunk-SVP7TREG-CD-Zf9rn.js} +1 -1
  68. package/dist/client/assets/chunk-SVP7TREG-CD-Zf9rn.js.br +0 -0
  69. package/dist/client/assets/chunk-SVP7TREG-CD-Zf9rn.js.gz +0 -0
  70. package/dist/client/assets/{chunk-TICWLB2K-Ba1mI99F.js → chunk-TICWLB2K-Clpg1zwp.js} +1 -1
  71. package/dist/client/assets/chunk-TICWLB2K-Clpg1zwp.js.br +0 -0
  72. package/dist/client/assets/chunk-TICWLB2K-Clpg1zwp.js.gz +0 -0
  73. package/dist/client/assets/{chunk-XXDRQBXY-DmKIl18h.js → chunk-XXDRQBXY-BanPVnIr.js} +1 -1
  74. package/dist/client/assets/classDiagram-ZZMXUADV-FyKDan8T.js +1 -0
  75. package/dist/client/assets/classDiagram-v2-VYDZK3BY-FyKDan8T.js +1 -0
  76. package/dist/client/assets/{cose-bilkent-JH36ORCC-C-NMDUHW.js → cose-bilkent-JH36ORCC-431u7cfU.js} +1 -1
  77. package/dist/client/assets/cose-bilkent-JH36ORCC-431u7cfU.js.br +0 -0
  78. package/dist/client/assets/cose-bilkent-JH36ORCC-431u7cfU.js.gz +0 -0
  79. package/dist/client/assets/{cynefin-OW5HDTMX-CZgEc1ab.js → cynefin-OW5HDTMX-BuLFGx14.js} +1 -1
  80. package/dist/client/assets/cynefin-OW5HDTMX-BuLFGx14.js.br +0 -0
  81. package/dist/client/assets/cynefin-OW5HDTMX-BuLFGx14.js.gz +0 -0
  82. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-CHQeSNm2.js → cynefinDiagram-5FMLGOSQ-qLzjwMMG.js} +1 -1
  83. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-qLzjwMMG.js.br +0 -0
  84. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-qLzjwMMG.js.gz +0 -0
  85. package/dist/client/assets/{dagre-GXQ25YYZ-B_jkMdPS.js → dagre-GXQ25YYZ-CUdd5M5g.js} +1 -1
  86. package/dist/client/assets/dagre-GXQ25YYZ-CUdd5M5g.js.br +0 -0
  87. package/dist/client/assets/dagre-GXQ25YYZ-CUdd5M5g.js.gz +0 -0
  88. package/dist/client/assets/{diagram-S7CK7UJ4-nv6Lnsrp.js → diagram-S7CK7UJ4-DLQClBzm.js} +1 -1
  89. package/dist/client/assets/diagram-S7CK7UJ4-DLQClBzm.js.br +0 -0
  90. package/dist/client/assets/diagram-S7CK7UJ4-DLQClBzm.js.gz +0 -0
  91. package/dist/client/assets/{diagram-UQ7AKVKN-BZf2fzaA.js → diagram-UQ7AKVKN-1RGASXU_.js} +1 -1
  92. package/dist/client/assets/diagram-UQ7AKVKN-1RGASXU_.js.br +0 -0
  93. package/dist/client/assets/diagram-UQ7AKVKN-1RGASXU_.js.gz +0 -0
  94. package/dist/client/assets/{diagram-VSXAHHWV-CxL0_BH8.js → diagram-VSXAHHWV-DqnCzn2R.js} +1 -1
  95. package/dist/client/assets/diagram-VSXAHHWV-DqnCzn2R.js.br +0 -0
  96. package/dist/client/assets/diagram-VSXAHHWV-DqnCzn2R.js.gz +0 -0
  97. package/dist/client/assets/{diagram-VX7I27RA-Dm9MqpIE.js → diagram-VX7I27RA-CMXsPqTS.js} +1 -1
  98. package/dist/client/assets/diagram-VX7I27RA-CMXsPqTS.js.br +0 -0
  99. package/dist/client/assets/diagram-VX7I27RA-CMXsPqTS.js.gz +0 -0
  100. package/dist/client/assets/{diagram-Z3DM3KII-BIfTa7P5.js → diagram-Z3DM3KII-BM0N1kCR.js} +1 -1
  101. package/dist/client/assets/diagram-Z3DM3KII-BM0N1kCR.js.br +0 -0
  102. package/dist/client/assets/diagram-Z3DM3KII-BM0N1kCR.js.gz +0 -0
  103. package/dist/client/assets/{ebnfDiagram-PWID7BFC-D4XhCDFS.js → ebnfDiagram-PWID7BFC-CvaVo-wh.js} +1 -1
  104. package/dist/client/assets/ebnfDiagram-PWID7BFC-CvaVo-wh.js.br +0 -0
  105. package/dist/client/assets/ebnfDiagram-PWID7BFC-CvaVo-wh.js.gz +0 -0
  106. package/dist/client/assets/{erDiagram-RLTQ6QDP-Dxd48dXC.js → erDiagram-RLTQ6QDP-okw-AY7i.js} +1 -1
  107. package/dist/client/assets/erDiagram-RLTQ6QDP-okw-AY7i.js.br +0 -0
  108. package/dist/client/assets/erDiagram-RLTQ6QDP-okw-AY7i.js.gz +0 -0
  109. package/dist/client/assets/{flowDiagram-HODETNUW-BXBMsEmE.js → flowDiagram-HODETNUW-B_DWtzOe.js} +1 -1
  110. package/dist/client/assets/flowDiagram-HODETNUW-B_DWtzOe.js.br +0 -0
  111. package/dist/client/assets/flowDiagram-HODETNUW-B_DWtzOe.js.gz +0 -0
  112. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-CBfDd-KZ.js → ganttDiagram-EL5Y4UJY-Bm4nYUVg.js} +1 -1
  113. package/dist/client/assets/ganttDiagram-EL5Y4UJY-Bm4nYUVg.js.br +0 -0
  114. package/dist/client/assets/ganttDiagram-EL5Y4UJY-Bm4nYUVg.js.gz +0 -0
  115. package/dist/client/assets/{gestureArbiter-DXLmNGli.js → gestureArbiter-XalN4TaN.js} +1 -1
  116. package/dist/client/assets/gestureArbiter-XalN4TaN.js.br +0 -0
  117. package/dist/client/assets/gestureArbiter-XalN4TaN.js.gz +0 -0
  118. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-DtLM68fN.js → gitGraphDiagram-WWUBYQGX-B7LAo8S2.js} +1 -1
  119. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-B7LAo8S2.js.br +0 -0
  120. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-B7LAo8S2.js.gz +0 -0
  121. package/dist/client/assets/{index-KuPaZyuZ.css → index-BObjbh2R.css} +1 -1
  122. package/dist/client/assets/index-BObjbh2R.css.br +0 -0
  123. package/dist/client/assets/{index-KuPaZyuZ.css.gz → index-BObjbh2R.css.gz} +0 -0
  124. package/dist/client/assets/{infoDiagram-27XIBGKW-FRhqdJvW.js → infoDiagram-27XIBGKW-DXncUrwz.js} +1 -1
  125. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-DAHBvAZ-.js → ishikawaDiagram-5VMMS53U-Ds28H7pI.js} +1 -1
  126. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-DAHBvAZ-.js.br → ishikawaDiagram-5VMMS53U-Ds28H7pI.js.br} +0 -0
  127. package/dist/client/assets/ishikawaDiagram-5VMMS53U-Ds28H7pI.js.gz +0 -0
  128. package/dist/client/assets/{journeyDiagram-3NMN7TZE-CVuWuL3Z.js → journeyDiagram-3NMN7TZE-WeF_efZ2.js} +1 -1
  129. package/dist/client/assets/journeyDiagram-3NMN7TZE-WeF_efZ2.js.br +0 -0
  130. package/dist/client/assets/journeyDiagram-3NMN7TZE-WeF_efZ2.js.gz +0 -0
  131. package/dist/client/assets/{kanban-definition-UXKFOSKX-ByQSUVJV.js → kanban-definition-UXKFOSKX-CMbZcy6U.js} +1 -1
  132. package/dist/client/assets/kanban-definition-UXKFOSKX-CMbZcy6U.js.br +0 -0
  133. package/dist/client/assets/kanban-definition-UXKFOSKX-CMbZcy6U.js.gz +0 -0
  134. package/dist/client/assets/{layout-Bb3Nb1c4.js → layout-DNapC8T-.js} +1 -1
  135. package/dist/client/assets/layout-DNapC8T-.js.br +0 -0
  136. package/dist/client/assets/layout-DNapC8T-.js.gz +0 -0
  137. package/dist/client/assets/{linear-DHMMQlOo.js → linear-B9AFx-TF.js} +1 -1
  138. package/dist/client/assets/linear-B9AFx-TF.js.br +0 -0
  139. package/dist/client/assets/linear-B9AFx-TF.js.gz +0 -0
  140. package/dist/client/assets/{mermaid.core-BYfniK0H.js → mermaid.core-Ddh1Z0hf.js} +5 -5
  141. package/dist/client/assets/mermaid.core-Ddh1Z0hf.js.br +0 -0
  142. package/dist/client/assets/mermaid.core-Ddh1Z0hf.js.gz +0 -0
  143. package/dist/client/assets/{mindmap-definition-YA3MSWOX-EDLD5AyH.js → mindmap-definition-YA3MSWOX-B0xMGUol.js} +1 -1
  144. package/dist/client/assets/mindmap-definition-YA3MSWOX-B0xMGUol.js.br +0 -0
  145. package/dist/client/assets/mindmap-definition-YA3MSWOX-B0xMGUol.js.gz +0 -0
  146. package/dist/client/assets/{passwordBootstrap-DCrtirwT.js → passwordBootstrap-DQRd5vCF.js} +1 -1
  147. package/dist/client/assets/passwordBootstrap-DQRd5vCF.js.br +0 -0
  148. package/dist/client/assets/{passwordBootstrap-DCrtirwT.js.gz → passwordBootstrap-DQRd5vCF.js.gz} +0 -0
  149. package/dist/client/assets/{pegDiagram-XKGWAZYB-BHYhkqJN.js → pegDiagram-XKGWAZYB-BVZ-3kEF.js} +1 -1
  150. package/dist/client/assets/pegDiagram-XKGWAZYB-BVZ-3kEF.js.br +0 -0
  151. package/dist/client/assets/pegDiagram-XKGWAZYB-BVZ-3kEF.js.gz +0 -0
  152. package/dist/client/assets/{pieDiagram-E7YTZNPT-BUIJlswC.js → pieDiagram-E7YTZNPT-Cim4Hk3I.js} +1 -1
  153. package/dist/client/assets/pieDiagram-E7YTZNPT-Cim4Hk3I.js.br +0 -0
  154. package/dist/client/assets/pieDiagram-E7YTZNPT-Cim4Hk3I.js.gz +0 -0
  155. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-D8Im-7yC.js → quadrantDiagram-AXDQQJYC-CYiEj5sp.js} +1 -1
  156. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CYiEj5sp.js.br +0 -0
  157. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CYiEj5sp.js.gz +0 -0
  158. package/dist/client/assets/{railroadDiagram-O6MQD6OU-D7n6z2G1.js → railroadDiagram-O6MQD6OU-DjNNfYra.js} +1 -1
  159. package/dist/client/assets/railroadDiagram-O6MQD6OU-DjNNfYra.js.br +0 -0
  160. package/dist/client/assets/railroadDiagram-O6MQD6OU-DjNNfYra.js.gz +0 -0
  161. package/dist/client/assets/{rdpSession-DJlNIbVk.js → rdpSession-DEzSQAuN.js} +1 -1
  162. package/dist/client/assets/rdpSession-DEzSQAuN.js.br +0 -0
  163. package/dist/client/assets/rdpSession-DEzSQAuN.js.gz +0 -0
  164. package/dist/client/assets/{referenceLongPress-DFSrssSr.js → referenceLongPress-BjyTtoDY.js} +1 -1
  165. package/dist/client/assets/referenceLongPress-BjyTtoDY.js.br +0 -0
  166. package/dist/client/assets/referenceLongPress-BjyTtoDY.js.gz +0 -0
  167. package/dist/client/assets/{requirementDiagram-BXWQKSXE-Ki0rR-F7.js → requirementDiagram-BXWQKSXE-ZwiKdiI3.js} +1 -1
  168. package/dist/client/assets/requirementDiagram-BXWQKSXE-ZwiKdiI3.js.br +0 -0
  169. package/dist/client/assets/{requirementDiagram-BXWQKSXE-Ki0rR-F7.js.gz → requirementDiagram-BXWQKSXE-ZwiKdiI3.js.gz} +0 -0
  170. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-36NmMqsW.js → sankeyDiagram-P5KCCOFB-BYR7ctps.js} +1 -1
  171. package/dist/client/assets/sankeyDiagram-P5KCCOFB-BYR7ctps.js.br +0 -0
  172. package/dist/client/assets/sankeyDiagram-P5KCCOFB-BYR7ctps.js.gz +0 -0
  173. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-5vsPuFyO.js → sequenceDiagram-WJ2MYXX4-DxYCvK80.js} +1 -1
  174. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DxYCvK80.js.br +0 -0
  175. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DxYCvK80.js.gz +0 -0
  176. package/dist/client/assets/{sizeCapture-INFHLROL-DbAulwBg.js → sizeCapture-INFHLROL-CXruk8Ko.js} +1 -1
  177. package/dist/client/assets/sizeCapture-INFHLROL-CXruk8Ko.js.br +0 -0
  178. package/dist/client/assets/sizeCapture-INFHLROL-CXruk8Ko.js.gz +0 -0
  179. package/dist/client/assets/{sparkles-CapLTKAs.js → sparkles-DRH97PDH.js} +1 -1
  180. package/dist/client/assets/{stateDiagram-D77RDMKH-Bgwe0g5S.js → stateDiagram-D77RDMKH-CENDGrxr.js} +1 -1
  181. package/dist/client/assets/stateDiagram-D77RDMKH-CENDGrxr.js.br +0 -0
  182. package/dist/client/assets/stateDiagram-D77RDMKH-CENDGrxr.js.gz +0 -0
  183. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-De-tGy_n.js +1 -0
  184. package/dist/client/assets/{swimlanes-42K2YHIH-COGAWe-g.js → swimlanes-42K2YHIH-BZQeVFeA.js} +1 -1
  185. package/dist/client/assets/swimlanes-42K2YHIH-BZQeVFeA.js.br +0 -0
  186. package/dist/client/assets/swimlanes-42K2YHIH-BZQeVFeA.js.gz +0 -0
  187. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-D1YMLrIO.js +8 -0
  188. package/dist/client/assets/{timeline-definition-24CTP7MA-C4gt5z68.js → timeline-definition-24CTP7MA-DiJ9i33g.js} +1 -1
  189. package/dist/client/assets/timeline-definition-24CTP7MA-DiJ9i33g.js.br +0 -0
  190. package/dist/client/assets/{timeline-definition-24CTP7MA-C4gt5z68.js.gz → timeline-definition-24CTP7MA-DiJ9i33g.js.gz} +0 -0
  191. package/dist/client/assets/{triangle-alert-xPHw25jD.js → triangle-alert-DECoBoOV.js} +1 -1
  192. package/dist/client/assets/{vennDiagram-4TSXK5OY-CIEXh9oD.js → vennDiagram-4TSXK5OY-DBiEJQ9Y.js} +1 -1
  193. package/dist/client/assets/vennDiagram-4TSXK5OY-DBiEJQ9Y.js.br +0 -0
  194. package/dist/client/assets/vennDiagram-4TSXK5OY-DBiEJQ9Y.js.gz +0 -0
  195. package/dist/client/assets/{videoCompression-CUkCS2-q.js → videoCompression-8r1jOza9.js} +1 -1
  196. package/dist/client/assets/videoCompression-8r1jOza9.js.br +0 -0
  197. package/dist/client/assets/videoCompression-8r1jOza9.js.gz +0 -0
  198. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-gQhcW1vd.js → wardleyDiagram-VM6X3IG4-B6wCSfya.js} +1 -1
  199. package/dist/client/assets/wardleyDiagram-VM6X3IG4-B6wCSfya.js.br +0 -0
  200. package/dist/client/assets/wardleyDiagram-VM6X3IG4-B6wCSfya.js.gz +0 -0
  201. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-BmIcdejz.js → xychartDiagram-S5SC5T6Z-DlNQayU5.js} +1 -1
  202. package/dist/client/assets/xychartDiagram-S5SC5T6Z-DlNQayU5.js.br +0 -0
  203. package/dist/client/assets/xychartDiagram-S5SC5T6Z-DlNQayU5.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 +30 -8
  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 +15 -3
  215. package/dist/server/agent/integrationServer.js +16 -1
  216. package/dist/server/agent/integrationSessions.js +342 -14
  217. package/dist/server/agent/integrationStore.js +1 -1
  218. package/dist/server/agent/promptDelivery.js +7 -1
  219. package/dist/server/agent/sessionLaunchDiagnostics.js +26 -0
  220. package/dist/server/agent/sessionLifecycle.js +4 -0
  221. package/dist/server/agent/sessionManagement.js +87 -0
  222. package/dist/server/agent/terminalInput.js +9 -1
  223. package/dist/server/routes/terminal.js +172 -21
  224. package/docs/integrations.md +208 -0
  225. package/package.json +1 -1
  226. package/runtime-manifest.json +3 -3
  227. package/dist/client/assets/App-ChS2-lkz.js.br +0 -0
  228. package/dist/client/assets/App-ChS2-lkz.js.gz +0 -0
  229. package/dist/client/assets/ArchitecturePanel-JtjyyJoW.js.br +0 -0
  230. package/dist/client/assets/ArchitecturePanel-JtjyyJoW.js.gz +0 -0
  231. package/dist/client/assets/ChangeWalkthroughPanel-BlQ5-VPp.js.br +0 -0
  232. package/dist/client/assets/ChangeWalkthroughPanel-BlQ5-VPp.js.gz +0 -0
  233. package/dist/client/assets/CollaborationMainWorkspace-aFLAMqDr.js.br +0 -0
  234. package/dist/client/assets/CollaborationMainWorkspace-aFLAMqDr.js.gz +0 -0
  235. package/dist/client/assets/CollaborationTaskContent-BDQMRhU9.js +0 -2
  236. package/dist/client/assets/ComputerControlView-TAKDbBUl.js +0 -5
  237. package/dist/client/assets/ComputerControlView-TAKDbBUl.js.br +0 -0
  238. package/dist/client/assets/ComputerControlView-TAKDbBUl.js.gz +0 -0
  239. package/dist/client/assets/DagPlayground-CR4uDFOx.js.br +0 -0
  240. package/dist/client/assets/DagPlayground-CR4uDFOx.js.gz +0 -0
  241. package/dist/client/assets/DiffLab-BqeHMDOy.js.br +0 -0
  242. package/dist/client/assets/DiffLab-BqeHMDOy.js.gz +0 -0
  243. package/dist/client/assets/DiffReview-DqrOcRfP.js.br +0 -0
  244. package/dist/client/assets/DiffReview-DqrOcRfP.js.gz +0 -0
  245. package/dist/client/assets/DiffReviewLab-CEYpbrL6.js.br +0 -0
  246. package/dist/client/assets/DiffReviewLab-CEYpbrL6.js.gz +0 -0
  247. package/dist/client/assets/DiffViewer-F-uQSmhG.js.br +0 -0
  248. package/dist/client/assets/DiffViewer-F-uQSmhG.js.gz +0 -0
  249. package/dist/client/assets/ModelPreview-KmXFkgij.js.br +0 -0
  250. package/dist/client/assets/ModelPreview-KmXFkgij.js.gz +0 -0
  251. package/dist/client/assets/RightSidebar-VMdXpo4h.js.br +0 -0
  252. package/dist/client/assets/RightSidebar-VMdXpo4h.js.gz +0 -0
  253. package/dist/client/assets/abnfDiagram-VCTEODGH-CAMk1C0N.js.br +0 -0
  254. package/dist/client/assets/abnfDiagram-VCTEODGH-CAMk1C0N.js.gz +0 -0
  255. package/dist/client/assets/app-CHxLSuGQ.js +0 -35
  256. package/dist/client/assets/app-CHxLSuGQ.js.br +0 -0
  257. package/dist/client/assets/app-CHxLSuGQ.js.gz +0 -0
  258. package/dist/client/assets/arc-CYG_-1vC.js.br +0 -0
  259. package/dist/client/assets/arc-CYG_-1vC.js.gz +0 -0
  260. package/dist/client/assets/architectureDiagram-5GKGNRK7-BqHzezLR.js.br +0 -0
  261. package/dist/client/assets/architectureDiagram-5GKGNRK7-BqHzezLR.js.gz +0 -0
  262. package/dist/client/assets/blockDiagram-I7D4REHJ-D6GWRO_Z.js.br +0 -0
  263. package/dist/client/assets/blockDiagram-I7D4REHJ-D6GWRO_Z.js.gz +0 -0
  264. package/dist/client/assets/c4Diagram-7LVT6UL2-CutmGIGb.js.br +0 -0
  265. package/dist/client/assets/c4Diagram-7LVT6UL2-CutmGIGb.js.gz +0 -0
  266. package/dist/client/assets/channel-B3BKM2gg.js +0 -1
  267. package/dist/client/assets/chunk-F27PBJKO-CNptP19P.js.br +0 -0
  268. package/dist/client/assets/chunk-F27PBJKO-CNptP19P.js.gz +0 -0
  269. package/dist/client/assets/chunk-IMKFNOWR-DHdpB9A0.js.br +0 -0
  270. package/dist/client/assets/chunk-IMKFNOWR-DHdpB9A0.js.gz +0 -0
  271. package/dist/client/assets/chunk-SVP7TREG-B70pX8OB.js.br +0 -0
  272. package/dist/client/assets/chunk-SVP7TREG-B70pX8OB.js.gz +0 -0
  273. package/dist/client/assets/chunk-TICWLB2K-Ba1mI99F.js.br +0 -0
  274. package/dist/client/assets/chunk-TICWLB2K-Ba1mI99F.js.gz +0 -0
  275. package/dist/client/assets/classDiagram-ZZMXUADV-CS4V_MQS.js +0 -1
  276. package/dist/client/assets/classDiagram-v2-VYDZK3BY-CS4V_MQS.js +0 -1
  277. package/dist/client/assets/cose-bilkent-JH36ORCC-C-NMDUHW.js.br +0 -0
  278. package/dist/client/assets/cose-bilkent-JH36ORCC-C-NMDUHW.js.gz +0 -0
  279. package/dist/client/assets/cynefin-OW5HDTMX-CZgEc1ab.js.br +0 -0
  280. package/dist/client/assets/cynefin-OW5HDTMX-CZgEc1ab.js.gz +0 -0
  281. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CHQeSNm2.js.br +0 -0
  282. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CHQeSNm2.js.gz +0 -0
  283. package/dist/client/assets/dagre-GXQ25YYZ-B_jkMdPS.js.br +0 -0
  284. package/dist/client/assets/dagre-GXQ25YYZ-B_jkMdPS.js.gz +0 -0
  285. package/dist/client/assets/diagram-S7CK7UJ4-nv6Lnsrp.js.br +0 -0
  286. package/dist/client/assets/diagram-S7CK7UJ4-nv6Lnsrp.js.gz +0 -0
  287. package/dist/client/assets/diagram-UQ7AKVKN-BZf2fzaA.js.br +0 -0
  288. package/dist/client/assets/diagram-UQ7AKVKN-BZf2fzaA.js.gz +0 -0
  289. package/dist/client/assets/diagram-VSXAHHWV-CxL0_BH8.js.br +0 -0
  290. package/dist/client/assets/diagram-VSXAHHWV-CxL0_BH8.js.gz +0 -0
  291. package/dist/client/assets/diagram-VX7I27RA-Dm9MqpIE.js.br +0 -0
  292. package/dist/client/assets/diagram-VX7I27RA-Dm9MqpIE.js.gz +0 -0
  293. package/dist/client/assets/diagram-Z3DM3KII-BIfTa7P5.js.br +0 -0
  294. package/dist/client/assets/diagram-Z3DM3KII-BIfTa7P5.js.gz +0 -0
  295. package/dist/client/assets/ebnfDiagram-PWID7BFC-D4XhCDFS.js.br +0 -0
  296. package/dist/client/assets/ebnfDiagram-PWID7BFC-D4XhCDFS.js.gz +0 -0
  297. package/dist/client/assets/erDiagram-RLTQ6QDP-Dxd48dXC.js.br +0 -0
  298. package/dist/client/assets/erDiagram-RLTQ6QDP-Dxd48dXC.js.gz +0 -0
  299. package/dist/client/assets/flowDiagram-HODETNUW-BXBMsEmE.js.br +0 -0
  300. package/dist/client/assets/flowDiagram-HODETNUW-BXBMsEmE.js.gz +0 -0
  301. package/dist/client/assets/ganttDiagram-EL5Y4UJY-CBfDd-KZ.js.br +0 -0
  302. package/dist/client/assets/ganttDiagram-EL5Y4UJY-CBfDd-KZ.js.gz +0 -0
  303. package/dist/client/assets/gestureArbiter-DXLmNGli.js.br +0 -0
  304. package/dist/client/assets/gestureArbiter-DXLmNGli.js.gz +0 -0
  305. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DtLM68fN.js.br +0 -0
  306. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DtLM68fN.js.gz +0 -0
  307. package/dist/client/assets/index-KuPaZyuZ.css.br +0 -0
  308. package/dist/client/assets/ishikawaDiagram-5VMMS53U-DAHBvAZ-.js.gz +0 -0
  309. package/dist/client/assets/journeyDiagram-3NMN7TZE-CVuWuL3Z.js.br +0 -0
  310. package/dist/client/assets/journeyDiagram-3NMN7TZE-CVuWuL3Z.js.gz +0 -0
  311. package/dist/client/assets/kanban-definition-UXKFOSKX-ByQSUVJV.js.br +0 -0
  312. package/dist/client/assets/kanban-definition-UXKFOSKX-ByQSUVJV.js.gz +0 -0
  313. package/dist/client/assets/layout-Bb3Nb1c4.js.br +0 -0
  314. package/dist/client/assets/layout-Bb3Nb1c4.js.gz +0 -0
  315. package/dist/client/assets/linear-DHMMQlOo.js.br +0 -0
  316. package/dist/client/assets/linear-DHMMQlOo.js.gz +0 -0
  317. package/dist/client/assets/mermaid.core-BYfniK0H.js.br +0 -0
  318. package/dist/client/assets/mermaid.core-BYfniK0H.js.gz +0 -0
  319. package/dist/client/assets/mindmap-definition-YA3MSWOX-EDLD5AyH.js.br +0 -0
  320. package/dist/client/assets/mindmap-definition-YA3MSWOX-EDLD5AyH.js.gz +0 -0
  321. package/dist/client/assets/passwordBootstrap-DCrtirwT.js.br +0 -0
  322. package/dist/client/assets/pegDiagram-XKGWAZYB-BHYhkqJN.js.br +0 -0
  323. package/dist/client/assets/pegDiagram-XKGWAZYB-BHYhkqJN.js.gz +0 -0
  324. package/dist/client/assets/pieDiagram-E7YTZNPT-BUIJlswC.js.br +0 -0
  325. package/dist/client/assets/pieDiagram-E7YTZNPT-BUIJlswC.js.gz +0 -0
  326. package/dist/client/assets/quadrantDiagram-AXDQQJYC-D8Im-7yC.js.br +0 -0
  327. package/dist/client/assets/quadrantDiagram-AXDQQJYC-D8Im-7yC.js.gz +0 -0
  328. package/dist/client/assets/railroadDiagram-O6MQD6OU-D7n6z2G1.js.br +0 -0
  329. package/dist/client/assets/railroadDiagram-O6MQD6OU-D7n6z2G1.js.gz +0 -0
  330. package/dist/client/assets/rdpSession-DJlNIbVk.js.br +0 -0
  331. package/dist/client/assets/rdpSession-DJlNIbVk.js.gz +0 -0
  332. package/dist/client/assets/referenceLongPress-DFSrssSr.js.br +0 -0
  333. package/dist/client/assets/referenceLongPress-DFSrssSr.js.gz +0 -0
  334. package/dist/client/assets/requirementDiagram-BXWQKSXE-Ki0rR-F7.js.br +0 -0
  335. package/dist/client/assets/sankeyDiagram-P5KCCOFB-36NmMqsW.js.br +0 -0
  336. package/dist/client/assets/sankeyDiagram-P5KCCOFB-36NmMqsW.js.gz +0 -0
  337. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-5vsPuFyO.js.br +0 -0
  338. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-5vsPuFyO.js.gz +0 -0
  339. package/dist/client/assets/sizeCapture-INFHLROL-DbAulwBg.js.br +0 -0
  340. package/dist/client/assets/sizeCapture-INFHLROL-DbAulwBg.js.gz +0 -0
  341. package/dist/client/assets/stateDiagram-D77RDMKH-Bgwe0g5S.js.br +0 -0
  342. package/dist/client/assets/stateDiagram-D77RDMKH-Bgwe0g5S.js.gz +0 -0
  343. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-Bg6S3Zm0.js +0 -1
  344. package/dist/client/assets/swimlanes-42K2YHIH-COGAWe-g.js.br +0 -0
  345. package/dist/client/assets/swimlanes-42K2YHIH-COGAWe-g.js.gz +0 -0
  346. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DwBBOocG.js +0 -8
  347. package/dist/client/assets/timeline-definition-24CTP7MA-C4gt5z68.js.br +0 -0
  348. package/dist/client/assets/vennDiagram-4TSXK5OY-CIEXh9oD.js.br +0 -0
  349. package/dist/client/assets/vennDiagram-4TSXK5OY-CIEXh9oD.js.gz +0 -0
  350. package/dist/client/assets/videoCompression-CUkCS2-q.js.br +0 -0
  351. package/dist/client/assets/videoCompression-CUkCS2-q.js.gz +0 -0
  352. package/dist/client/assets/wardleyDiagram-VM6X3IG4-gQhcW1vd.js.br +0 -0
  353. package/dist/client/assets/wardleyDiagram-VM6X3IG4-gQhcW1vd.js.gz +0 -0
  354. package/dist/client/assets/xychartDiagram-S5SC5T6Z-BmIcdejz.js.br +0 -0
  355. package/dist/client/assets/xychartDiagram-S5SC5T6Z-BmIcdejz.js.gz +0 -0
@@ -1,10 +1,13 @@
1
1
  import fs from 'node:fs';
2
+ import { cleanMemberName } from './collaborationRoutes.js';
2
3
  import path from 'node:path';
3
4
  import { createHash, randomBytes, randomUUID } from 'node:crypto';
4
5
  import { atomicJson, integrationError } from './integrationStore.js';
5
6
  import { SessionLifecycleCoordinator, assertMessageRuntime, assertReleaseFacts, assertReleaseGeneration } from './sessionLifecycle.js';
6
7
  import { resumeConfigurationFingerprint } from './sessionResumeConfiguration.js';
7
8
  import { NativeResumeOwnerError } from './nativeResumeOwner.js';
9
+ import { CollaborationError } from './collaborationProtocol.js';
10
+ import { beginLaunchDiagnostics, launchFailure, launchProgress } from './sessionLaunchDiagnostics.js';
8
11
  /** Quote each configured argument as literal shell data, including paths. */
9
12
  export function integrationLaunchCommand(record, restore) {
10
13
  const launchArgs = record.profile.argv.map(arg => arg === '{cwd}' ? record.cwd : arg);
@@ -20,8 +23,9 @@ function startupInput(record, now) {
20
23
  return condition ? { state: 'pending', deadline: now + (condition.timeoutMs ?? 120000), matched_since: null, observed_at: null } : undefined;
21
24
  }
22
25
  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 } : {}) };
26
+ const { profile: _, deadline: _deadline, launch_submitted: _submitted, startup_condition: _condition, restore_diagnostics: diagnostics, launch_diagnostics: launchDiagnostics, launch_diagnostics_history: _history, message_history_seen: _messages, close_intent: _closeIntent, ...publicRecord } = record;
27
+ return { ...publicRecord, close_pending: !!_closeIntent, ...(diagnostics ? { restore_diagnostics_available: true } : {}),
28
+ ...(launchDiagnostics ? { launch_diagnostics_available: true } : {}) };
25
29
  }
26
30
  export function permittedCwd(profile, cwd) {
27
31
  if (typeof cwd !== 'string' || !path.isAbsolute(cwd) || /[\x00-\x1f\x7f]/.test(cwd))
@@ -56,6 +60,8 @@ export class IntegrationSessions {
56
60
  listeners = new Set();
57
61
  lifecycle = new SessionLifecycleCoordinator();
58
62
  mutations = new Map();
63
+ coldRetries = new Set();
64
+ closingOperations = new Set();
59
65
  timers = new Set();
60
66
  stopObservation;
61
67
  stopDeliveryGuard;
@@ -80,7 +86,7 @@ export class IntegrationSessions {
80
86
  record.runtime_present ??= null;
81
87
  }
82
88
  for (const record of this.doc.sessions)
83
- if (['starting', 'restoring', 'binding_pending'].includes(record.state) || record.state === 'releasing' || record.startup_input?.state === 'pending')
89
+ if (['starting', 'restoring', 'binding_pending'].includes(record.state) || ['releasing', 'closing'].includes(record.state) || record.startup_input?.state === 'pending')
84
90
  this.scheduleRefresh(record);
85
91
  // A pre-restart partial match cannot prove continuity of the live screen.
86
92
  for (const record of this.doc.sessions)
@@ -111,7 +117,9 @@ export class IntegrationSessions {
111
117
  }
112
118
  saveRecord(record) {
113
119
  const before = this.doc.sessions;
114
- this.doc.sessions = [...before.filter(s => s.session_id !== record.session_id), structuredClone(record)];
120
+ const seen = before.find(s => s.session_id === record.session_id)?.message_history_seen;
121
+ this.doc.sessions = [...before.filter(s => s.session_id !== record.session_id), structuredClone({ ...record,
122
+ ...(seen ? { message_history_seen: true } : {}) })];
115
123
  try {
116
124
  this.save();
117
125
  }
@@ -154,7 +162,8 @@ export class IntegrationSessions {
154
162
  const now = Date.now(), record = { operation_id: randomUUID(), session_id: randomBytes(6).toString('hex'),
155
163
  group_id: principal.groupId, principal_id: principal.id, agent_slug: profile.agentSlug, agent_native_session_id: null,
156
164
  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 };
165
+ created_at: now, updated_at: now, deadline: now + this.bindingTimeout, launch_submitted: false, message_history_seen: false };
166
+ record.launch_diagnostics = beginLaunchDiagnostics(record.operation_id, 1, 'cold_start');
158
167
  record.startup_input = startupInput(record, now);
159
168
  this.doc.requests[request.scoped] = { hash: request.hash, sessionId: record.session_id };
160
169
  try {
@@ -166,7 +175,7 @@ export class IntegrationSessions {
166
175
  }
167
176
  return this.launch(record, false);
168
177
  }
169
- launch(record, restoring) {
178
+ launch(record, restoring, retryCold = false) {
170
179
  const promise = (async () => {
171
180
  try {
172
181
  // Store intent before launching. A failed persistence cannot execute.
@@ -181,17 +190,29 @@ export class IntegrationSessions {
181
190
  catch (error) {
182
191
  // Existing creation supports plugins without an exact resume path.
183
192
  // They remain launchable, but cannot gain a releasable descriptor.
184
- if (restoring || error.code !== 'EXACT_RESUME_UNSUPPORTED')
193
+ if (restoring || retryCold || error.code !== 'EXACT_RESUME_UNSUPPORTED')
185
194
  throw error;
186
195
  }
187
196
  }
188
197
  record.launch_submitted = true;
189
198
  this.saveRecord(record);
199
+ const progress = (phase) => {
200
+ const latest = this.doc.sessions.find(s => s.session_id === record.session_id);
201
+ if (latest.operation_id !== record.operation_id || latest.generation !== record.generation)
202
+ integrationError('SESSION_GENERATION_MISMATCH', 'Launch operation changed during progress recording', 409);
203
+ if (latest.launch_diagnostics) {
204
+ record.launch_diagnostics = launchProgress(latest.launch_diagnostics, phase);
205
+ this.saveRecord({ ...latest, launch_diagnostics: record.launch_diagnostics });
206
+ }
207
+ };
190
208
  const prepared = (binding) => { record.terminal_binding = binding; this.saveRecord(record); };
191
- if (restoring)
192
- await this.adapter.restore(record, prepared);
209
+ if (retryCold)
210
+ await this.adapter.retryCold(record, prepared, progress);
211
+ else if (restoring)
212
+ await this.adapter.restore(record, prepared, progress);
193
213
  else
194
- await this.adapter.create(record, prepared);
214
+ await this.adapter.create(record, prepared, progress);
215
+ progress('binding_observe');
195
216
  await this.refresh(record.session_id);
196
217
  this.scheduleRefresh(record);
197
218
  }
@@ -199,6 +220,7 @@ export class IntegrationSessions {
199
220
  const current = this.doc.sessions.find(s => s.session_id === record.session_id);
200
221
  const code = error.code;
201
222
  this.saveRecord({ ...current, state: 'failed', error_code: typeof code === 'string' ? code : 'SESSION_LAUNCH_FAILED',
223
+ launch_diagnostics: current.launch_diagnostics ? launchFailure(current.launch_diagnostics, error, typeof code === 'string' ? code : 'SESSION_LAUNCH_FAILED') : undefined,
202
224
  restore_diagnostics: error instanceof NativeResumeOwnerError ? { ...structuredClone(error.diagnostics), operation_id: current.operation_id } : undefined,
203
225
  updated_at: Date.now() });
204
226
  }
@@ -216,10 +238,33 @@ export class IntegrationSessions {
216
238
  return structuredClone({ session_id: record.session_id, operation_id: record.operation_id,
217
239
  state: record.state, error_code: record.error_code, diagnostics: record.restore_diagnostics ?? null });
218
240
  }
219
- assertRuntimeMessage(id) { assertMessageRuntime(this.doc.sessions.find(s => s.session_id === id)); }
241
+ launchDiagnostics(id) {
242
+ const record = this.doc.sessions.find(s => s.session_id === id);
243
+ if (!record)
244
+ return integrationError('INTEGRATION_SESSION_NOT_FOUND', 'Integration session does not exist', 404);
245
+ return structuredClone({ launch_diagnostics: record.launch_diagnostics ?? null,
246
+ launch_diagnostics_history: record.launch_diagnostics_history ?? [] });
247
+ }
248
+ assertRuntimeMessage(id) {
249
+ const record = this.doc.sessions.find(s => s.session_id === id);
250
+ if (this.closingOperations.has(id))
251
+ integrationError('SESSION_OPERATION_IN_PROGRESS', 'Session close preflight is in progress', 409);
252
+ if (this.coldRetries.has(id) || record?.cold_retry_pending)
253
+ integrationError('SESSION_OPERATION_IN_PROGRESS', 'Cold retry must finish or be reconciled before sending', 409);
254
+ if (record?.state === 'closing' && !record.operation_uncertain)
255
+ integrationError('SESSION_OPERATION_IN_PROGRESS', 'Session close is in progress', 409);
256
+ if (record?.close_intent)
257
+ integrationError('OPERATION_OUTCOME_UNCONFIRMED', 'Close outcome requires reconciliation', 409);
258
+ assertMessageRuntime(record);
259
+ // Durable, conservative latch before admission; even a later enqueue
260
+ // failure cannot make a previously attempted business request disappear.
261
+ if (record && !record.message_history_seen)
262
+ this.saveRecord({ ...record, message_history_seen: true });
263
+ }
220
264
  assertMessageTarget(principal, id) {
221
265
  const record = this.doc.sessions.find(s => s.session_id === id && s.group_id === principal.groupId);
222
- assertMessageRuntime(record);
266
+ if (record)
267
+ this.assertRuntimeMessage(id);
223
268
  }
224
269
  async mutate(principal, key, input, action) {
225
270
  const request = this.request(principal, key, input);
@@ -259,6 +304,76 @@ export class IntegrationSessions {
259
304
  async restore(principal, id, key) {
260
305
  return this.mutate(principal, key, ['restore', id], () => this.lifecycle.run(id, () => this.restoreOnce(principal, id, key)));
261
306
  }
307
+ async retryCold(principal, id, generation, key) {
308
+ return this.mutate(principal, key, ['retry-cold', id, generation], () => this.lifecycle.run(id, async () => {
309
+ const request = this.request(principal, key, ['retry-cold', id, generation]);
310
+ if (request.previous)
311
+ return this.replayRequest(principal, id, request.previous);
312
+ this.assertManagementSettled(this.lookup(principal, id));
313
+ if (!this.adapter.retryCold || !this.adapter.messageHistory)
314
+ integrationError('SESSION_COLD_RETRY_UNSUPPORTED', 'Runtime adapter does not support verified cold retry', 409);
315
+ if (this.pending.has(id))
316
+ integrationError('SESSION_OPERATION_IN_PROGRESS', 'Launch is in progress', 409);
317
+ this.coldRetries.add(id);
318
+ try {
319
+ const record = await this.get(principal, id);
320
+ this.assertManagementSettled(record);
321
+ assertReleaseGeneration(record, generation);
322
+ if (record.cold_retry_pending || record.operation_uncertain)
323
+ integrationError('OPERATION_OUTCOME_UNCONFIRMED', 'Reconcile prior lifecycle outcome before cold retry', 409);
324
+ if (record.agent_native_session_id)
325
+ integrationError('SESSION_COLD_RETRY_NATIVE_BOUND', 'Use exact native restore for a bound session', 409);
326
+ if (record.state !== 'failed')
327
+ integrationError('SESSION_COLD_RETRY_NOT_FAILED', 'Only failed unbound cold starts can be retried', 409);
328
+ const history = this.adapter.messageHistory(id);
329
+ if (history === null)
330
+ integrationError('SESSION_MESSAGE_HISTORY_UNCONFIRMED', 'Message history cannot be verified', 409);
331
+ if (record.message_history_seen || history || this.adapter.pendingMessages?.(id))
332
+ integrationError('SESSION_MESSAGE_HISTORY_PRESENT', 'Cold retry refuses any TD business message history or attempted admission', 409);
333
+ const authorized = principal.launchProfiles.find(p => p.id === record.launch_profile);
334
+ if (!authorized)
335
+ integrationError('LAUNCH_PROFILE_DENIED', 'Original launch profile is no longer authorized', 403);
336
+ permittedCwd(authorized, record.cwd);
337
+ permittedCwd(record.profile, record.cwd);
338
+ if (!record.resume_configuration_fingerprint)
339
+ integrationError('RESUME_CONFIGURATION_UNCONFIRMED', 'Administrator must confirm the launcher/plugin fingerprint', 409);
340
+ if (record.resume_configuration_fingerprint !== await resumeConfigurationFingerprint(record, this.adapter))
341
+ integrationError('RESUME_CONFIGURATION_CHANGED', 'Launcher/plugin configuration changed', 409);
342
+ const observed = await this.adapter.inspect(record);
343
+ if (!record.terminal_binding || !observed.exists || observed.running || !observed.shell || observed.nativeId)
344
+ integrationError('SESSION_COLD_RETRY_RUNTIME_UNCONFIRMED', 'Retry requires the exact original, exited foreground shell', 409);
345
+ record.launch_diagnostics_history = [...(record.launch_diagnostics_history ?? []), ...(record.launch_diagnostics ? [record.launch_diagnostics] : [])].slice(-16);
346
+ record.generation = generation + 1;
347
+ record.operation_id = randomUUID();
348
+ record.state = 'starting';
349
+ record.error_code = null;
350
+ record.cold_retry_pending = true;
351
+ record.cold_retry_count = (record.cold_retry_count ?? 0) + 1;
352
+ record.runtime_present = true;
353
+ record.launch_submitted = false;
354
+ record.updated_at = Date.now();
355
+ record.deadline = Date.now() + this.bindingTimeout;
356
+ record.restore_diagnostics = undefined;
357
+ record.startup_input = startupInput(record, Date.now());
358
+ record.launch_diagnostics = beginLaunchDiagnostics(record.operation_id, record.generation, 'cold_retry');
359
+ this.doc.requests[request.scoped] = { hash: request.hash, sessionId: id, operationId: record.operation_id, generation: record.generation };
360
+ try {
361
+ this.saveRecord(record);
362
+ }
363
+ catch (error) {
364
+ delete this.doc.requests[request.scoped];
365
+ throw error;
366
+ }
367
+ const result = await this.launch(record, false, true);
368
+ result.cold_retry_pending = false;
369
+ this.saveRecord(result);
370
+ return result;
371
+ }
372
+ finally {
373
+ this.coldRetries.delete(id);
374
+ }
375
+ }));
376
+ }
262
377
  async restoreOnce(principal, id, idempotencyKey) {
263
378
  const request = this.request(principal, idempotencyKey, ['restore', id]);
264
379
  if (request.previous)
@@ -268,6 +383,9 @@ export class IntegrationSessions {
268
383
  let releaseNative;
269
384
  try {
270
385
  const record = await this.get(principal, id);
386
+ this.assertManagementSettled(record);
387
+ if (record.cold_retry_pending)
388
+ integrationError('OPERATION_OUTCOME_UNCONFIRMED', 'Reconcile the cold retry before native restore', 409);
271
389
  if (!record.agent_native_session_id)
272
390
  integrationError('NATIVE_SESSION_ID_MISSING', 'An exact native session binding is required', 409);
273
391
  // Recheck the current grant and actual directories; restore uses the
@@ -310,6 +428,8 @@ export class IntegrationSessions {
310
428
  record.deadline = Date.now() + this.bindingTimeout;
311
429
  record.updated_at = Date.now();
312
430
  record.restore_diagnostics = undefined;
431
+ record.launch_diagnostics_history = [...(record.launch_diagnostics_history ?? []), ...(record.launch_diagnostics ? [record.launch_diagnostics] : [])].slice(-16);
432
+ record.launch_diagnostics = beginLaunchDiagnostics(record.operation_id, record.generation, 'native_restore');
313
433
  if (!record.startup_input_disabled && !record.profile.startupInput && !record.startup_condition)
314
434
  record.startup_condition = structuredClone(principal.launchProfiles.find(profile => profile.id === record.launch_profile)?.startupInput);
315
435
  record.startup_input = startupInput(record, Date.now());
@@ -339,6 +459,7 @@ export class IntegrationSessions {
339
459
  const record = structuredClone(this.doc.sessions.find(s => s.session_id === id));
340
460
  if (!record)
341
461
  return integrationError('INTEGRATION_SESSION_NOT_FOUND', 'Recovery record does not exist', 404);
462
+ this.assertManagementSettled(record);
342
463
  assertReleaseGeneration(record, generation);
343
464
  if (this.pending.has(id) || record.operation_uncertain || ['starting', 'restoring', 'binding_pending', 'releasing'].includes(record.state)) {
344
465
  integrationError('SESSION_OPERATION_IN_PROGRESS', 'Resolve the current lifecycle operation before clearing startup input conditions', 409);
@@ -360,6 +481,7 @@ export class IntegrationSessions {
360
481
  const record = structuredClone(this.doc.sessions.find(s => s.session_id === id));
361
482
  if (!record)
362
483
  return integrationError('INTEGRATION_SESSION_NOT_FOUND', 'Recovery record does not exist', 404);
484
+ this.assertManagementSettled(record);
363
485
  assertReleaseGeneration(record, generation);
364
486
  if (this.pending.has(id) || ['starting', 'restoring', 'binding_pending', 'releasing'].includes(record.state))
365
487
  integrationError('SESSION_OPERATION_IN_PROGRESS', 'Resolve the current operation before confirming compatibility', 409);
@@ -372,16 +494,145 @@ export class IntegrationSessions {
372
494
  return record;
373
495
  });
374
496
  }
497
+ assertManagementSettled(record) {
498
+ if (record.state === 'closed')
499
+ integrationError('SESSION_CLOSED', 'Explicitly closed sessions cannot be restored or restarted', 409);
500
+ if (record.state === 'closing' && !record.operation_uncertain)
501
+ integrationError('SESSION_OPERATION_IN_PROGRESS', 'Session close is in progress', 409);
502
+ if (record.close_intent || record.state === 'closing')
503
+ integrationError('OPERATION_OUTCOME_UNCONFIRMED', 'Reconcile the pending close before any lifecycle operation', 409);
504
+ if (record.rename_pending)
505
+ integrationError('SESSION_RENAME_SYNC_PENDING', 'Read session get to reconcile the pending name update', 409);
506
+ }
507
+ assertManagementIdle(record) {
508
+ if (this.pending.has(record.session_id) || record.cold_retry_pending || record.operation_uncertain || ['starting', 'restoring', 'binding_pending', 'releasing', 'closing'].includes(record.state)) {
509
+ integrationError('SESSION_OPERATION_IN_PROGRESS', 'Resolve the current lifecycle operation first', 409);
510
+ }
511
+ }
512
+ async rename(principal, id, generation, value, key) {
513
+ if (typeof value !== 'string')
514
+ integrationError('INVALID_NAME', 'name must be non-empty text up to 80 characters');
515
+ const name = cleanMemberName(value);
516
+ if (!name)
517
+ integrationError('INVALID_NAME', 'name must be non-empty text up to 80 characters');
518
+ return this.mutate(principal, key, ['rename', id, generation, name], () => this.lifecycle.run(id, async () => {
519
+ const request = this.request(principal, key, ['rename', id, generation, name]);
520
+ if (request.previous)
521
+ return this.replayRequest(principal, id, request.previous);
522
+ if (!this.adapter.rename)
523
+ integrationError('SESSION_RENAME_UNSUPPORTED', 'Runtime adapter does not support renaming', 409);
524
+ const record = await this.get(principal, id);
525
+ assertReleaseGeneration(record, generation);
526
+ if (record.close_intent || record.rename_pending)
527
+ integrationError('SESSION_OPERATION_IN_PROGRESS', 'Resolve the pending management operation first', 409);
528
+ this.assertManagementIdle(record);
529
+ await this.adapter.prepareRename?.(record);
530
+ record.name = name;
531
+ record.name_updated_at = Date.now();
532
+ record.updated_at = record.name_updated_at;
533
+ record.generation = generation + 1;
534
+ record.name_generation = record.generation;
535
+ record.name_operation_id = record.operation_id;
536
+ record.rename_pending = true;
537
+ this.doc.requests[request.scoped] = { hash: request.hash, sessionId: id, operationId: record.operation_id, generation: record.generation };
538
+ try {
539
+ this.saveRecord(record);
540
+ }
541
+ catch (error) {
542
+ delete this.doc.requests[request.scoped];
543
+ throw error;
544
+ }
545
+ try {
546
+ await this.adapter.rename(record);
547
+ record.rename_pending = false;
548
+ this.saveRecord(record);
549
+ }
550
+ catch { /* Durable intent is retried by get/restart; no runtime is created. */ }
551
+ return this.lookup(principal, id);
552
+ }));
553
+ }
554
+ async closeSession(principal, id, generation, key) {
555
+ return this.mutate(principal, key, ['close', id, generation], () => this.lifecycle.run(id, async () => {
556
+ const request = this.request(principal, key, ['close', id, generation]);
557
+ if (request.previous)
558
+ return this.replayRequest(principal, id, request.previous);
559
+ this.closingOperations.add(id);
560
+ try {
561
+ if (!this.adapter.prepareClose || !this.adapter.closeRuntime || !this.adapter.runtimePresent)
562
+ integrationError('SESSION_CLOSE_UNSUPPORTED', 'Runtime adapter does not support closing', 409);
563
+ const record = await this.get(principal, id);
564
+ assertReleaseGeneration(record, generation);
565
+ if (record.close_intent || record.rename_pending)
566
+ integrationError('OPERATION_OUTCOME_UNCONFIRMED', 'Read session get to reconcile prior management intent', 409);
567
+ this.assertManagementIdle(record);
568
+ if (record.state === 'closed') {
569
+ if (await this.adapter.runtimePresent(record))
570
+ integrationError('OPERATION_OUTCOME_UNCONFIRMED', 'Unexpected runtime exists for a closed record', 409);
571
+ this.doc.requests[request.scoped] = { hash: request.hash, sessionId: id, operationId: record.operation_id, generation: record.generation };
572
+ try {
573
+ this.save();
574
+ }
575
+ catch (error) {
576
+ delete this.doc.requests[request.scoped];
577
+ throw error;
578
+ }
579
+ return record;
580
+ }
581
+ if (this.adapter.pendingMessages?.(id))
582
+ integrationError('SESSION_PENDING_MESSAGES', 'Pending messages must be resolved before closing', 409);
583
+ const target = await this.adapter.prepareClose(record);
584
+ record.operation_id = randomUUID();
585
+ record.generation = generation + 1;
586
+ record.state = 'closing';
587
+ record.close_intent = { operation_id: record.operation_id, target };
588
+ record.error_code = null;
589
+ record.operation_uncertain = false;
590
+ record.updated_at = Date.now();
591
+ this.doc.requests[request.scoped] = { hash: request.hash, sessionId: id, operationId: record.operation_id, generation: record.generation };
592
+ try {
593
+ this.saveRecord(record);
594
+ }
595
+ catch (error) {
596
+ delete this.doc.requests[request.scoped];
597
+ throw error;
598
+ }
599
+ try {
600
+ await this.adapter.closeRuntime(record, false);
601
+ if (await this.adapter.runtimePresent(record))
602
+ integrationError('OPERATION_OUTCOME_UNCONFIRMED', 'Runtime removal cannot be confirmed', 409);
603
+ record.state = 'closed';
604
+ record.runtime_present = false;
605
+ record.terminal_binding = null;
606
+ record.startup_input = undefined;
607
+ record.close_intent = undefined;
608
+ }
609
+ catch (error) {
610
+ record.state = 'failed';
611
+ record.operation_uncertain = true;
612
+ record.runtime_present = null;
613
+ record.error_code = typeof error.code === 'string' ? error.code : 'SESSION_CLOSE_FAILED';
614
+ }
615
+ record.updated_at = Date.now();
616
+ this.saveRecord(record);
617
+ return record;
618
+ }
619
+ finally {
620
+ this.closingOperations.delete(id);
621
+ }
622
+ }));
623
+ }
375
624
  async release(principal, id, generation, key) {
376
625
  return this.mutate(principal, key, ['release', id, generation], () => this.lifecycle.run(id, async () => {
377
626
  const request = this.request(principal, key, ['release', id, generation]);
378
627
  if (request.previous)
379
628
  return this.replayRequest(principal, id, request.previous);
629
+ this.assertManagementSettled(this.lookup(principal, id));
380
630
  if (!this.adapter.release || !this.adapter.runtimePresent)
381
631
  integrationError('SESSION_RELEASE_UNSUPPORTED', 'Runtime adapter does not support release', 409);
382
632
  if (this.pending.has(id))
383
633
  integrationError('SESSION_OPERATION_IN_PROGRESS', 'Launch is in progress', 409);
384
634
  const record = await this.get(principal, id);
635
+ this.assertManagementSettled(record);
385
636
  assertReleaseGeneration(record, generation);
386
637
  if (record.state !== 'released') {
387
638
  assertReleaseFacts(record, await this.adapter.inspect(record));
@@ -443,6 +694,54 @@ export class IntegrationSessions {
443
694
  const record = structuredClone(this.doc.sessions.find(s => s.session_id === id));
444
695
  if (!record)
445
696
  return;
697
+ if (record.rename_pending) {
698
+ if (this.lifecycle.active(id))
699
+ return;
700
+ try {
701
+ await this.lifecycle.run(id, async () => {
702
+ if (!this.adapter.rename)
703
+ return;
704
+ await this.adapter.rename(record);
705
+ if (JSON.stringify(this.doc.sessions.find(s => s.session_id === id)) !== JSON.stringify(record))
706
+ return;
707
+ record.rename_pending = false;
708
+ this.saveRecord(record);
709
+ });
710
+ }
711
+ catch { /* Keep the persisted intent for a later get/restart. */ }
712
+ return;
713
+ }
714
+ if (record.state === 'closed' || record.state === 'closing' || record.close_intent) {
715
+ if (this.lifecycle.active(id))
716
+ return;
717
+ try {
718
+ if (record.state !== 'closed') {
719
+ if (!this.adapter.closeRuntime)
720
+ integrationError('SESSION_CLOSE_UNSUPPORTED', 'Close reconciliation is unavailable', 409);
721
+ await this.adapter.closeRuntime(record, true);
722
+ }
723
+ if (!this.adapter.runtimePresent || await this.adapter.runtimePresent(record))
724
+ integrationError('OPERATION_OUTCOME_UNCONFIRMED', 'Runtime exists for a closed or closing session', 409);
725
+ const next = { ...record, state: 'closed', runtime_present: false, terminal_binding: null, close_intent: undefined,
726
+ operation_uncertain: false, error_code: null, startup_input: undefined };
727
+ if (JSON.stringify(this.doc.sessions.find(s => s.session_id === id)) !== JSON.stringify(record))
728
+ return;
729
+ if (JSON.stringify(next) !== JSON.stringify(record))
730
+ this.saveRecord({ ...next, updated_at: Date.now() });
731
+ }
732
+ catch (error) {
733
+ if (JSON.stringify(this.doc.sessions.find(s => s.session_id === id)) !== JSON.stringify(record))
734
+ return;
735
+ // Keep closed terminal, and keep unresolved intent fenced. Never kill on refresh.
736
+ const next = { ...record, runtime_present: null, operation_uncertain: true,
737
+ error_code: typeof error.code === 'string' ? error.code : 'OPERATION_OUTCOME_UNCONFIRMED' };
738
+ if (JSON.stringify(next) !== JSON.stringify(record))
739
+ this.saveRecord({ ...next, updated_at: Date.now() });
740
+ }
741
+ return;
742
+ }
743
+ if (record.cold_retry_pending && (this.lifecycle.active(id) || this.pending.has(id)))
744
+ return;
446
745
  if (record.state === 'released' || record.state === 'releasing' || record.operation_uncertain) {
447
746
  if (this.lifecycle.active(id))
448
747
  return;
@@ -483,8 +782,10 @@ export class IntegrationSessions {
483
782
  if (JSON.stringify(current) !== JSON.stringify(record))
484
783
  return;
485
784
  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() });
785
+ const errorCode = typeof code === 'string' ? code : 'SESSION_OBSERVATION_FAILED';
786
+ if (record.state !== 'failed' || record.error_code !== errorCode)
787
+ this.saveRecord({ ...record, state: 'failed', error_code: errorCode,
788
+ launch_diagnostics: record.launch_diagnostics ? launchFailure(record.launch_diagnostics, error, errorCode) : undefined, updated_at: Date.now() });
488
789
  return;
489
790
  }
490
791
  const next = { ...record, runtime_present: this.adapter.runtimePresent ? await this.adapter.runtimePresent(record) : observed.exists };
@@ -521,6 +822,27 @@ export class IntegrationSessions {
521
822
  next.state = 'failed';
522
823
  next.error_code = 'SESSION_BINDING_TIMEOUT';
523
824
  }
825
+ if (record.cold_retry_pending) {
826
+ if (next.state === 'ready')
827
+ next.cold_retry_pending = false;
828
+ else if (record.terminal_binding && observed.exists && !observed.running && observed.shell && !observed.nativeId) {
829
+ next.state = 'failed';
830
+ next.error_code = 'SESSION_COLD_RETRY_INTERRUPTED';
831
+ next.cold_retry_pending = false;
832
+ if (next.launch_diagnostics)
833
+ next.launch_diagnostics = launchProgress(next.launch_diagnostics, 'reconciled_shell');
834
+ }
835
+ else if (!observed.exists) {
836
+ next.state = 'failed';
837
+ next.error_code = 'SESSION_COLD_RETRY_RUNTIME_UNCONFIRMED';
838
+ }
839
+ }
840
+ if (next.launch_diagnostics) {
841
+ next.launch_diagnostics = { ...next.launch_diagnostics, runtime_exists: observed.exists };
842
+ if (next.state === 'failed' && next.error_code && (record.state !== 'failed' || record.error_code !== next.error_code)) {
843
+ next.launch_diagnostics = launchFailure(next.launch_diagnostics, new CollaborationError(next.error_code, '', 409), next.error_code);
844
+ }
845
+ }
524
846
  if (next.startup_input && next.startup_input.state !== 'observed') {
525
847
  const condition = next.startup_condition ?? next.profile.startupInput;
526
848
  let matched = false;
@@ -554,6 +876,12 @@ export class IntegrationSessions {
554
876
  const existing = this.doc.sessions.find(record => record.session_id === id);
555
877
  if (!existing)
556
878
  return null;
879
+ if (this.closingOperations.has(id))
880
+ return { allowed: false, reason: 'SESSION_OPERATION_IN_PROGRESS' };
881
+ if (existing.state === 'closed')
882
+ return { allowed: false, reason: 'SESSION_CLOSED' };
883
+ if (existing.close_intent || existing.state === 'closing')
884
+ return { allowed: false, reason: 'SESSION_OPERATION_IN_PROGRESS' };
557
885
  if (existing.state === 'released' || existing.state === 'releasing' || existing.operation_uncertain)
558
886
  return { allowed: false, reason: existing.state === 'released' ? 'SESSION_RELEASED' : 'SESSION_OPERATION_IN_PROGRESS' };
559
887
  if (!existing.startup_input)
@@ -3,7 +3,7 @@ import path from 'node:path';
3
3
  import { createHash, randomBytes, randomUUID, timingSafeEqual } from 'node:crypto';
4
4
  import { CollaborationError } from './collaborationProtocol.js';
5
5
  export const INTEGRATION_PROTOCOL = 1;
6
- export const INTEGRATION_OPERATIONS = ['message.send', 'message.read', 'task.read', 'task.create', 'task.configure', 'task.assign', 'task.comment', 'task.revise', 'task.answer', 'events.read', 'session.create', 'session.read', 'session.restore', 'session.release'];
6
+ export const INTEGRATION_OPERATIONS = ['message.send', 'message.read', 'task.read', 'task.create', 'task.configure', 'task.assign', 'task.comment', 'task.revise', 'task.answer', 'events.read', 'session.create', 'session.read', 'session.restore', 'session.release', 'session.rename', 'session.close'];
7
7
  export function integrationError(code, message, status = 400) { throw new CollaborationError(code, message, status); }
8
8
  export function atomicJson(file, value) {
9
9
  fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
@@ -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
+ }
@@ -50,6 +50,10 @@ export function assertReleaseFacts(record, facts) {
50
50
  export function assertMessageRuntime(record) {
51
51
  if (!record)
52
52
  return;
53
+ if (record.state === 'closed')
54
+ fail('SESSION_CLOSED', 'Session was explicitly closed; it cannot be sent to or restored');
55
+ if (record.state === 'closing')
56
+ fail('SESSION_OPERATION_IN_PROGRESS', 'Session close is in progress');
53
57
  if (record.state === 'released')
54
58
  fail('SESSION_RELEASED', 'Runtime was released; explicitly restore this session before sending');
55
59
  if (record.state === 'releasing')