termdock 1.4.295 → 1.4.297
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/.desktop-dist/main.js +35 -2
- package/README.en.md +257 -0
- package/README.md +284 -133
- package/dist/client/assets/App-BbqtNY2x.js +177 -0
- package/dist/client/assets/App-BbqtNY2x.js.br +0 -0
- package/dist/client/assets/App-BbqtNY2x.js.gz +0 -0
- package/dist/client/assets/{ChangeWalkthroughPanel-Dv5XRtRh.js → ChangeWalkthroughPanel-CvQJIp_C.js} +1 -1
- package/dist/client/assets/ChangeWalkthroughPanel-CvQJIp_C.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-CvQJIp_C.js.gz +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-B0OgRtyR.js +1 -0
- package/dist/client/assets/CollaborationMainWorkspace-B0OgRtyR.js.br +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-B0OgRtyR.js.gz +0 -0
- package/dist/client/assets/CollaborationTaskContent-C01GXOEq.js +2 -0
- package/dist/client/assets/ComputerControlView-CW1uA133.js +4 -0
- package/dist/client/assets/ComputerControlView-CW1uA133.js.br +0 -0
- package/dist/client/assets/ComputerControlView-CW1uA133.js.gz +0 -0
- package/dist/client/assets/{DagPlayground-mq69dKyr.js → DagPlayground-CdE3tQsl.js} +1 -1
- package/dist/client/assets/DagPlayground-CdE3tQsl.js.br +0 -0
- package/dist/client/assets/DagPlayground-CdE3tQsl.js.gz +0 -0
- package/dist/client/assets/{DiffLab-BqdHYGi5.js → DiffLab-BLGNnazd.js} +1 -1
- package/dist/client/assets/DiffLab-BLGNnazd.js.br +0 -0
- package/dist/client/assets/DiffLab-BLGNnazd.js.gz +0 -0
- package/dist/client/assets/{DiffReview-BvzGxpuc.js → DiffReview-CYw3ASI6.js} +1 -1
- package/dist/client/assets/DiffReview-CYw3ASI6.js.br +0 -0
- package/dist/client/assets/DiffReview-CYw3ASI6.js.gz +0 -0
- package/dist/client/assets/{DiffReviewLab-DrfddB7x.js → DiffReviewLab-CySIuWq_.js} +1 -1
- package/dist/client/assets/DiffReviewLab-CySIuWq_.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-CySIuWq_.js.gz +0 -0
- package/dist/client/assets/{DiffViewer-3bJV_A5s.js → DiffViewer-WsYvN75z.js} +13 -13
- package/dist/client/assets/DiffViewer-WsYvN75z.js.br +0 -0
- package/dist/client/assets/DiffViewer-WsYvN75z.js.gz +0 -0
- package/dist/client/assets/{ModelPreview-CX7VtoJB.js → ModelPreview-Dnlx9ByX.js} +1 -1
- package/dist/client/assets/ModelPreview-Dnlx9ByX.js.br +0 -0
- package/dist/client/assets/ModelPreview-Dnlx9ByX.js.gz +0 -0
- package/dist/client/assets/RightSidebar-Cp5b_y0u.js +1678 -0
- package/dist/client/assets/RightSidebar-Cp5b_y0u.js.br +0 -0
- package/dist/client/assets/RightSidebar-Cp5b_y0u.js.gz +0 -0
- package/dist/client/assets/{abnfDiagram-VCTEODGH-PJwhLTPH.js → abnfDiagram-VCTEODGH-CK1mGFRQ.js} +1 -1
- package/dist/client/assets/abnfDiagram-VCTEODGH-CK1mGFRQ.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-CK1mGFRQ.js.gz +0 -0
- package/dist/client/assets/app-DfACMixk.js +35 -0
- package/dist/client/assets/app-DfACMixk.js.br +0 -0
- package/dist/client/assets/app-DfACMixk.js.gz +0 -0
- package/dist/client/assets/{arc-l3FXjCEl.js → arc-yZE1gqDl.js} +1 -1
- package/dist/client/assets/arc-yZE1gqDl.js.br +0 -0
- package/dist/client/assets/arc-yZE1gqDl.js.gz +0 -0
- package/dist/client/assets/{architectureDiagram-5GKGNRK7-DdNbKi-4.js → architectureDiagram-5GKGNRK7-U5XSC7cY.js} +1 -1
- package/dist/client/assets/architectureDiagram-5GKGNRK7-U5XSC7cY.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-U5XSC7cY.js.gz +0 -0
- package/dist/client/assets/{blockDiagram-I7D4REHJ-Cu63oaxR.js → blockDiagram-I7D4REHJ-pVJnntSG.js} +1 -1
- package/dist/client/assets/blockDiagram-I7D4REHJ-pVJnntSG.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-pVJnntSG.js.gz +0 -0
- package/dist/client/assets/{c4Diagram-7LVT6UL2-DQiV_yk6.js → c4Diagram-7LVT6UL2-Bwz0AJJV.js} +1 -1
- package/dist/client/assets/c4Diagram-7LVT6UL2-Bwz0AJJV.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-Bwz0AJJV.js.gz +0 -0
- package/dist/client/assets/channel-qqjDJtcZ.js +1 -0
- package/dist/client/assets/{chunk-2Q5K7J3B-COKJ79Ld.js → chunk-2Q5K7J3B-CXJ1kP4X.js} +1 -1
- package/dist/client/assets/{chunk-5VM5RSS4-BfV-m7oa.js → chunk-5VM5RSS4-Dpdum_2z.js} +1 -1
- package/dist/client/assets/{chunk-F27PBJKO-sLDCEnU8.js → chunk-F27PBJKO-BCG5Zi_-.js} +1 -1
- package/dist/client/assets/chunk-F27PBJKO-BCG5Zi_-.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-BCG5Zi_-.js.gz +0 -0
- package/dist/client/assets/{chunk-IMKFNOWR-DYu5qS7g.js → chunk-IMKFNOWR-BM-GcNcv.js} +1 -1
- package/dist/client/assets/chunk-IMKFNOWR-BM-GcNcv.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-BM-GcNcv.js.gz +0 -0
- package/dist/client/assets/{chunk-JWPE2WC7-DixkILcl.js → chunk-JWPE2WC7-BWiXpQT9.js} +1 -1
- package/dist/client/assets/{chunk-POPQ4Y6H-CfW5Vm_-.js → chunk-POPQ4Y6H-vQSslMNv.js} +1 -1
- package/dist/client/assets/{chunk-SVP7TREG-nJnbUFzs.js → chunk-SVP7TREG-Aqfz6nPA.js} +1 -1
- package/dist/client/assets/chunk-SVP7TREG-Aqfz6nPA.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-Aqfz6nPA.js.gz +0 -0
- package/dist/client/assets/{chunk-TICWLB2K-BwyiSQgx.js → chunk-TICWLB2K-DDjekMd0.js} +1 -1
- package/dist/client/assets/chunk-TICWLB2K-DDjekMd0.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-DDjekMd0.js.gz +0 -0
- package/dist/client/assets/{chunk-XXDRQBXY-TCk4c2XN.js → chunk-XXDRQBXY-BegIBcFg.js} +1 -1
- package/dist/client/assets/classDiagram-ZZMXUADV-BDuBrfNz.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-BDuBrfNz.js +1 -0
- package/dist/client/assets/{cose-bilkent-JH36ORCC-rroo-EOb.js → cose-bilkent-JH36ORCC-B2izFsBY.js} +1 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-B2izFsBY.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-B2izFsBY.js.gz +0 -0
- package/dist/client/assets/{cynefin-OW5HDTMX-CkFeV85k.js → cynefin-OW5HDTMX-C7HA99Zc.js} +1 -1
- package/dist/client/assets/cynefin-OW5HDTMX-C7HA99Zc.js.br +0 -0
- package/dist/client/assets/{cynefin-OW5HDTMX-CkFeV85k.js.gz → cynefin-OW5HDTMX-C7HA99Zc.js.gz} +0 -0
- package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-hBwpU_bW.js → cynefinDiagram-5FMLGOSQ-vNIzcCYl.js} +1 -1
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-vNIzcCYl.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-vNIzcCYl.js.gz +0 -0
- package/dist/client/assets/{dagre-GXQ25YYZ-B321-hdp.js → dagre-GXQ25YYZ-Bv9WHNT9.js} +1 -1
- package/dist/client/assets/dagre-GXQ25YYZ-Bv9WHNT9.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-Bv9WHNT9.js.gz +0 -0
- package/dist/client/assets/{diagram-S7CK7UJ4-bY87_ptA.js → diagram-S7CK7UJ4-DFg5UNic.js} +1 -1
- package/dist/client/assets/diagram-S7CK7UJ4-DFg5UNic.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-DFg5UNic.js.gz +0 -0
- package/dist/client/assets/{diagram-UQ7AKVKN--cez0H_o.js → diagram-UQ7AKVKN-BFQsCAs7.js} +1 -1
- package/dist/client/assets/diagram-UQ7AKVKN-BFQsCAs7.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-BFQsCAs7.js.gz +0 -0
- package/dist/client/assets/{diagram-VSXAHHWV-BupH_VRK.js → diagram-VSXAHHWV-C4R8TKEv.js} +1 -1
- package/dist/client/assets/diagram-VSXAHHWV-C4R8TKEv.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-C4R8TKEv.js.gz +0 -0
- package/dist/client/assets/{diagram-VX7I27RA-DewqaxvF.js → diagram-VX7I27RA-CL75HIf0.js} +1 -1
- package/dist/client/assets/diagram-VX7I27RA-CL75HIf0.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-CL75HIf0.js.gz +0 -0
- package/dist/client/assets/{diagram-Z3DM3KII-wDumcTuR.js → diagram-Z3DM3KII-CfJampuO.js} +1 -1
- package/dist/client/assets/diagram-Z3DM3KII-CfJampuO.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-CfJampuO.js.gz +0 -0
- package/dist/client/assets/{ebnfDiagram-PWID7BFC-C0OY91We.js → ebnfDiagram-PWID7BFC-Ct53jhNd.js} +1 -1
- package/dist/client/assets/ebnfDiagram-PWID7BFC-Ct53jhNd.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-Ct53jhNd.js.gz +0 -0
- package/dist/client/assets/{erDiagram-RLTQ6QDP-Cw9aNqvJ.js → erDiagram-RLTQ6QDP-BgL2xOOa.js} +1 -1
- package/dist/client/assets/erDiagram-RLTQ6QDP-BgL2xOOa.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-BgL2xOOa.js.gz +0 -0
- package/dist/client/assets/{flowDiagram-HODETNUW-BC7XUXeI.js → flowDiagram-HODETNUW-Cp4Nu5jY.js} +1 -1
- package/dist/client/assets/{flowDiagram-HODETNUW-BC7XUXeI.js.br → flowDiagram-HODETNUW-Cp4Nu5jY.js.br} +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-Cp4Nu5jY.js.gz +0 -0
- package/dist/client/assets/{ganttDiagram-EL5Y4UJY-DovhJIz5.js → ganttDiagram-EL5Y4UJY-DI0rdyPX.js} +1 -1
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-DI0rdyPX.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-DI0rdyPX.js.gz +0 -0
- package/dist/client/assets/{gestureArbiter-wjVok2Lg.js → gestureArbiter-Belsq4xq.js} +1 -1
- package/dist/client/assets/gestureArbiter-Belsq4xq.js.br +0 -0
- package/dist/client/assets/gestureArbiter-Belsq4xq.js.gz +0 -0
- package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-BmrbbyW1.js → gitGraphDiagram-WWUBYQGX-C0H4loQP.js} +1 -1
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-C0H4loQP.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-C0H4loQP.js.gz +0 -0
- package/dist/client/assets/index-CYmI1EsU.css +1 -0
- package/dist/client/assets/index-CYmI1EsU.css.br +0 -0
- package/dist/client/assets/index-CYmI1EsU.css.gz +0 -0
- package/dist/client/assets/{infoDiagram-27XIBGKW-CQEu4Jwy.js → infoDiagram-27XIBGKW-BN4RpQTL.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-BPqibqsm.js → ishikawaDiagram-5VMMS53U-BZQ5qZB_.js} +1 -1
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-BZQ5qZB_.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-BZQ5qZB_.js.gz +0 -0
- package/dist/client/assets/{journeyDiagram-3NMN7TZE-DIkhubnf.js → journeyDiagram-3NMN7TZE-Q8bx0_N4.js} +1 -1
- package/dist/client/assets/journeyDiagram-3NMN7TZE-Q8bx0_N4.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-Q8bx0_N4.js.gz +0 -0
- package/dist/client/assets/{kanban-definition-UXKFOSKX-CBT0DIUR.js → kanban-definition-UXKFOSKX-D7JhGtpO.js} +1 -1
- package/dist/client/assets/kanban-definition-UXKFOSKX-D7JhGtpO.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-D7JhGtpO.js.gz +0 -0
- package/dist/client/assets/{layout-C1CMlOIU.js → layout-DERUg0xU.js} +1 -1
- package/dist/client/assets/layout-DERUg0xU.js.br +0 -0
- package/dist/client/assets/layout-DERUg0xU.js.gz +0 -0
- package/dist/client/assets/{linear-C4gyqor0.js → linear-lNTe4x00.js} +1 -1
- package/dist/client/assets/linear-lNTe4x00.js.br +0 -0
- package/dist/client/assets/linear-lNTe4x00.js.gz +0 -0
- package/dist/client/assets/{mermaid.core-CMfa4ncd.js → mermaid.core-WHCwLQDQ.js} +5 -5
- package/dist/client/assets/mermaid.core-WHCwLQDQ.js.br +0 -0
- package/dist/client/assets/mermaid.core-WHCwLQDQ.js.gz +0 -0
- package/dist/client/assets/{mindmap-definition-YA3MSWOX-C-JmgKOI.js → mindmap-definition-YA3MSWOX-BouapA4v.js} +1 -1
- package/dist/client/assets/mindmap-definition-YA3MSWOX-BouapA4v.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-BouapA4v.js.gz +0 -0
- package/dist/client/assets/{passwordBootstrap-BmUG2IwA.js → passwordBootstrap-E0piP814.js} +1 -1
- package/dist/client/assets/passwordBootstrap-E0piP814.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-E0piP814.js.gz +0 -0
- package/dist/client/assets/{pegDiagram-XKGWAZYB-IY-AEKQa.js → pegDiagram-XKGWAZYB-Curpo5Rq.js} +1 -1
- package/dist/client/assets/pegDiagram-XKGWAZYB-Curpo5Rq.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-Curpo5Rq.js.gz +0 -0
- package/dist/client/assets/{pieDiagram-E7YTZNPT-9Qq43qED.js → pieDiagram-E7YTZNPT-BLQCHaOG.js} +1 -1
- package/dist/client/assets/pieDiagram-E7YTZNPT-BLQCHaOG.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-BLQCHaOG.js.gz +0 -0
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-BjQncx5i.js → quadrantDiagram-AXDQQJYC-PViFqGao.js} +1 -1
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-PViFqGao.js.br +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-PViFqGao.js.gz +0 -0
- package/dist/client/assets/{railroadDiagram-O6MQD6OU-Cr1rL0wZ.js → railroadDiagram-O6MQD6OU-BtHo1LpT.js} +1 -1
- package/dist/client/assets/railroadDiagram-O6MQD6OU-BtHo1LpT.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-BtHo1LpT.js.gz +0 -0
- package/dist/client/assets/rdpSession-O_f9ejOI.js +1 -0
- package/dist/client/assets/rdpSession-O_f9ejOI.js.br +0 -0
- package/dist/client/assets/rdpSession-O_f9ejOI.js.gz +0 -0
- package/dist/client/assets/{referenceLongPress-ConC5-ym.js → referenceLongPress-BZr7Lqzh.js} +1 -1
- package/dist/client/assets/referenceLongPress-BZr7Lqzh.js.br +0 -0
- package/dist/client/assets/referenceLongPress-BZr7Lqzh.js.gz +0 -0
- package/dist/client/assets/{requirementDiagram-BXWQKSXE-DU2q_iZg.js → requirementDiagram-BXWQKSXE-BUm81HUU.js} +1 -1
- package/dist/client/assets/requirementDiagram-BXWQKSXE-BUm81HUU.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-BUm81HUU.js.gz +0 -0
- package/dist/client/assets/rfb-CxsXsMUX.js +5 -0
- package/dist/client/assets/rfb-CxsXsMUX.js.br +0 -0
- package/dist/client/assets/rfb-CxsXsMUX.js.gz +0 -0
- package/dist/client/assets/{sankeyDiagram-P5KCCOFB-BYlx9kXC.js → sankeyDiagram-P5KCCOFB-B-_-aZ_y.js} +1 -1
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-B-_-aZ_y.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-B-_-aZ_y.js.gz +0 -0
- package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-D_uAKme-.js → sequenceDiagram-WJ2MYXX4-DT6LDIfx.js} +1 -1
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DT6LDIfx.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DT6LDIfx.js.gz +0 -0
- package/dist/client/assets/{sizeCapture-INFHLROL-H_uqscf4.js → sizeCapture-INFHLROL-CTYerd9j.js} +1 -1
- package/dist/client/assets/sizeCapture-INFHLROL-CTYerd9j.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-CTYerd9j.js.gz +0 -0
- package/dist/client/assets/{sparkles-D2z4Ue6G.js → sparkles-CgaUBIwH.js} +1 -1
- package/dist/client/assets/{stateDiagram-D77RDMKH-BvsQjIIW.js → stateDiagram-D77RDMKH-CQbb5x2_.js} +1 -1
- package/dist/client/assets/stateDiagram-D77RDMKH-CQbb5x2_.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-CQbb5x2_.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-CJAVXcx1.js +1 -0
- package/dist/client/assets/{swimlanes-42K2YHIH-LmUJag-p.js → swimlanes-42K2YHIH-BHZ4X2Fd.js} +1 -1
- package/dist/client/assets/swimlanes-42K2YHIH-BHZ4X2Fd.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-BHZ4X2Fd.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-VL2nyI27.js +8 -0
- package/dist/client/assets/{timeline-definition-24CTP7MA-DZ5n0Pim.js → timeline-definition-24CTP7MA-BrjH6R6w.js} +1 -1
- package/dist/client/assets/timeline-definition-24CTP7MA-BrjH6R6w.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-BrjH6R6w.js.gz +0 -0
- package/dist/client/assets/{triangle-alert-Ct6iIBmv.js → triangle-alert-C9IHD_eF.js} +1 -1
- package/dist/client/assets/{vennDiagram-4TSXK5OY-BkTA_Ciz.js → vennDiagram-4TSXK5OY-C9f5jYgk.js} +1 -1
- package/dist/client/assets/{vennDiagram-4TSXK5OY-BkTA_Ciz.js.br → vennDiagram-4TSXK5OY-C9f5jYgk.js.br} +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-C9f5jYgk.js.gz +0 -0
- package/dist/client/assets/{videoCompression-VZIoFnyJ.js → videoCompression-DJaU8exd.js} +1 -1
- package/dist/client/assets/videoCompression-DJaU8exd.js.br +0 -0
- package/dist/client/assets/videoCompression-DJaU8exd.js.gz +0 -0
- package/dist/client/assets/{wardleyDiagram-VM6X3IG4-7hzU176j.js → wardleyDiagram-VM6X3IG4-6ljFvtiC.js} +1 -1
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-6ljFvtiC.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-6ljFvtiC.js.gz +0 -0
- package/dist/client/assets/{xychartDiagram-S5SC5T6Z-Bx4P96Bb.js → xychartDiagram-S5SC5T6Z-BaR2hm3e.js} +1 -1
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-BaR2hm3e.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-BaR2hm3e.js.gz +0 -0
- package/dist/client/index.html +2 -2
- package/dist/client/index.html.br +0 -0
- package/dist/client/index.html.gz +0 -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 +45 -4
- package/dist/server/agent/collaborationDeliveryWorker.js +1 -1
- package/dist/server/agent/collaborationGroupRoutes.js +0 -2
- package/dist/server/agent/collaborationPeerTransport.js +8 -2
- package/dist/server/agent/collaborationResultPresentation.js +14 -0
- package/dist/server/agent/collaborationRoutes.js +18 -2
- package/dist/server/agent/collaborationService.js +46 -2
- package/dist/server/agent/collaborationStore.js +12 -21
- package/dist/server/agent/collaborationTaskBundles.js +121 -0
- package/dist/server/agent/collaborationTaskCli.js +54 -0
- package/dist/server/agent/collaborationTaskRoutes.js +58 -0
- package/dist/server/agent/collaborationTaskService.js +355 -0
- package/dist/server/agent/collaborationTaskStore.js +835 -0
- package/dist/server/agent/collaborationTaskTypes.js +1 -0
- package/dist/server/agent/collaborationTaskWorkspace.js +165 -0
- package/dist/server/agent/collaborationTeam.js +16 -0
- package/dist/server/agent/executionArchives.js +52 -0
- package/dist/server/entry.js +17 -2
- package/dist/server/federation/runtime.js +30 -7
- package/dist/server/routes/computer.js +198 -0
- package/dist/server/routes/computerTarget.js +23 -0
- package/dist/server/routes/guacamoleProtocol.js +55 -0
- package/dist/server/routes/rdp.js +162 -0
- package/dist/server/routes/terminal.js +441 -362
- package/dist/server/shared/computerPreferences.js +29 -0
- package/dist/server/utils/computerCredentials.js +88 -0
- package/dist/server/utils/sharedSampling.js +93 -0
- package/dist/server/utils/terminalOutputDelivery.js +8 -1
- package/dist/server/utils/tmuxMetadataWriter.js +61 -0
- package/package.json +4 -1
- package/runtime-manifest.json +4 -4
- package/dist/client/assets/App-D-cerXsD.js +0 -158
- package/dist/client/assets/App-D-cerXsD.js.br +0 -0
- package/dist/client/assets/App-D-cerXsD.js.gz +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-Dv5XRtRh.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-Dv5XRtRh.js.gz +0 -0
- package/dist/client/assets/DagPlayground-mq69dKyr.js.br +0 -0
- package/dist/client/assets/DagPlayground-mq69dKyr.js.gz +0 -0
- package/dist/client/assets/DiffLab-BqdHYGi5.js.br +0 -0
- package/dist/client/assets/DiffLab-BqdHYGi5.js.gz +0 -0
- package/dist/client/assets/DiffReview-BvzGxpuc.js.br +0 -0
- package/dist/client/assets/DiffReview-BvzGxpuc.js.gz +0 -0
- package/dist/client/assets/DiffReviewLab-DrfddB7x.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-DrfddB7x.js.gz +0 -0
- package/dist/client/assets/DiffViewer-3bJV_A5s.js.br +0 -0
- package/dist/client/assets/DiffViewer-3bJV_A5s.js.gz +0 -0
- package/dist/client/assets/ModelPreview-CX7VtoJB.js.br +0 -0
- package/dist/client/assets/ModelPreview-CX7VtoJB.js.gz +0 -0
- package/dist/client/assets/RightSidebar-BK6vWNw3.js +0 -1678
- package/dist/client/assets/RightSidebar-BK6vWNw3.js.br +0 -0
- package/dist/client/assets/RightSidebar-BK6vWNw3.js.gz +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-PJwhLTPH.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-PJwhLTPH.js.gz +0 -0
- package/dist/client/assets/app-C7pXMvSE.js +0 -35
- package/dist/client/assets/app-C7pXMvSE.js.br +0 -0
- package/dist/client/assets/app-C7pXMvSE.js.gz +0 -0
- package/dist/client/assets/arc-l3FXjCEl.js.br +0 -0
- package/dist/client/assets/arc-l3FXjCEl.js.gz +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-DdNbKi-4.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-DdNbKi-4.js.gz +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-Cu63oaxR.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-Cu63oaxR.js.gz +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-DQiV_yk6.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-DQiV_yk6.js.gz +0 -0
- package/dist/client/assets/channel-CwC957gi.js +0 -1
- package/dist/client/assets/chunk-F27PBJKO-sLDCEnU8.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-sLDCEnU8.js.gz +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-DYu5qS7g.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-DYu5qS7g.js.gz +0 -0
- package/dist/client/assets/chunk-SVP7TREG-nJnbUFzs.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-nJnbUFzs.js.gz +0 -0
- package/dist/client/assets/chunk-TICWLB2K-BwyiSQgx.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-BwyiSQgx.js.gz +0 -0
- package/dist/client/assets/classDiagram-ZZMXUADV-CmoJ7-rE.js +0 -1
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-CmoJ7-rE.js +0 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-rroo-EOb.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-rroo-EOb.js.gz +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-CkFeV85k.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-hBwpU_bW.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-hBwpU_bW.js.gz +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-B321-hdp.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-B321-hdp.js.gz +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-bY87_ptA.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-bY87_ptA.js.gz +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN--cez0H_o.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN--cez0H_o.js.gz +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-BupH_VRK.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-BupH_VRK.js.gz +0 -0
- package/dist/client/assets/diagram-VX7I27RA-DewqaxvF.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-DewqaxvF.js.gz +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-wDumcTuR.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-wDumcTuR.js.gz +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-C0OY91We.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-C0OY91We.js.gz +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-Cw9aNqvJ.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-Cw9aNqvJ.js.gz +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-BC7XUXeI.js.gz +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-DovhJIz5.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-DovhJIz5.js.gz +0 -0
- package/dist/client/assets/gestureArbiter-wjVok2Lg.js.br +0 -0
- package/dist/client/assets/gestureArbiter-wjVok2Lg.js.gz +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BmrbbyW1.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BmrbbyW1.js.gz +0 -0
- package/dist/client/assets/index-BeD4iJ6L.css +0 -1
- package/dist/client/assets/index-BeD4iJ6L.css.br +0 -0
- package/dist/client/assets/index-BeD4iJ6L.css.gz +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-BPqibqsm.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-BPqibqsm.js.gz +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DIkhubnf.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DIkhubnf.js.gz +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-CBT0DIUR.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-CBT0DIUR.js.gz +0 -0
- package/dist/client/assets/layout-C1CMlOIU.js.br +0 -0
- package/dist/client/assets/layout-C1CMlOIU.js.gz +0 -0
- package/dist/client/assets/linear-C4gyqor0.js.br +0 -0
- package/dist/client/assets/linear-C4gyqor0.js.gz +0 -0
- package/dist/client/assets/mermaid.core-CMfa4ncd.js.br +0 -0
- package/dist/client/assets/mermaid.core-CMfa4ncd.js.gz +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-C-JmgKOI.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-C-JmgKOI.js.gz +0 -0
- package/dist/client/assets/passwordBootstrap-BmUG2IwA.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-BmUG2IwA.js.gz +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-IY-AEKQa.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-IY-AEKQa.js.gz +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-9Qq43qED.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-9Qq43qED.js.gz +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-BjQncx5i.js.br +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-BjQncx5i.js.gz +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-Cr1rL0wZ.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-Cr1rL0wZ.js.gz +0 -0
- package/dist/client/assets/referenceLongPress-ConC5-ym.js.br +0 -0
- package/dist/client/assets/referenceLongPress-ConC5-ym.js.gz +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-DU2q_iZg.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-DU2q_iZg.js.gz +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BYlx9kXC.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BYlx9kXC.js.gz +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D_uAKme-.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D_uAKme-.js.gz +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-H_uqscf4.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-H_uqscf4.js.gz +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-BvsQjIIW.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-BvsQjIIW.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-DNgoExtD.js +0 -1
- package/dist/client/assets/swimlanes-42K2YHIH-LmUJag-p.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-LmUJag-p.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-BRuArMR5.js +0 -8
- package/dist/client/assets/timeline-definition-24CTP7MA-DZ5n0Pim.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-DZ5n0Pim.js.gz +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-BkTA_Ciz.js.gz +0 -0
- package/dist/client/assets/videoCompression-VZIoFnyJ.js.br +0 -0
- package/dist/client/assets/videoCompression-VZIoFnyJ.js.gz +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-7hzU176j.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-7hzU176j.js.gz +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-Bx4P96Bb.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-Bx4P96Bb.js.gz +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function defaultComputerPreferences(os) {
|
|
2
|
+
const platform = os === 'darwin' ? 'mac' : os === 'win32' ? 'windows' : 'linux';
|
|
3
|
+
const profile = { host: '127.0.0.1', platform, protocol: platform === 'mac' ? 'vnc' : 'rdp', port: '3389', username: '', domain: '', ignoreCert: false, rememberLogin: true };
|
|
4
|
+
return { target: 'local', local: profile, remote: { ...profile, host: '' }, viewOnly: false, fit: true, autoConnect: true };
|
|
5
|
+
}
|
|
6
|
+
/** Project only non-secret, supported fields, including when reading old files. */
|
|
7
|
+
export function computerPreferences(value, os) {
|
|
8
|
+
const defaults = defaultComputerPreferences(os);
|
|
9
|
+
if (!value || typeof value !== 'object')
|
|
10
|
+
return defaults;
|
|
11
|
+
const raw = value;
|
|
12
|
+
const profile = (value, fallback) => {
|
|
13
|
+
const p = value && typeof value === 'object' ? value : {};
|
|
14
|
+
const text = (key, limit) => typeof p[key] === 'string' && p[key].length <= limit && !/[\x00-\x1f]/.test(p[key]) ? p[key] : fallback[key];
|
|
15
|
+
return {
|
|
16
|
+
host: text('host', 253), username: text('username', 255), domain: text('domain', 255),
|
|
17
|
+
platform: ['mac', 'linux', 'windows'].includes(String(p.platform)) ? p.platform : fallback.platform,
|
|
18
|
+
protocol: p.protocol === 'rdp' || p.protocol === 'vnc' ? p.protocol : fallback.protocol,
|
|
19
|
+
port: typeof p.port === 'string' && /^\d{0,5}$/.test(p.port) && Number(p.port) <= 65535 ? p.port : fallback.port,
|
|
20
|
+
ignoreCert: p.ignoreCert === true,
|
|
21
|
+
rememberLogin: p.rememberLogin !== false,
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
return { target: raw.target === 'remote' ? 'remote' : 'local', local: { ...profile(raw.local, defaults.local), host: '127.0.0.1' }, remote: profile(raw.remote, defaults.remote), viewOnly: raw.viewOnly === true, fit: raw.fit !== false, autoConnect: raw.autoConnect !== false };
|
|
25
|
+
}
|
|
26
|
+
/** Identity binding deliberately excludes display and certificate preferences. */
|
|
27
|
+
export function computerLoginKey(profile) {
|
|
28
|
+
return JSON.stringify([profile.host.trim().toLowerCase(), profile.protocol, profile.protocol === 'vnc' ? 5900 : Number(profile.port), profile.username.trim(), profile.domain.trim()]);
|
|
29
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, chmodSync, unlinkSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { computerLoginKey } from '../shared/computerPreferences.js';
|
|
6
|
+
/** Credentials are independent of ordinary settings, encrypted and owner-readable. */
|
|
7
|
+
export class ComputerCredentialStore {
|
|
8
|
+
directory;
|
|
9
|
+
file;
|
|
10
|
+
keyFile;
|
|
11
|
+
constructor(directory = join(homedir(), '.termdock')) {
|
|
12
|
+
this.directory = directory;
|
|
13
|
+
this.file = join(directory, 'computer-credentials.json');
|
|
14
|
+
this.keyFile = join(directory, 'computer-credentials.key');
|
|
15
|
+
}
|
|
16
|
+
id(profile) { return createHash('sha256').update(computerLoginKey(profile)).digest('hex'); }
|
|
17
|
+
records() {
|
|
18
|
+
if (!existsSync(this.file))
|
|
19
|
+
return {};
|
|
20
|
+
const bytes = readFileSync(this.file);
|
|
21
|
+
if (bytes.length > 1024 * 1024)
|
|
22
|
+
throw new Error('COMPUTER_CREDENTIALS_READ_FAILED');
|
|
23
|
+
const data = JSON.parse(bytes.toString());
|
|
24
|
+
if (!data || typeof data !== 'object' || Array.isArray(data))
|
|
25
|
+
throw new Error('COMPUTER_CREDENTIALS_READ_FAILED');
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
key() {
|
|
29
|
+
if (!existsSync(this.keyFile)) {
|
|
30
|
+
if (existsSync(this.file))
|
|
31
|
+
throw new Error('COMPUTER_CREDENTIALS_KEY_MISSING');
|
|
32
|
+
mkdirSync(this.directory, { recursive: true, mode: 0o700 });
|
|
33
|
+
try {
|
|
34
|
+
writeFileSync(this.keyFile, randomBytes(32), { flag: 'wx', mode: 0o600 });
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
if (error.code !== 'EEXIST')
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const key = readFileSync(this.keyFile);
|
|
42
|
+
if (key.length !== 32)
|
|
43
|
+
throw new Error('COMPUTER_CREDENTIALS_KEY_INVALID');
|
|
44
|
+
chmodSync(this.keyFile, 0o600);
|
|
45
|
+
return key;
|
|
46
|
+
}
|
|
47
|
+
write(records) {
|
|
48
|
+
mkdirSync(this.directory, { recursive: true, mode: 0o700 });
|
|
49
|
+
const temporary = `${this.file}.${randomBytes(8).toString('hex')}.tmp`;
|
|
50
|
+
try {
|
|
51
|
+
writeFileSync(temporary, JSON.stringify(records), { flag: 'wx', mode: 0o600 });
|
|
52
|
+
renameSync(temporary, this.file);
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
if (existsSync(temporary))
|
|
56
|
+
unlinkSync(temporary);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
has(profile) { return Boolean(this.records()[this.id(profile)]); }
|
|
60
|
+
get(profile) {
|
|
61
|
+
const id = this.id(profile), record = this.records()[id];
|
|
62
|
+
if (!record)
|
|
63
|
+
return null;
|
|
64
|
+
const decipher = createDecipheriv('aes-256-gcm', this.key(), Buffer.from(record.iv, 'base64'));
|
|
65
|
+
decipher.setAAD(Buffer.from(id));
|
|
66
|
+
decipher.setAuthTag(Buffer.from(record.tag, 'base64'));
|
|
67
|
+
return Buffer.concat([decipher.update(Buffer.from(record.ciphertext, 'base64')), decipher.final()]).toString();
|
|
68
|
+
}
|
|
69
|
+
save(profile, password) {
|
|
70
|
+
if (!password || password.length > 1024 || password.includes('\0'))
|
|
71
|
+
throw new Error('INVALID_COMPUTER_CREDENTIALS');
|
|
72
|
+
const records = this.records(), id = this.id(profile), iv = randomBytes(12);
|
|
73
|
+
const cipher = createCipheriv('aes-256-gcm', this.key(), iv);
|
|
74
|
+
cipher.setAAD(Buffer.from(id));
|
|
75
|
+
const ciphertext = Buffer.concat([cipher.update(password, 'utf8'), cipher.final()]);
|
|
76
|
+
if (!records[id] && Object.keys(records).length >= 64)
|
|
77
|
+
delete records[Object.keys(records)[0]];
|
|
78
|
+
records[id] = { iv: iv.toString('base64'), tag: cipher.getAuthTag().toString('base64'), ciphertext: ciphertext.toString('base64') };
|
|
79
|
+
this.write(records);
|
|
80
|
+
}
|
|
81
|
+
forget(profile) {
|
|
82
|
+
const records = this.records(), id = this.id(profile);
|
|
83
|
+
if (!records[id])
|
|
84
|
+
return;
|
|
85
|
+
delete records[id];
|
|
86
|
+
this.write(records);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/** Bounded snapshots with one refresh per key, including forced refreshes.
|
|
2
|
+
* Failures are never cached; a later observation can retry immediately. */
|
|
3
|
+
export class SharedSnapshotCache {
|
|
4
|
+
ttlMs;
|
|
5
|
+
maxEntries;
|
|
6
|
+
entries = new Map();
|
|
7
|
+
pending = new Map();
|
|
8
|
+
constructor(ttlMs, maxEntries = 256) {
|
|
9
|
+
this.ttlMs = ttlMs;
|
|
10
|
+
this.maxEntries = maxEntries;
|
|
11
|
+
}
|
|
12
|
+
get(key, load, refresh = false) {
|
|
13
|
+
const pending = this.pending.get(key);
|
|
14
|
+
if (pending)
|
|
15
|
+
return pending;
|
|
16
|
+
const entry = this.entries.get(key);
|
|
17
|
+
if (!refresh && entry && Date.now() - entry.at < this.ttlMs)
|
|
18
|
+
return Promise.resolve(entry.value);
|
|
19
|
+
const promise = Promise.resolve().then(load).then(value => {
|
|
20
|
+
this.entries.delete(key);
|
|
21
|
+
this.entries.set(key, { value, at: Date.now() });
|
|
22
|
+
while (this.entries.size > this.maxEntries)
|
|
23
|
+
this.entries.delete(this.entries.keys().next().value);
|
|
24
|
+
return value;
|
|
25
|
+
}).finally(() => { this.pending.delete(key); });
|
|
26
|
+
this.pending.set(key, promise);
|
|
27
|
+
return promise;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** One non-overlapping sampler per session. Observers receive a full initial
|
|
31
|
+
* snapshot and subsequent changes, including observers joining during a poll. */
|
|
32
|
+
export class SharedSessionSampler {
|
|
33
|
+
sample;
|
|
34
|
+
intervalMs;
|
|
35
|
+
onError;
|
|
36
|
+
observers = new Set();
|
|
37
|
+
latest = new Map();
|
|
38
|
+
timer = null;
|
|
39
|
+
pending = null;
|
|
40
|
+
epoch = 0;
|
|
41
|
+
constructor(sample, intervalMs, onError) {
|
|
42
|
+
this.sample = sample;
|
|
43
|
+
this.intervalMs = intervalMs;
|
|
44
|
+
this.onError = onError;
|
|
45
|
+
}
|
|
46
|
+
subscribe(observer) {
|
|
47
|
+
this.observers.add(observer);
|
|
48
|
+
for (const { event } of this.latest.values())
|
|
49
|
+
observer(event);
|
|
50
|
+
if (!this.timer) {
|
|
51
|
+
this.timer = setInterval(() => { void this.poll(); }, this.intervalMs());
|
|
52
|
+
this.timer.unref?.();
|
|
53
|
+
void this.poll();
|
|
54
|
+
}
|
|
55
|
+
return () => {
|
|
56
|
+
this.observers.delete(observer);
|
|
57
|
+
if (this.observers.size === 0)
|
|
58
|
+
this.stop();
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
stop() {
|
|
62
|
+
this.epoch += 1;
|
|
63
|
+
if (this.timer)
|
|
64
|
+
clearInterval(this.timer);
|
|
65
|
+
this.timer = null;
|
|
66
|
+
this.latest.clear();
|
|
67
|
+
this.observers.clear();
|
|
68
|
+
}
|
|
69
|
+
poll() {
|
|
70
|
+
if (this.pending)
|
|
71
|
+
return this.pending;
|
|
72
|
+
const epoch = this.epoch;
|
|
73
|
+
this.pending = Promise.resolve().then(this.sample).then(events => {
|
|
74
|
+
if (epoch !== this.epoch)
|
|
75
|
+
return;
|
|
76
|
+
for (const event of events) {
|
|
77
|
+
const signature = JSON.stringify(event);
|
|
78
|
+
if (this.latest.get(event.type)?.signature === signature)
|
|
79
|
+
continue;
|
|
80
|
+
this.latest.set(event.type, { event, signature });
|
|
81
|
+
for (const observer of this.observers) {
|
|
82
|
+
try {
|
|
83
|
+
observer(event);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
this.onError(error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}).catch(this.onError).finally(() => { this.pending = null; });
|
|
91
|
+
return this.pending;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -8,6 +8,7 @@ export class TerminalOutputDelivery {
|
|
|
8
8
|
active = true;
|
|
9
9
|
replaying = true;
|
|
10
10
|
needsReplay = false;
|
|
11
|
+
paused = false;
|
|
11
12
|
queue = [];
|
|
12
13
|
queuedBytes = 0;
|
|
13
14
|
outstanding = [];
|
|
@@ -30,6 +31,12 @@ export class TerminalOutputDelivery {
|
|
|
30
31
|
}
|
|
31
32
|
return changed;
|
|
32
33
|
}
|
|
34
|
+
/** Short flow-control pauses retain the ordered stream within its budget.
|
|
35
|
+
* Unlike an unsubscribe, they do not discard output or require a new PTY. */
|
|
36
|
+
setPaused(paused) {
|
|
37
|
+
this.paused = paused;
|
|
38
|
+
this.flush();
|
|
39
|
+
}
|
|
33
40
|
enqueue(frame) {
|
|
34
41
|
if (!this.active || this.needsReplay)
|
|
35
42
|
return;
|
|
@@ -68,7 +75,7 @@ export class TerminalOutputDelivery {
|
|
|
68
75
|
}
|
|
69
76
|
get pendingBytes() { return this.queuedBytes + this.outstandingBytes; }
|
|
70
77
|
flush() {
|
|
71
|
-
if (!this.active || this.replaying || this.needsReplay)
|
|
78
|
+
if (!this.active || this.paused || this.replaying || this.needsReplay)
|
|
72
79
|
return;
|
|
73
80
|
while (this.queue.length && (!this.flowControl || this.outstandingBytes < this.windowBytes)) {
|
|
74
81
|
const frame = this.queue.shift();
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export function batchTmuxOptions(name, options) {
|
|
2
|
+
const args = [];
|
|
3
|
+
// tmux parses a trailing semicolon as a command separator even when argv
|
|
4
|
+
// came from execFile. Escape data arguments, leaving our separators intact.
|
|
5
|
+
const literal = (value) => value.endsWith(';') ? `${value.slice(0, -1)}\\;` : value;
|
|
6
|
+
for (const [key, value] of Object.entries(options)) {
|
|
7
|
+
if (args.length)
|
|
8
|
+
args.push(';');
|
|
9
|
+
args.push('set-option', '-t', literal(name), key, literal(value));
|
|
10
|
+
}
|
|
11
|
+
return args;
|
|
12
|
+
}
|
|
13
|
+
/** Deduplicate across observers and inventory. Keep only the newest desired
|
|
14
|
+
* state during a slow write; commit the snapshot only after a successful write. */
|
|
15
|
+
export class TmuxMetadataWriter {
|
|
16
|
+
write;
|
|
17
|
+
heartbeatMs;
|
|
18
|
+
states = new Map();
|
|
19
|
+
constructor(write, heartbeatMs = 30_000) {
|
|
20
|
+
this.write = write;
|
|
21
|
+
this.heartbeatMs = heartbeatMs;
|
|
22
|
+
}
|
|
23
|
+
sync(name, metadata) {
|
|
24
|
+
let state = this.states.get(name);
|
|
25
|
+
if (!state) {
|
|
26
|
+
state = { desired: metadata, at: 0 };
|
|
27
|
+
this.states.set(name, state);
|
|
28
|
+
}
|
|
29
|
+
state.desired = metadata;
|
|
30
|
+
if (state.pending)
|
|
31
|
+
return state.pending;
|
|
32
|
+
const current = state;
|
|
33
|
+
current.pending = Promise.resolve().then(async () => {
|
|
34
|
+
while (this.states.get(name) === current) {
|
|
35
|
+
const desired = current.desired;
|
|
36
|
+
const signature = JSON.stringify(desired);
|
|
37
|
+
const changed = signature !== current.written;
|
|
38
|
+
const now = Date.now();
|
|
39
|
+
if (!changed && now - current.at < this.heartbeatMs)
|
|
40
|
+
return;
|
|
41
|
+
await this.write(name, {
|
|
42
|
+
...(changed ? {
|
|
43
|
+
'@termdock-label': desired.label,
|
|
44
|
+
'@termdock-program': desired.program ?? '',
|
|
45
|
+
'@termdock-cwd': desired.cwd ?? '',
|
|
46
|
+
} : {}),
|
|
47
|
+
'@termdock-last-active-at': String(now),
|
|
48
|
+
});
|
|
49
|
+
current.written = signature;
|
|
50
|
+
current.at = now;
|
|
51
|
+
}
|
|
52
|
+
}).finally(() => { current.pending = undefined; });
|
|
53
|
+
return current.pending;
|
|
54
|
+
}
|
|
55
|
+
retain(names) {
|
|
56
|
+
for (const name of this.states.keys())
|
|
57
|
+
if (!names.has(name))
|
|
58
|
+
this.states.delete(name);
|
|
59
|
+
}
|
|
60
|
+
forget(name) { this.states.delete(name); }
|
|
61
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "termdock",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.297",
|
|
4
4
|
"description": "A complete web-based terminal application with modern UI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": ".desktop-dist/main.js",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"@libp2p/peer-id": "6.0.0",
|
|
58
58
|
"@libp2p/utils": "7.0.7",
|
|
59
59
|
"@noble/hashes": "2.4.0",
|
|
60
|
+
"@novnc/novnc": "^1.7.0",
|
|
60
61
|
"@serenity-kit/opaque": "1.1.0",
|
|
61
62
|
"@types/cookie-parser": "^1.4.10",
|
|
62
63
|
"@types/csurf": "^1.11.5",
|
|
@@ -80,6 +81,7 @@
|
|
|
80
81
|
"dompurify": "^3.4.14",
|
|
81
82
|
"dotenv": "^17.4.2",
|
|
82
83
|
"express": "^5.2.1",
|
|
84
|
+
"guacamole-common-js": "^1.5.0",
|
|
83
85
|
"heic-convert": "^2.1.0",
|
|
84
86
|
"katex": "^0.17.0",
|
|
85
87
|
"lucide-react": "^1.17.0",
|
|
@@ -108,6 +110,7 @@
|
|
|
108
110
|
"@testing-library/user-event": "^14.5.0",
|
|
109
111
|
"@types/busboy": "^1.5.4",
|
|
110
112
|
"@types/express": "^4.17.21",
|
|
113
|
+
"@types/guacamole-common-js": "^1.5.5",
|
|
111
114
|
"@types/heic-convert": "^2.1.1",
|
|
112
115
|
"@types/node": "^20.11.0",
|
|
113
116
|
"@types/react": "^18.2.0",
|
package/runtime-manifest.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"packageName": "termdock",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.297",
|
|
5
5
|
"runtimeProtocolVersion": 1,
|
|
6
6
|
"minimumDesktopVersion": "1.4.46",
|
|
7
7
|
"nodeMajor": 22,
|
|
8
|
-
"dependencyHash": "sha256
|
|
9
|
-
"serverBundleHash": "sha256-
|
|
10
|
-
"clientBundleHash": "sha256-
|
|
8
|
+
"dependencyHash": "sha256-E9GDa4nrCXADRXdyPKufusZt6IcCr4m2mGdx5h34KMQ=",
|
|
9
|
+
"serverBundleHash": "sha256-3VqbogIbygH3YPQHa9IyJIP/n0q0heoRoeYit4ahVs0=",
|
|
10
|
+
"clientBundleHash": "sha256-NncnQcLTlh41QmOg641M52b31XtLTqRYlKA4THOcVEY=",
|
|
11
11
|
"entrypoint": "dist/server/cli.js",
|
|
12
12
|
"clientEntrypoint": "dist/client/index.html"
|
|
13
13
|
}
|