termdock 1.4.173 → 1.4.175
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 +204 -7
- package/dist/client/assets/App-BXYZyI_k.js +150 -0
- package/dist/client/assets/App-BXYZyI_k.js.br +0 -0
- package/dist/client/assets/App-BXYZyI_k.js.gz +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-DeVtCf73.js +2 -0
- package/dist/client/assets/ChangeWalkthroughPanel-DeVtCf73.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-DeVtCf73.js.gz +0 -0
- package/dist/client/assets/DagPlayground-ZIqLZoMo.js +1 -0
- package/dist/client/assets/DagPlayground-ZIqLZoMo.js.br +0 -0
- package/dist/client/assets/DagPlayground-ZIqLZoMo.js.gz +0 -0
- package/dist/client/assets/{DiffLab-xuS6rtpv.js → DiffLab-CSMf8So2.js} +2 -2
- package/dist/client/assets/DiffLab-CSMf8So2.js.br +0 -0
- package/dist/client/assets/DiffLab-CSMf8So2.js.gz +0 -0
- package/dist/client/assets/DiffReview-CE5lW1zQ.js +1 -0
- package/dist/client/assets/DiffReview-CE5lW1zQ.js.br +0 -0
- package/dist/client/assets/DiffReview-CE5lW1zQ.js.gz +0 -0
- package/dist/client/assets/DiffReviewLab-CpUW75fZ.js +2 -0
- package/dist/client/assets/DiffReviewLab-CpUW75fZ.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-CpUW75fZ.js.gz +0 -0
- package/dist/client/assets/{DiffViewer-BQGXUr8t.js → DiffViewer-BomvZ4kq.js} +5 -5
- package/dist/client/assets/DiffViewer-BomvZ4kq.js.br +0 -0
- package/dist/client/assets/DiffViewer-BomvZ4kq.js.gz +0 -0
- package/dist/client/assets/{ModelPreview-BfZzS1_d.js → ModelPreview-BWdZFyhh.js} +3 -3
- package/dist/client/assets/ModelPreview-BWdZFyhh.js.br +0 -0
- package/dist/client/assets/ModelPreview-BWdZFyhh.js.gz +0 -0
- package/dist/client/assets/RightSidebar-CYVwFbOc.js +79 -0
- package/dist/client/assets/RightSidebar-CYVwFbOc.js.br +0 -0
- package/dist/client/assets/RightSidebar-CYVwFbOc.js.gz +0 -0
- package/dist/client/assets/{abnfDiagram-VCTEODGH-Dn_lmPcC.js → abnfDiagram-VCTEODGH-BIPsLStE.js} +1 -1
- package/dist/client/assets/abnfDiagram-VCTEODGH-BIPsLStE.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-BIPsLStE.js.gz +0 -0
- package/dist/client/assets/app-D6KzR8B3.js +34 -0
- package/dist/client/assets/app-D6KzR8B3.js.br +0 -0
- package/dist/client/assets/app-D6KzR8B3.js.gz +0 -0
- package/dist/client/assets/{arc-DUybtKGZ.js → arc-DzeT6hBj.js} +1 -1
- package/dist/client/assets/arc-DzeT6hBj.js.br +0 -0
- package/dist/client/assets/arc-DzeT6hBj.js.gz +0 -0
- package/dist/client/assets/{architectureDiagram-5GKGNRK7-CLEmOHBp.js → architectureDiagram-5GKGNRK7-B1qsxd_5.js} +1 -1
- package/dist/client/assets/architectureDiagram-5GKGNRK7-B1qsxd_5.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-B1qsxd_5.js.gz +0 -0
- package/dist/client/assets/{blockDiagram-I7D4REHJ-O_XM5b9_.js → blockDiagram-I7D4REHJ-NLsa29Jp.js} +1 -1
- package/dist/client/assets/blockDiagram-I7D4REHJ-NLsa29Jp.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-NLsa29Jp.js.gz +0 -0
- package/dist/client/assets/{c4Diagram-7LVT6UL2-DlUEslcV.js → c4Diagram-7LVT6UL2-DBAUvou3.js} +1 -1
- package/dist/client/assets/c4Diagram-7LVT6UL2-DBAUvou3.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-DBAUvou3.js.gz +0 -0
- package/dist/client/assets/channel-BhwBAWhq.js +1 -0
- package/dist/client/assets/{chunk-2Q5K7J3B-DCrP6W79.js → chunk-2Q5K7J3B-BsVAXGLa.js} +1 -1
- package/dist/client/assets/{chunk-5VM5RSS4-Zm6_pYQv.js → chunk-5VM5RSS4-BKtILsst.js} +1 -1
- package/dist/client/assets/{chunk-F27PBJKO-DkyD-X9z.js → chunk-F27PBJKO-Dn9zcQZG.js} +1 -1
- package/dist/client/assets/chunk-F27PBJKO-Dn9zcQZG.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-Dn9zcQZG.js.gz +0 -0
- package/dist/client/assets/{chunk-IMKFNOWR-UvWxXAkh.js → chunk-IMKFNOWR-MVtVQeTr.js} +1 -1
- package/dist/client/assets/chunk-IMKFNOWR-MVtVQeTr.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-MVtVQeTr.js.gz +0 -0
- package/dist/client/assets/{chunk-JWPE2WC7-BjeBAFYM.js → chunk-JWPE2WC7-DliIIMe7.js} +1 -1
- package/dist/client/assets/{chunk-POPQ4Y6H-CnqrQdZC.js → chunk-POPQ4Y6H-XBSus3IC.js} +1 -1
- package/dist/client/assets/{chunk-SVP7TREG-C4a1s0v4.js → chunk-SVP7TREG-wleSQcJR.js} +1 -1
- package/dist/client/assets/chunk-SVP7TREG-wleSQcJR.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-wleSQcJR.js.gz +0 -0
- package/dist/client/assets/{chunk-TICWLB2K-hnmjYAl_.js → chunk-TICWLB2K-Dq6LdswN.js} +1 -1
- package/dist/client/assets/chunk-TICWLB2K-Dq6LdswN.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-Dq6LdswN.js.gz +0 -0
- package/dist/client/assets/{chunk-XXDRQBXY-xR4LOz28.js → chunk-XXDRQBXY-xafyKlM-.js} +1 -1
- package/dist/client/assets/classDiagram-ZZMXUADV-slQB0ns2.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-slQB0ns2.js +1 -0
- package/dist/client/assets/{cose-bilkent-JH36ORCC-CqY84fFp.js → cose-bilkent-JH36ORCC-BR7Ohnm_.js} +1 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-BR7Ohnm_.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-BR7Ohnm_.js.gz +0 -0
- package/dist/client/assets/{cynefin-OW5HDTMX-Bd14zuaD.js → cynefin-OW5HDTMX-CmPjQgER.js} +1 -1
- package/dist/client/assets/cynefin-OW5HDTMX-CmPjQgER.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-CmPjQgER.js.gz +0 -0
- package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-DSHcNXDs.js → cynefinDiagram-5FMLGOSQ-CFyR9RvM.js} +1 -1
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CFyR9RvM.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CFyR9RvM.js.gz +0 -0
- package/dist/client/assets/{dagre-GXQ25YYZ-CIGWQYeP.js → dagre-GXQ25YYZ-D_RVMRO1.js} +1 -1
- package/dist/client/assets/dagre-GXQ25YYZ-D_RVMRO1.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-D_RVMRO1.js.gz +0 -0
- package/dist/client/assets/{diagram-S7CK7UJ4-C9Fg7OLN.js → diagram-S7CK7UJ4-6fr-ZoPj.js} +1 -1
- package/dist/client/assets/diagram-S7CK7UJ4-6fr-ZoPj.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-6fr-ZoPj.js.gz +0 -0
- package/dist/client/assets/{diagram-UQ7AKVKN-DoRhl7Fd.js → diagram-UQ7AKVKN-CgwiUtz0.js} +1 -1
- package/dist/client/assets/diagram-UQ7AKVKN-CgwiUtz0.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-CgwiUtz0.js.gz +0 -0
- package/dist/client/assets/{diagram-VSXAHHWV-CI83g3iM.js → diagram-VSXAHHWV-CLxzTB9k.js} +1 -1
- package/dist/client/assets/diagram-VSXAHHWV-CLxzTB9k.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-CLxzTB9k.js.gz +0 -0
- package/dist/client/assets/{diagram-VX7I27RA-Dp2kP4PB.js → diagram-VX7I27RA-DjxDAvdZ.js} +1 -1
- package/dist/client/assets/diagram-VX7I27RA-DjxDAvdZ.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-DjxDAvdZ.js.gz +0 -0
- package/dist/client/assets/{diagram-Z3DM3KII-KtLMCM-V.js → diagram-Z3DM3KII-CDPOjiz4.js} +1 -1
- package/dist/client/assets/diagram-Z3DM3KII-CDPOjiz4.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-CDPOjiz4.js.gz +0 -0
- package/dist/client/assets/{ebnfDiagram-PWID7BFC-D_zseu1m.js → ebnfDiagram-PWID7BFC-BLbwyF1O.js} +1 -1
- package/dist/client/assets/ebnfDiagram-PWID7BFC-BLbwyF1O.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-BLbwyF1O.js.gz +0 -0
- package/dist/client/assets/{erDiagram-RLTQ6QDP-DaWUl_Kz.js → erDiagram-RLTQ6QDP-DbjtZnJx.js} +1 -1
- package/dist/client/assets/{erDiagram-RLTQ6QDP-DaWUl_Kz.js.br → erDiagram-RLTQ6QDP-DbjtZnJx.js.br} +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-DbjtZnJx.js.gz +0 -0
- package/dist/client/assets/{flowDiagram-HODETNUW-BMoJ46zJ.js → flowDiagram-HODETNUW-BirJInAN.js} +1 -1
- package/dist/client/assets/flowDiagram-HODETNUW-BirJInAN.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-BirJInAN.js.gz +0 -0
- package/dist/client/assets/{ganttDiagram-EL5Y4UJY-lV_iVmoW.js → ganttDiagram-EL5Y4UJY-d6Q9vSbv.js} +1 -1
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-d6Q9vSbv.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-d6Q9vSbv.js.gz +0 -0
- package/dist/client/assets/gestureArbiter-C2J0D0kV.css +1 -0
- package/dist/client/assets/gestureArbiter-C2J0D0kV.css.br +0 -0
- package/dist/client/assets/gestureArbiter-C2J0D0kV.css.gz +0 -0
- package/dist/client/assets/gestureArbiter-D1SNS_gK.js +1 -0
- package/dist/client/assets/gestureArbiter-D1SNS_gK.js.br +0 -0
- package/dist/client/assets/gestureArbiter-D1SNS_gK.js.gz +0 -0
- package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-BVCT9Btd.js → gitGraphDiagram-WWUBYQGX-BWBoIeS6.js} +1 -1
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BWBoIeS6.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BWBoIeS6.js.gz +0 -0
- package/dist/client/assets/{index-CnKSUg74.css → index-DUI8KRf6.css} +1 -1
- package/dist/client/assets/index-DUI8KRf6.css.br +0 -0
- package/dist/client/assets/index-DUI8KRf6.css.gz +0 -0
- package/dist/client/assets/{infoDiagram-27XIBGKW-BVhXOx1S.js → infoDiagram-27XIBGKW-BH4AynkM.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-Cyzfuoys.js → ishikawaDiagram-5VMMS53U-BQw90AKR.js} +1 -1
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-BQw90AKR.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-BQw90AKR.js.gz +0 -0
- package/dist/client/assets/{journeyDiagram-3NMN7TZE-CEIPDhQF.js → journeyDiagram-3NMN7TZE-DISkQocf.js} +1 -1
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DISkQocf.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DISkQocf.js.gz +0 -0
- package/dist/client/assets/{kanban-definition-UXKFOSKX-C8OulEOF.js → kanban-definition-UXKFOSKX-Qg2LyEVy.js} +1 -1
- package/dist/client/assets/kanban-definition-UXKFOSKX-Qg2LyEVy.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-Qg2LyEVy.js.gz +0 -0
- package/dist/client/assets/{layout-YN93qRzb.js → layout-Cd7-4_Vr.js} +1 -1
- package/dist/client/assets/layout-Cd7-4_Vr.js.br +0 -0
- package/dist/client/assets/layout-Cd7-4_Vr.js.gz +0 -0
- package/dist/client/assets/{linear-D9T4dYh7.js → linear-DFTi2fTn.js} +1 -1
- package/dist/client/assets/linear-DFTi2fTn.js.br +0 -0
- package/dist/client/assets/linear-DFTi2fTn.js.gz +0 -0
- package/dist/client/assets/{mermaid.core-BdCvvCGV.js → mermaid.core-2v726lUU.js} +5 -5
- package/dist/client/assets/mermaid.core-2v726lUU.js.br +0 -0
- package/dist/client/assets/mermaid.core-2v726lUU.js.gz +0 -0
- package/dist/client/assets/{mindmap-definition-YA3MSWOX-CSpES3Jh.js → mindmap-definition-YA3MSWOX-_FpwteCy.js} +4 -4
- package/dist/client/assets/mindmap-definition-YA3MSWOX-_FpwteCy.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-_FpwteCy.js.gz +0 -0
- package/dist/client/assets/passwordBootstrap-D9Ffc7NY.js +2 -0
- package/dist/client/assets/passwordBootstrap-D9Ffc7NY.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-D9Ffc7NY.js.gz +0 -0
- package/dist/client/assets/{pegDiagram-XKGWAZYB-6f4vAA1Q.js → pegDiagram-XKGWAZYB-DLFf-HmZ.js} +1 -1
- package/dist/client/assets/pegDiagram-XKGWAZYB-DLFf-HmZ.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-DLFf-HmZ.js.gz +0 -0
- package/dist/client/assets/{pieDiagram-E7YTZNPT-BC4Jd-I8.js → pieDiagram-E7YTZNPT-DqTnfXHG.js} +1 -1
- package/dist/client/assets/pieDiagram-E7YTZNPT-DqTnfXHG.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-DqTnfXHG.js.gz +0 -0
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-B0pnPaEN.js → quadrantDiagram-AXDQQJYC-B_oBH52Q.js} +1 -1
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-B_oBH52Q.js.br +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-B_oBH52Q.js.gz +0 -0
- package/dist/client/assets/{railroadDiagram-O6MQD6OU-B-oOamZT.js → railroadDiagram-O6MQD6OU-HxFQ7Pce.js} +1 -1
- package/dist/client/assets/railroadDiagram-O6MQD6OU-HxFQ7Pce.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-HxFQ7Pce.js.gz +0 -0
- package/dist/client/assets/referenceLongPress-B3NGIjvv.js +1 -0
- package/dist/client/assets/referenceLongPress-B3NGIjvv.js.br +0 -0
- package/dist/client/assets/referenceLongPress-B3NGIjvv.js.gz +0 -0
- package/dist/client/assets/{requirementDiagram-BXWQKSXE-DBSyxt0k.js → requirementDiagram-BXWQKSXE-NZdfaZFk.js} +1 -1
- package/dist/client/assets/requirementDiagram-BXWQKSXE-NZdfaZFk.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-NZdfaZFk.js.gz +0 -0
- package/dist/client/assets/{sankeyDiagram-P5KCCOFB-CcohzEZE.js → sankeyDiagram-P5KCCOFB-BgCctv6X.js} +1 -1
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BgCctv6X.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BgCctv6X.js.gz +0 -0
- package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-D7KS6rq_.js → sequenceDiagram-WJ2MYXX4-Br42Za1R.js} +1 -1
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-Br42Za1R.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-Br42Za1R.js.gz +0 -0
- package/dist/client/assets/{sizeCapture-INFHLROL-CaRXtn4g.js → sizeCapture-INFHLROL-FT4z4S1b.js} +1 -1
- package/dist/client/assets/sizeCapture-INFHLROL-FT4z4S1b.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-FT4z4S1b.js.gz +0 -0
- package/dist/client/assets/sparkles-BaGaevME.js +1 -0
- package/dist/client/assets/{stateDiagram-D77RDMKH-Dz836LqY.js → stateDiagram-D77RDMKH-DD0t9f84.js} +1 -1
- package/dist/client/assets/stateDiagram-D77RDMKH-DD0t9f84.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-DD0t9f84.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-BhvVVB56.js +1 -0
- package/dist/client/assets/{swimlanes-42K2YHIH-BK4KAY00.js → swimlanes-42K2YHIH-DcC8pGLx.js} +1 -1
- package/dist/client/assets/swimlanes-42K2YHIH-DcC8pGLx.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-DcC8pGLx.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DSC5lz0i.js +8 -0
- package/dist/client/assets/{timeline-definition-24CTP7MA-DWgxTDhO.js → timeline-definition-24CTP7MA-DnwO_Pxd.js} +1 -1
- package/dist/client/assets/timeline-definition-24CTP7MA-DnwO_Pxd.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-DnwO_Pxd.js.gz +0 -0
- package/dist/client/assets/triangle-alert-BCQO9Ap9.js +1 -0
- package/dist/client/assets/{vennDiagram-4TSXK5OY-BV1TIfOp.js → vennDiagram-4TSXK5OY-IVNSrZDM.js} +1 -1
- package/dist/client/assets/vennDiagram-4TSXK5OY-IVNSrZDM.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-IVNSrZDM.js.gz +0 -0
- package/dist/client/assets/{wardleyDiagram-VM6X3IG4-GYClC5F0.js → wardleyDiagram-VM6X3IG4-BnGetaQL.js} +1 -1
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-BnGetaQL.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-BnGetaQL.js.gz +0 -0
- package/dist/client/assets/{xychartDiagram-S5SC5T6Z-D1oKV5W0.js → xychartDiagram-S5SC5T6Z-C01eBN-W.js} +1 -1
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-C01eBN-W.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-C01eBN-W.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/preview-shell.html +1 -0
- package/dist/client/preview-shell.js +20 -0
- package/dist/client/preview-shell.js.br +0 -0
- package/dist/client/preview-shell.js.gz +0 -0
- package/dist/client/sw-secure-api.js +132 -0
- package/dist/client/sw-secure-api.js.br +0 -0
- package/dist/client/sw-secure-api.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/collaborationCli.js +298 -0
- package/dist/server/agent/collaborationPrompt.js +12 -3
- package/dist/server/agent/collaborationProtocol.js +50 -0
- package/dist/server/agent/collaborationRoutes.js +86 -0
- package/dist/server/agent/collaborationStore.js +311 -20
- package/dist/server/cli.js +28 -163
- package/dist/server/entry.js +114 -51
- package/dist/server/federation/accessPolicy.js +122 -0
- package/dist/server/federation/authorization.js +226 -0
- package/dist/server/federation/bootstrapCors.js +23 -0
- package/dist/server/federation/cli.js +185 -0
- package/dist/server/federation/deviceNames.js +29 -0
- package/dist/server/federation/directRoutes.js +72 -0
- package/dist/server/federation/invitations.js +123 -0
- package/dist/server/federation/openAccess.js +25 -0
- package/dist/server/federation/originPolicy.js +19 -0
- package/dist/server/federation/packets.js +116 -0
- package/dist/server/federation/passwordBootstrap.js +86 -0
- package/dist/server/federation/passwordLoginRoutes.js +98 -0
- package/dist/server/federation/relay.js +346 -0
- package/dist/server/federation/requestContext.js +4 -0
- package/dist/server/federation/routeAccess.js +124 -0
- package/dist/server/federation/routeInvitations.js +160 -0
- package/dist/server/federation/runtime.js +537 -0
- package/dist/server/federation/secureProtocol.js +223 -0
- package/dist/server/federation/socketDuplex.js +42 -0
- package/dist/server/federation/streamLimits.js +5 -0
- package/dist/server/routes/filesystem.js +2 -1
- package/dist/server/routes/terminal.js +89 -79
- package/dist/server/utils/authProtection.js +13 -0
- package/dist/server/utils/csrfProtection.js +3 -0
- package/dist/server/utils/publicSecurity.js +8 -3
- package/package.json +10 -3
- package/runtime-manifest.json +4 -4
- package/dist/client/assets/ChangeWalkthroughPanel-DKj7F0ex.js +0 -2
- package/dist/client/assets/ChangeWalkthroughPanel-DKj7F0ex.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-DKj7F0ex.js.gz +0 -0
- package/dist/client/assets/DagPlayground-D2Wui4jd.js +0 -1
- package/dist/client/assets/DagPlayground-D2Wui4jd.js.br +0 -0
- package/dist/client/assets/DagPlayground-D2Wui4jd.js.gz +0 -0
- package/dist/client/assets/DiffLab-xuS6rtpv.js.br +0 -0
- package/dist/client/assets/DiffLab-xuS6rtpv.js.gz +0 -0
- package/dist/client/assets/DiffReview-CAwpqM_w.js +0 -1
- package/dist/client/assets/DiffReview-CAwpqM_w.js.br +0 -0
- package/dist/client/assets/DiffReview-CAwpqM_w.js.gz +0 -0
- package/dist/client/assets/DiffReviewLab-BM_uGdyI.js +0 -2
- package/dist/client/assets/DiffReviewLab-BM_uGdyI.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-BM_uGdyI.js.gz +0 -0
- package/dist/client/assets/DiffViewer-BQGXUr8t.js.br +0 -0
- package/dist/client/assets/DiffViewer-BQGXUr8t.js.gz +0 -0
- package/dist/client/assets/ModelPreview-BfZzS1_d.js.br +0 -0
- package/dist/client/assets/ModelPreview-BfZzS1_d.js.gz +0 -0
- package/dist/client/assets/RightSidebar-Cdqt3C7V.js +0 -55
- package/dist/client/assets/RightSidebar-Cdqt3C7V.js.br +0 -0
- package/dist/client/assets/RightSidebar-Cdqt3C7V.js.gz +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-Dn_lmPcC.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-Dn_lmPcC.js.gz +0 -0
- package/dist/client/assets/app-DDCkFsNe.js +0 -175
- package/dist/client/assets/app-DDCkFsNe.js.br +0 -0
- package/dist/client/assets/app-DDCkFsNe.js.gz +0 -0
- package/dist/client/assets/arc-DUybtKGZ.js.br +0 -0
- package/dist/client/assets/arc-DUybtKGZ.js.gz +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-CLEmOHBp.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-CLEmOHBp.js.gz +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-O_XM5b9_.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-O_XM5b9_.js.gz +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-DlUEslcV.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-DlUEslcV.js.gz +0 -0
- package/dist/client/assets/channel-Bk1VkYvd.js +0 -1
- package/dist/client/assets/chunk-F27PBJKO-DkyD-X9z.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-DkyD-X9z.js.gz +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-UvWxXAkh.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-UvWxXAkh.js.gz +0 -0
- package/dist/client/assets/chunk-SVP7TREG-C4a1s0v4.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-C4a1s0v4.js.gz +0 -0
- package/dist/client/assets/chunk-TICWLB2K-hnmjYAl_.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-hnmjYAl_.js.gz +0 -0
- package/dist/client/assets/classDiagram-ZZMXUADV-_tUz3Cxt.js +0 -1
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-_tUz3Cxt.js +0 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-CqY84fFp.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-CqY84fFp.js.gz +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-Bd14zuaD.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-Bd14zuaD.js.gz +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-DSHcNXDs.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-DSHcNXDs.js.gz +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-CIGWQYeP.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-CIGWQYeP.js.gz +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-C9Fg7OLN.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-C9Fg7OLN.js.gz +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-DoRhl7Fd.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-DoRhl7Fd.js.gz +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-CI83g3iM.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-CI83g3iM.js.gz +0 -0
- package/dist/client/assets/diagram-VX7I27RA-Dp2kP4PB.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-Dp2kP4PB.js.gz +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-KtLMCM-V.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-KtLMCM-V.js.gz +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-D_zseu1m.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-D_zseu1m.js.gz +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-DaWUl_Kz.js.gz +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-BMoJ46zJ.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-BMoJ46zJ.js.gz +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-lV_iVmoW.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-lV_iVmoW.js.gz +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BVCT9Btd.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BVCT9Btd.js.gz +0 -0
- package/dist/client/assets/index-CnKSUg74.css.br +0 -0
- package/dist/client/assets/index-CnKSUg74.css.gz +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-Cyzfuoys.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-Cyzfuoys.js.gz +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-CEIPDhQF.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-CEIPDhQF.js.gz +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-C8OulEOF.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-C8OulEOF.js.gz +0 -0
- package/dist/client/assets/layout-YN93qRzb.js.br +0 -0
- package/dist/client/assets/layout-YN93qRzb.js.gz +0 -0
- package/dist/client/assets/linear-D9T4dYh7.js.br +0 -0
- package/dist/client/assets/linear-D9T4dYh7.js.gz +0 -0
- package/dist/client/assets/mermaid.core-BdCvvCGV.js.br +0 -0
- package/dist/client/assets/mermaid.core-BdCvvCGV.js.gz +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-CSpES3Jh.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-CSpES3Jh.js.gz +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-6f4vAA1Q.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-6f4vAA1Q.js.gz +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-BC4Jd-I8.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-BC4Jd-I8.js.gz +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-B0pnPaEN.js.br +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-B0pnPaEN.js.gz +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-B-oOamZT.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-B-oOamZT.js.gz +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-DBSyxt0k.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-DBSyxt0k.js.gz +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-CcohzEZE.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-CcohzEZE.js.gz +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D7KS6rq_.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D7KS6rq_.js.gz +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-CaRXtn4g.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-CaRXtn4g.js.gz +0 -0
- package/dist/client/assets/sparkles-CUdUt4qy.js +0 -1
- package/dist/client/assets/stateDiagram-D77RDMKH-Dz836LqY.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-Dz836LqY.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-5V5Y3wwn.js +0 -1
- package/dist/client/assets/swimlanes-42K2YHIH-BK4KAY00.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-BK4KAY00.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-Sj-7YK2P.js +0 -8
- package/dist/client/assets/timeline-definition-24CTP7MA-DWgxTDhO.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-DWgxTDhO.js.gz +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-BV1TIfOp.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-BV1TIfOp.js.gz +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-GYClC5F0.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-GYClC5F0.js.gz +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-D1oKV5W0.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-D1oKV5W0.js.gz +0 -0
package/.desktop-dist/main.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { CollaborationFederation, sessionAddress } from './collaborationFederation.js';
|
|
2
|
+
import { prepareBundledFrontend } from './bundledFrontend.js';
|
|
3
|
+
import { serviceConnection, serviceConnectionKeys, importServiceConnection, upsertServiceConnection, invitationForService } from './serviceConnections.js';
|
|
4
|
+
const pendingServiceInvitations = new WeakMap();
|
|
1
5
|
import { app, BrowserWindow, clipboard, dialog, ipcMain, Menu, net, nativeImage, Notification, powerMonitor, screen, session, shell, Tray, } from 'electron';
|
|
2
6
|
import { execFile, spawn } from 'node:child_process';
|
|
3
7
|
import crypto from 'node:crypto';
|
|
@@ -16,6 +20,7 @@ import { isExternalLinkStagingUrl, isSafeExternalUrl } from './externalLinks.js'
|
|
|
16
20
|
import { shouldThrottleDesktopRenderer } from './windowPolicy.js';
|
|
17
21
|
import { checkConnectedServiceRuntime, getConnectedServiceRuntimeState, restartConnectedServiceRuntime, } from './connectedServiceRuntime.js';
|
|
18
22
|
import { isOwnedDesktopRuntimeTarget } from './runtimeTarget.js';
|
|
23
|
+
import { canReadLocalInvite } from './localInviteGuard.js';
|
|
19
24
|
import { serviceDocumentNeedsReload } from './serviceWindowRecovery.js';
|
|
20
25
|
import { CertificateTrustRequests, resolveServiceCertificateTrust, canOfferCertificateTrust, downloadCertificateAuthority, isCertificateTrustError, isLocalNetworkHostname, matchManagedLocalCertificate, } from './certificateTrust.js';
|
|
21
26
|
const execFileAsync = promisify(execFile);
|
|
@@ -25,6 +30,7 @@ const termdockDir = path.join(os.homedir(), '.termdock');
|
|
|
25
30
|
const desktopConfigPath = path.join(termdockDir, 'desktop.json');
|
|
26
31
|
const serverStatePath = path.join(termdockDir, 'server.json');
|
|
27
32
|
const desktopRuntimeOwnerSocketPath = path.join(termdockDir, 'desktop-runtime-owner.sock');
|
|
33
|
+
let federationRelayProcess = null;
|
|
28
34
|
const DEFAULT_LOCAL_URL = 'http://localhost:9834';
|
|
29
35
|
const PROTOCOL_VERSION = 1;
|
|
30
36
|
const HEALTH_TIMEOUT_MS = 3_500;
|
|
@@ -80,6 +86,30 @@ let connectedServiceRuntimePollInFlight = false;
|
|
|
80
86
|
let isQuitting = false;
|
|
81
87
|
const FLOATING_WIDGET_WIDTHS = [64, 108, 152];
|
|
82
88
|
const FLOATING_WIDGET_HEIGHT = 40;
|
|
89
|
+
const collaborationFederation = new CollaborationFederation(() => [...serviceWindows.entries()]
|
|
90
|
+
.filter(([, window]) => !window.isDestroyed())
|
|
91
|
+
.map(([origin, window]) => ({ origin, label: serviceLabel(origin),
|
|
92
|
+
request: async (route, method = 'GET', body) => {
|
|
93
|
+
if (new URL(window.webContents.getURL()).origin !== origin)
|
|
94
|
+
throw new Error('服务窗口尚未就绪');
|
|
95
|
+
const args = JSON.stringify({ route, method, body });
|
|
96
|
+
return window.webContents.executeJavaScript(`(async () => {
|
|
97
|
+
const { route, method, body } = ${args};
|
|
98
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
99
|
+
if (method !== 'GET') {
|
|
100
|
+
const token = await fetch('/api/csrf-token', { signal: AbortSignal.timeout(5000) }).then(r => r.json());
|
|
101
|
+
headers['X-XSRF-TOKEN'] = token.csrfToken;
|
|
102
|
+
}
|
|
103
|
+
const response = await fetch('/api/terminal/operations' + route, {
|
|
104
|
+
method, headers, body: body === undefined ? undefined : JSON.stringify(body), signal: AbortSignal.timeout(5000)
|
|
105
|
+
});
|
|
106
|
+
const payload = response.status === 204 ? null : await response.json();
|
|
107
|
+
if (!response.ok) throw new Error(payload?.error || '服务不可达或需要升级 Termdock');
|
|
108
|
+
return payload;
|
|
109
|
+
})()`, true);
|
|
110
|
+
},
|
|
111
|
+
})));
|
|
112
|
+
let collaborationPollTimer = null;
|
|
83
113
|
function focusedWorkspaceWindow() {
|
|
84
114
|
const focused = BrowserWindow.getFocusedWindow();
|
|
85
115
|
if (focused && windowServiceOrigins.has(focused))
|
|
@@ -459,6 +489,8 @@ function readManagedLocalCertificateFingerprint() {
|
|
|
459
489
|
}
|
|
460
490
|
function installCertificateVerifyProcedure(targetSession = session.defaultSession, serviceOrigin) {
|
|
461
491
|
targetSession.setCertificateVerifyProc((request, callback) => {
|
|
492
|
+
const routeOrigins = serviceOrigin ? readDesktopConfig().connections.flatMap(item => item.routes || []).map(route => route.url) : [];
|
|
493
|
+
const requestedOrigin = [serviceOrigin, ...routeOrigins].find(origin => origin && new URL(origin).hostname.replace(/^\[|\]$/g, '').toLowerCase() === request.hostname.replace(/^\[|\]$/g, '').toLowerCase());
|
|
462
494
|
let isLocalTarget = false;
|
|
463
495
|
try {
|
|
464
496
|
isLocalTarget = isLocalNetworkTarget(new URL(`https://${request.hostname}`));
|
|
@@ -475,9 +507,7 @@ function installCertificateVerifyProcedure(targetSession = session.defaultSessio
|
|
|
475
507
|
}
|
|
476
508
|
const explicitlyTrustedTarget = presentedFingerprint
|
|
477
509
|
? serviceOrigin
|
|
478
|
-
?
|
|
479
|
-
=== request.hostname.replace(/^\[|\]$/g, '').toLowerCase()
|
|
480
|
-
&& sessionTrustedLeafByOrigin.get(serviceOrigin) === presentedFingerprint
|
|
510
|
+
? !!requestedOrigin && sessionTrustedLeafByOrigin.get(requestedOrigin) === presentedFingerprint
|
|
481
511
|
: sessionTrustedCertificateTargets.has(certificateTrustKey(request.hostname, presentedFingerprint))
|
|
482
512
|
: false;
|
|
483
513
|
const managedMatch = isLocalTarget
|
|
@@ -489,11 +519,11 @@ function installCertificateVerifyProcedure(targetSession = session.defaultSessio
|
|
|
489
519
|
callback(0);
|
|
490
520
|
return;
|
|
491
521
|
}
|
|
492
|
-
if (
|
|
522
|
+
if (requestedOrigin && canOfferCertificateTrust(requestedOrigin)
|
|
493
523
|
&& isCertificateTrustError(request.verificationResult)) {
|
|
494
524
|
// Resolve trust before Chromium caches a rejection. This covers fetch,
|
|
495
525
|
// WebSocket and navigation requests, not only the initial Node probe.
|
|
496
|
-
void resolveServiceCertificateTrust(
|
|
526
|
+
void resolveServiceCertificateTrust(requestedOrigin, request.hostname, request.certificate.data, () => requestCertificateTrust(requestedOrigin)).then((trusted) => callback(trusted ? 0 : -3), (error) => {
|
|
497
527
|
console.warn(`[desktop-certificate] ${serviceOrigin}: ${networkErrorDetails(error)}`);
|
|
498
528
|
callback(-3);
|
|
499
529
|
});
|
|
@@ -663,6 +693,7 @@ function readDesktopConfig() {
|
|
|
663
693
|
const lastConnectionUrl = typeof parsed.lastConnectionUrl === 'string' ? parsed.lastConnectionUrl : null;
|
|
664
694
|
return {
|
|
665
695
|
version: 1,
|
|
696
|
+
removedServiceKeys: Array.isArray(parsed.removedServiceKeys) ? parsed.removedServiceKeys.filter((key) => typeof key === 'string').slice(-768) : [],
|
|
666
697
|
connections: parsed.connections.filter((entry) => Boolean(entry)
|
|
667
698
|
&& typeof entry.id === 'string'
|
|
668
699
|
&& typeof entry.label === 'string'
|
|
@@ -946,6 +977,41 @@ function runtimePaths() {
|
|
|
946
977
|
source: 'development',
|
|
947
978
|
};
|
|
948
979
|
}
|
|
980
|
+
/** Explicit opt-in only; all routing and reconnect behavior lives in the shared CLI. */
|
|
981
|
+
function startConfiguredFederationRelay() {
|
|
982
|
+
const configPath = path.join(termdockDir, 'federation', 'relay.json');
|
|
983
|
+
if (federationRelayProcess || !fs.existsSync(configPath))
|
|
984
|
+
return;
|
|
985
|
+
let logFd;
|
|
986
|
+
try {
|
|
987
|
+
const runtime = runtimePaths();
|
|
988
|
+
if (!fs.existsSync(runtime.cli))
|
|
989
|
+
throw new Error('Runtime unavailable');
|
|
990
|
+
const logPath = path.join(termdockDir, 'federation', 'relay.log');
|
|
991
|
+
logFd = fs.openSync(logPath, 'a', 0o600);
|
|
992
|
+
fs.fchmodSync(logFd, 0o600);
|
|
993
|
+
const child = spawn(runtime.node, [runtime.cli, '--federation-relay', configPath], {
|
|
994
|
+
detached: false,
|
|
995
|
+
stdio: ['ignore', logFd, logFd],
|
|
996
|
+
env: desktopRuntimeEnv(runtime),
|
|
997
|
+
});
|
|
998
|
+
federationRelayProcess = child;
|
|
999
|
+
child.once('error', () => {
|
|
1000
|
+
if (federationRelayProcess === child)
|
|
1001
|
+
federationRelayProcess = null;
|
|
1002
|
+
console.error('[federation] Configured relay failed to start; inspect the private relay log.');
|
|
1003
|
+
});
|
|
1004
|
+
child.once('exit', () => { if (federationRelayProcess === child)
|
|
1005
|
+
federationRelayProcess = null; });
|
|
1006
|
+
}
|
|
1007
|
+
catch {
|
|
1008
|
+
console.error('[federation] Unable to start configured relay; verify the runtime and private configuration.');
|
|
1009
|
+
}
|
|
1010
|
+
finally {
|
|
1011
|
+
if (logFd !== undefined)
|
|
1012
|
+
fs.closeSync(logFd);
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
949
1015
|
async function executableVersion(executable) {
|
|
950
1016
|
try {
|
|
951
1017
|
const { stdout } = await execFileAsync(executable, ['--version'], {
|
|
@@ -1369,7 +1435,8 @@ async function connectWindow(rawUrl, options = {}) {
|
|
|
1369
1435
|
return await probeService(rawUrl);
|
|
1370
1436
|
}
|
|
1371
1437
|
}
|
|
1372
|
-
|
|
1438
|
+
const known = readDesktopConfig().connections.find(item => (item.serviceOrigin || item.url) === normalizeServiceUrl(rawUrl));
|
|
1439
|
+
let probe = known?.targetPeerId ? { ok: true, url: normalizeServiceUrl(rawUrl) } : await probeServiceWithLocalNetworkPermission(rawUrl, {
|
|
1373
1440
|
interactive: options.focus !== false,
|
|
1374
1441
|
});
|
|
1375
1442
|
if (!probe.ok)
|
|
@@ -1398,7 +1465,9 @@ async function connectWindow(rawUrl, options = {}) {
|
|
|
1398
1465
|
existing.lastConnectedAt = Date.now();
|
|
1399
1466
|
writeDesktopConfig(config);
|
|
1400
1467
|
}
|
|
1401
|
-
if (await serviceDocumentNeedsReload(existingWindow.webContents, key)) {
|
|
1468
|
+
if (options.invitation || await serviceDocumentNeedsReload(existingWindow.webContents, key)) {
|
|
1469
|
+
if (options.invitation)
|
|
1470
|
+
pendingServiceInvitations.set(existingWindow, options.invitation);
|
|
1402
1471
|
await existingWindow.loadURL(probe.url);
|
|
1403
1472
|
}
|
|
1404
1473
|
if (options.focus !== false) {
|
|
@@ -1411,6 +1480,9 @@ async function connectWindow(rawUrl, options = {}) {
|
|
|
1411
1480
|
return probe;
|
|
1412
1481
|
}
|
|
1413
1482
|
const workspaceWindow = createDesktopWindow({ serviceOrigin: key, label: serviceLabel(probe.url) });
|
|
1483
|
+
await prepareBundledFrontend(workspaceWindow.webContents.session, key, path.join(runtimePaths().serverRoot, 'dist', 'client'));
|
|
1484
|
+
if (options.invitation)
|
|
1485
|
+
pendingServiceInvitations.set(workspaceWindow, options.invitation);
|
|
1414
1486
|
serviceWindows.set(key, workspaceWindow);
|
|
1415
1487
|
broadcastServiceActivity();
|
|
1416
1488
|
while (!workspaceWindow.isDestroyed()) {
|
|
@@ -1786,7 +1858,91 @@ function installIpcHandlers() {
|
|
|
1786
1858
|
const png = image.toPNG();
|
|
1787
1859
|
return png.buffer.slice(png.byteOffset, png.byteOffset + png.byteLength);
|
|
1788
1860
|
});
|
|
1861
|
+
const collaborationOrigin = (event) => {
|
|
1862
|
+
const window = BrowserWindow.fromWebContents(event.sender);
|
|
1863
|
+
const origin = window ? windowServiceOrigins.get(window) : undefined;
|
|
1864
|
+
if (!origin || event.senderFrame !== event.sender.mainFrame
|
|
1865
|
+
|| new URL(event.sender.getURL()).origin !== origin)
|
|
1866
|
+
throw new Error('未授权的服务窗口');
|
|
1867
|
+
return origin;
|
|
1868
|
+
};
|
|
1869
|
+
ipcMain.handle('desktop:collaboration-list', (event) => collaborationFederation.list(collaborationOrigin(event)));
|
|
1870
|
+
ipcMain.handle('desktop:collaboration-save', (event, input) => collaborationFederation.save(collaborationOrigin(event), input));
|
|
1871
|
+
ipcMain.handle('desktop:collaboration-remove', (event, id) => collaborationFederation.remove(collaborationOrigin(event), id));
|
|
1872
|
+
ipcMain.handle('desktop:collaboration-focus', (event, id) => {
|
|
1873
|
+
collaborationOrigin(event);
|
|
1874
|
+
const address = sessionAddress(id);
|
|
1875
|
+
const target = address ? serviceWindows.get(address.origin) : null;
|
|
1876
|
+
if (!target || target.isDestroyed())
|
|
1877
|
+
return false;
|
|
1878
|
+
showAndFocusWindow(target);
|
|
1879
|
+
target.webContents.send('desktop:focus-session', address.id);
|
|
1880
|
+
return true;
|
|
1881
|
+
});
|
|
1882
|
+
collaborationPollTimer = setInterval(() => void collaborationFederation.refresh().catch(() => { }), 2000);
|
|
1883
|
+
collaborationPollTimer.unref();
|
|
1789
1884
|
ipcMain.handle('desktop:snapshot', () => snapshot());
|
|
1885
|
+
const directorySender = (event) => {
|
|
1886
|
+
const window = BrowserWindow.fromWebContents(event.sender);
|
|
1887
|
+
if (!window || event.senderFrame !== event.sender.mainFrame)
|
|
1888
|
+
throw new Error('无法访问服务列表。');
|
|
1889
|
+
const origin = windowServiceOrigins.get(window);
|
|
1890
|
+
const url = new URL(event.senderFrame.url);
|
|
1891
|
+
if (origin ? url.origin !== origin || url.pathname !== '/' : window !== mainWindow || url.protocol !== 'file:')
|
|
1892
|
+
throw new Error('无法访问服务列表。');
|
|
1893
|
+
return window;
|
|
1894
|
+
};
|
|
1895
|
+
const directoryChanged = () => {
|
|
1896
|
+
installMenu();
|
|
1897
|
+
for (const window of BrowserWindow.getAllWindows())
|
|
1898
|
+
window.webContents.send('desktop:service-connections-changed');
|
|
1899
|
+
broadcastServiceActivity();
|
|
1900
|
+
};
|
|
1901
|
+
ipcMain.handle('desktop:service-connections', event => { directorySender(event); return readDesktopConfig().connections; });
|
|
1902
|
+
ipcMain.handle('desktop:save-service-connection', (event, input) => {
|
|
1903
|
+
directorySender(event);
|
|
1904
|
+
const config = readDesktopConfig();
|
|
1905
|
+
config.connections = upsertServiceConnection(config.connections, input);
|
|
1906
|
+
writeDesktopConfig(config);
|
|
1907
|
+
directoryChanged();
|
|
1908
|
+
return config.connections;
|
|
1909
|
+
});
|
|
1910
|
+
ipcMain.handle('desktop:import-service-connection', (event, input) => {
|
|
1911
|
+
directorySender(event);
|
|
1912
|
+
const config = readDesktopConfig();
|
|
1913
|
+
config.connections = importServiceConnection(config.connections, config.removedServiceKeys || [], input);
|
|
1914
|
+
writeDesktopConfig(config);
|
|
1915
|
+
directoryChanged();
|
|
1916
|
+
return config.connections;
|
|
1917
|
+
});
|
|
1918
|
+
ipcMain.handle('desktop:remove-service-connection', (event, id) => {
|
|
1919
|
+
directorySender(event);
|
|
1920
|
+
const config = readDesktopConfig();
|
|
1921
|
+
const removed = config.connections.find(item => item.id === id);
|
|
1922
|
+
if (removed)
|
|
1923
|
+
config.removedServiceKeys = [...new Set([...(config.removedServiceKeys || []), ...serviceConnectionKeys(removed)])].slice(-768);
|
|
1924
|
+
config.connections = config.connections.filter(item => item.id !== id);
|
|
1925
|
+
writeDesktopConfig(config);
|
|
1926
|
+
directoryChanged();
|
|
1927
|
+
return config.connections;
|
|
1928
|
+
});
|
|
1929
|
+
ipcMain.handle('desktop:current-service-connection', event => {
|
|
1930
|
+
const window = directorySender(event), origin = windowServiceOrigins.get(window);
|
|
1931
|
+
const connection = readDesktopConfig().connections.find(item => (item.serviceOrigin || item.url) === origin);
|
|
1932
|
+
const invitation = pendingServiceInvitations.get(window);
|
|
1933
|
+
pendingServiceInvitations.delete(window);
|
|
1934
|
+
return connection ? { ...connection, ...(invitation ? { invitation } : {}) } : null;
|
|
1935
|
+
});
|
|
1936
|
+
ipcMain.handle('desktop:open-service-connection', async (event, input, rawInvitation) => {
|
|
1937
|
+
directorySender(event);
|
|
1938
|
+
const connection = serviceConnection(input), invitation = invitationForService(rawInvitation, connection);
|
|
1939
|
+
// A bookmark pin is connection metadata, never authorization to the service.
|
|
1940
|
+
const config = readDesktopConfig();
|
|
1941
|
+
config.connections = upsertServiceConnection(config.connections, connection);
|
|
1942
|
+
writeDesktopConfig(config);
|
|
1943
|
+
directoryChanged();
|
|
1944
|
+
return connectWindow(connection.serviceOrigin || connection.url, { invitation });
|
|
1945
|
+
});
|
|
1790
1946
|
ipcMain.handle('desktop:probe', (_event, url) => {
|
|
1791
1947
|
try {
|
|
1792
1948
|
certificateTrustRequests.retry(new URL(normalizeServiceUrl(url)).origin);
|
|
@@ -1862,6 +2018,42 @@ function installIpcHandlers() {
|
|
|
1862
2018
|
broadcastServiceActivity();
|
|
1863
2019
|
return true;
|
|
1864
2020
|
});
|
|
2021
|
+
ipcMain.handle('desktop:local-invite', async (event) => {
|
|
2022
|
+
const sourceWindow = BrowserWindow.fromWebContents(event.sender);
|
|
2023
|
+
if (!sourceWindow || sourceWindow.isDestroyed() || event.senderFrame !== event.sender.mainFrame)
|
|
2024
|
+
return null;
|
|
2025
|
+
const registeredOrigin = windowServiceOrigins.get(sourceWindow);
|
|
2026
|
+
const initialUrl = event.sender.getURL();
|
|
2027
|
+
// First reject remote/preview callers before any asynchronous local probing.
|
|
2028
|
+
let callerPort;
|
|
2029
|
+
try {
|
|
2030
|
+
const url = new URL(initialUrl);
|
|
2031
|
+
callerPort = Number(url.port || (url.protocol === 'https:' ? 443 : 80));
|
|
2032
|
+
}
|
|
2033
|
+
catch {
|
|
2034
|
+
return null;
|
|
2035
|
+
}
|
|
2036
|
+
if (!canReadLocalInvite({ registeredOrigin, currentUrl: initialUrl, mainFrame: true, running: true, desktopManaged: true, servicePort: callerPort }))
|
|
2037
|
+
return null;
|
|
2038
|
+
const status = await getLocalServiceStatus().catch(() => null);
|
|
2039
|
+
if (!status || !status.state || sourceWindow.isDestroyed() || event.sender.isDestroyed()
|
|
2040
|
+
|| event.senderFrame !== event.sender.mainFrame || event.sender.getURL() !== initialUrl
|
|
2041
|
+
|| windowServiceOrigins.get(sourceWindow) !== registeredOrigin
|
|
2042
|
+
|| !canReadLocalInvite({ registeredOrigin, currentUrl: event.sender.getURL(), mainFrame: true,
|
|
2043
|
+
running: status.running, desktopManaged: status.probe?.desktopManaged === true, servicePort: status.state.port })
|
|
2044
|
+
|| !isOwnedDesktopRuntimeWindow(sourceWindow, status))
|
|
2045
|
+
return null;
|
|
2046
|
+
try {
|
|
2047
|
+
const data = JSON.parse(fs.readFileSync(path.join(termdockDir, 'federation', 'pairing.json'), 'utf8'));
|
|
2048
|
+
if (typeof data.serviceId !== 'string' || !/^12D3KooW[1-9A-HJ-NP-Za-km-z]{44}$/.test(data.serviceId)
|
|
2049
|
+
|| typeof data.pairingCode !== 'string' || !/^[A-Za-z0-9_-]{32,128}$/.test(data.pairingCode))
|
|
2050
|
+
return null;
|
|
2051
|
+
return { url: registeredOrigin, targetPeerId: data.serviceId, pairingCode: data.pairingCode, serviceName: '本机 Termdock' };
|
|
2052
|
+
}
|
|
2053
|
+
catch {
|
|
2054
|
+
return null;
|
|
2055
|
+
}
|
|
2056
|
+
});
|
|
1865
2057
|
ipcMain.handle('desktop:start-local', () => startLocalService());
|
|
1866
2058
|
ipcMain.handle('desktop:update-preferences', async (_event, preferences) => {
|
|
1867
2059
|
updateDesktopPreferences({
|
|
@@ -2199,6 +2391,7 @@ app.whenReady().then(async () => {
|
|
|
2199
2391
|
});
|
|
2200
2392
|
});
|
|
2201
2393
|
startConnectedServiceRuntimePolling();
|
|
2394
|
+
startConfiguredFederationRelay();
|
|
2202
2395
|
const startupConfig = readDesktopConfig();
|
|
2203
2396
|
const restoreUrls = startupConfig.openConnectionUrls;
|
|
2204
2397
|
startupRestoreActive = true;
|
|
@@ -2257,8 +2450,12 @@ app.on('window-all-closed', () => {
|
|
|
2257
2450
|
});
|
|
2258
2451
|
app.on('before-quit', () => {
|
|
2259
2452
|
isQuitting = true;
|
|
2453
|
+
federationRelayProcess?.kill('SIGTERM');
|
|
2454
|
+
federationRelayProcess = null;
|
|
2260
2455
|
desktopRuntimeOwnerServer?.close();
|
|
2261
2456
|
desktopRuntimeOwnerServer = null;
|
|
2457
|
+
if (collaborationPollTimer)
|
|
2458
|
+
clearInterval(collaborationPollTimer);
|
|
2262
2459
|
if (connectedServiceRuntimePollTimer)
|
|
2263
2460
|
clearInterval(connectedServiceRuntimePollTimer);
|
|
2264
2461
|
connectedServiceRuntimePollTimer = null;
|