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.
- package/dist/client/assets/{App-ChS2-lkz.js → App-B2SFV3qg.js} +53 -53
- package/dist/client/assets/App-B2SFV3qg.js.br +0 -0
- package/dist/client/assets/App-B2SFV3qg.js.gz +0 -0
- package/dist/client/assets/{ArchitecturePanel-JtjyyJoW.js → ArchitecturePanel-Cj7za6DZ.js} +6 -6
- package/dist/client/assets/ArchitecturePanel-Cj7za6DZ.js.br +0 -0
- package/dist/client/assets/ArchitecturePanel-Cj7za6DZ.js.gz +0 -0
- package/dist/client/assets/{ChangeWalkthroughPanel-BlQ5-VPp.js → ChangeWalkthroughPanel-BB52iLLC.js} +2 -2
- package/dist/client/assets/ChangeWalkthroughPanel-BB52iLLC.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-BB52iLLC.js.gz +0 -0
- package/dist/client/assets/{CollaborationMainWorkspace-aFLAMqDr.js → CollaborationMainWorkspace-D5WKV3rA.js} +1 -1
- package/dist/client/assets/CollaborationMainWorkspace-D5WKV3rA.js.br +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-D5WKV3rA.js.gz +0 -0
- package/dist/client/assets/CollaborationTaskContent-MwUgcmG_.js +2 -0
- package/dist/client/assets/ComputerControlView-Dkc4R1IU.js +5 -0
- package/dist/client/assets/ComputerControlView-Dkc4R1IU.js.br +0 -0
- package/dist/client/assets/ComputerControlView-Dkc4R1IU.js.gz +0 -0
- package/dist/client/assets/{DagPlayground-CR4uDFOx.js → DagPlayground-BHY3l8UG.js} +1 -1
- package/dist/client/assets/DagPlayground-BHY3l8UG.js.br +0 -0
- package/dist/client/assets/DagPlayground-BHY3l8UG.js.gz +0 -0
- package/dist/client/assets/{DiffLab-BqeHMDOy.js → DiffLab-BSQiKfBJ.js} +1 -1
- package/dist/client/assets/DiffLab-BSQiKfBJ.js.br +0 -0
- package/dist/client/assets/DiffLab-BSQiKfBJ.js.gz +0 -0
- package/dist/client/assets/{DiffReview-DqrOcRfP.js → DiffReview-CYrBBq0V.js} +1 -1
- package/dist/client/assets/DiffReview-CYrBBq0V.js.br +0 -0
- package/dist/client/assets/DiffReview-CYrBBq0V.js.gz +0 -0
- package/dist/client/assets/{DiffReviewLab-CEYpbrL6.js → DiffReviewLab-VSIbEnxm.js} +1 -1
- package/dist/client/assets/DiffReviewLab-VSIbEnxm.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-VSIbEnxm.js.gz +0 -0
- package/dist/client/assets/{DiffViewer-F-uQSmhG.js → DiffViewer-Cx5fyiMB.js} +8 -8
- package/dist/client/assets/DiffViewer-Cx5fyiMB.js.br +0 -0
- package/dist/client/assets/DiffViewer-Cx5fyiMB.js.gz +0 -0
- package/dist/client/assets/{ModelPreview-KmXFkgij.js → ModelPreview-B22odexG.js} +1 -1
- package/dist/client/assets/ModelPreview-B22odexG.js.br +0 -0
- package/dist/client/assets/ModelPreview-B22odexG.js.gz +0 -0
- package/dist/client/assets/{RightSidebar-VMdXpo4h.js → RightSidebar-DKA0jXPW.js} +3 -3
- package/dist/client/assets/RightSidebar-DKA0jXPW.js.br +0 -0
- package/dist/client/assets/RightSidebar-DKA0jXPW.js.gz +0 -0
- package/dist/client/assets/{abnfDiagram-VCTEODGH-CAMk1C0N.js → abnfDiagram-VCTEODGH-sbUSsiPn.js} +1 -1
- package/dist/client/assets/abnfDiagram-VCTEODGH-sbUSsiPn.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-sbUSsiPn.js.gz +0 -0
- package/dist/client/assets/app-CYOLJycb.js +35 -0
- package/dist/client/assets/app-CYOLJycb.js.br +0 -0
- package/dist/client/assets/app-CYOLJycb.js.gz +0 -0
- package/dist/client/assets/{arc-CYG_-1vC.js → arc-GhJ9aeQ3.js} +1 -1
- package/dist/client/assets/arc-GhJ9aeQ3.js.br +0 -0
- package/dist/client/assets/arc-GhJ9aeQ3.js.gz +0 -0
- package/dist/client/assets/{architectureDiagram-5GKGNRK7-BqHzezLR.js → architectureDiagram-5GKGNRK7-BYmAIJBx.js} +1 -1
- package/dist/client/assets/architectureDiagram-5GKGNRK7-BYmAIJBx.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-BYmAIJBx.js.gz +0 -0
- package/dist/client/assets/{blockDiagram-I7D4REHJ-D6GWRO_Z.js → blockDiagram-I7D4REHJ-CZNZT_ez.js} +1 -1
- package/dist/client/assets/blockDiagram-I7D4REHJ-CZNZT_ez.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-CZNZT_ez.js.gz +0 -0
- package/dist/client/assets/{c4Diagram-7LVT6UL2-CutmGIGb.js → c4Diagram-7LVT6UL2-6xcSowLn.js} +1 -1
- package/dist/client/assets/c4Diagram-7LVT6UL2-6xcSowLn.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-6xcSowLn.js.gz +0 -0
- package/dist/client/assets/channel-C1FwyjiU.js +1 -0
- package/dist/client/assets/{chunk-2Q5K7J3B-DwiUpGFu.js → chunk-2Q5K7J3B-C06nkhUQ.js} +1 -1
- package/dist/client/assets/{chunk-5VM5RSS4-C35gLPSH.js → chunk-5VM5RSS4-BHY43hJO.js} +1 -1
- package/dist/client/assets/{chunk-F27PBJKO-CNptP19P.js → chunk-F27PBJKO-Dl8JYcZO.js} +1 -1
- package/dist/client/assets/chunk-F27PBJKO-Dl8JYcZO.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-Dl8JYcZO.js.gz +0 -0
- package/dist/client/assets/{chunk-IMKFNOWR-DHdpB9A0.js → chunk-IMKFNOWR-BALi4Q3g.js} +1 -1
- package/dist/client/assets/chunk-IMKFNOWR-BALi4Q3g.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-BALi4Q3g.js.gz +0 -0
- package/dist/client/assets/{chunk-JWPE2WC7-CrKSOzdE.js → chunk-JWPE2WC7-BBD2d7j7.js} +1 -1
- package/dist/client/assets/{chunk-POPQ4Y6H-CiZGLRSk.js → chunk-POPQ4Y6H-CZN0_ndj.js} +1 -1
- package/dist/client/assets/{chunk-SVP7TREG-B70pX8OB.js → chunk-SVP7TREG-CD-Zf9rn.js} +1 -1
- package/dist/client/assets/chunk-SVP7TREG-CD-Zf9rn.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-CD-Zf9rn.js.gz +0 -0
- package/dist/client/assets/{chunk-TICWLB2K-Ba1mI99F.js → chunk-TICWLB2K-Clpg1zwp.js} +1 -1
- package/dist/client/assets/chunk-TICWLB2K-Clpg1zwp.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-Clpg1zwp.js.gz +0 -0
- package/dist/client/assets/{chunk-XXDRQBXY-DmKIl18h.js → chunk-XXDRQBXY-BanPVnIr.js} +1 -1
- package/dist/client/assets/classDiagram-ZZMXUADV-FyKDan8T.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-FyKDan8T.js +1 -0
- package/dist/client/assets/{cose-bilkent-JH36ORCC-C-NMDUHW.js → cose-bilkent-JH36ORCC-431u7cfU.js} +1 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-431u7cfU.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-431u7cfU.js.gz +0 -0
- package/dist/client/assets/{cynefin-OW5HDTMX-CZgEc1ab.js → cynefin-OW5HDTMX-BuLFGx14.js} +1 -1
- package/dist/client/assets/cynefin-OW5HDTMX-BuLFGx14.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-BuLFGx14.js.gz +0 -0
- package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-CHQeSNm2.js → cynefinDiagram-5FMLGOSQ-qLzjwMMG.js} +1 -1
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-qLzjwMMG.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-qLzjwMMG.js.gz +0 -0
- package/dist/client/assets/{dagre-GXQ25YYZ-B_jkMdPS.js → dagre-GXQ25YYZ-CUdd5M5g.js} +1 -1
- package/dist/client/assets/dagre-GXQ25YYZ-CUdd5M5g.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-CUdd5M5g.js.gz +0 -0
- package/dist/client/assets/{diagram-S7CK7UJ4-nv6Lnsrp.js → diagram-S7CK7UJ4-DLQClBzm.js} +1 -1
- package/dist/client/assets/diagram-S7CK7UJ4-DLQClBzm.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-DLQClBzm.js.gz +0 -0
- package/dist/client/assets/{diagram-UQ7AKVKN-BZf2fzaA.js → diagram-UQ7AKVKN-1RGASXU_.js} +1 -1
- package/dist/client/assets/diagram-UQ7AKVKN-1RGASXU_.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-1RGASXU_.js.gz +0 -0
- package/dist/client/assets/{diagram-VSXAHHWV-CxL0_BH8.js → diagram-VSXAHHWV-DqnCzn2R.js} +1 -1
- package/dist/client/assets/diagram-VSXAHHWV-DqnCzn2R.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-DqnCzn2R.js.gz +0 -0
- package/dist/client/assets/{diagram-VX7I27RA-Dm9MqpIE.js → diagram-VX7I27RA-CMXsPqTS.js} +1 -1
- package/dist/client/assets/diagram-VX7I27RA-CMXsPqTS.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-CMXsPqTS.js.gz +0 -0
- package/dist/client/assets/{diagram-Z3DM3KII-BIfTa7P5.js → diagram-Z3DM3KII-BM0N1kCR.js} +1 -1
- package/dist/client/assets/diagram-Z3DM3KII-BM0N1kCR.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-BM0N1kCR.js.gz +0 -0
- package/dist/client/assets/{ebnfDiagram-PWID7BFC-D4XhCDFS.js → ebnfDiagram-PWID7BFC-CvaVo-wh.js} +1 -1
- package/dist/client/assets/ebnfDiagram-PWID7BFC-CvaVo-wh.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-CvaVo-wh.js.gz +0 -0
- package/dist/client/assets/{erDiagram-RLTQ6QDP-Dxd48dXC.js → erDiagram-RLTQ6QDP-okw-AY7i.js} +1 -1
- package/dist/client/assets/erDiagram-RLTQ6QDP-okw-AY7i.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-okw-AY7i.js.gz +0 -0
- package/dist/client/assets/{flowDiagram-HODETNUW-BXBMsEmE.js → flowDiagram-HODETNUW-B_DWtzOe.js} +1 -1
- package/dist/client/assets/flowDiagram-HODETNUW-B_DWtzOe.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-B_DWtzOe.js.gz +0 -0
- package/dist/client/assets/{ganttDiagram-EL5Y4UJY-CBfDd-KZ.js → ganttDiagram-EL5Y4UJY-Bm4nYUVg.js} +1 -1
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-Bm4nYUVg.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-Bm4nYUVg.js.gz +0 -0
- package/dist/client/assets/{gestureArbiter-DXLmNGli.js → gestureArbiter-XalN4TaN.js} +1 -1
- package/dist/client/assets/gestureArbiter-XalN4TaN.js.br +0 -0
- package/dist/client/assets/gestureArbiter-XalN4TaN.js.gz +0 -0
- package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-DtLM68fN.js → gitGraphDiagram-WWUBYQGX-B7LAo8S2.js} +1 -1
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-B7LAo8S2.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-B7LAo8S2.js.gz +0 -0
- package/dist/client/assets/{index-KuPaZyuZ.css → index-BObjbh2R.css} +1 -1
- package/dist/client/assets/index-BObjbh2R.css.br +0 -0
- package/dist/client/assets/{index-KuPaZyuZ.css.gz → index-BObjbh2R.css.gz} +0 -0
- package/dist/client/assets/{infoDiagram-27XIBGKW-FRhqdJvW.js → infoDiagram-27XIBGKW-DXncUrwz.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-DAHBvAZ-.js → ishikawaDiagram-5VMMS53U-Ds28H7pI.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-DAHBvAZ-.js.br → ishikawaDiagram-5VMMS53U-Ds28H7pI.js.br} +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-Ds28H7pI.js.gz +0 -0
- package/dist/client/assets/{journeyDiagram-3NMN7TZE-CVuWuL3Z.js → journeyDiagram-3NMN7TZE-WeF_efZ2.js} +1 -1
- package/dist/client/assets/journeyDiagram-3NMN7TZE-WeF_efZ2.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-WeF_efZ2.js.gz +0 -0
- package/dist/client/assets/{kanban-definition-UXKFOSKX-ByQSUVJV.js → kanban-definition-UXKFOSKX-CMbZcy6U.js} +1 -1
- package/dist/client/assets/kanban-definition-UXKFOSKX-CMbZcy6U.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-CMbZcy6U.js.gz +0 -0
- package/dist/client/assets/{layout-Bb3Nb1c4.js → layout-DNapC8T-.js} +1 -1
- package/dist/client/assets/layout-DNapC8T-.js.br +0 -0
- package/dist/client/assets/layout-DNapC8T-.js.gz +0 -0
- package/dist/client/assets/{linear-DHMMQlOo.js → linear-B9AFx-TF.js} +1 -1
- package/dist/client/assets/linear-B9AFx-TF.js.br +0 -0
- package/dist/client/assets/linear-B9AFx-TF.js.gz +0 -0
- package/dist/client/assets/{mermaid.core-BYfniK0H.js → mermaid.core-Ddh1Z0hf.js} +5 -5
- package/dist/client/assets/mermaid.core-Ddh1Z0hf.js.br +0 -0
- package/dist/client/assets/mermaid.core-Ddh1Z0hf.js.gz +0 -0
- package/dist/client/assets/{mindmap-definition-YA3MSWOX-EDLD5AyH.js → mindmap-definition-YA3MSWOX-B0xMGUol.js} +1 -1
- package/dist/client/assets/mindmap-definition-YA3MSWOX-B0xMGUol.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-B0xMGUol.js.gz +0 -0
- package/dist/client/assets/{passwordBootstrap-DCrtirwT.js → passwordBootstrap-DQRd5vCF.js} +1 -1
- package/dist/client/assets/passwordBootstrap-DQRd5vCF.js.br +0 -0
- package/dist/client/assets/{passwordBootstrap-DCrtirwT.js.gz → passwordBootstrap-DQRd5vCF.js.gz} +0 -0
- package/dist/client/assets/{pegDiagram-XKGWAZYB-BHYhkqJN.js → pegDiagram-XKGWAZYB-BVZ-3kEF.js} +1 -1
- package/dist/client/assets/pegDiagram-XKGWAZYB-BVZ-3kEF.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-BVZ-3kEF.js.gz +0 -0
- package/dist/client/assets/{pieDiagram-E7YTZNPT-BUIJlswC.js → pieDiagram-E7YTZNPT-Cim4Hk3I.js} +1 -1
- package/dist/client/assets/pieDiagram-E7YTZNPT-Cim4Hk3I.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-Cim4Hk3I.js.gz +0 -0
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-D8Im-7yC.js → quadrantDiagram-AXDQQJYC-CYiEj5sp.js} +1 -1
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-CYiEj5sp.js.br +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-CYiEj5sp.js.gz +0 -0
- package/dist/client/assets/{railroadDiagram-O6MQD6OU-D7n6z2G1.js → railroadDiagram-O6MQD6OU-DjNNfYra.js} +1 -1
- package/dist/client/assets/railroadDiagram-O6MQD6OU-DjNNfYra.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-DjNNfYra.js.gz +0 -0
- package/dist/client/assets/{rdpSession-DJlNIbVk.js → rdpSession-DEzSQAuN.js} +1 -1
- package/dist/client/assets/rdpSession-DEzSQAuN.js.br +0 -0
- package/dist/client/assets/rdpSession-DEzSQAuN.js.gz +0 -0
- package/dist/client/assets/{referenceLongPress-DFSrssSr.js → referenceLongPress-BjyTtoDY.js} +1 -1
- package/dist/client/assets/referenceLongPress-BjyTtoDY.js.br +0 -0
- package/dist/client/assets/referenceLongPress-BjyTtoDY.js.gz +0 -0
- package/dist/client/assets/{requirementDiagram-BXWQKSXE-Ki0rR-F7.js → requirementDiagram-BXWQKSXE-ZwiKdiI3.js} +1 -1
- package/dist/client/assets/requirementDiagram-BXWQKSXE-ZwiKdiI3.js.br +0 -0
- package/dist/client/assets/{requirementDiagram-BXWQKSXE-Ki0rR-F7.js.gz → requirementDiagram-BXWQKSXE-ZwiKdiI3.js.gz} +0 -0
- package/dist/client/assets/{sankeyDiagram-P5KCCOFB-36NmMqsW.js → sankeyDiagram-P5KCCOFB-BYR7ctps.js} +1 -1
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BYR7ctps.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BYR7ctps.js.gz +0 -0
- package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-5vsPuFyO.js → sequenceDiagram-WJ2MYXX4-DxYCvK80.js} +1 -1
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DxYCvK80.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DxYCvK80.js.gz +0 -0
- package/dist/client/assets/{sizeCapture-INFHLROL-DbAulwBg.js → sizeCapture-INFHLROL-CXruk8Ko.js} +1 -1
- package/dist/client/assets/sizeCapture-INFHLROL-CXruk8Ko.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-CXruk8Ko.js.gz +0 -0
- package/dist/client/assets/{sparkles-CapLTKAs.js → sparkles-DRH97PDH.js} +1 -1
- package/dist/client/assets/{stateDiagram-D77RDMKH-Bgwe0g5S.js → stateDiagram-D77RDMKH-CENDGrxr.js} +1 -1
- package/dist/client/assets/stateDiagram-D77RDMKH-CENDGrxr.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-CENDGrxr.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-De-tGy_n.js +1 -0
- package/dist/client/assets/{swimlanes-42K2YHIH-COGAWe-g.js → swimlanes-42K2YHIH-BZQeVFeA.js} +1 -1
- package/dist/client/assets/swimlanes-42K2YHIH-BZQeVFeA.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-BZQeVFeA.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-D1YMLrIO.js +8 -0
- package/dist/client/assets/{timeline-definition-24CTP7MA-C4gt5z68.js → timeline-definition-24CTP7MA-DiJ9i33g.js} +1 -1
- package/dist/client/assets/timeline-definition-24CTP7MA-DiJ9i33g.js.br +0 -0
- package/dist/client/assets/{timeline-definition-24CTP7MA-C4gt5z68.js.gz → timeline-definition-24CTP7MA-DiJ9i33g.js.gz} +0 -0
- package/dist/client/assets/{triangle-alert-xPHw25jD.js → triangle-alert-DECoBoOV.js} +1 -1
- package/dist/client/assets/{vennDiagram-4TSXK5OY-CIEXh9oD.js → vennDiagram-4TSXK5OY-DBiEJQ9Y.js} +1 -1
- package/dist/client/assets/vennDiagram-4TSXK5OY-DBiEJQ9Y.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-DBiEJQ9Y.js.gz +0 -0
- package/dist/client/assets/{videoCompression-CUkCS2-q.js → videoCompression-8r1jOza9.js} +1 -1
- package/dist/client/assets/videoCompression-8r1jOza9.js.br +0 -0
- package/dist/client/assets/videoCompression-8r1jOza9.js.gz +0 -0
- package/dist/client/assets/{wardleyDiagram-VM6X3IG4-gQhcW1vd.js → wardleyDiagram-VM6X3IG4-B6wCSfya.js} +1 -1
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-B6wCSfya.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-B6wCSfya.js.gz +0 -0
- package/dist/client/assets/{xychartDiagram-S5SC5T6Z-BmIcdejz.js → xychartDiagram-S5SC5T6Z-DlNQayU5.js} +1 -1
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-DlNQayU5.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-DlNQayU5.js.gz +0 -0
- package/dist/client/index.html +3 -2
- package/dist/client/index.html.br +0 -0
- package/dist/client/index.html.gz +0 -0
- package/dist/client/ipad-status-bar.js +12 -0
- package/dist/client/sw.js +1 -1
- package/dist/client/sw.js.br +0 -0
- package/dist/client/sw.js.gz +0 -0
- package/dist/server/agent/collaborationCli.js +30 -8
- package/dist/server/agent/collaborationStore.js +25 -2
- package/dist/server/agent/collaborationTmuxDelivery.js +11 -3
- package/dist/server/agent/integrationCli.js +15 -3
- package/dist/server/agent/integrationServer.js +16 -1
- package/dist/server/agent/integrationSessions.js +342 -14
- package/dist/server/agent/integrationStore.js +1 -1
- package/dist/server/agent/promptDelivery.js +7 -1
- package/dist/server/agent/sessionLaunchDiagnostics.js +26 -0
- package/dist/server/agent/sessionLifecycle.js +4 -0
- package/dist/server/agent/sessionManagement.js +87 -0
- package/dist/server/agent/terminalInput.js +9 -1
- package/dist/server/routes/terminal.js +172 -21
- package/docs/integrations.md +208 -0
- package/package.json +1 -1
- package/runtime-manifest.json +3 -3
- package/dist/client/assets/App-ChS2-lkz.js.br +0 -0
- package/dist/client/assets/App-ChS2-lkz.js.gz +0 -0
- package/dist/client/assets/ArchitecturePanel-JtjyyJoW.js.br +0 -0
- package/dist/client/assets/ArchitecturePanel-JtjyyJoW.js.gz +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-BlQ5-VPp.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-BlQ5-VPp.js.gz +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-aFLAMqDr.js.br +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-aFLAMqDr.js.gz +0 -0
- package/dist/client/assets/CollaborationTaskContent-BDQMRhU9.js +0 -2
- package/dist/client/assets/ComputerControlView-TAKDbBUl.js +0 -5
- package/dist/client/assets/ComputerControlView-TAKDbBUl.js.br +0 -0
- package/dist/client/assets/ComputerControlView-TAKDbBUl.js.gz +0 -0
- package/dist/client/assets/DagPlayground-CR4uDFOx.js.br +0 -0
- package/dist/client/assets/DagPlayground-CR4uDFOx.js.gz +0 -0
- package/dist/client/assets/DiffLab-BqeHMDOy.js.br +0 -0
- package/dist/client/assets/DiffLab-BqeHMDOy.js.gz +0 -0
- package/dist/client/assets/DiffReview-DqrOcRfP.js.br +0 -0
- package/dist/client/assets/DiffReview-DqrOcRfP.js.gz +0 -0
- package/dist/client/assets/DiffReviewLab-CEYpbrL6.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-CEYpbrL6.js.gz +0 -0
- package/dist/client/assets/DiffViewer-F-uQSmhG.js.br +0 -0
- package/dist/client/assets/DiffViewer-F-uQSmhG.js.gz +0 -0
- package/dist/client/assets/ModelPreview-KmXFkgij.js.br +0 -0
- package/dist/client/assets/ModelPreview-KmXFkgij.js.gz +0 -0
- package/dist/client/assets/RightSidebar-VMdXpo4h.js.br +0 -0
- package/dist/client/assets/RightSidebar-VMdXpo4h.js.gz +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-CAMk1C0N.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-CAMk1C0N.js.gz +0 -0
- package/dist/client/assets/app-CHxLSuGQ.js +0 -35
- package/dist/client/assets/app-CHxLSuGQ.js.br +0 -0
- package/dist/client/assets/app-CHxLSuGQ.js.gz +0 -0
- package/dist/client/assets/arc-CYG_-1vC.js.br +0 -0
- package/dist/client/assets/arc-CYG_-1vC.js.gz +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-BqHzezLR.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-BqHzezLR.js.gz +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-D6GWRO_Z.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-D6GWRO_Z.js.gz +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-CutmGIGb.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-CutmGIGb.js.gz +0 -0
- package/dist/client/assets/channel-B3BKM2gg.js +0 -1
- package/dist/client/assets/chunk-F27PBJKO-CNptP19P.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-CNptP19P.js.gz +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-DHdpB9A0.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-DHdpB9A0.js.gz +0 -0
- package/dist/client/assets/chunk-SVP7TREG-B70pX8OB.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-B70pX8OB.js.gz +0 -0
- package/dist/client/assets/chunk-TICWLB2K-Ba1mI99F.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-Ba1mI99F.js.gz +0 -0
- package/dist/client/assets/classDiagram-ZZMXUADV-CS4V_MQS.js +0 -1
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-CS4V_MQS.js +0 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-C-NMDUHW.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-C-NMDUHW.js.gz +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-CZgEc1ab.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-CZgEc1ab.js.gz +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CHQeSNm2.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CHQeSNm2.js.gz +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-B_jkMdPS.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-B_jkMdPS.js.gz +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-nv6Lnsrp.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-nv6Lnsrp.js.gz +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-BZf2fzaA.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-BZf2fzaA.js.gz +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-CxL0_BH8.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-CxL0_BH8.js.gz +0 -0
- package/dist/client/assets/diagram-VX7I27RA-Dm9MqpIE.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-Dm9MqpIE.js.gz +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-BIfTa7P5.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-BIfTa7P5.js.gz +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-D4XhCDFS.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-D4XhCDFS.js.gz +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-Dxd48dXC.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-Dxd48dXC.js.gz +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-BXBMsEmE.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-BXBMsEmE.js.gz +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-CBfDd-KZ.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-CBfDd-KZ.js.gz +0 -0
- package/dist/client/assets/gestureArbiter-DXLmNGli.js.br +0 -0
- package/dist/client/assets/gestureArbiter-DXLmNGli.js.gz +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DtLM68fN.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DtLM68fN.js.gz +0 -0
- package/dist/client/assets/index-KuPaZyuZ.css.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-DAHBvAZ-.js.gz +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-CVuWuL3Z.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-CVuWuL3Z.js.gz +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-ByQSUVJV.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-ByQSUVJV.js.gz +0 -0
- package/dist/client/assets/layout-Bb3Nb1c4.js.br +0 -0
- package/dist/client/assets/layout-Bb3Nb1c4.js.gz +0 -0
- package/dist/client/assets/linear-DHMMQlOo.js.br +0 -0
- package/dist/client/assets/linear-DHMMQlOo.js.gz +0 -0
- package/dist/client/assets/mermaid.core-BYfniK0H.js.br +0 -0
- package/dist/client/assets/mermaid.core-BYfniK0H.js.gz +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-EDLD5AyH.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-EDLD5AyH.js.gz +0 -0
- package/dist/client/assets/passwordBootstrap-DCrtirwT.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-BHYhkqJN.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-BHYhkqJN.js.gz +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-BUIJlswC.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-BUIJlswC.js.gz +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-D8Im-7yC.js.br +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-D8Im-7yC.js.gz +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-D7n6z2G1.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-D7n6z2G1.js.gz +0 -0
- package/dist/client/assets/rdpSession-DJlNIbVk.js.br +0 -0
- package/dist/client/assets/rdpSession-DJlNIbVk.js.gz +0 -0
- package/dist/client/assets/referenceLongPress-DFSrssSr.js.br +0 -0
- package/dist/client/assets/referenceLongPress-DFSrssSr.js.gz +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-Ki0rR-F7.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-36NmMqsW.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-36NmMqsW.js.gz +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-5vsPuFyO.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-5vsPuFyO.js.gz +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-DbAulwBg.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-DbAulwBg.js.gz +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-Bgwe0g5S.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-Bgwe0g5S.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-Bg6S3Zm0.js +0 -1
- package/dist/client/assets/swimlanes-42K2YHIH-COGAWe-g.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-COGAWe-g.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DwBBOocG.js +0 -8
- package/dist/client/assets/timeline-definition-24CTP7MA-C4gt5z68.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-CIEXh9oD.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-CIEXh9oD.js.gz +0 -0
- package/dist/client/assets/videoCompression-CUkCS2-q.js.br +0 -0
- package/dist/client/assets/videoCompression-CUkCS2-q.js.gz +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-gQhcW1vd.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-gQhcW1vd.js.gz +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-BmIcdejz.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-BmIcdejz.js.gz +0 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import { execFile } from 'node:child_process';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
4
|
+
import { CollaborationError } from './collaborationProtocol.js';
|
|
5
|
+
const fail = (code, message) => { throw new CollaborationError(code, message, 409); };
|
|
6
|
+
/** Read the live foreground process instance, not a historical PID. */
|
|
7
|
+
export async function foregroundProcessInstance(pid) {
|
|
8
|
+
if (!Number.isSafeInteger(pid) || pid < 1)
|
|
9
|
+
return fail('SESSION_CLOSE_TARGET_UNCONFIRMED', 'Foreground process is unavailable');
|
|
10
|
+
try {
|
|
11
|
+
if (process.platform === 'linux') {
|
|
12
|
+
const stat = await fs.readFile(`/proc/${pid}/stat`, 'utf8');
|
|
13
|
+
const fields = stat.slice(stat.lastIndexOf(')') + 2).trim().split(/\s+/);
|
|
14
|
+
if (fields[0] === 'Z' || Number(fields[2]) <= 0 || fields[2] !== fields[5] || !/^\d+$/.test(fields[19]))
|
|
15
|
+
throw new Error();
|
|
16
|
+
return `linux:${fields[19]}`;
|
|
17
|
+
}
|
|
18
|
+
if (process.platform === 'darwin') {
|
|
19
|
+
const { stdout } = await promisify(execFile)('ps', ['-p', String(pid), '-o', 'pgid=,tpgid=,stat=,lstart='], { timeout: 2000 });
|
|
20
|
+
const match = stdout.trim().match(/^(\d+)\s+(\d+)\s+(\S+)\s+(.+)$/);
|
|
21
|
+
if (!match || Number(match[1]) < 1 || match[1] !== match[2] || match[3].startsWith('Z'))
|
|
22
|
+
throw new Error();
|
|
23
|
+
return `darwin:${match[4]}`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch { /* Never fall back to PID existence. */ }
|
|
27
|
+
return fail('SESSION_CLOSE_TARGET_UNCONFIRMED', 'Current foreground process instance cannot be verified');
|
|
28
|
+
}
|
|
29
|
+
/** A missing PID is absence; inaccessible identity remains an error. */
|
|
30
|
+
export async function processStartIdentity(pid) {
|
|
31
|
+
if (process.platform === 'linux') {
|
|
32
|
+
try {
|
|
33
|
+
const stat = await fs.readFile(`/proc/${pid}/stat`, 'utf8');
|
|
34
|
+
const fields = stat.slice(stat.lastIndexOf(')') + 2).trim().split(/\s+/);
|
|
35
|
+
if (fields[0] === 'Z')
|
|
36
|
+
return null;
|
|
37
|
+
if (!/^\d+$/.test(fields[19]))
|
|
38
|
+
throw new Error();
|
|
39
|
+
return `linux:${fields[19]}`;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error.code === 'ENOENT')
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else if (process.platform === 'darwin') {
|
|
47
|
+
try {
|
|
48
|
+
const { stdout } = await promisify(execFile)('ps', ['-p', String(pid), '-o', 'stat=,lstart='], { timeout: 2000 });
|
|
49
|
+
const match = stdout.trim().match(/^(\S+)\s+(.+)$/);
|
|
50
|
+
if (match)
|
|
51
|
+
return match[1].startsWith('Z') ? null : `darwin:${match[2]}`;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
try {
|
|
55
|
+
process.kill(pid, 0);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error.code === 'ESRCH')
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return fail('SESSION_CLOSE_TARGET_UNCONFIRMED', 'Process disappearance cannot be verified');
|
|
64
|
+
}
|
|
65
|
+
/** Restart reconciliation never issues termination. External tmux/process
|
|
66
|
+
* changes are outside the service lock; final fresh checks reduce, not erase,
|
|
67
|
+
* that race. The exact tmux session ID is used for teardown. */
|
|
68
|
+
export async function closeSessionRuntime(adapter, target, reconcile) {
|
|
69
|
+
await adapter.barrier(async () => {
|
|
70
|
+
if (adapter.pendingMessages())
|
|
71
|
+
fail('SESSION_PENDING_MESSAGES', 'Pending messages must be resolved before closing');
|
|
72
|
+
if (await adapter.exists()) {
|
|
73
|
+
if (reconcile)
|
|
74
|
+
fail('OPERATION_OUTCOME_UNCONFIRMED', 'Runtime still exists; reconciliation will not terminate a process');
|
|
75
|
+
if (!target || JSON.stringify(await adapter.observe()) !== JSON.stringify(target))
|
|
76
|
+
fail('SESSION_CLOSE_TARGET_CHANGED', 'Runtime or process instance changed after close intent');
|
|
77
|
+
await adapter.destroy(target);
|
|
78
|
+
const deadline = Date.now() + 2000;
|
|
79
|
+
// Observe actual disappearance; do not issue repeated termination.
|
|
80
|
+
while (await adapter.exists() && Date.now() < deadline)
|
|
81
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
82
|
+
}
|
|
83
|
+
if (await adapter.exists())
|
|
84
|
+
fail('OPERATION_OUTCOME_UNCONFIRMED', 'Runtime absence cannot be confirmed');
|
|
85
|
+
await adapter.forgetRuntime();
|
|
86
|
+
});
|
|
87
|
+
}
|
|
@@ -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
|
|
29
|
+
throw new TerminalInputTargetChangedError();
|
|
22
30
|
};
|
|
23
31
|
}
|
|
24
32
|
/** Await the actual write instead of leaving detached timers after reporting success. */
|
|
@@ -2,6 +2,7 @@ import { collaborationSessionDisplayName } from '../utils/sessionDisplayName.js'
|
|
|
2
2
|
import { integrationError } from '../agent/integrationStore.js';
|
|
3
3
|
import { assertNativeResumeAvailable, collectNativeResumeOwnerCandidates } from '../agent/nativeResumeOwner.js';
|
|
4
4
|
import { readNativeProcessIdentity } from '../agent/nativeProcessIdentity.js';
|
|
5
|
+
import { closeSessionRuntime, foregroundProcessInstance, processStartIdentity } from '../agent/sessionManagement.js';
|
|
5
6
|
import { releaseSessionRuntime } from '../agent/sessionLifecycle.js';
|
|
6
7
|
import { resumeConfigurationFingerprint } from '../agent/sessionResumeConfiguration.js';
|
|
7
8
|
import { integrationLaunchCommand } from '../agent/integrationSessions.js';
|
|
@@ -50,7 +51,7 @@ import { archiveTaskWorkspace, restoreTaskWorkspace, snapshotTaskWorkspace } fro
|
|
|
50
51
|
import { isTmuxRecoveryCandidate } from '../utils/tmuxRecoveryCandidate.js';
|
|
51
52
|
import { AutomationStore, normalizeAutomationSchedule } from '../agent/automationStore.js';
|
|
52
53
|
import { writeBracketedPrompt, canDeliverPromptToAgent } from '../agent/promptDelivery.js';
|
|
53
|
-
import { captureTerminalInputGuard, waitAndWriteTerminalInput } from '../agent/terminalInput.js';
|
|
54
|
+
import { captureTerminalInputGuard, waitAndWriteTerminalInput, TerminalInputTargetChangedError } from '../agent/terminalInput.js';
|
|
54
55
|
import { agentLaunchBlockReason, normalizeAgentLaunchCheck } from '../agent/agentLaunchCheck.js';
|
|
55
56
|
import { prepareSupervisionEnable } from '../utils/enableSupervision.js';
|
|
56
57
|
import { buildServerHealthState, dismissServerHealth } from '../utils/serverHealth.js';
|
|
@@ -629,7 +630,7 @@ function schedulePersistGlobalState() {
|
|
|
629
630
|
}
|
|
630
631
|
}, 200);
|
|
631
632
|
}
|
|
632
|
-
async function persistGlobalStateNow() {
|
|
633
|
+
async function persistGlobalStateNow(strict = false) {
|
|
633
634
|
if (persistGlobalStateTimer) {
|
|
634
635
|
clearTimeout(persistGlobalStateTimer);
|
|
635
636
|
persistGlobalStateTimer = null;
|
|
@@ -639,6 +640,8 @@ async function persistGlobalStateNow() {
|
|
|
639
640
|
}
|
|
640
641
|
catch (error) {
|
|
641
642
|
console.warn('[session-persist] Failed to persist global state:', getErrorMessage(error));
|
|
643
|
+
if (strict)
|
|
644
|
+
throw error;
|
|
642
645
|
}
|
|
643
646
|
}
|
|
644
647
|
// 进程退出前立即刷盘,避免 tsx watch 重启导致状态丢失
|
|
@@ -1479,21 +1482,21 @@ async function observeAgentLaunchCheck(record, observed) {
|
|
|
1479
1482
|
function terminalInputGuard(record) {
|
|
1480
1483
|
const frontendSessionId = record.sessionId;
|
|
1481
1484
|
const backendSessionId = record.backendSessionId;
|
|
1482
|
-
const
|
|
1483
|
-
.find(candidate => candidate.sessionId === frontendSessionId)?.agentLaunchGeneration ?? null, record.agentLaunchGeneration ?? null);
|
|
1485
|
+
const launchId = record.agentLaunchGeneration ?? null;
|
|
1484
1486
|
const backend = backendSessionId ? terminalSessions.get(backendSessionId) : undefined;
|
|
1485
1487
|
return () => {
|
|
1486
1488
|
const latest = globalSessionState.sessions.find(candidate => candidate.sessionId === frontendSessionId);
|
|
1487
1489
|
if (!latest)
|
|
1488
1490
|
throw new Error('SESSION_REMOVED');
|
|
1489
|
-
|
|
1490
|
-
if (latest.backendSessionId !== backendSessionId
|
|
1491
|
-
|
|
1492
|
-
|
|
1491
|
+
const instanceMatches = !backendSessionId || terminalSessions.get(backendSessionId) === backend;
|
|
1492
|
+
if ((latest.agentLaunchGeneration ?? null) !== launchId || latest.backendSessionId !== backendSessionId || !instanceMatches) {
|
|
1493
|
+
throw new TerminalInputTargetChangedError({ expected_backend_session_id: backendSessionId, current_backend_session_id: latest.backendSessionId,
|
|
1494
|
+
expected_launch_id: launchId, current_launch_id: latest.agentLaunchGeneration ?? null, backend_instance_matches: instanceMatches });
|
|
1495
|
+
}
|
|
1493
1496
|
};
|
|
1494
1497
|
}
|
|
1495
1498
|
/** tmux input always uses the pane queue, including automation and launch commands. */
|
|
1496
|
-
async function automaticTerminalInput(record, assertCurrent = terminalInputGuard(record)) {
|
|
1499
|
+
async function automaticTerminalInput(record, assertCurrent = terminalInputGuard(record), progress) {
|
|
1497
1500
|
assertCurrent();
|
|
1498
1501
|
if (record.mode === 'tmux') {
|
|
1499
1502
|
const binding = collaborationRouting.get(record.sessionId) ?? {
|
|
@@ -1505,18 +1508,18 @@ async function automaticTerminalInput(record, assertCurrent = terminalInputGuard
|
|
|
1505
1508
|
if (inspected.state !== 'ready' || !inspected.pane)
|
|
1506
1509
|
throw new Error(inspected.reason ?? 'TMUX_PANE_UNAVAILABLE');
|
|
1507
1510
|
const pane = inspected.pane;
|
|
1508
|
-
return (prompt) => writeCollaborationTmuxPane(runTmux, pane, prompt, runTmuxStdin, assertCurrent);
|
|
1511
|
+
return (prompt) => writeCollaborationTmuxPane(runTmux, pane, prompt, runTmuxStdin, assertCurrent, progress);
|
|
1509
1512
|
}
|
|
1510
1513
|
const backend = record.backendSessionId ? terminalSessions.get(record.backendSessionId) : null;
|
|
1511
1514
|
if (!backend)
|
|
1512
1515
|
throw new Error('SHELL_BACKEND_NOT_RUNNING');
|
|
1513
|
-
return (prompt) => writeBracketedPrompt(backend.ptyProcess, prompt, assertCurrent);
|
|
1516
|
+
return (prompt) => writeBracketedPrompt(backend.ptyProcess, prompt, assertCurrent, progress);
|
|
1514
1517
|
}
|
|
1515
|
-
async function writeAutomaticTerminalPrompt(frontendSessionId, prompt) {
|
|
1518
|
+
async function writeAutomaticTerminalPrompt(frontendSessionId, prompt, progress) {
|
|
1516
1519
|
const record = globalSessionState.sessions.find(candidate => candidate.sessionId === frontendSessionId);
|
|
1517
1520
|
if (!record)
|
|
1518
1521
|
throw new Error('SESSION_REMOVED');
|
|
1519
|
-
const write = await automaticTerminalInput(record);
|
|
1522
|
+
const write = await automaticTerminalInput(record, terminalInputGuard(record), progress);
|
|
1520
1523
|
await write(prompt);
|
|
1521
1524
|
}
|
|
1522
1525
|
async function deliverAutomationPromptWhenReady(backendSessionId, prompt) {
|
|
@@ -1980,11 +1983,131 @@ async function integrationTmuxPresent(record) {
|
|
|
1980
1983
|
throw error;
|
|
1981
1984
|
}
|
|
1982
1985
|
}
|
|
1986
|
+
async function verifyIntegrationRuntimeOwnership(record) {
|
|
1987
|
+
await integrationSessionAdapter.prepareRelease(record);
|
|
1988
|
+
const terminal = integrationTerminalRecord(record);
|
|
1989
|
+
if (terminal && globalSessionState.sessions.some(other => other.sessionId !== record.session_id
|
|
1990
|
+
&& (other.tmuxSessionName === terminal.tmuxSessionName || terminal.backendSessionId && other.backendSessionId === terminal.backendSessionId))) {
|
|
1991
|
+
integrationError('SESSION_IDENTITY_MISMATCH', 'Runtime has another logical owner', 409);
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
async function forgetIntegrationRuntime(record) {
|
|
1995
|
+
if (await integrationTmuxPresent(record))
|
|
1996
|
+
integrationError('OPERATION_OUTCOME_UNCONFIRMED', 'Owned tmux still exists', 409);
|
|
1997
|
+
await verifyIntegrationRuntimeOwnership(record);
|
|
1998
|
+
for (const [id, backend] of terminalSessions)
|
|
1999
|
+
if (backend.mode === 'tmux' && backend.tmuxSessionName === `wt-integration-${record.session_id}`)
|
|
2000
|
+
cleanupSession(id, { killProcess: true });
|
|
2001
|
+
removeGlobalSessionRecord(record.session_id);
|
|
2002
|
+
collaborationStore.archiveSession(record.session_id);
|
|
2003
|
+
collaborationRouting.remove(record.session_id);
|
|
2004
|
+
await persistGlobalStateNow(true);
|
|
2005
|
+
broadcastClientState();
|
|
2006
|
+
}
|
|
2007
|
+
async function observeIntegrationCloseTarget(record) {
|
|
2008
|
+
await verifyIntegrationRuntimeOwnership(record);
|
|
2009
|
+
const terminal = integrationTerminalRecord(record);
|
|
2010
|
+
if (!terminal || !record.terminal_binding)
|
|
2011
|
+
integrationError('SESSION_CLOSE_TARGET_UNCONFIRMED', 'Original runtime binding is unavailable', 409);
|
|
2012
|
+
const inspected = await inspectCollaborationTmux({ sessionId: record.session_id, backendSessionId: terminal.backendSessionId,
|
|
2013
|
+
mode: 'tmux', tmuxSessionName: terminal.tmuxSessionName, agentSlug: record.agent_slug,
|
|
2014
|
+
nativeSessionId: record.agent_native_session_id, pane: record.terminal_binding }, undefined, false, true);
|
|
2015
|
+
if (inspected.state !== 'ready' || !inspected.pane)
|
|
2016
|
+
integrationError('SESSION_CLOSE_TARGET_UNCONFIRMED', 'Original pinned pane cannot be verified', 409);
|
|
2017
|
+
const layout = await getTmuxLayout(terminal.tmuxSessionName);
|
|
2018
|
+
const panes = layout.windows.flatMap(window => window.panes);
|
|
2019
|
+
if (panes.length !== 1 || layout.activePaneId !== record.terminal_binding.paneId)
|
|
2020
|
+
integrationError('SESSION_IDENTITY_MISMATCH', 'Only the single original owned pane can be closed', 409);
|
|
2021
|
+
const pane = panes[0];
|
|
2022
|
+
const paneOwners = (await runTmux(['list-panes', '-a', '-F', '#{session_id} #{pane_id}'])).trim().split('\n');
|
|
2023
|
+
if (paneOwners.some(line => { const [owner, id] = line.trim().split(/\s+/); return id === pane.id && owner !== record.terminal_binding.sessionId; }))
|
|
2024
|
+
integrationError('SESSION_SCOPE_CONFLICT', 'Owned pane is linked into another tmux session', 409);
|
|
2025
|
+
if (process.platform === 'linux')
|
|
2026
|
+
await getProcessSnapshot(true);
|
|
2027
|
+
const program = await resolveTmuxPaneProgram(pane, true, true);
|
|
2028
|
+
const agent = detectAgentFromCommand(program?.rawArgs ?? program?.command ?? '', agentCustomCommands());
|
|
2029
|
+
let kind, pid, nativeId = null;
|
|
2030
|
+
if (agent) {
|
|
2031
|
+
if (!record.agent_native_session_id || agent.slug !== record.agent_slug || program?.source !== 'tmux-tty' || !program.processPid) {
|
|
2032
|
+
integrationError('SESSION_CLOSE_TARGET_UNCONFIRMED', 'A running Agent requires a live exact native identity', 409);
|
|
2033
|
+
}
|
|
2034
|
+
const identity = await observeProgramNativeIdentity(agent, program);
|
|
2035
|
+
if (identity.failure || identity.nativeId !== record.agent_native_session_id)
|
|
2036
|
+
integrationError('SESSION_IDENTITY_MISMATCH', 'Current Agent native identity differs from the owned record', 409);
|
|
2037
|
+
kind = 'agent';
|
|
2038
|
+
pid = program.processPid;
|
|
2039
|
+
nativeId = identity.nativeId;
|
|
2040
|
+
}
|
|
2041
|
+
else {
|
|
2042
|
+
if (!await integrationPaneIsIdleShell(inspected.pane))
|
|
2043
|
+
integrationError('SESSION_CLOSE_TARGET_UNCONFIRMED', 'Current runtime is not a verified foreground shell', 409);
|
|
2044
|
+
kind = 'shell';
|
|
2045
|
+
pid = pane.pid;
|
|
2046
|
+
}
|
|
2047
|
+
const serverStart = await processStartIdentity(record.terminal_binding.serverPid);
|
|
2048
|
+
if (!serverStart)
|
|
2049
|
+
integrationError('SESSION_CLOSE_TARGET_UNCONFIRMED', 'Current tmux server instance is unavailable', 409);
|
|
2050
|
+
return { binding: { ...record.terminal_binding }, tmux_server_start_id: serverStart, kind, process_pid: pid,
|
|
2051
|
+
process_start_id: await foregroundProcessInstance(pid), native_id: nativeId };
|
|
2052
|
+
}
|
|
1983
2053
|
export const integrationSessionAdapter = {
|
|
1984
2054
|
subscribe(listener) { integrationSessionObservers.add(listener); return () => { integrationSessionObservers.delete(listener); }; },
|
|
1985
2055
|
registerDeliveryGuard(guard) { integrationDeliveryGuard = guard; return () => { if (integrationDeliveryGuard === guard)
|
|
1986
2056
|
integrationDeliveryGuard = undefined; }; },
|
|
2057
|
+
async prepareRename(record) {
|
|
2058
|
+
await verifyIntegrationRuntimeOwnership(record);
|
|
2059
|
+
if (!integrationTerminalRecord(record) && await integrationTmuxPresent(record))
|
|
2060
|
+
integrationError('SESSION_IDENTITY_MISMATCH', 'Live tmux lacks its owned terminal registration', 409);
|
|
2061
|
+
},
|
|
2062
|
+
async rename(record) {
|
|
2063
|
+
await integrationSessionAdapter.prepareRename(record);
|
|
2064
|
+
const terminal = integrationTerminalRecord(record);
|
|
2065
|
+
if (!terminal)
|
|
2066
|
+
return; // Metadata survives released/closed; never recreate a runtime.
|
|
2067
|
+
if (!record.name)
|
|
2068
|
+
integrationError('INVALID_NAME', 'Missing persistent display name');
|
|
2069
|
+
if (await integrationTmuxPresent(record))
|
|
2070
|
+
await setTmuxOption(terminal.tmuxSessionName, '@termdock-friendly-name', record.name);
|
|
2071
|
+
upsertGlobalSessionRecord({ ...terminal, name: record.name, customName: true, autoTitle: null });
|
|
2072
|
+
await persistGlobalStateNow(true);
|
|
2073
|
+
await getSessionInventorySnapshot({ refresh: true });
|
|
2074
|
+
broadcastClientState();
|
|
2075
|
+
},
|
|
2076
|
+
async prepareClose(record) {
|
|
2077
|
+
if (collaborationStore.pendingCount(record.session_id))
|
|
2078
|
+
integrationError('SESSION_PENDING_MESSAGES', 'Pending messages must be resolved before closing', 409);
|
|
2079
|
+
await verifyIntegrationRuntimeOwnership(record);
|
|
2080
|
+
return await integrationTmuxPresent(record) ? observeIntegrationCloseTarget(record) : null;
|
|
2081
|
+
},
|
|
2082
|
+
async closeRuntime(record, reconcile) {
|
|
2083
|
+
await closeSessionRuntime({
|
|
2084
|
+
barrier: action => collaborationDeliveryWorker.reconfigure(record.session_id, action),
|
|
2085
|
+
async exists() {
|
|
2086
|
+
if (await integrationTmuxPresent(record))
|
|
2087
|
+
return true;
|
|
2088
|
+
const target = record.close_intent?.target;
|
|
2089
|
+
return !!target && await processStartIdentity(target.process_pid) === target.process_start_id;
|
|
2090
|
+
},
|
|
2091
|
+
pendingMessages: () => collaborationStore.pendingCount(record.session_id),
|
|
2092
|
+
observe: () => observeIntegrationCloseTarget(record),
|
|
2093
|
+
async destroy(target) {
|
|
2094
|
+
// Kill by immutable tmux session ID, not by a potentially reused name.
|
|
2095
|
+
// No process-group kill or application prompt is sent.
|
|
2096
|
+
if (JSON.stringify(await observeIntegrationCloseTarget(record)) !== JSON.stringify(target))
|
|
2097
|
+
integrationError('SESSION_CLOSE_TARGET_CHANGED', 'Close target changed before teardown', 409);
|
|
2098
|
+
intentionallyDeletingTmuxSessions.add(`wt-integration-${record.session_id}`);
|
|
2099
|
+
try {
|
|
2100
|
+
await runTmux(['kill-session', '-t', target.binding.sessionId]);
|
|
2101
|
+
}
|
|
2102
|
+
finally {
|
|
2103
|
+
intentionallyDeletingTmuxSessions.delete(`wt-integration-${record.session_id}`);
|
|
2104
|
+
}
|
|
2105
|
+
},
|
|
2106
|
+
forgetRuntime: () => forgetIntegrationRuntime(record),
|
|
2107
|
+
}, record.close_intent?.target ?? null, reconcile);
|
|
2108
|
+
},
|
|
1987
2109
|
pendingMessages(id) { return collaborationStore.pendingCount(id); },
|
|
2110
|
+
messageHistory(id) { return collaborationStore.hasTerminalMessageHistory(id); },
|
|
1988
2111
|
async prepareRelease(record) {
|
|
1989
2112
|
if (collaborationStore.groupsForSession(record.session_id).some(group => group.id !== record.group_id))
|
|
1990
2113
|
integrationError('SESSION_SCOPE_CONFLICT', 'Runtime belongs to another collaboration group; administrator must resolve its membership first', 409);
|
|
@@ -2076,21 +2199,28 @@ export const integrationSessionAdapter = {
|
|
|
2076
2199
|
collaborationRouting.bind({ ...route, nativeSessionId: nativeId, pane: { ...route.pane, nativeSessionId: nativeId } });
|
|
2077
2200
|
return { exists: true, running: Boolean(pane.agentSlug), shell: await integrationPaneIsIdleShell(pane), agentSlug: pane.agentSlug || null, nativeId };
|
|
2078
2201
|
},
|
|
2079
|
-
async create(record, prepared) {
|
|
2202
|
+
async create(record, prepared, progress) {
|
|
2080
2203
|
await listDetectedAgentLaunchers();
|
|
2081
2204
|
if (!agentBySlug(record.agent_slug))
|
|
2082
2205
|
integrationError('COLLAB_AGENT_UNAVAILABLE', 'Configured agent plugin is not installed');
|
|
2083
2206
|
if (integrationTerminalRecord(record))
|
|
2084
2207
|
integrationError('SESSION_CREATE_OUTCOME_UNKNOWN', 'Creation intent already has a terminal; inspect it instead of relaunching', 409);
|
|
2085
|
-
await launchIntegrationTerminal(record, false, prepared);
|
|
2208
|
+
await launchIntegrationTerminal(record, false, prepared, progress);
|
|
2086
2209
|
},
|
|
2087
|
-
async restore(record, prepared) {
|
|
2210
|
+
async restore(record, prepared, progress) {
|
|
2088
2211
|
await listDetectedAgentLaunchers();
|
|
2089
2212
|
const agent = agentBySlug(record.agent_slug);
|
|
2090
2213
|
if (!record.agent_native_session_id || !agent || !buildResumeCommand(agent, record.agent_native_session_id, null))
|
|
2091
2214
|
integrationError('EXACT_RESUME_UNSUPPORTED', 'Agent plugin must support exact native resume');
|
|
2215
|
+
progress?.('native_owner_check');
|
|
2092
2216
|
await assertIntegrationNativeResumeAvailable(record);
|
|
2093
|
-
await launchIntegrationTerminal(record, true, prepared);
|
|
2217
|
+
await launchIntegrationTerminal(record, true, prepared, progress);
|
|
2218
|
+
},
|
|
2219
|
+
async retryCold(record, prepared, progress) {
|
|
2220
|
+
await listDetectedAgentLaunchers();
|
|
2221
|
+
if (!agentBySlug(record.agent_slug))
|
|
2222
|
+
integrationError('COLLAB_AGENT_UNAVAILABLE', 'Configured agent plugin is not installed');
|
|
2223
|
+
await launchIntegrationTerminal(record, false, prepared, progress, true);
|
|
2094
2224
|
},
|
|
2095
2225
|
};
|
|
2096
2226
|
async function assertIntegrationNativeResumeAvailable(record) {
|
|
@@ -2141,12 +2271,28 @@ async function assertIntegrationNativeResumeAvailable(record) {
|
|
|
2141
2271
|
program: program?.command ?? null, processSource: program?.source, argumentsObserved: !!program?.rawArgs }];
|
|
2142
2272
|
});
|
|
2143
2273
|
}
|
|
2144
|
-
async function launchIntegrationTerminal(record, restoring, prepared) {
|
|
2274
|
+
async function launchIntegrationTerminal(record, restoring, prepared, progress, retryCold = false) {
|
|
2145
2275
|
await collaborationDeliveryWorker.reconfigure(record.session_id, async () => {
|
|
2276
|
+
progress?.('runtime_prepare');
|
|
2146
2277
|
const group = collaborationStore.getGroup(record.group_id);
|
|
2147
2278
|
if (!group || group.deleted)
|
|
2148
2279
|
integrationError('TASK_GROUP_NOT_FOUND', 'Integration group no longer exists', 404);
|
|
2149
2280
|
const original = await integrationSessionAdapter.inspect(record);
|
|
2281
|
+
if (retryCold) {
|
|
2282
|
+
await integrationSessionAdapter.prepareRelease(record);
|
|
2283
|
+
const owned = integrationTerminalRecord(record);
|
|
2284
|
+
if (!owned || globalSessionState.sessions.some(other => other.sessionId !== record.session_id
|
|
2285
|
+
&& (other.tmuxSessionName === owned.tmuxSessionName || owned.backendSessionId && other.backendSessionId === owned.backendSessionId))) {
|
|
2286
|
+
integrationError('SESSION_IDENTITY_MISMATCH', 'Cold retry runtime lacks unique logical ownership', 409);
|
|
2287
|
+
}
|
|
2288
|
+
const history = collaborationStore.hasTerminalMessageHistory(record.session_id);
|
|
2289
|
+
if (history === null)
|
|
2290
|
+
integrationError('SESSION_MESSAGE_HISTORY_UNCONFIRMED', 'Message history cannot be verified', 409);
|
|
2291
|
+
if (history || collaborationStore.pendingCount(record.session_id))
|
|
2292
|
+
integrationError('SESSION_MESSAGE_HISTORY_PRESENT', 'TD message history appeared before retry', 409);
|
|
2293
|
+
if (!record.terminal_binding || !original.exists || original.running || !original.shell || original.nativeId)
|
|
2294
|
+
integrationError('SESSION_COLD_RETRY_RUNTIME_UNCONFIRMED', 'Original shell could not be confirmed before retry', 409);
|
|
2295
|
+
}
|
|
2150
2296
|
if (!original.exists) {
|
|
2151
2297
|
let tmuxExists = false;
|
|
2152
2298
|
try {
|
|
@@ -2162,7 +2308,7 @@ async function launchIntegrationTerminal(record, restoring, prepared) {
|
|
|
2162
2308
|
}
|
|
2163
2309
|
const opened = await openInventorySession({}, { preferredFrontendSessionId: record.session_id,
|
|
2164
2310
|
mode: 'tmux', tmuxSessionName: `wt-integration-${record.session_id}`, cwd: record.cwd,
|
|
2165
|
-
name: `${record.agent_slug} · ${group.name}`, customName: true });
|
|
2311
|
+
name: record.name ?? `${record.agent_slug} · ${group.name}`, customName: true });
|
|
2166
2312
|
if (opened.session.sessionId !== record.session_id)
|
|
2167
2313
|
integrationError('SESSION_IDENTITY_MISMATCH', 'Terminal id changed', 409);
|
|
2168
2314
|
const terminal = integrationTerminalRecord(record);
|
|
@@ -2178,6 +2324,7 @@ async function launchIntegrationTerminal(record, restoring, prepared) {
|
|
|
2178
2324
|
const pane = inspected.pane;
|
|
2179
2325
|
const pinned = { serverPid: pane.serverPid, sessionId: pane.sessionId,
|
|
2180
2326
|
paneId: pane.paneId, panePid: pane.panePid, agentSlug: record.agent_slug, nativeSessionId: record.agent_native_session_id };
|
|
2327
|
+
progress?.('binding_persist');
|
|
2181
2328
|
prepared(pinned); // Must persist before the command enters the terminal.
|
|
2182
2329
|
collaborationRouting.bind({ sessionId: record.session_id, backendSessionId: opened.terminalSession.sessionId,
|
|
2183
2330
|
mode: 'tmux', tmuxSessionName: terminal.tmuxSessionName, agentSlug: record.agent_slug, nativeSessionId: record.agent_native_session_id, pane: pinned });
|
|
@@ -2195,8 +2342,11 @@ async function launchIntegrationTerminal(record, restoring, prepared) {
|
|
|
2195
2342
|
// use an active-pane target which might have changed during preparation.
|
|
2196
2343
|
if (record.resume_configuration_fingerprint && record.resume_configuration_fingerprint !== await resumeConfigurationFingerprint(record, integrationSessionAdapter))
|
|
2197
2344
|
integrationError('RESUME_CONFIGURATION_CHANGED', 'Recovery configuration changed before terminal input', 409);
|
|
2198
|
-
if (restoring)
|
|
2345
|
+
if (restoring) {
|
|
2346
|
+
progress?.('native_owner_check');
|
|
2199
2347
|
await assertIntegrationNativeResumeAvailable(record);
|
|
2348
|
+
}
|
|
2349
|
+
progress?.('runtime_verify');
|
|
2200
2350
|
const shell = await inspectCollaborationTmux({ sessionId: record.session_id, backendSessionId: opened.terminalSession.sessionId,
|
|
2201
2351
|
mode: 'tmux', tmuxSessionName: terminal.tmuxSessionName, agentSlug: null, nativeSessionId: null, pane: pinned });
|
|
2202
2352
|
if (shell.state !== 'ready' || !shell.pane || !await integrationPaneIsIdleShell(shell.pane))
|
|
@@ -2206,8 +2356,9 @@ async function launchIntegrationTerminal(record, restoring, prepared) {
|
|
|
2206
2356
|
backend.agentSession = null;
|
|
2207
2357
|
backend.agent = null;
|
|
2208
2358
|
backend.agentResumeRecovered = false;
|
|
2359
|
+
progress?.('launch_intent');
|
|
2209
2360
|
await beginAgentLaunchCheck(record.session_id, record.agent_slug, restoring ? record.agent_native_session_id : null);
|
|
2210
|
-
await writeAutomaticTerminalPrompt(record.session_id, integrationLaunchCommand(record, restoring));
|
|
2361
|
+
await writeAutomaticTerminalPrompt(record.session_id, integrationLaunchCommand(record, restoring), progress);
|
|
2211
2362
|
broadcastClientState();
|
|
2212
2363
|
});
|
|
2213
2364
|
}
|