termdock 1.4.356 → 1.4.357
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/README.md +22 -4
- package/dist/client/assets/AndroidMirrorView-BGagwKtL.js +3 -0
- package/dist/client/assets/AndroidMirrorView-BGagwKtL.js.br +0 -0
- package/dist/client/assets/AndroidMirrorView-BGagwKtL.js.gz +0 -0
- package/dist/client/assets/App-DpMhxwYW.js +178 -0
- package/dist/client/assets/App-DpMhxwYW.js.br +0 -0
- package/dist/client/assets/App-DpMhxwYW.js.gz +0 -0
- package/dist/client/assets/ArchitecturePanel-Bd_l74EC.js +9 -0
- package/dist/client/assets/ArchitecturePanel-Bd_l74EC.js.br +0 -0
- package/dist/client/assets/ArchitecturePanel-Bd_l74EC.js.gz +0 -0
- package/dist/client/assets/{ChangeWalkthroughPanel-DO_zJfZr.js → ChangeWalkthroughPanel-6DN-2BdR.js} +2 -2
- package/dist/client/assets/ChangeWalkthroughPanel-6DN-2BdR.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-6DN-2BdR.js.gz +0 -0
- package/dist/client/assets/{ChatRichContent-Cu1E1cJ8.js → ChatRichContent-DjwpmW7d.js} +29 -29
- package/dist/client/assets/ChatRichContent-DjwpmW7d.js.br +0 -0
- package/dist/client/assets/ChatRichContent-DjwpmW7d.js.gz +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-DPTJ9pCt.js +1 -0
- package/dist/client/assets/CollaborationMainWorkspace-DPTJ9pCt.js.br +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-DPTJ9pCt.js.gz +0 -0
- package/dist/client/assets/CollaborationTaskContent-Cbu1Bjl0.js +1 -0
- package/dist/client/assets/ComputerControlView-CwB-wQqB.js +6 -0
- package/dist/client/assets/ComputerControlView-CwB-wQqB.js.br +0 -0
- package/dist/client/assets/ComputerControlView-CwB-wQqB.js.gz +0 -0
- package/dist/client/assets/{DagPlayground-CPYwfryM.js → DagPlayground-DMn9Gyrw.js} +1 -1
- package/dist/client/assets/DagPlayground-DMn9Gyrw.js.br +0 -0
- package/dist/client/assets/DagPlayground-DMn9Gyrw.js.gz +0 -0
- package/dist/client/assets/{DiffLab-ptw96Q_4.js → DiffLab-YBWlCU2T.js} +1 -1
- package/dist/client/assets/DiffLab-YBWlCU2T.js.br +0 -0
- package/dist/client/assets/DiffLab-YBWlCU2T.js.gz +0 -0
- package/dist/client/assets/DiffReview-YOPDWqhv.js +1 -0
- package/dist/client/assets/DiffReview-YOPDWqhv.js.br +0 -0
- package/dist/client/assets/DiffReview-YOPDWqhv.js.gz +0 -0
- package/dist/client/assets/{DiffReviewLab-eEi3y-0G.js → DiffReviewLab-SYomq14c.js} +1 -1
- package/dist/client/assets/DiffReviewLab-SYomq14c.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-SYomq14c.js.gz +0 -0
- package/dist/client/assets/{DiffViewer-DqcQxp4Q.js → DiffViewer-mh9cBl5v.js} +1 -1
- package/dist/client/assets/DiffViewer-mh9cBl5v.js.br +0 -0
- package/dist/client/assets/DiffViewer-mh9cBl5v.js.gz +0 -0
- package/dist/client/assets/{GitLoadingSkeleton-DYrDIDF1.js → GitLoadingSkeleton-DKRTc5sz.js} +1 -1
- package/dist/client/assets/GitLoadingSkeleton-DKRTc5sz.js.br +0 -0
- package/dist/client/assets/GitLoadingSkeleton-DKRTc5sz.js.gz +0 -0
- package/dist/client/assets/Markdown-C8OP1j-g.js +23 -0
- package/dist/client/assets/Markdown-C8OP1j-g.js.br +0 -0
- package/dist/client/assets/Markdown-C8OP1j-g.js.gz +0 -0
- package/dist/client/assets/Markdown-DKQhs57e.css +1 -0
- package/dist/client/assets/Markdown-DKQhs57e.css.br +0 -0
- package/dist/client/assets/Markdown-DKQhs57e.css.gz +0 -0
- package/dist/client/assets/{ModelPreview-DjtHLlqP.js → ModelPreview-CsZry3Wd.js} +3 -3
- package/dist/client/assets/ModelPreview-CsZry3Wd.js.br +0 -0
- package/dist/client/assets/ModelPreview-CsZry3Wd.js.gz +0 -0
- package/dist/client/assets/RecordingSaveDialog-CoRGi97z.js +1 -0
- package/dist/client/assets/RecordingSaveDialog-CoRGi97z.js.br +0 -0
- package/dist/client/assets/RecordingSaveDialog-CoRGi97z.js.gz +0 -0
- package/dist/client/assets/RightSidebar-DNY2kC6B.js +1662 -0
- package/dist/client/assets/RightSidebar-DNY2kC6B.js.br +0 -0
- package/dist/client/assets/RightSidebar-DNY2kC6B.js.gz +0 -0
- package/dist/client/assets/SessionChatView-DXNpYUrk.js +13 -0
- package/dist/client/assets/SessionChatView-DXNpYUrk.js.br +0 -0
- package/dist/client/assets/SessionChatView-DXNpYUrk.js.gz +0 -0
- package/dist/client/assets/SessionResourceSidebar-B_379HBJ.js +2 -0
- package/dist/client/assets/SessionResourceSidebar-B_379HBJ.js.br +0 -0
- package/dist/client/assets/SessionResourceSidebar-B_379HBJ.js.gz +0 -0
- package/dist/client/assets/TodoWorkspace-DfwGOAHB.js +1 -0
- package/dist/client/assets/TodoWorkspace-DfwGOAHB.js.br +0 -0
- package/dist/client/assets/TodoWorkspace-DfwGOAHB.js.gz +0 -0
- package/dist/client/assets/{abnfDiagram-VCTEODGH-Cvf_KWZ0.js → abnfDiagram-VCTEODGH-C9M0gnl-.js} +1 -1
- package/dist/client/assets/abnfDiagram-VCTEODGH-C9M0gnl-.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-C9M0gnl-.js.gz +0 -0
- package/dist/client/assets/app-CovJYQoW.js +37 -0
- package/dist/client/assets/app-CovJYQoW.js.br +0 -0
- package/dist/client/assets/app-CovJYQoW.js.gz +0 -0
- package/dist/client/assets/{arc-UvdowQOf.js → arc-q4wfkQcT.js} +1 -1
- package/dist/client/assets/arc-q4wfkQcT.js.br +0 -0
- package/dist/client/assets/arc-q4wfkQcT.js.gz +0 -0
- package/dist/client/assets/{architectureDiagram-5GKGNRK7-DotsbCCA.js → architectureDiagram-5GKGNRK7-CCuna3ab.js} +1 -1
- package/dist/client/assets/architectureDiagram-5GKGNRK7-CCuna3ab.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-CCuna3ab.js.gz +0 -0
- package/dist/client/assets/{arrow-down-FGzRy9D-.js → arrow-down-WyzmLXwQ.js} +1 -1
- package/dist/client/assets/{blockDiagram-I7D4REHJ-CoOfSG4k.js → blockDiagram-I7D4REHJ-BXK68Qyt.js} +1 -1
- package/dist/client/assets/blockDiagram-I7D4REHJ-BXK68Qyt.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-BXK68Qyt.js.gz +0 -0
- package/dist/client/assets/{c4Diagram-7LVT6UL2-BAfjgs8B.js → c4Diagram-7LVT6UL2-BqwmmVmS.js} +1 -1
- package/dist/client/assets/c4Diagram-7LVT6UL2-BqwmmVmS.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-BqwmmVmS.js.gz +0 -0
- package/dist/client/assets/channel-Dd6WQGB7.js +1 -0
- package/dist/client/assets/{chevron-left-xqARwD-7.js → chevron-left-CxeWIsDK.js} +1 -1
- package/dist/client/assets/{chunk-2Q5K7J3B-DiiQ7BvG.js → chunk-2Q5K7J3B-esKGR38U.js} +1 -1
- package/dist/client/assets/{chunk-5VM5RSS4-CczSK8wW.js → chunk-5VM5RSS4-B3InxqDA.js} +1 -1
- package/dist/client/assets/{chunk-F27PBJKO-BI3Di4Ve.js → chunk-F27PBJKO-CjUVyF-E.js} +1 -1
- package/dist/client/assets/chunk-F27PBJKO-CjUVyF-E.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-CjUVyF-E.js.gz +0 -0
- package/dist/client/assets/{chunk-IMKFNOWR-Cvvs1wmn.js → chunk-IMKFNOWR-BR8mmBs7.js} +1 -1
- package/dist/client/assets/chunk-IMKFNOWR-BR8mmBs7.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-BR8mmBs7.js.gz +0 -0
- package/dist/client/assets/{chunk-JWPE2WC7-lrJRD9WA.js → chunk-JWPE2WC7-CplXNOA7.js} +1 -1
- package/dist/client/assets/{chunk-POPQ4Y6H-CnPC9D8B.js → chunk-POPQ4Y6H-D0JWCGnb.js} +1 -1
- package/dist/client/assets/{chunk-SVP7TREG-BZfMhm64.js → chunk-SVP7TREG-BdJtJSmy.js} +1 -1
- package/dist/client/assets/chunk-SVP7TREG-BdJtJSmy.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-BdJtJSmy.js.gz +0 -0
- package/dist/client/assets/{chunk-TICWLB2K-DmkEaRK3.js → chunk-TICWLB2K-CoevFj8I.js} +1 -1
- package/dist/client/assets/chunk-TICWLB2K-CoevFj8I.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-CoevFj8I.js.gz +0 -0
- package/dist/client/assets/{chunk-XXDRQBXY-BP9Lccpe.js → chunk-XXDRQBXY-D7qYRhMH.js} +1 -1
- package/dist/client/assets/{circle-DGZOpG8V.js → circle-xgKDXpwG.js} +1 -1
- package/dist/client/assets/classDiagram-ZZMXUADV-BdIUq_D7.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-BdIUq_D7.js +1 -0
- package/dist/client/assets/{clipboard-rLx5CzbY.js → clipboard-DeK6pJD3.js} +1 -1
- package/dist/client/assets/clipboardText-BWOwer6N.js +1 -0
- package/dist/client/assets/clipboardText-BWOwer6N.js.br +0 -0
- package/dist/client/assets/clipboardText-BWOwer6N.js.gz +0 -0
- package/dist/client/assets/clipboardText-vX90C7eX.css +1 -0
- package/dist/client/assets/clipboardText-vX90C7eX.css.br +0 -0
- package/dist/client/assets/clipboardText-vX90C7eX.css.gz +0 -0
- package/dist/client/assets/{cose-bilkent-JH36ORCC-0xPYMc2z.js → cose-bilkent-JH36ORCC-CvnsiaWP.js} +1 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-CvnsiaWP.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-CvnsiaWP.js.gz +0 -0
- package/dist/client/assets/{cynefin-OW5HDTMX-BQ7-lCHm.js → cynefin-OW5HDTMX-BSGz8Olu.js} +1 -1
- package/dist/client/assets/cynefin-OW5HDTMX-BSGz8Olu.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-BSGz8Olu.js.gz +0 -0
- package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-CazHuSj1.js → cynefinDiagram-5FMLGOSQ-DYYT0AHs.js} +1 -1
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-DYYT0AHs.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-DYYT0AHs.js.gz +0 -0
- package/dist/client/assets/{dagre-GXQ25YYZ-CJNgsyHQ.js → dagre-GXQ25YYZ-BM883MN7.js} +1 -1
- package/dist/client/assets/dagre-GXQ25YYZ-BM883MN7.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-BM883MN7.js.gz +0 -0
- package/dist/client/assets/{diagram-S7CK7UJ4-D4xXIj1P.js → diagram-S7CK7UJ4-CYnxXy7R.js} +1 -1
- package/dist/client/assets/diagram-S7CK7UJ4-CYnxXy7R.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-CYnxXy7R.js.gz +0 -0
- package/dist/client/assets/{diagram-UQ7AKVKN-BWhpL-35.js → diagram-UQ7AKVKN-UOIBVxRf.js} +1 -1
- package/dist/client/assets/diagram-UQ7AKVKN-UOIBVxRf.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-UOIBVxRf.js.gz +0 -0
- package/dist/client/assets/{diagram-VSXAHHWV-DG9A7EgJ.js → diagram-VSXAHHWV-CqTJzfmm.js} +1 -1
- package/dist/client/assets/diagram-VSXAHHWV-CqTJzfmm.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-CqTJzfmm.js.gz +0 -0
- package/dist/client/assets/{diagram-VX7I27RA-L5PSvynM.js → diagram-VX7I27RA-T9Y88CFB.js} +1 -1
- package/dist/client/assets/diagram-VX7I27RA-T9Y88CFB.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-T9Y88CFB.js.gz +0 -0
- package/dist/client/assets/{diagram-Z3DM3KII-moBH7ruR.js → diagram-Z3DM3KII-kIQDy7E0.js} +1 -1
- package/dist/client/assets/diagram-Z3DM3KII-kIQDy7E0.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-kIQDy7E0.js.gz +0 -0
- package/dist/client/assets/{ebnfDiagram-PWID7BFC-DEiGgcRP.js → ebnfDiagram-PWID7BFC-z_VqR_JE.js} +1 -1
- package/dist/client/assets/ebnfDiagram-PWID7BFC-z_VqR_JE.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-z_VqR_JE.js.gz +0 -0
- package/dist/client/assets/{erDiagram-RLTQ6QDP-BboIleYi.js → erDiagram-RLTQ6QDP-0q52Z-pm.js} +1 -1
- package/dist/client/assets/erDiagram-RLTQ6QDP-0q52Z-pm.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-0q52Z-pm.js.gz +0 -0
- package/dist/client/assets/{external-link-AZ3wjUg5.js → external-link-CsydVmO1.js} +1 -1
- package/dist/client/assets/{flowDiagram-HODETNUW-COxz7Rda.js → flowDiagram-HODETNUW-BrGqcUWn.js} +1 -1
- package/dist/client/assets/flowDiagram-HODETNUW-BrGqcUWn.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-BrGqcUWn.js.gz +0 -0
- package/dist/client/assets/{ganttDiagram-EL5Y4UJY-_XdRvgyZ.js → ganttDiagram-EL5Y4UJY-CHAN6vQv.js} +1 -1
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-CHAN6vQv.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-CHAN6vQv.js.gz +0 -0
- package/dist/client/assets/{git-compare-90v75Jal.js → git-compare-BmKAtQTt.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-CBb9xBNW.js → gitGraphDiagram-WWUBYQGX-C0ZV4FeB.js} +1 -1
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-C0ZV4FeB.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-C0ZV4FeB.js.gz +0 -0
- package/dist/client/assets/index-DEAMSl55.css +1 -0
- package/dist/client/assets/index-DEAMSl55.css.br +0 -0
- package/dist/client/assets/index-DEAMSl55.css.gz +0 -0
- package/dist/client/assets/{infoDiagram-27XIBGKW-DjLdeNZi.js → infoDiagram-27XIBGKW-CrLj9y1o.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-Bcr-lhIE.js → ishikawaDiagram-5VMMS53U-BxGvUfLX.js} +1 -1
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-BxGvUfLX.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-BxGvUfLX.js.gz +0 -0
- package/dist/client/assets/{journeyDiagram-3NMN7TZE-3vK6s9Pq.js → journeyDiagram-3NMN7TZE-rW9xlQ8G.js} +1 -1
- package/dist/client/assets/journeyDiagram-3NMN7TZE-rW9xlQ8G.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-rW9xlQ8G.js.gz +0 -0
- package/dist/client/assets/{kanban-definition-UXKFOSKX-DqDYDca0.js → kanban-definition-UXKFOSKX-CFI5iv9R.js} +1 -1
- package/dist/client/assets/kanban-definition-UXKFOSKX-CFI5iv9R.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-CFI5iv9R.js.gz +0 -0
- package/dist/client/assets/{layout-C7_WwzCP.js → layout-Ct_an5XT.js} +1 -1
- package/dist/client/assets/layout-Ct_an5XT.js.br +0 -0
- package/dist/client/assets/layout-Ct_an5XT.js.gz +0 -0
- package/dist/client/assets/{linear-BQCRhl6P.js → linear-DpEFOA9l.js} +1 -1
- package/dist/client/assets/linear-DpEFOA9l.js.br +0 -0
- package/dist/client/assets/linear-DpEFOA9l.js.gz +0 -0
- package/dist/client/assets/{link-Cq14tNBm.js → link-34ChBc4F.js} +3 -3
- package/dist/client/assets/{link-Cq14tNBm.js.br → link-34ChBc4F.js.br} +0 -0
- package/dist/client/assets/link-34ChBc4F.js.gz +0 -0
- package/dist/client/assets/{list-tree-C281zrdg.js → list-tree-48dzbuUh.js} +1 -1
- package/dist/client/assets/{maximize-2-CovPxWdw.js → maximize-2-CbvSsu7O.js} +1 -1
- package/dist/client/assets/{mermaid.core-DGsccxt-.js → mermaid.core-DnVKnMmy.js} +5 -5
- package/dist/client/assets/mermaid.core-DnVKnMmy.js.br +0 -0
- package/dist/client/assets/mermaid.core-DnVKnMmy.js.gz +0 -0
- package/dist/client/assets/{mindmap-definition-YA3MSWOX-l0eF1PQE.js → mindmap-definition-YA3MSWOX-C6shupTY.js} +1 -1
- package/dist/client/assets/mindmap-definition-YA3MSWOX-C6shupTY.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-C6shupTY.js.gz +0 -0
- package/dist/client/assets/{passwordBootstrap-B5VzheZz.js → passwordBootstrap-Doe50DSa.js} +1 -1
- package/dist/client/assets/{passwordBootstrap-B5VzheZz.js.br → passwordBootstrap-Doe50DSa.js.br} +0 -0
- package/dist/client/assets/passwordBootstrap-Doe50DSa.js.gz +0 -0
- package/dist/client/assets/{pegDiagram-XKGWAZYB-fRrxGIDM.js → pegDiagram-XKGWAZYB-CDcnrvKX.js} +1 -1
- package/dist/client/assets/pegDiagram-XKGWAZYB-CDcnrvKX.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-CDcnrvKX.js.gz +0 -0
- package/dist/client/assets/{pieDiagram-E7YTZNPT-B-EBa3qN.js → pieDiagram-E7YTZNPT-CrGc03Tg.js} +1 -1
- package/dist/client/assets/pieDiagram-E7YTZNPT-CrGc03Tg.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-CrGc03Tg.js.gz +0 -0
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-Dj4e6f4h.js → quadrantDiagram-AXDQQJYC-3-aldwKj.js} +1 -1
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-3-aldwKj.js.br +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-3-aldwKj.js.gz +0 -0
- package/dist/client/assets/{quote-COQfrXhi.js → quote-B5GeKEq1.js} +1 -1
- package/dist/client/assets/{railroadDiagram-O6MQD6OU-CEMppxTC.js → railroadDiagram-O6MQD6OU-51uKwR2_.js} +1 -1
- package/dist/client/assets/railroadDiagram-O6MQD6OU-51uKwR2_.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-51uKwR2_.js.gz +0 -0
- package/dist/client/assets/rdpSession-ocpkj4XY.js +1 -0
- package/dist/client/assets/rdpSession-ocpkj4XY.js.br +0 -0
- package/dist/client/assets/rdpSession-ocpkj4XY.js.gz +0 -0
- package/dist/client/assets/referenceSelection-fvfRDbgp.js +4 -0
- package/dist/client/assets/referenceSelection-fvfRDbgp.js.br +0 -0
- package/dist/client/assets/referenceSelection-fvfRDbgp.js.gz +0 -0
- package/dist/client/assets/{requirementDiagram-BXWQKSXE-Dri1k4_x.js → requirementDiagram-BXWQKSXE-CY6kp0_Y.js} +1 -1
- package/dist/client/assets/requirementDiagram-BXWQKSXE-CY6kp0_Y.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-CY6kp0_Y.js.gz +0 -0
- package/dist/client/assets/{sankeyDiagram-P5KCCOFB-CMsL_tYL.js → sankeyDiagram-P5KCCOFB-BsA0NkHG.js} +1 -1
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BsA0NkHG.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BsA0NkHG.js.gz +0 -0
- package/dist/client/assets/{search-Dg6HWygj.js → search-CbpNLSpd.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-4_4hZtOd.js → sequenceDiagram-WJ2MYXX4-BDzn7N2D.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-4_4hZtOd.js.br → sequenceDiagram-WJ2MYXX4-BDzn7N2D.js.br} +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-BDzn7N2D.js.gz +0 -0
- package/dist/client/assets/{sizeCapture-INFHLROL-3QA6qj2j.js → sizeCapture-INFHLROL-gxtam7nc.js} +1 -1
- package/dist/client/assets/sizeCapture-INFHLROL-gxtam7nc.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-gxtam7nc.js.gz +0 -0
- package/dist/client/assets/{stateDiagram-D77RDMKH-90IFPhD9.js → stateDiagram-D77RDMKH-C4XjYLZR.js} +1 -1
- package/dist/client/assets/stateDiagram-D77RDMKH-C4XjYLZR.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-C4XjYLZR.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-BfHWFf-I.js +1 -0
- package/dist/client/assets/{sun-BAMMjiA8.js → sun-CMXn_ntS.js} +1 -1
- package/dist/client/assets/{swimlanes-42K2YHIH-BuHieVWC.js → swimlanes-42K2YHIH--a1wkQO8.js} +1 -1
- package/dist/client/assets/swimlanes-42K2YHIH--a1wkQO8.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH--a1wkQO8.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DsiDF1XD.js +8 -0
- package/dist/client/assets/swiper-CTPycjLq.js +1 -0
- package/dist/client/assets/swiper-CTPycjLq.js.br +0 -0
- package/dist/client/assets/swiper-CTPycjLq.js.gz +0 -0
- package/dist/client/assets/{terminal-Dea8wJF3.js → terminal-DaiFCKy_.js} +7 -7
- package/dist/client/assets/terminal-DaiFCKy_.js.br +0 -0
- package/dist/client/assets/terminal-DaiFCKy_.js.gz +0 -0
- package/dist/client/assets/{timeline-definition-24CTP7MA-C7FpaNwf.js → timeline-definition-24CTP7MA-DFmXXUuU.js} +1 -1
- package/dist/client/assets/timeline-definition-24CTP7MA-DFmXXUuU.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-DFmXXUuU.js.gz +0 -0
- package/dist/client/assets/triangle-alert-DgGU_xB4.js +1 -0
- package/dist/client/assets/{unplug-DN2SNXUL.js → unplug-CnZtWzVW.js} +1 -1
- package/dist/client/assets/use-gesture-react.esm-DHU0wi7Q.js +1 -0
- package/dist/client/assets/use-gesture-react.esm-DHU0wi7Q.js.br +0 -0
- package/dist/client/assets/use-gesture-react.esm-DHU0wi7Q.js.gz +0 -0
- package/dist/client/assets/{vennDiagram-4TSXK5OY-CxoHHVcs.js → vennDiagram-4TSXK5OY-DgR4zroQ.js} +1 -1
- package/dist/client/assets/vennDiagram-4TSXK5OY-DgR4zroQ.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-DgR4zroQ.js.gz +0 -0
- package/dist/client/assets/{videoCompression-rr2lu3uy.js → videoCompression-CcffRZdP.js} +1 -1
- package/dist/client/assets/videoCompression-CcffRZdP.js.br +0 -0
- package/dist/client/assets/videoCompression-CcffRZdP.js.gz +0 -0
- package/dist/client/assets/{wardleyDiagram-VM6X3IG4-B4Hsh-Ad.js → wardleyDiagram-VM6X3IG4-CY4SVUkf.js} +1 -1
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-CY4SVUkf.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-CY4SVUkf.js.gz +0 -0
- package/dist/client/assets/{xychartDiagram-S5SC5T6Z-CghzsxQv.js → xychartDiagram-S5SC5T6Z-PblQhR-b.js} +1 -1
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-PblQhR-b.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-PblQhR-b.js.gz +0 -0
- package/dist/client/index.html +3 -3
- package/dist/client/index.html.br +0 -0
- package/dist/client/index.html.gz +0 -0
- package/dist/client/sw-encrypted-background.js +1 -1
- package/dist/client/sw-encrypted-background.js.br +0 -0
- package/dist/client/sw-encrypted-background.js.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/collaborationPeerTransport.js +14 -69
- package/dist/server/agent/collaborationStore.js +5 -0
- package/dist/server/agent/installers.js +89 -33
- package/dist/server/agent/integrationServer.js +31 -2
- package/dist/server/agent/pluginPackages.js +51 -22
- package/dist/server/agent/sessionChatRoutes.js +45 -7
- package/dist/server/agentHook.js +56 -12
- package/dist/server/android/adb.js +24 -31
- package/dist/server/cli.js +52 -110
- package/dist/server/entry.js +17 -23
- package/dist/server/federation/cli.js +13 -47
- package/dist/server/federation/connectionErrors.js +37 -0
- package/dist/server/federation/connectionModel.js +83 -0
- package/dist/server/federation/desktopTargets.js +35 -13
- package/dist/server/federation/directRoutes.js +28 -36
- package/dist/server/federation/directTargetRegistry.js +106 -0
- package/dist/server/federation/httpUploadLimit.js +8 -0
- package/dist/server/federation/relay.js +13 -6
- package/dist/server/federation/relayTransport.js +147 -0
- package/dist/server/federation/routeAccess.js +5 -3
- package/dist/server/federation/runtime.js +4 -2
- package/dist/server/federation/selfRelay.js +10 -59
- package/dist/server/federation/serviceTransport.js +123 -0
- package/dist/server/federation/streamLimits.js +3 -0
- package/dist/server/federation/trustedCa.js +61 -0
- package/dist/server/routes/android.js +5 -7
- package/dist/server/routes/terminal.js +149 -111
- package/dist/server/shared/androidDevices.js +64 -0
- package/dist/server/shared/programStatus.js +174 -0
- package/dist/server/shared/shareResources.js +3 -2
- package/dist/server/todos/routes.js +36 -0
- package/dist/server/todos/store.js +31 -1
- package/dist/server/utils/bootCheck.js +41 -271
- package/dist/server/utils/localHttpsSetup.js +257 -0
- package/dist/server/utils/oscBuffer.js +9 -0
- package/dist/server/utils/sessionDisplayName.js +11 -9
- package/dist/server/utils/settings.js +6 -3
- package/dist/server/utils/tmuxDisplayGeometry.js +54 -0
- package/dist/server/utils/tmuxObserverSize.js +26 -0
- package/docs/integrations.md +2 -1
- package/package.json +5 -1
- package/runtime-manifest.json +3 -3
- package/scripts/install-utils.cjs +81 -0
- package/scripts/postinstall.mjs +19 -106
- package/dist/client/assets/AndroidMirrorView-DW9oRr0w.js +0 -3
- package/dist/client/assets/AndroidMirrorView-DW9oRr0w.js.br +0 -0
- package/dist/client/assets/AndroidMirrorView-DW9oRr0w.js.gz +0 -0
- package/dist/client/assets/App-DEZ2i9ZZ.js +0 -178
- package/dist/client/assets/App-DEZ2i9ZZ.js.br +0 -0
- package/dist/client/assets/App-DEZ2i9ZZ.js.gz +0 -0
- package/dist/client/assets/ArchitecturePanel-Bf4b-6An.js +0 -9
- package/dist/client/assets/ArchitecturePanel-Bf4b-6An.js.br +0 -0
- package/dist/client/assets/ArchitecturePanel-Bf4b-6An.js.gz +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-DO_zJfZr.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-DO_zJfZr.js.gz +0 -0
- package/dist/client/assets/ChatRichContent-Cu1E1cJ8.js.br +0 -0
- package/dist/client/assets/ChatRichContent-Cu1E1cJ8.js.gz +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-BhmpSEbf.js +0 -1
- package/dist/client/assets/CollaborationMainWorkspace-BhmpSEbf.js.br +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-BhmpSEbf.js.gz +0 -0
- package/dist/client/assets/CollaborationTaskContent-CX0Aqdi2.js +0 -2
- package/dist/client/assets/ComputerControlView-DjQLzn10.js +0 -6
- package/dist/client/assets/ComputerControlView-DjQLzn10.js.br +0 -0
- package/dist/client/assets/ComputerControlView-DjQLzn10.js.gz +0 -0
- package/dist/client/assets/DagPlayground-CPYwfryM.js.br +0 -0
- package/dist/client/assets/DagPlayground-CPYwfryM.js.gz +0 -0
- package/dist/client/assets/DiffLab-ptw96Q_4.js.br +0 -0
- package/dist/client/assets/DiffLab-ptw96Q_4.js.gz +0 -0
- package/dist/client/assets/DiffReview-12E2zWyL.js +0 -1
- package/dist/client/assets/DiffReview-12E2zWyL.js.br +0 -0
- package/dist/client/assets/DiffReview-12E2zWyL.js.gz +0 -0
- package/dist/client/assets/DiffReviewLab-eEi3y-0G.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-eEi3y-0G.js.gz +0 -0
- package/dist/client/assets/DiffViewer-DqcQxp4Q.js.br +0 -0
- package/dist/client/assets/DiffViewer-DqcQxp4Q.js.gz +0 -0
- package/dist/client/assets/GitLoadingSkeleton-DYrDIDF1.js.br +0 -0
- package/dist/client/assets/GitLoadingSkeleton-DYrDIDF1.js.gz +0 -0
- package/dist/client/assets/MarkdownPreview-CsJGsDRL.js +0 -19
- package/dist/client/assets/MarkdownPreview-CsJGsDRL.js.br +0 -0
- package/dist/client/assets/MarkdownPreview-CsJGsDRL.js.gz +0 -0
- package/dist/client/assets/ModelPreview-DjtHLlqP.js.br +0 -0
- package/dist/client/assets/ModelPreview-DjtHLlqP.js.gz +0 -0
- package/dist/client/assets/RecordingSaveDialog-DUtwgIME.js +0 -1
- package/dist/client/assets/RecordingSaveDialog-DUtwgIME.js.br +0 -0
- package/dist/client/assets/RecordingSaveDialog-DUtwgIME.js.gz +0 -0
- package/dist/client/assets/RightSidebar-BltjUFwI.js +0 -1662
- package/dist/client/assets/RightSidebar-BltjUFwI.js.br +0 -0
- package/dist/client/assets/RightSidebar-BltjUFwI.js.gz +0 -0
- package/dist/client/assets/SessionChatView-CdKfHRp8.js +0 -13
- package/dist/client/assets/SessionChatView-CdKfHRp8.js.br +0 -0
- package/dist/client/assets/SessionChatView-CdKfHRp8.js.gz +0 -0
- package/dist/client/assets/SessionChatView-D8GoESjb.css +0 -1
- package/dist/client/assets/SessionChatView-D8GoESjb.css.br +0 -0
- package/dist/client/assets/SessionChatView-D8GoESjb.css.gz +0 -0
- package/dist/client/assets/SessionResourceSidebar-DmQOydhf.js +0 -2
- package/dist/client/assets/SessionResourceSidebar-DmQOydhf.js.br +0 -0
- package/dist/client/assets/SessionResourceSidebar-DmQOydhf.js.gz +0 -0
- package/dist/client/assets/TodoWorkspace-Bh1C035B.js +0 -1
- package/dist/client/assets/TodoWorkspace-Bh1C035B.js.br +0 -0
- package/dist/client/assets/TodoWorkspace-Bh1C035B.js.gz +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-Cvf_KWZ0.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-Cvf_KWZ0.js.gz +0 -0
- package/dist/client/assets/app-DuUnqxq-.js +0 -37
- package/dist/client/assets/app-DuUnqxq-.js.br +0 -0
- package/dist/client/assets/app-DuUnqxq-.js.gz +0 -0
- package/dist/client/assets/arc-UvdowQOf.js.br +0 -0
- package/dist/client/assets/arc-UvdowQOf.js.gz +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-DotsbCCA.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-DotsbCCA.js.gz +0 -0
- package/dist/client/assets/arrow-up-DNkfesW0.js +0 -1
- package/dist/client/assets/blockDiagram-I7D4REHJ-CoOfSG4k.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-CoOfSG4k.js.gz +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-BAfjgs8B.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-BAfjgs8B.js.gz +0 -0
- package/dist/client/assets/channel-BzMU9Wks.js +0 -1
- package/dist/client/assets/chunk-F27PBJKO-BI3Di4Ve.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-BI3Di4Ve.js.gz +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-Cvvs1wmn.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-Cvvs1wmn.js.gz +0 -0
- package/dist/client/assets/chunk-SVP7TREG-BZfMhm64.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-BZfMhm64.js.gz +0 -0
- package/dist/client/assets/chunk-TICWLB2K-DmkEaRK3.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-DmkEaRK3.js.gz +0 -0
- package/dist/client/assets/classDiagram-ZZMXUADV-DtAtEoWU.js +0 -1
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-DtAtEoWU.js +0 -1
- package/dist/client/assets/clipboardText-cZXParp1.js +0 -1
- package/dist/client/assets/clipboardText-cZXParp1.js.br +0 -0
- package/dist/client/assets/clipboardText-cZXParp1.js.gz +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-0xPYMc2z.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-0xPYMc2z.js.gz +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-BQ7-lCHm.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-BQ7-lCHm.js.gz +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CazHuSj1.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CazHuSj1.js.gz +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-CJNgsyHQ.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-CJNgsyHQ.js.gz +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-D4xXIj1P.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-D4xXIj1P.js.gz +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-BWhpL-35.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-BWhpL-35.js.gz +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-DG9A7EgJ.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-DG9A7EgJ.js.gz +0 -0
- package/dist/client/assets/diagram-VX7I27RA-L5PSvynM.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-L5PSvynM.js.gz +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-moBH7ruR.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-moBH7ruR.js.gz +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-DEiGgcRP.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-DEiGgcRP.js.gz +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-BboIleYi.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-BboIleYi.js.gz +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-COxz7Rda.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-COxz7Rda.js.gz +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-_XdRvgyZ.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-_XdRvgyZ.js.gz +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-CBb9xBNW.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-CBb9xBNW.js.gz +0 -0
- package/dist/client/assets/index-nIgxJ6I3.css +0 -1
- package/dist/client/assets/index-nIgxJ6I3.css.br +0 -0
- package/dist/client/assets/index-nIgxJ6I3.css.gz +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-Bcr-lhIE.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-Bcr-lhIE.js.gz +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-3vK6s9Pq.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-3vK6s9Pq.js.gz +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-DqDYDca0.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-DqDYDca0.js.gz +0 -0
- package/dist/client/assets/layout-C7_WwzCP.js.br +0 -0
- package/dist/client/assets/layout-C7_WwzCP.js.gz +0 -0
- package/dist/client/assets/linear-BQCRhl6P.js.br +0 -0
- package/dist/client/assets/linear-BQCRhl6P.js.gz +0 -0
- package/dist/client/assets/link-Cq14tNBm.js.gz +0 -0
- package/dist/client/assets/loader-circle-Df0zpx5N.js +0 -1
- package/dist/client/assets/mermaid.core-DGsccxt-.js.br +0 -0
- package/dist/client/assets/mermaid.core-DGsccxt-.js.gz +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-l0eF1PQE.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-l0eF1PQE.js.gz +0 -0
- package/dist/client/assets/passwordBootstrap-B5VzheZz.js.gz +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-fRrxGIDM.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-fRrxGIDM.js.gz +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-B-EBa3qN.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-B-EBa3qN.js.gz +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-Dj4e6f4h.js.br +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-Dj4e6f4h.js.gz +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-CEMppxTC.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-CEMppxTC.js.gz +0 -0
- package/dist/client/assets/rdpSession-C5rS-ImV.js +0 -1
- package/dist/client/assets/rdpSession-C5rS-ImV.js.br +0 -0
- package/dist/client/assets/rdpSession-C5rS-ImV.js.gz +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-Dri1k4_x.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-Dri1k4_x.js.gz +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-CMsL_tYL.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-CMsL_tYL.js.gz +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-4_4hZtOd.js.gz +0 -0
- package/dist/client/assets/settings-2-iGqzPez0.js +0 -1
- package/dist/client/assets/sizeCapture-INFHLROL-3QA6qj2j.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-3QA6qj2j.js.gz +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-90IFPhD9.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-90IFPhD9.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-CH-yvmL4.js +0 -1
- package/dist/client/assets/swimlanes-42K2YHIH-BuHieVWC.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-BuHieVWC.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-P_rDqbtg.js +0 -8
- package/dist/client/assets/swiper-DJjq1TYT.js +0 -1
- package/dist/client/assets/swiper-DJjq1TYT.js.br +0 -0
- package/dist/client/assets/swiper-DJjq1TYT.js.gz +0 -0
- package/dist/client/assets/syntaxHighlight-Cz6TPDW9.js +0 -4
- package/dist/client/assets/syntaxHighlight-Cz6TPDW9.js.br +0 -0
- package/dist/client/assets/syntaxHighlight-Cz6TPDW9.js.gz +0 -0
- package/dist/client/assets/terminal-Dea8wJF3.js.br +0 -0
- package/dist/client/assets/terminal-Dea8wJF3.js.gz +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-C7FpaNwf.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-C7FpaNwf.js.gz +0 -0
- package/dist/client/assets/triangle-alert-Oj-OsZDw.js +0 -1
- package/dist/client/assets/use-gesture-react.esm-DYpdiE_k.js +0 -1
- package/dist/client/assets/use-gesture-react.esm-DYpdiE_k.js.br +0 -0
- package/dist/client/assets/use-gesture-react.esm-DYpdiE_k.js.gz +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-CxoHHVcs.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-CxoHHVcs.js.gz +0 -0
- package/dist/client/assets/videoCompression-rr2lu3uy.js.br +0 -0
- package/dist/client/assets/videoCompression-rr2lu3uy.js.gz +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-B4Hsh-Ad.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-B4Hsh-Ad.js.gz +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-CghzsxQv.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-CghzsxQv.js.gz +0 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { createHash, createPrivateKey, X509Certificate, randomUUID } from 'node:crypto';
|
|
5
|
+
import { execFile, spawn } from 'node:child_process';
|
|
6
|
+
import { createRequire } from 'node:module';
|
|
7
|
+
import { isIP } from 'node:net';
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const { findExecutable } = require('../../../scripts/install-utils.cjs');
|
|
10
|
+
export const MKCERT_VERSION = '1.4.4';
|
|
11
|
+
// Pinned official release assets: https://github.com/FiloSottile/mkcert/releases/tag/v1.4.4
|
|
12
|
+
export const MKCERT_SHA256 = {
|
|
13
|
+
'linux-amd64': '6d31c65b03972c6dc4a14ab429f2928300518b26503f58723e532d1b0a3bbb52',
|
|
14
|
+
'linux-arm64': 'b98f2cc69fd9147fe4d405d859c57504571adec0d3611c3eefd04107c7ac00d0',
|
|
15
|
+
'linux-arm': '2f22ff62dfc13357e147e027117724e7ce1ff810e30d2b061b05b668ecb4f1d7',
|
|
16
|
+
'darwin-amd64': 'a32dfab51f1845d51e810db8e47dcf0e6b51ae3422426514bf5a2b8302e97d4e',
|
|
17
|
+
'darwin-arm64': 'c8af0df44bce04359794dad8ea28d750437411d632748049d08644ffb66a60c6',
|
|
18
|
+
};
|
|
19
|
+
const runTool = async (file, args, options) => {
|
|
20
|
+
try {
|
|
21
|
+
return await new Promise((resolve, reject) => {
|
|
22
|
+
const child = execFile(file, args, { timeout: 120_000, maxBuffer: 4 * 1024 * 1024, ...options }, (error, stdout, stderr) => error ? reject(error) : resolve({ stdout, stderr }));
|
|
23
|
+
// A nested sudo must receive EOF, never wait on an unused stdin pipe.
|
|
24
|
+
child.stdin?.end();
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
const failure = error;
|
|
29
|
+
throw new Error(`${path.basename(file)} ${args.join(' ')} failed (${failure.code ?? failure.signal ?? 'spawn error'}): ${failure.stderr?.trim() || failure.message}`, { cause: error });
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
export async function downloadVerifiedExecutable(url, sha256, target, fetcher = fetch) {
|
|
33
|
+
const response = await fetcher(url, { signal: AbortSignal.timeout(120_000) });
|
|
34
|
+
if (!response.ok)
|
|
35
|
+
throw new Error(`mkcert download returned HTTP ${response.status}. Install mkcert manually and retry td --setup-local-https.`);
|
|
36
|
+
if (Number(response.headers.get('content-length')) > 20 * 1024 * 1024)
|
|
37
|
+
throw new Error('mkcert download is unexpectedly large');
|
|
38
|
+
const chunks = [];
|
|
39
|
+
let size = 0;
|
|
40
|
+
if (!response.body)
|
|
41
|
+
throw new Error('Empty mkcert download');
|
|
42
|
+
const reader = response.body.getReader();
|
|
43
|
+
try {
|
|
44
|
+
for (;;) {
|
|
45
|
+
const { done, value } = await reader.read();
|
|
46
|
+
if (done)
|
|
47
|
+
break;
|
|
48
|
+
size += value.length;
|
|
49
|
+
if (size > 20 * 1024 * 1024) {
|
|
50
|
+
await reader.cancel();
|
|
51
|
+
throw new Error('mkcert download is unexpectedly large');
|
|
52
|
+
}
|
|
53
|
+
chunks.push(value);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
reader.releaseLock();
|
|
58
|
+
}
|
|
59
|
+
const bytes = Buffer.concat(chunks);
|
|
60
|
+
if (createHash('sha256').update(bytes).digest('hex') !== sha256)
|
|
61
|
+
throw new Error('mkcert download SHA-256 mismatch; the executable was not installed');
|
|
62
|
+
fs.mkdirSync(path.dirname(target), { recursive: true, mode: 0o700 });
|
|
63
|
+
const temporary = `${target}.${randomUUID()}.tmp`;
|
|
64
|
+
try {
|
|
65
|
+
fs.writeFileSync(temporary, bytes, { mode: 0o700, flag: 'wx' });
|
|
66
|
+
fs.renameSync(temporary, target);
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
fs.rmSync(temporary, { force: true });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export async function ensureMkcert(options = {}) {
|
|
73
|
+
const find = options.find ?? findExecutable, run = options.run ?? runTool;
|
|
74
|
+
const home = options.home ?? os.homedir();
|
|
75
|
+
const target = path.join(home, '.termdock/bin/mkcert');
|
|
76
|
+
// Check our own location explicitly, including when HOME/PATH is restricted.
|
|
77
|
+
const existing = find('mkcert') || (fs.existsSync(target) ? target : null);
|
|
78
|
+
if (existing) {
|
|
79
|
+
try {
|
|
80
|
+
await run(existing, ['--version'], { timeout: 5000 });
|
|
81
|
+
return existing;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
throw new Error(`The installed mkcert is unusable: ${String(error)}. Repair or remove ${existing} and retry.`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const platform = options.platform ?? process.platform, arch = options.arch ?? process.arch;
|
|
88
|
+
const asset = `${platform}-${arch === 'x64' ? 'amd64' : arch}`;
|
|
89
|
+
const checksum = MKCERT_SHA256[asset];
|
|
90
|
+
if (!checksum)
|
|
91
|
+
throw new Error(`Automatic mkcert installation is unavailable for ${platform}/${arch}. Install mkcert manually (Windows: use WSL).`);
|
|
92
|
+
options.log?.(`Downloading verified mkcert ${MKCERT_VERSION} to ${target} (no administrator permission required)...`);
|
|
93
|
+
const url = `https://github.com/FiloSottile/mkcert/releases/download/v${MKCERT_VERSION}/mkcert-v${MKCERT_VERSION}-${asset}`;
|
|
94
|
+
try {
|
|
95
|
+
await (options.download ?? downloadVerifiedExecutable)(url, checksum, target);
|
|
96
|
+
await run(target, ['--version'], { timeout: 5000 });
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
throw new Error(`Could not prepare mkcert: ${String(error)}. Install mkcert manually and retry td --setup-local-https.`, { cause: error });
|
|
100
|
+
}
|
|
101
|
+
return target;
|
|
102
|
+
}
|
|
103
|
+
export function localHttpsPaths(directory) {
|
|
104
|
+
return { cert: path.join(directory, 'termdock-local.pem'), key: path.join(directory, 'termdock-local-key.pem'), ca: path.join(directory, 'rootCA.pem') };
|
|
105
|
+
}
|
|
106
|
+
export function inspectLocalCertificate(files, names, now = Date.now()) {
|
|
107
|
+
const cert = new X509Certificate(fs.readFileSync(files.cert)), ca = new X509Certificate(fs.readFileSync(files.ca));
|
|
108
|
+
if (!ca.ca || cert.ca || !cert.checkIssued(ca) || !cert.verify(ca.publicKey)
|
|
109
|
+
|| !cert.checkPrivateKey(createPrivateKey(fs.readFileSync(files.key))))
|
|
110
|
+
throw new Error('Certificate, private key and local CA do not match');
|
|
111
|
+
if (cert.keyUsage && !cert.keyUsage.includes('1.3.6.1.5.5.7.3.1'))
|
|
112
|
+
throw new Error('Local certificate does not allow TLS server authentication');
|
|
113
|
+
for (const item of [cert, ca]) {
|
|
114
|
+
if (Date.parse(item.validFrom) > now || Date.parse(item.validTo) <= now)
|
|
115
|
+
throw new Error('Local HTTPS certificate or CA is not currently valid');
|
|
116
|
+
}
|
|
117
|
+
const missing = names.filter(name => isIP(name) ? cert.checkIP(name) === undefined : cert.checkHost(name, { subject: 'never', wildcards: false }) === undefined);
|
|
118
|
+
if (missing.length)
|
|
119
|
+
throw new Error(`Certificate is missing names: ${missing.join(', ')}`);
|
|
120
|
+
return { cert, ca };
|
|
121
|
+
}
|
|
122
|
+
export function localCertificateNeedsRefresh(directory, names, now = Date.now()) {
|
|
123
|
+
try {
|
|
124
|
+
const { cert, ca } = inspectLocalCertificate(localHttpsPaths(directory), names, now);
|
|
125
|
+
return Math.min(Date.parse(cert.validTo), Date.parse(ca.validTo)) < now + 30 * 86400_000;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function runInteractive(file, args) {
|
|
132
|
+
return new Promise((resolve, reject) => {
|
|
133
|
+
const child = spawn(file, args, { stdio: 'inherit', timeout: 120_000 });
|
|
134
|
+
child.once('error', reject);
|
|
135
|
+
child.once('exit', (code, signal) => code === 0 ? resolve() : reject(new Error(`mkcert -install failed (${signal ?? code})`)));
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
export async function setupLocalHttps(options) {
|
|
139
|
+
const run = options.run ?? runTool, find = options.find ?? findExecutable;
|
|
140
|
+
const mkcert = options.mkcert ?? await ensureMkcert({ log: options.log });
|
|
141
|
+
const names = [...new Set(options.names)];
|
|
142
|
+
if (!names.length)
|
|
143
|
+
throw new Error('At least one HTTPS certificate name is required');
|
|
144
|
+
fs.mkdirSync(options.directory, { recursive: true, mode: 0o700 });
|
|
145
|
+
const lock = path.join(options.directory, '.setup.lock');
|
|
146
|
+
try {
|
|
147
|
+
fs.writeFileSync(lock, String(process.pid), { flag: 'wx', mode: 0o600 });
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
if (error.code !== 'EEXIST')
|
|
151
|
+
throw error;
|
|
152
|
+
const owner = Number(fs.readFileSync(lock, 'utf8'));
|
|
153
|
+
if (!Number.isSafeInteger(owner) || owner <= 0)
|
|
154
|
+
throw new Error('Invalid HTTPS setup lock; inspect ' + lock);
|
|
155
|
+
try {
|
|
156
|
+
process.kill(owner, 0);
|
|
157
|
+
}
|
|
158
|
+
catch (failure) {
|
|
159
|
+
if (failure.code === 'ESRCH') {
|
|
160
|
+
fs.rmSync(lock);
|
|
161
|
+
return setupLocalHttps({ ...options, mkcert });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
throw new Error('Local HTTPS setup is already running; retry after it completes');
|
|
165
|
+
}
|
|
166
|
+
let stage;
|
|
167
|
+
try {
|
|
168
|
+
stage = fs.mkdtempSync(path.join(options.directory, '.setup-'));
|
|
169
|
+
const candidate = localHttpsPaths(stage), files = localHttpsPaths(options.directory);
|
|
170
|
+
await run(mkcert, ['-cert-file', candidate.cert, '-key-file', candidate.key, ...names], { cwd: stage });
|
|
171
|
+
const caroot = (await run(mkcert, ['-CAROOT'], { timeout: 5000 })).stdout.trim();
|
|
172
|
+
if (!path.isAbsolute(caroot))
|
|
173
|
+
throw new Error('mkcert returned an invalid CA directory');
|
|
174
|
+
fs.copyFileSync(path.join(caroot, 'rootCA.pem'), candidate.ca);
|
|
175
|
+
const verified = inspectLocalCertificate(candidate, names);
|
|
176
|
+
let oldFingerprint;
|
|
177
|
+
const hadCa = fs.existsSync(files.ca);
|
|
178
|
+
if (hadCa) {
|
|
179
|
+
try {
|
|
180
|
+
oldFingerprint = new X509Certificate(fs.readFileSync(files.ca)).fingerprint256;
|
|
181
|
+
}
|
|
182
|
+
catch { /* An explicit setup may repair a damaged CA; automatic renewal may not replace it. */ }
|
|
183
|
+
}
|
|
184
|
+
const caChanged = hadCa && oldFingerprint !== verified.ca.fingerprint256;
|
|
185
|
+
if (caChanged && options.allowCaChange === false)
|
|
186
|
+
throw new Error('Automatic renewal would replace the trusted CA. Restore its mkcert CAROOT/private key, or explicitly run td --setup-local-https to replace it and trust it again.');
|
|
187
|
+
const keys = ['cert', 'key', 'ca'];
|
|
188
|
+
const backups = new Map(keys.map(key => [key, fs.existsSync(files[key]) ? fs.readFileSync(files[key]) : undefined]));
|
|
189
|
+
for (const key of keys)
|
|
190
|
+
fs.chmodSync(candidate[key], 0o600);
|
|
191
|
+
try {
|
|
192
|
+
// No await between renames: filesystem watchers observe the complete set.
|
|
193
|
+
for (const key of keys)
|
|
194
|
+
fs.renameSync(candidate[key], files[key]);
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
for (const key of keys) {
|
|
198
|
+
const backup = backups.get(key);
|
|
199
|
+
if (backup)
|
|
200
|
+
fs.writeFileSync(files[key], backup, { mode: 0o600 });
|
|
201
|
+
else
|
|
202
|
+
fs.rmSync(files[key], { force: true });
|
|
203
|
+
}
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
const warnings = [];
|
|
207
|
+
if (caChanged)
|
|
208
|
+
warnings.push('The local CA changed. Install and trust the new rootCA.pem on every device again.');
|
|
209
|
+
let trust = 'skipped';
|
|
210
|
+
if (options.installCa !== false) {
|
|
211
|
+
const platform = options.platform ?? process.platform;
|
|
212
|
+
const interactive = options.interactive ?? (process.stdin.isTTY === true && process.stdout.isTTY === true);
|
|
213
|
+
let canInstallSystem = interactive || (options.uid ?? process.getuid?.()) === 0;
|
|
214
|
+
if (!canInstallSystem) {
|
|
215
|
+
const sudo = find('sudo');
|
|
216
|
+
if (sudo) {
|
|
217
|
+
try {
|
|
218
|
+
await run(sudo, ['-n', 'true'], { timeout: 5000 });
|
|
219
|
+
canInstallSystem = true;
|
|
220
|
+
}
|
|
221
|
+
catch { /* No password prompts in a pipe/daemon. */ }
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (platform === 'linux' && !find('certutil'))
|
|
225
|
+
warnings.push('Browser CA trust needs certutil: Debian/Ubuntu: apt install libnss3-tools; Fedora/RHEL: dnf install nss-tools; Arch: pacman -S nss; openSUSE: zypper install mozilla-nss-tools.');
|
|
226
|
+
if (platform === 'linux' && !['update-ca-certificates', 'update-ca-trust', 'trust'].some(tool => find(tool)))
|
|
227
|
+
warnings.push('No Linux system CA trust updater was found. Install the ca-certificates package or configure this server\'s trust store manually.');
|
|
228
|
+
if (canInstallSystem) {
|
|
229
|
+
try {
|
|
230
|
+
if (interactive && !options.run)
|
|
231
|
+
await runInteractive(mkcert, ['-install']);
|
|
232
|
+
else {
|
|
233
|
+
const result = await run(mkcert, ['-install']);
|
|
234
|
+
if (result.stderr.trim())
|
|
235
|
+
warnings.push(result.stderr.trim());
|
|
236
|
+
}
|
|
237
|
+
trust = 'requested';
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
trust = 'failed';
|
|
241
|
+
warnings.push(`Certificate generation succeeded, but local CA trust installation failed: ${String(error)}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
else
|
|
245
|
+
warnings.push('Local CA trust was skipped because this non-interactive process cannot elevate privileges.');
|
|
246
|
+
const quotedMkcert = "'" + mkcert.replaceAll("'", "'\\''") + "'";
|
|
247
|
+
if (trust !== 'requested')
|
|
248
|
+
warnings.push(`To trust this CA on the server, run ${quotedMkcert} -install from an interactive terminal under the same user/CAROOT.`);
|
|
249
|
+
}
|
|
250
|
+
return { files, warnings, trust, caChanged };
|
|
251
|
+
}
|
|
252
|
+
finally {
|
|
253
|
+
if (stage)
|
|
254
|
+
fs.rmSync(stage, { recursive: true, force: true });
|
|
255
|
+
fs.rmSync(lock, { force: true });
|
|
256
|
+
}
|
|
257
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Retain the entire incomplete OSC, including a split ESC/ST terminator.
|
|
2
|
+
* Hook prompt payloads can be much longer than a normal terminal title. */
|
|
3
|
+
export function incompleteOscSuffix(buffer, consumed, cap = 512 * 1024) {
|
|
4
|
+
const tail = buffer.slice(consumed);
|
|
5
|
+
const start = tail.lastIndexOf('\x1b]');
|
|
6
|
+
if (start >= 0 && tail.length - start <= cap)
|
|
7
|
+
return tail.slice(start);
|
|
8
|
+
return tail.endsWith('\x1b') ? '\x1b' : '';
|
|
9
|
+
}
|
|
@@ -18,7 +18,7 @@ export function getCwdLeafName(cwd) {
|
|
|
18
18
|
return segments[segments.length - 1] || cwd;
|
|
19
19
|
}
|
|
20
20
|
export function getSessionDisplayLines(session, activeProgram, cwd, shellNames = DEFAULT_SESSION_DISPLAY_SHELL_NAMES, shellTitle = null, promptState = null) {
|
|
21
|
-
if (session.customName)
|
|
21
|
+
if (session.customName && session.name.trim())
|
|
22
22
|
return { primary: session.name, secondary: getCwdLeafName(cwd) };
|
|
23
23
|
// Shell integration (OSC 2) provides real-time title: command name when running,
|
|
24
24
|
// cwd when idle. This is faster and more accurate than server-side process polling.
|
|
@@ -37,17 +37,19 @@ export function getSessionDisplayLines(session, activeProgram, cwd, shellNames =
|
|
|
37
37
|
const dir = getCwdLeafName(cwd);
|
|
38
38
|
if (dir)
|
|
39
39
|
return { primary: dir, secondary: null };
|
|
40
|
-
|
|
40
|
+
const stored = session.name.trim();
|
|
41
|
+
const internal = /^(?:tmux:|remote:|wt-)/i.test(stored) || stored === session.sessionId || stored === session.id;
|
|
42
|
+
return { primary: stored && !internal ? stored : session.agent?.displayName || '终端会话', secondary: null };
|
|
41
43
|
}
|
|
42
44
|
export function getSessionDisplayName(session, activeProgram, cwd, shellNames = DEFAULT_SESSION_DISPLAY_SHELL_NAMES, shellTitle = null, promptState = null) {
|
|
43
45
|
return getSessionDisplayLines(session, activeProgram, cwd, shellNames, shellTitle, promptState).primary;
|
|
44
46
|
}
|
|
45
|
-
/**
|
|
47
|
+
/** Sidebar, tabs, inventories, selectors and server messages use this same projection. */
|
|
48
|
+
export function getSessionPresentation(session, shellNames = DEFAULT_SESSION_DISPLAY_SHELL_NAMES) {
|
|
49
|
+
const { primary, secondary } = getSessionDisplayLines(session, session.activeProgram ?? null, session.cwd ?? null, shellNames, session.shellTitle ?? null, session.promptState ?? null);
|
|
50
|
+
return { displayName: primary, displaySubtitle: secondary };
|
|
51
|
+
}
|
|
52
|
+
/** Compatibility export for callers that still consume `name` in orchestration payloads. */
|
|
46
53
|
export function collaborationSessionDisplayName(session) {
|
|
47
|
-
|
|
48
|
-
const title = session.shellTitle === session.cwd || session.shellTitle === cwdLeaf ? null : session.shellTitle ?? null;
|
|
49
|
-
const name = getSessionDisplayName(session, session.activeProgram ?? null, null, DEFAULT_SESSION_DISPLAY_SHELL_NAMES, title);
|
|
50
|
-
return !name.trim() || /^(?:tmux:|remote:|wt-)/i.test(name) || name === session.sessionId
|
|
51
|
-
? session.agent?.displayName || cwdLeaf || '终端会话'
|
|
52
|
-
: name;
|
|
54
|
+
return getSessionPresentation(session).displayName;
|
|
53
55
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isValidAndroidSerial } from '../shared/androidDevices.js';
|
|
1
2
|
import crypto from 'crypto';
|
|
2
3
|
import fs from 'fs';
|
|
3
4
|
import os from 'os';
|
|
@@ -173,8 +174,9 @@ export function normalizeAndroidPanel(value) {
|
|
|
173
174
|
docked = { sessionId: item.sessionId, side };
|
|
174
175
|
}
|
|
175
176
|
}
|
|
176
|
-
const deviceSerial = typeof raw.deviceSerial === 'string' &&
|
|
177
|
-
|
|
177
|
+
const deviceSerial = typeof raw.deviceSerial === 'string' && isValidAndroidSerial(raw.deviceSerial) ? raw.deviceSerial : null;
|
|
178
|
+
const devicePhysicalId = typeof raw.devicePhysicalId === 'string' && /^[a-f0-9]{64}$/.test(raw.devicePhysicalId) ? raw.devicePhysicalId : null;
|
|
179
|
+
return { enabled, quality, activePresetId, presets, docked, deviceSerial, devicePhysicalId };
|
|
178
180
|
}
|
|
179
181
|
export function normalizePinnedExplorerRoots(value) {
|
|
180
182
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
@@ -786,7 +788,8 @@ export function setRightSidebarTabsSetting(patch) {
|
|
|
786
788
|
export function getAndroidPanelSetting() { return loadSettings().androidPanel; }
|
|
787
789
|
export function setAndroidPanelSetting(patch) {
|
|
788
790
|
return updateSettings((settings) => {
|
|
789
|
-
|
|
791
|
+
const resetIdentity = patch.deviceSerial !== undefined && patch.deviceSerial !== settings.androidPanel.deviceSerial && patch.devicePhysicalId === undefined;
|
|
792
|
+
settings.androidPanel = normalizeAndroidPanel({ ...settings.androidPanel, ...(resetIdentity ? { devicePhysicalId: null } : {}), ...patch });
|
|
790
793
|
});
|
|
791
794
|
}
|
|
792
795
|
export function getCollaborationPanelsSetting() { return loadSettings().collaborationPanels; }
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { claimTmuxSize } from './tmuxSizeOwnership.js';
|
|
2
|
+
import { retainTmuxObserverSize } from './tmuxObserverSize.js';
|
|
3
|
+
/** All tmux display entries use this owner/observer transaction. Resizing a
|
|
4
|
+
* display without its observer makes refreshing the page shrink the window.
|
|
5
|
+
* The session's existing I/O queue serializes these operations across clients.
|
|
6
|
+
*/
|
|
7
|
+
export class TmuxDisplayGeometry {
|
|
8
|
+
observer;
|
|
9
|
+
run;
|
|
10
|
+
sessionName;
|
|
11
|
+
displayPids;
|
|
12
|
+
initialSize;
|
|
13
|
+
current;
|
|
14
|
+
firstResize = true;
|
|
15
|
+
constructor(observer, run, sessionName, displayPids, initialSize) {
|
|
16
|
+
this.observer = observer;
|
|
17
|
+
this.run = run;
|
|
18
|
+
this.sessionName = sessionName;
|
|
19
|
+
this.displayPids = displayPids;
|
|
20
|
+
this.initialSize = initialSize;
|
|
21
|
+
this.current = { cols: initialSize?.cols ?? observer.cols, rows: initialSize?.rows ?? observer.rows };
|
|
22
|
+
}
|
|
23
|
+
get size() { return { cols: this.current.cols, rows: this.current.rows }; }
|
|
24
|
+
reset() { this.firstResize = true; }
|
|
25
|
+
async prepareAttach(size, supportsOwnership) {
|
|
26
|
+
const clients = (await this.run(['list-clients', '-t', this.sessionName, '-F', '#{client_pid} #{client_tty} #{client_flags}']))
|
|
27
|
+
.split('\n').map(line => line.trim().split(/\s+/));
|
|
28
|
+
const metadata = clients.find(([pid]) => pid === String(this.observer.ptyProcess.pid));
|
|
29
|
+
if (metadata?.[1] && supportsOwnership) {
|
|
30
|
+
await this.run(['refresh-client', '-t', metadata[1], '-f', 'ignore-size']);
|
|
31
|
+
}
|
|
32
|
+
const hasSizeOwner = clients.some(([pid, tty, flags]) => tty && pid !== String(this.observer.ptyProcess.pid)
|
|
33
|
+
&& !flags?.split(',').includes('ignore-size'));
|
|
34
|
+
if (this.initialSize && supportsOwnership && !hasSizeOwner)
|
|
35
|
+
retainTmuxObserverSize(this.observer, size.cols, size.rows);
|
|
36
|
+
}
|
|
37
|
+
async resize(display, requested, supportsOwnership) {
|
|
38
|
+
if (!display.attached || !Number.isFinite(requested.cols) || !Number.isFinite(requested.rows) || requested.cols < 1 || requested.rows < 1) {
|
|
39
|
+
return { ok: false, ...this.size, redraw: false };
|
|
40
|
+
}
|
|
41
|
+
const size = { cols: Math.floor(requested.cols), rows: Math.floor(requested.rows) };
|
|
42
|
+
if (supportsOwnership)
|
|
43
|
+
await claimTmuxSize(this.run, this.sessionName, display.pid, this.displayPids());
|
|
44
|
+
const same = this.current.cols === size.cols && this.current.rows === size.rows;
|
|
45
|
+
const ok = same ? display.attached : display.resize(size.cols, size.rows);
|
|
46
|
+
if (!ok)
|
|
47
|
+
return { ok: false, ...this.size, redraw: false };
|
|
48
|
+
retainTmuxObserverSize(this.observer, size.cols, size.rows);
|
|
49
|
+
const redraw = same && !this.firstResize;
|
|
50
|
+
this.firstResize = false;
|
|
51
|
+
this.current = size;
|
|
52
|
+
return { ok: true, ...this.size, redraw };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** An ignored observer still becomes tmux's size fallback when every browser
|
|
2
|
+
* disconnects. Keep it at the selected display's grid, never the 80x24 default.
|
|
3
|
+
*/
|
|
4
|
+
export function retainTmuxObserverSize(session, cols, rows) {
|
|
5
|
+
if (session.cols === cols && session.rows === rows)
|
|
6
|
+
return;
|
|
7
|
+
session.ptyProcess.resize(cols, rows);
|
|
8
|
+
session.cols = cols;
|
|
9
|
+
session.rows = rows;
|
|
10
|
+
}
|
|
11
|
+
/** Preserve an existing window when creating its backend observer, including
|
|
12
|
+
* after a service restart. A guessed default would resize the running TUI.
|
|
13
|
+
*/
|
|
14
|
+
export async function readTmuxObserverSize(run, target) {
|
|
15
|
+
// display-message resolves a pane; an exact session target needs its colon.
|
|
16
|
+
const paneTarget = target.startsWith('=') && !target.includes(':') ? `${target}:` : target;
|
|
17
|
+
const raw = await run(['display-message', '-p', '-t', paneTarget, '#{window_width} #{window_height} #{status}']);
|
|
18
|
+
const [width, height, status] = raw.trim().split(/\s+/);
|
|
19
|
+
const cols = Number(width), paneRows = Number(height);
|
|
20
|
+
const statusRows = status === 'on' ? 1 : status === 'off' ? 0 : Number(status);
|
|
21
|
+
if (![cols, paneRows, statusRows].every(Number.isSafeInteger)
|
|
22
|
+
|| cols < 1 || paneRows < 1 || statusRows < 0 || statusRows > 5) {
|
|
23
|
+
throw new Error('TMUX_WINDOW_GEOMETRY_UNAVAILABLE');
|
|
24
|
+
}
|
|
25
|
+
return { cols, rows: paneRows + statusRows };
|
|
26
|
+
}
|
package/docs/integrations.md
CHANGED
|
@@ -107,7 +107,8 @@ after-id 不在本组保留记录中返回 MESSAGE_NOT_FOUND;前缀不唯一
|
|
|
107
107
|
|
|
108
108
|
## 管理员配置身份
|
|
109
109
|
|
|
110
|
-
接口只监听本机 Unix socket `~/.termdock/integration-<port>.sock`(0600
|
|
110
|
+
接口只监听本机 Unix socket `~/.termdock/integration-<port>.sock`(0600)。
|
|
111
|
+
用户目录过长时自动使用 `/tmp` 下按用户与目录摘要隔离的私有短路径(目录 0700);CLI 会自动解析同一路径。
|
|
111
112
|
不暴露 HTTP 业务接口,不使用网页转发。首版身份绑定**一个本机协作组**,
|
|
112
113
|
不支持跨服务组。先在 TD 建立本机组,再查询其 ID:
|
|
113
114
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "termdock",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.357",
|
|
4
4
|
"description": "A complete web-based terminal application with modern UI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": ".desktop-dist/main.js",
|
|
@@ -43,7 +43,11 @@
|
|
|
43
43
|
"trace:fsio": "node scripts/inspect-fs-io.mjs",
|
|
44
44
|
"release:classify": "node scripts/classify-release.mjs",
|
|
45
45
|
"test": "vitest --passWithNoTests",
|
|
46
|
+
"test:initialization": "node --test tests/nodePtyInstall.test.mjs tests/installUtils.test.mjs && node --import tsx --test tests/initialization.process.test.mjs && vitest run --maxWorkers=2 src/server/utils/bootCheck.test.ts src/server/utils/localHttpsSetup.test.ts src/server/utils/nodePtyCleanup.test.ts",
|
|
47
|
+
"test:initialization:real": "node --import tsx --test tests/initialization.real.test.mjs",
|
|
46
48
|
"test:webgl": "vitest run --config vitest.webgl.config.ts",
|
|
49
|
+
"test:terminal-geometry": "vitest run src/lib/terminal/geometry.test.ts src/lib/terminal/geometryBoundary.test.ts src/lib/terminal/fitHysteresis.test.ts src/lib/terminal/api.continuousReconnect.test.ts src/lib/components/terminal/TerminalViewportPasteOwnership.test.tsx src/lib/federation/SessionAccessView.test.tsx src/server/utils/tmuxDisplayGeometry.test.ts src/server/utils/tmuxObserverSize.test.ts src/server/utils/tmuxSizeOwnership.test.ts src/server/utils/terminalHandshakeDimensions.test.ts src/server/routes/terminalInitialSize.test.ts src/server/routes/terminalSampling.test.ts",
|
|
50
|
+
"test:terminal-geometry:browser": "vitest run --config vitest.webgl.config.ts src/lib/terminal/geometry.browser.ts",
|
|
47
51
|
"test:ui": "vitest --ui",
|
|
48
52
|
"prepublishOnly": "npm run build",
|
|
49
53
|
"postinstall": "node scripts/postinstall.mjs",
|
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.357",
|
|
5
5
|
"runtimeProtocolVersion": 1,
|
|
6
6
|
"minimumDesktopVersion": "1.4.46",
|
|
7
7
|
"nodeMajor": 22,
|
|
8
8
|
"dependencyHash": "sha256-uodaeckvlR6JDQ73ORIEefAICJ13wyApaFoGn2b0/GA=",
|
|
9
|
-
"serverBundleHash": "sha256-
|
|
10
|
-
"clientBundleHash": "sha256-
|
|
9
|
+
"serverBundleHash": "sha256-LrgxHOq6BzR9VFmkNZxOiK7Lgp7ni4xHbMySIQZlfjA=",
|
|
10
|
+
"clientBundleHash": "sha256-SV6wLRzsYqg3fI+zXukBIdsqpzRzaJk01KT3kP1TnyY=",
|
|
11
11
|
"entrypoint": "dist/server/cli.js",
|
|
12
12
|
"clientEntrypoint": "dist/client/index.html"
|
|
13
13
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Shared by npm postinstall and the first-start checks. Never invoke a shell or
|
|
2
|
+
// open a sudo password prompt from an npm lifecycle/background process.
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const os = require('node:os');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
const { spawnSync } = require('node:child_process');
|
|
7
|
+
|
|
8
|
+
function findExecutable(command, { env = process.env, home = os.homedir(), platform = process.platform } = {}) {
|
|
9
|
+
const extra = [path.join(home, '.termdock/bin'), path.join(home, '.local/bin'), '/usr/local/bin', '/usr/bin', '/bin', '/usr/sbin', '/sbin'];
|
|
10
|
+
if (platform === 'darwin') extra.push('/opt/homebrew/bin', '/opt/local/bin');
|
|
11
|
+
const candidates = command.includes(path.sep) ? [path.resolve(command)] : [...new Set([...(env.PATH || '').split(path.delimiter).filter(Boolean), ...extra])].map(dir => path.resolve(dir, command));
|
|
12
|
+
for (const candidate of candidates) {
|
|
13
|
+
try {
|
|
14
|
+
fs.accessSync(candidate, fs.constants.X_OK);
|
|
15
|
+
if (fs.statSync(candidate).isFile()) return candidate;
|
|
16
|
+
} catch { /* Continue through the actual executable paths. */ }
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function runFile(command, args, options = {}) {
|
|
22
|
+
const result = spawnSync(command, args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], timeout: 120_000, ...options });
|
|
23
|
+
return { ok: !result.error && result.status === 0, stdout: result.stdout || '', stderr: result.stderr || '',
|
|
24
|
+
error: result.error?.message || (result.status !== 0 ? `exit status=${result.status ?? 'none'}${result.signal ? `; signal=${result.signal}` : ''}` : '') };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function tmuxInstallPlan(platform = process.platform, find = findExecutable) {
|
|
28
|
+
const candidates = platform === 'darwin' ? [
|
|
29
|
+
['brew', ['install', 'tmux'], false], ['port', ['install', 'tmux'], true], ['nix-env', ['-iA', 'nixpkgs.tmux'], false],
|
|
30
|
+
] : platform === 'linux' ? [
|
|
31
|
+
['apt-get', ['install', '-y', 'tmux'], true], ['dnf', ['install', '-y', 'tmux'], true],
|
|
32
|
+
['yum', ['install', '-y', 'tmux'], true], ['apk', ['add', 'tmux'], true],
|
|
33
|
+
['pacman', ['-S', '--noconfirm', 'tmux'], true], ['zypper', ['--non-interactive', 'install', 'tmux'], true],
|
|
34
|
+
['nix-env', ['-iA', 'nixpkgs.tmux'], false],
|
|
35
|
+
] : [];
|
|
36
|
+
for (const [name, args, needsRoot] of candidates) {
|
|
37
|
+
const command = find(name);
|
|
38
|
+
if (command) return { command, args, needsRoot, hint: `${needsRoot ? 'sudo ' : ''}${name} ${args.join(' ')}` };
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function checkTmux({ platform = process.platform, uid = process.getuid?.(), find = findExecutable, run = runFile } = {}) {
|
|
44
|
+
const probe = () => {
|
|
45
|
+
const command = find('tmux');
|
|
46
|
+
if (!command) return null;
|
|
47
|
+
const result = run(command, ['-V'], { timeout: 5000 });
|
|
48
|
+
return result.ok && /^tmux\s+\d/.test(result.stdout.trim()) ? result.stdout.trim() : null;
|
|
49
|
+
};
|
|
50
|
+
const version = probe();
|
|
51
|
+
if (version) return { ok: true, installed: false, version };
|
|
52
|
+
const plan = tmuxInstallPlan(platform, find);
|
|
53
|
+
if (!plan) return { ok: false, installed: false, error: 'tmux is unavailable. Install it with your system package manager (Windows: use WSL).' };
|
|
54
|
+
let command = plan.command, args = plan.args;
|
|
55
|
+
if (plan.needsRoot && uid !== 0) {
|
|
56
|
+
const sudo = find('sudo');
|
|
57
|
+
if (!sudo || !run(sudo, ['-n', 'true'], { timeout: 5000 }).ok) {
|
|
58
|
+
return { ok: false, installed: false, error: `tmux is unavailable; automatic installation needs root or passwordless sudo. Run: ${plan.hint}` };
|
|
59
|
+
}
|
|
60
|
+
command = sudo; args = ['-n', plan.command, ...args];
|
|
61
|
+
}
|
|
62
|
+
const installed = run(command, args);
|
|
63
|
+
const checked = probe();
|
|
64
|
+
return checked ? { ok: true, installed: true, version: checked }
|
|
65
|
+
: { ok: false, installed: false, error: `tmux installation did not produce a usable executable. Run: ${plan.hint}. ${(installed.stderr || installed.error || 'Installer returned without a working tmux').trim().slice(-1500)}` };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function probeNodePty(ptyRoot) {
|
|
69
|
+
const pty = require(ptyRoot);
|
|
70
|
+
// A stale/nonexistent $SHELL (or a minimal distro without bash) does not mean
|
|
71
|
+
// the native addon needs recompiling. Probe the portable system shell.
|
|
72
|
+
const child = pty.spawn(process.platform === 'win32' ? process.env.ComSpec || 'cmd.exe' : '/bin/sh',
|
|
73
|
+
process.platform === 'win32' ? ['/c', 'exit', '0'] : ['-c', 'exit 0'], { name: 'xterm', cols: 80, rows: 24 });
|
|
74
|
+
child.kill();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function clearPtyModuleCache(ptyRoot) {
|
|
78
|
+
for (const file of Object.keys(require.cache)) if (file.startsWith(ptyRoot + path.sep)) delete require.cache[file];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = { findExecutable, runFile, tmuxInstallPlan, checkTmux, probeNodePty, clearPtyModuleCache };
|