termdock 1.4.263 → 1.4.265
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/assets/App-u-k6rrzb.js +156 -0
- package/dist/client/assets/App-u-k6rrzb.js.br +0 -0
- package/dist/client/assets/App-u-k6rrzb.js.gz +0 -0
- package/dist/client/assets/{ChangeWalkthroughPanel-CzrJ6gJP.js → ChangeWalkthroughPanel-BfPRxDiF.js} +2 -2
- package/dist/client/assets/ChangeWalkthroughPanel-BfPRxDiF.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-BfPRxDiF.js.gz +0 -0
- package/dist/client/assets/{DagPlayground-C7RaD0hD.js → DagPlayground-DIFzVISA.js} +1 -1
- package/dist/client/assets/DagPlayground-DIFzVISA.js.br +0 -0
- package/dist/client/assets/DagPlayground-DIFzVISA.js.gz +0 -0
- package/dist/client/assets/{DiffLab-Cl8rs4sk.js → DiffLab-gjCZJZHD.js} +1 -1
- package/dist/client/assets/DiffLab-gjCZJZHD.js.br +0 -0
- package/dist/client/assets/DiffLab-gjCZJZHD.js.gz +0 -0
- package/dist/client/assets/{DiffReview-D4715gv-.js → DiffReview-_Ehf5r7B.js} +1 -1
- package/dist/client/assets/DiffReview-_Ehf5r7B.js.br +0 -0
- package/dist/client/assets/DiffReview-_Ehf5r7B.js.gz +0 -0
- package/dist/client/assets/{DiffReviewLab-DelgnRri.js → DiffReviewLab-D5ZZmL0c.js} +1 -1
- package/dist/client/assets/DiffReviewLab-D5ZZmL0c.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-D5ZZmL0c.js.gz +0 -0
- package/dist/client/assets/DiffViewer-CYn0xF79.js +37 -0
- package/dist/client/assets/DiffViewer-CYn0xF79.js.br +0 -0
- package/dist/client/assets/DiffViewer-CYn0xF79.js.gz +0 -0
- package/dist/client/assets/{ModelPreview-COGEMw6A.js → ModelPreview-CD59YJ_a.js} +1 -1
- package/dist/client/assets/ModelPreview-CD59YJ_a.js.br +0 -0
- package/dist/client/assets/ModelPreview-CD59YJ_a.js.gz +0 -0
- package/dist/client/assets/{RightSidebar-B4lwUjHl.js → RightSidebar-CeHCLhLy.js} +47 -47
- package/dist/client/assets/RightSidebar-CeHCLhLy.js.br +0 -0
- package/dist/client/assets/RightSidebar-CeHCLhLy.js.gz +0 -0
- package/dist/client/assets/{abnfDiagram-VCTEODGH-COWpaiS-.js → abnfDiagram-VCTEODGH-DSa1Ysa8.js} +1 -1
- package/dist/client/assets/abnfDiagram-VCTEODGH-DSa1Ysa8.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-DSa1Ysa8.js.gz +0 -0
- package/dist/client/assets/{app-DHnc6XU3.js → app-L3gaEB1i.js} +11 -11
- package/dist/client/assets/app-L3gaEB1i.js.br +0 -0
- package/dist/client/assets/app-L3gaEB1i.js.gz +0 -0
- package/dist/client/assets/{arc-B5ZIGNkR.js → arc-BheyZ1mz.js} +1 -1
- package/dist/client/assets/arc-BheyZ1mz.js.br +0 -0
- package/dist/client/assets/arc-BheyZ1mz.js.gz +0 -0
- package/dist/client/assets/{architectureDiagram-5GKGNRK7-D9KCt4gq.js → architectureDiagram-5GKGNRK7-BXlasfrQ.js} +1 -1
- package/dist/client/assets/architectureDiagram-5GKGNRK7-BXlasfrQ.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-BXlasfrQ.js.gz +0 -0
- package/dist/client/assets/{blockDiagram-I7D4REHJ-wwBKtSqS.js → blockDiagram-I7D4REHJ-DwCl8uZj.js} +1 -1
- package/dist/client/assets/blockDiagram-I7D4REHJ-DwCl8uZj.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-DwCl8uZj.js.gz +0 -0
- package/dist/client/assets/{c4Diagram-7LVT6UL2-BSWUY2m8.js → c4Diagram-7LVT6UL2-Coq6KCH6.js} +1 -1
- package/dist/client/assets/c4Diagram-7LVT6UL2-Coq6KCH6.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-Coq6KCH6.js.gz +0 -0
- package/dist/client/assets/channel-Cm5edA5B.js +1 -0
- package/dist/client/assets/{chunk-2Q5K7J3B-C6tBCDpG.js → chunk-2Q5K7J3B-CUFYwTko.js} +1 -1
- package/dist/client/assets/{chunk-5VM5RSS4-BboWsUGn.js → chunk-5VM5RSS4-COcgIAqN.js} +1 -1
- package/dist/client/assets/{chunk-F27PBJKO-t8LC2p6f.js → chunk-F27PBJKO-BWhCCTPq.js} +1 -1
- package/dist/client/assets/chunk-F27PBJKO-BWhCCTPq.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-BWhCCTPq.js.gz +0 -0
- package/dist/client/assets/{chunk-IMKFNOWR-BLpilR76.js → chunk-IMKFNOWR-C7TuNlR1.js} +1 -1
- package/dist/client/assets/chunk-IMKFNOWR-C7TuNlR1.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-C7TuNlR1.js.gz +0 -0
- package/dist/client/assets/{chunk-JWPE2WC7-UAJgqWvI.js → chunk-JWPE2WC7-DjNz0bcc.js} +1 -1
- package/dist/client/assets/{chunk-POPQ4Y6H-CpVzK8jo.js → chunk-POPQ4Y6H-TT5BNkJr.js} +1 -1
- package/dist/client/assets/{chunk-SVP7TREG-irhVxs6O.js → chunk-SVP7TREG-DK9JcY1h.js} +1 -1
- package/dist/client/assets/chunk-SVP7TREG-DK9JcY1h.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-DK9JcY1h.js.gz +0 -0
- package/dist/client/assets/{chunk-TICWLB2K-Au4c5Tnt.js → chunk-TICWLB2K-B19MlAfZ.js} +1 -1
- package/dist/client/assets/chunk-TICWLB2K-B19MlAfZ.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-B19MlAfZ.js.gz +0 -0
- package/dist/client/assets/{chunk-XXDRQBXY-NlJK-TD4.js → chunk-XXDRQBXY-BI9irqHN.js} +1 -1
- package/dist/client/assets/classDiagram-ZZMXUADV-o0rDEd1E.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-o0rDEd1E.js +1 -0
- package/dist/client/assets/{cose-bilkent-JH36ORCC-CBucN9Xa.js → cose-bilkent-JH36ORCC-DSg7_PN1.js} +1 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-DSg7_PN1.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-DSg7_PN1.js.gz +0 -0
- package/dist/client/assets/{cynefin-OW5HDTMX-DBkqdsPg.js → cynefin-OW5HDTMX-uC7egYG5.js} +1 -1
- package/dist/client/assets/cynefin-OW5HDTMX-uC7egYG5.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-uC7egYG5.js.gz +0 -0
- package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-g-mNhqWP.js → cynefinDiagram-5FMLGOSQ-C-XGZrRz.js} +1 -1
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-C-XGZrRz.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-C-XGZrRz.js.gz +0 -0
- package/dist/client/assets/{dagre-GXQ25YYZ-aMhTipKP.js → dagre-GXQ25YYZ-B5YJUKWx.js} +1 -1
- package/dist/client/assets/dagre-GXQ25YYZ-B5YJUKWx.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-B5YJUKWx.js.gz +0 -0
- package/dist/client/assets/{diagram-S7CK7UJ4-FTXlqV5C.js → diagram-S7CK7UJ4-Bnyrx-jR.js} +1 -1
- package/dist/client/assets/diagram-S7CK7UJ4-Bnyrx-jR.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-Bnyrx-jR.js.gz +0 -0
- package/dist/client/assets/{diagram-UQ7AKVKN-CWKlCxDh.js → diagram-UQ7AKVKN-CUp603fW.js} +1 -1
- package/dist/client/assets/diagram-UQ7AKVKN-CUp603fW.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-CUp603fW.js.gz +0 -0
- package/dist/client/assets/{diagram-VSXAHHWV-DuCN1zfS.js → diagram-VSXAHHWV-uIXayijw.js} +1 -1
- package/dist/client/assets/diagram-VSXAHHWV-uIXayijw.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-uIXayijw.js.gz +0 -0
- package/dist/client/assets/{diagram-VX7I27RA-BYYvrnH1.js → diagram-VX7I27RA-6J1oIMOb.js} +1 -1
- package/dist/client/assets/diagram-VX7I27RA-6J1oIMOb.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-6J1oIMOb.js.gz +0 -0
- package/dist/client/assets/{diagram-Z3DM3KII-BJ_UXuWt.js → diagram-Z3DM3KII-C0WgBWqD.js} +1 -1
- package/dist/client/assets/diagram-Z3DM3KII-C0WgBWqD.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-C0WgBWqD.js.gz +0 -0
- package/dist/client/assets/{ebnfDiagram-PWID7BFC-BLb31-CG.js → ebnfDiagram-PWID7BFC-B5DEM-bI.js} +1 -1
- package/dist/client/assets/ebnfDiagram-PWID7BFC-B5DEM-bI.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-B5DEM-bI.js.gz +0 -0
- package/dist/client/assets/{erDiagram-RLTQ6QDP-Dt5T_zZr.js → erDiagram-RLTQ6QDP-BzxCr-aA.js} +1 -1
- package/dist/client/assets/erDiagram-RLTQ6QDP-BzxCr-aA.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-BzxCr-aA.js.gz +0 -0
- package/dist/client/assets/{flowDiagram-HODETNUW-CC8Rn9fH.js → flowDiagram-HODETNUW-DHjjUn1K.js} +1 -1
- package/dist/client/assets/flowDiagram-HODETNUW-DHjjUn1K.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-DHjjUn1K.js.gz +0 -0
- package/dist/client/assets/{ganttDiagram-EL5Y4UJY-Bki2eBkC.js → ganttDiagram-EL5Y4UJY-wH7qPWQb.js} +1 -1
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-wH7qPWQb.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-wH7qPWQb.js.gz +0 -0
- package/dist/client/assets/{gestureArbiter-BX-zjr4n.js → gestureArbiter-D6RWPMQo.js} +1 -1
- package/dist/client/assets/gestureArbiter-D6RWPMQo.js.br +0 -0
- package/dist/client/assets/gestureArbiter-D6RWPMQo.js.gz +0 -0
- package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-DlR3hAyj.js → gitGraphDiagram-WWUBYQGX-CcY9a3m3.js} +1 -1
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-CcY9a3m3.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-CcY9a3m3.js.gz +0 -0
- package/dist/client/assets/{index-ddQQwU7M.css → index-BOv8uqyA.css} +1 -1
- package/dist/client/assets/index-BOv8uqyA.css.br +0 -0
- package/dist/client/assets/{index-ddQQwU7M.css.gz → index-BOv8uqyA.css.gz} +0 -0
- package/dist/client/assets/{infoDiagram-27XIBGKW-C-5zXbqy.js → infoDiagram-27XIBGKW-0ylnBr_8.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-D_KAjhux.js → ishikawaDiagram-5VMMS53U-CjrSMq_a.js} +1 -1
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-CjrSMq_a.js.br +0 -0
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-D_KAjhux.js.gz → ishikawaDiagram-5VMMS53U-CjrSMq_a.js.gz} +0 -0
- package/dist/client/assets/{journeyDiagram-3NMN7TZE-DasVMhbH.js → journeyDiagram-3NMN7TZE-DrzTWkK-.js} +1 -1
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DrzTWkK-.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DrzTWkK-.js.gz +0 -0
- package/dist/client/assets/{kanban-definition-UXKFOSKX-BeDZ9x71.js → kanban-definition-UXKFOSKX-D9CCE6r8.js} +1 -1
- package/dist/client/assets/kanban-definition-UXKFOSKX-D9CCE6r8.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-D9CCE6r8.js.gz +0 -0
- package/dist/client/assets/{layout-BonFkvNe.js → layout-BjxwetPy.js} +1 -1
- package/dist/client/assets/layout-BjxwetPy.js.br +0 -0
- package/dist/client/assets/layout-BjxwetPy.js.gz +0 -0
- package/dist/client/assets/{linear-amKhUz-E.js → linear-C0mh26-a.js} +1 -1
- package/dist/client/assets/linear-C0mh26-a.js.br +0 -0
- package/dist/client/assets/linear-C0mh26-a.js.gz +0 -0
- package/dist/client/assets/{mermaid.core-C743W_cw.js → mermaid.core-CWIVZHBb.js} +5 -5
- package/dist/client/assets/mermaid.core-CWIVZHBb.js.br +0 -0
- package/dist/client/assets/mermaid.core-CWIVZHBb.js.gz +0 -0
- package/dist/client/assets/{mindmap-definition-YA3MSWOX-dnSMIb-2.js → mindmap-definition-YA3MSWOX-BGo9fKR8.js} +1 -1
- package/dist/client/assets/mindmap-definition-YA3MSWOX-BGo9fKR8.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-BGo9fKR8.js.gz +0 -0
- package/dist/client/assets/{passwordBootstrap-Z-zMfeRE.js → passwordBootstrap-CHyPbAR9.js} +2 -2
- package/dist/client/assets/passwordBootstrap-CHyPbAR9.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-CHyPbAR9.js.gz +0 -0
- package/dist/client/assets/{pegDiagram-XKGWAZYB-BMMrDjH3.js → pegDiagram-XKGWAZYB-0Nb1LL5B.js} +1 -1
- package/dist/client/assets/pegDiagram-XKGWAZYB-0Nb1LL5B.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-0Nb1LL5B.js.gz +0 -0
- package/dist/client/assets/{pieDiagram-E7YTZNPT-CGZ4yhWL.js → pieDiagram-E7YTZNPT-84u6YN0w.js} +1 -1
- package/dist/client/assets/pieDiagram-E7YTZNPT-84u6YN0w.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-84u6YN0w.js.gz +0 -0
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-BfUxBRZx.js → quadrantDiagram-AXDQQJYC-BUHd3sQq.js} +1 -1
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-BUHd3sQq.js.br +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-BUHd3sQq.js.gz +0 -0
- package/dist/client/assets/{railroadDiagram-O6MQD6OU-DRtstXqY.js → railroadDiagram-O6MQD6OU-CENx-rxh.js} +1 -1
- package/dist/client/assets/railroadDiagram-O6MQD6OU-CENx-rxh.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-CENx-rxh.js.gz +0 -0
- package/dist/client/assets/{referenceLongPress-OgQ-br0J.js → referenceLongPress-D9JDfvlW.js} +1 -1
- package/dist/client/assets/referenceLongPress-D9JDfvlW.js.br +0 -0
- package/dist/client/assets/referenceLongPress-D9JDfvlW.js.gz +0 -0
- package/dist/client/assets/{requirementDiagram-BXWQKSXE-jIWvwxYZ.js → requirementDiagram-BXWQKSXE-CBQ0Ny7q.js} +1 -1
- package/dist/client/assets/requirementDiagram-BXWQKSXE-CBQ0Ny7q.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-CBQ0Ny7q.js.gz +0 -0
- package/dist/client/assets/{sankeyDiagram-P5KCCOFB-CmV9o38-.js → sankeyDiagram-P5KCCOFB-3bBhyXPE.js} +1 -1
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-3bBhyXPE.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-3bBhyXPE.js.gz +0 -0
- package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-C37VhGXR.js → sequenceDiagram-WJ2MYXX4-BK6pizap.js} +1 -1
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-BK6pizap.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-BK6pizap.js.gz +0 -0
- package/dist/client/assets/{sizeCapture-INFHLROL-D3aZUvMq.js → sizeCapture-INFHLROL-3qlKfimL.js} +1 -1
- package/dist/client/assets/sizeCapture-INFHLROL-3qlKfimL.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-3qlKfimL.js.gz +0 -0
- package/dist/client/assets/{sparkles-BwJHncXI.js → sparkles-CT3DLxs9.js} +1 -1
- package/dist/client/assets/{stateDiagram-D77RDMKH-B3W9KWRf.js → stateDiagram-D77RDMKH-DJ5Eljth.js} +1 -1
- package/dist/client/assets/stateDiagram-D77RDMKH-DJ5Eljth.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-DJ5Eljth.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-IzUrIY-v.js +1 -0
- package/dist/client/assets/{swimlanes-42K2YHIH-CgFI-TZF.js → swimlanes-42K2YHIH-D2LOfXqZ.js} +1 -1
- package/dist/client/assets/swimlanes-42K2YHIH-D2LOfXqZ.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-D2LOfXqZ.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-fxwyakfK.js +8 -0
- package/dist/client/assets/{timeline-definition-24CTP7MA-Ad00a495.js → timeline-definition-24CTP7MA-CXi-wBS0.js} +1 -1
- package/dist/client/assets/timeline-definition-24CTP7MA-CXi-wBS0.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-CXi-wBS0.js.gz +0 -0
- package/dist/client/assets/{triangle-alert-DDQ67k7N.js → triangle-alert-C6No3Q8u.js} +1 -1
- package/dist/client/assets/{vennDiagram-4TSXK5OY-CSawzFTi.js → vennDiagram-4TSXK5OY-CIz0V4J6.js} +1 -1
- package/dist/client/assets/vennDiagram-4TSXK5OY-CIz0V4J6.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-CIz0V4J6.js.gz +0 -0
- package/dist/client/assets/{wardleyDiagram-VM6X3IG4-Emoh-n_o.js → wardleyDiagram-VM6X3IG4-B0UrTqd3.js} +1 -1
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-B0UrTqd3.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-B0UrTqd3.js.gz +0 -0
- package/dist/client/assets/{xychartDiagram-S5SC5T6Z-BPgImmcN.js → xychartDiagram-S5SC5T6Z-CGda0vcy.js} +1 -1
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-CGda0vcy.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-CGda0vcy.js.gz +0 -0
- package/dist/client/index.html +2 -2
- package/dist/client/index.html.br +0 -0
- package/dist/client/index.html.gz +0 -0
- package/dist/client/sw.js +1 -1
- package/dist/client/sw.js.br +0 -0
- package/dist/client/sw.js.gz +0 -0
- package/dist/server/android/recording.js +178 -0
- package/dist/server/cli.js +20 -0
- package/dist/server/entry.js +5 -2
- package/dist/server/routes/android.js +55 -0
- package/dist/server/routes/filesystem.js +13 -3
- package/dist/server/routes/terminal.js +30 -2
- package/dist/server/supervisionHandoff.js +33 -0
- package/dist/server/supervisor.js +6 -3
- package/dist/server/utils/enableSupervision.js +80 -0
- package/dist/server/utils/serverHealth.js +28 -3
- package/dist/server/utils/settings.js +1 -1
- package/dist/server/utils/startupFailure.js +16 -0
- package/dist/server/utils/supervisorProtocol.js +5 -0
- package/package.json +1 -1
- package/runtime-manifest.json +3 -3
- package/dist/client/assets/App-Be0tsVAS.js +0 -156
- package/dist/client/assets/App-Be0tsVAS.js.br +0 -0
- package/dist/client/assets/App-Be0tsVAS.js.gz +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-CzrJ6gJP.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-CzrJ6gJP.js.gz +0 -0
- package/dist/client/assets/DagPlayground-C7RaD0hD.js.br +0 -0
- package/dist/client/assets/DagPlayground-C7RaD0hD.js.gz +0 -0
- package/dist/client/assets/DiffLab-Cl8rs4sk.js.br +0 -0
- package/dist/client/assets/DiffLab-Cl8rs4sk.js.gz +0 -0
- package/dist/client/assets/DiffReview-D4715gv-.js.br +0 -0
- package/dist/client/assets/DiffReview-D4715gv-.js.gz +0 -0
- package/dist/client/assets/DiffReviewLab-DelgnRri.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-DelgnRri.js.gz +0 -0
- package/dist/client/assets/DiffViewer-DxGkdCpG.js +0 -36
- package/dist/client/assets/DiffViewer-DxGkdCpG.js.br +0 -0
- package/dist/client/assets/DiffViewer-DxGkdCpG.js.gz +0 -0
- package/dist/client/assets/ModelPreview-COGEMw6A.js.br +0 -0
- package/dist/client/assets/ModelPreview-COGEMw6A.js.gz +0 -0
- package/dist/client/assets/RightSidebar-B4lwUjHl.js.br +0 -0
- package/dist/client/assets/RightSidebar-B4lwUjHl.js.gz +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-COWpaiS-.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-COWpaiS-.js.gz +0 -0
- package/dist/client/assets/app-DHnc6XU3.js.br +0 -0
- package/dist/client/assets/app-DHnc6XU3.js.gz +0 -0
- package/dist/client/assets/arc-B5ZIGNkR.js.br +0 -0
- package/dist/client/assets/arc-B5ZIGNkR.js.gz +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-D9KCt4gq.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-D9KCt4gq.js.gz +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-wwBKtSqS.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-wwBKtSqS.js.gz +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-BSWUY2m8.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-BSWUY2m8.js.gz +0 -0
- package/dist/client/assets/channel-TGPTnJaC.js +0 -1
- package/dist/client/assets/chunk-F27PBJKO-t8LC2p6f.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-t8LC2p6f.js.gz +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-BLpilR76.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-BLpilR76.js.gz +0 -0
- package/dist/client/assets/chunk-SVP7TREG-irhVxs6O.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-irhVxs6O.js.gz +0 -0
- package/dist/client/assets/chunk-TICWLB2K-Au4c5Tnt.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-Au4c5Tnt.js.gz +0 -0
- package/dist/client/assets/classDiagram-ZZMXUADV-ECZW8RQZ.js +0 -1
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-ECZW8RQZ.js +0 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-CBucN9Xa.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-CBucN9Xa.js.gz +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-DBkqdsPg.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-DBkqdsPg.js.gz +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-g-mNhqWP.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-g-mNhqWP.js.gz +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-aMhTipKP.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-aMhTipKP.js.gz +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-FTXlqV5C.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-FTXlqV5C.js.gz +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-CWKlCxDh.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-CWKlCxDh.js.gz +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-DuCN1zfS.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-DuCN1zfS.js.gz +0 -0
- package/dist/client/assets/diagram-VX7I27RA-BYYvrnH1.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-BYYvrnH1.js.gz +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-BJ_UXuWt.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-BJ_UXuWt.js.gz +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-BLb31-CG.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-BLb31-CG.js.gz +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-Dt5T_zZr.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-Dt5T_zZr.js.gz +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-CC8Rn9fH.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-CC8Rn9fH.js.gz +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-Bki2eBkC.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-Bki2eBkC.js.gz +0 -0
- package/dist/client/assets/gestureArbiter-BX-zjr4n.js.br +0 -0
- package/dist/client/assets/gestureArbiter-BX-zjr4n.js.gz +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DlR3hAyj.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DlR3hAyj.js.gz +0 -0
- package/dist/client/assets/index-ddQQwU7M.css.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-D_KAjhux.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DasVMhbH.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DasVMhbH.js.gz +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-BeDZ9x71.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-BeDZ9x71.js.gz +0 -0
- package/dist/client/assets/layout-BonFkvNe.js.br +0 -0
- package/dist/client/assets/layout-BonFkvNe.js.gz +0 -0
- package/dist/client/assets/linear-amKhUz-E.js.br +0 -0
- package/dist/client/assets/linear-amKhUz-E.js.gz +0 -0
- package/dist/client/assets/mermaid.core-C743W_cw.js.br +0 -0
- package/dist/client/assets/mermaid.core-C743W_cw.js.gz +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-dnSMIb-2.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-dnSMIb-2.js.gz +0 -0
- package/dist/client/assets/passwordBootstrap-Z-zMfeRE.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-Z-zMfeRE.js.gz +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-BMMrDjH3.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-BMMrDjH3.js.gz +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-CGZ4yhWL.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-CGZ4yhWL.js.gz +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-BfUxBRZx.js.br +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-BfUxBRZx.js.gz +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-DRtstXqY.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-DRtstXqY.js.gz +0 -0
- package/dist/client/assets/referenceLongPress-OgQ-br0J.js.br +0 -0
- package/dist/client/assets/referenceLongPress-OgQ-br0J.js.gz +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-jIWvwxYZ.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-jIWvwxYZ.js.gz +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-CmV9o38-.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-CmV9o38-.js.gz +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-C37VhGXR.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-C37VhGXR.js.gz +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-D3aZUvMq.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-D3aZUvMq.js.gz +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-B3W9KWRf.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-B3W9KWRf.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-D9yMXUEN.js +0 -1
- package/dist/client/assets/swimlanes-42K2YHIH-CgFI-TZF.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-CgFI-TZF.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DfgFmAr4.js +0 -8
- package/dist/client/assets/timeline-definition-24CTP7MA-Ad00a495.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-Ad00a495.js.gz +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-CSawzFTi.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-CSawzFTi.js.gz +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-Emoh-n_o.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-Emoh-n_o.js.gz +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-BPgImmcN.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-BPgImmcN.js.gz +0 -0
package/dist/server/entry.js
CHANGED
|
@@ -31,6 +31,8 @@ import { fileURLToPath } from 'url';
|
|
|
31
31
|
import { WebSocketServer } from 'ws';
|
|
32
32
|
import terminalRoutes, { handleTerminalWebSocket, handleControlWebSocket, resolveStableFederationSessionId } from './routes/terminal.js';
|
|
33
33
|
import androidRoutes, { handleAndroidWebSocket } from './routes/android.js';
|
|
34
|
+
import { exitWithStartupFailure } from './utils/startupFailure.js';
|
|
35
|
+
import { androidRecordings } from './android/recording.js';
|
|
34
36
|
import { stopAllScrcpySessions } from './android/scrcpy.js';
|
|
35
37
|
import filesystemRoutes from './routes/filesystem.js';
|
|
36
38
|
import authRoutes from './routes/auth.js';
|
|
@@ -463,7 +465,7 @@ export function startServer(options = {}) {
|
|
|
463
465
|
server.once('close', () => { clearInterval(desktopRoutesTimer); for (const target of dynamicDirectTargets.values())
|
|
464
466
|
target.close(); });
|
|
465
467
|
server.once('close', () => relayRouter.close());
|
|
466
|
-
server.once('close', () => { void stopAllScrcpySessions(); });
|
|
468
|
+
server.once('close', () => { void stopAllScrcpySessions(); void androidRecordings.stopAll(); });
|
|
467
469
|
const federation = createFederationRuntime(app, path.join(homedir(), '.termdock', 'federation'), {
|
|
468
470
|
terminal: handleTerminalWebSocket, control: handleControlWebSocket, android: handleAndroidWebSocket,
|
|
469
471
|
}, {
|
|
@@ -773,7 +775,8 @@ export function startServer(options = {}) {
|
|
|
773
775
|
crashForensics.recordIncident('port-conflict', { extra: { port, host, code: error.code } });
|
|
774
776
|
console.error(`Port ${port} is already in use.`);
|
|
775
777
|
console.error(`To free it, find and stop the process: lsof -tiTCP:${port} -sTCP:LISTEN | xargs kill`);
|
|
776
|
-
|
|
778
|
+
exitWithStartupFailure('port-conflict', `Port ${port} is already in use (EADDRINUSE).`);
|
|
779
|
+
return;
|
|
777
780
|
}
|
|
778
781
|
console.error('Server error:', error);
|
|
779
782
|
process.exit(1);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import { connectDevice, disconnectDevice, listDevices, resolveAdbBinary } from '../android/adb.js';
|
|
3
3
|
import { createScrcpySession, resolveScrcpyBinaries } from '../android/scrcpy.js';
|
|
4
|
+
import { androidRecordings } from '../android/recording.js';
|
|
5
|
+
import { pathValidator } from '../utils/pathValidator.js';
|
|
4
6
|
const router = Router();
|
|
5
7
|
const SERIAL_PATTERN = /^[0-9a-zA-Z_.:\-]{1,128}$/;
|
|
6
8
|
/** 逐帧/逐控件的诊断日志默认关闭,需要时 TERMDOCK_ANDROID_DEBUG=1 打开。 */
|
|
@@ -46,6 +48,59 @@ router.post('/disconnect', async (req, res) => {
|
|
|
46
48
|
res.status(400).json({ error: message, code: message });
|
|
47
49
|
}
|
|
48
50
|
});
|
|
51
|
+
router.get('/recordings', async (req, res) => {
|
|
52
|
+
const serial = typeof req.query.serial === 'string' ? req.query.serial : '';
|
|
53
|
+
if (!isValidAndroidSerial(serial)) {
|
|
54
|
+
res.status(400).json({ error: 'INVALID_SERIAL' });
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
res.json({ recordings: await androidRecordings.list(serial) });
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
res.status(500).json({ error: String(error) });
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
router.post('/recordings', async (req, res) => {
|
|
65
|
+
const serial = typeof req.body?.serial === 'string' ? req.body.serial : '';
|
|
66
|
+
if (!isValidAndroidSerial(serial)) {
|
|
67
|
+
res.status(400).json({ error: 'INVALID_SERIAL' });
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
res.json(await androidRecordings.start(serial));
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
router.post('/recordings/:id/stop', async (req, res) => {
|
|
78
|
+
try {
|
|
79
|
+
res.json(await androidRecordings.stop(req.params.id));
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
res.status(400).json({ error: String(error) });
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
router.post('/recordings/:id/save', async (req, res) => {
|
|
86
|
+
try {
|
|
87
|
+
const directory = req.body?.directory === undefined ? undefined
|
|
88
|
+
: await (req.pathValidator ?? pathValidator).validateAsync(req.body.directory);
|
|
89
|
+
res.json({ path: await androidRecordings.save(req.params.id, directory) });
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
router.delete('/recordings/:id', async (req, res) => {
|
|
96
|
+
try {
|
|
97
|
+
await androidRecordings.discard(req.params.id);
|
|
98
|
+
res.json({ ok: true });
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
res.status(400).json({ error: String(error) });
|
|
102
|
+
}
|
|
103
|
+
});
|
|
49
104
|
export default router;
|
|
50
105
|
function clampInt(value, min, max, fallback) {
|
|
51
106
|
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
@@ -1349,7 +1349,7 @@ async function getCachedGitBundle(resolvedCwd, gitRoot, includeNested, refresh,
|
|
|
1349
1349
|
const now = Date.now();
|
|
1350
1350
|
if (signal)
|
|
1351
1351
|
throwIfAborted(signal, 'git.bundle');
|
|
1352
|
-
const cached =
|
|
1352
|
+
const cached = getCompatibleGitBundleCache(gitRoot, includeNested, discoverOnly);
|
|
1353
1353
|
if (!refresh && cached && (cached.expiresAt > now || allowStale)) {
|
|
1354
1354
|
const cacheAgeMs = Math.max(0, now - (cached.expiresAt - GIT_BUNDLE_CACHE_TTL_MS));
|
|
1355
1355
|
return {
|
|
@@ -1399,8 +1399,7 @@ async function refreshGitBundleCacheDetached(resolvedCwd, gitRoot, includeNested
|
|
|
1399
1399
|
return promise;
|
|
1400
1400
|
}
|
|
1401
1401
|
function getGitBundleCache(gitRoot, includeNested, allowStale = false, discoverOnly = false) {
|
|
1402
|
-
const
|
|
1403
|
-
const cached = gitBundleCache.get(cacheKey);
|
|
1402
|
+
const cached = getCompatibleGitBundleCache(gitRoot, includeNested, discoverOnly);
|
|
1404
1403
|
if (!cached)
|
|
1405
1404
|
return null;
|
|
1406
1405
|
const now = Date.now();
|
|
@@ -2438,6 +2437,17 @@ const gitBundleBuildPromises = new Map();
|
|
|
2438
2437
|
function getGitBundleCacheKey(gitRoot, includeNested, discoverOnly = false) {
|
|
2439
2438
|
return `${gitRoot}\u0000${includeNested ? 'nested' : 'single'}${discoverOnly ? ' discover' : ''}`;
|
|
2440
2439
|
}
|
|
2440
|
+
function getCompatibleGitBundleCache(gitRoot, includeNested, discoverOnly) {
|
|
2441
|
+
const cached = gitBundleCache.get(getGitBundleCacheKey(gitRoot, includeNested, discoverOnly));
|
|
2442
|
+
if (!includeNested || !discoverOnly)
|
|
2443
|
+
return cached;
|
|
2444
|
+
// Reopening the sidebar requests discovery, while manual refresh builds the
|
|
2445
|
+
// full snapshot. Full data satisfies discovery too: do not return an older
|
|
2446
|
+
// discovery snapshot and roll back both the file list and its timestamp.
|
|
2447
|
+
// The reverse is unsafe because discovery contains deferred placeholders.
|
|
2448
|
+
const full = gitBundleCache.get(getGitBundleCacheKey(gitRoot, true));
|
|
2449
|
+
return full && (!cached || full.updatedAt >= cached.updatedAt) ? full : cached;
|
|
2450
|
+
}
|
|
2441
2451
|
function clearGitBundleCacheForRoot(root) {
|
|
2442
2452
|
for (const key of gitBundleCache.keys()) {
|
|
2443
2453
|
if (key.startsWith(`${root}\u0000`))
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { androidRecordings } from '../android/recording.js';
|
|
1
2
|
import { assertPeerRegistrationAuthority } from '../agent/collaborationPeerTransport.js';
|
|
2
3
|
import { progressRoutes } from '../notifications/progressRoutes.js';
|
|
3
4
|
import { ensureNodePty } from '../utils/ensureNodePty.js';
|
|
@@ -38,6 +39,7 @@ import { AgentResumeHistoryStore } from '../agent/resumeHistory.js';
|
|
|
38
39
|
import { isTmuxRecoveryCandidate } from '../utils/tmuxRecoveryCandidate.js';
|
|
39
40
|
import { AutomationStore, normalizeAutomationSchedule } from '../agent/automationStore.js';
|
|
40
41
|
import { buildBracketedSubmitBytes, canDeliverPromptToAgent } from '../agent/promptDelivery.js';
|
|
42
|
+
import { prepareSupervisionEnable } from '../utils/enableSupervision.js';
|
|
41
43
|
import { buildServerHealthState, dismissServerHealth } from '../utils/serverHealth.js';
|
|
42
44
|
import { collaborationRoutes } from '../agent/collaborationRoutes.js';
|
|
43
45
|
import { extrasFromBody } from '../agent/collaborationProtocol.js';
|
|
@@ -625,8 +627,24 @@ function flushPersistAndExit() {
|
|
|
625
627
|
}
|
|
626
628
|
catch { /* best effort */ }
|
|
627
629
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
+
let shuttingDown = false;
|
|
631
|
+
const shutdownWithRecordings = async () => {
|
|
632
|
+
if (shuttingDown)
|
|
633
|
+
return;
|
|
634
|
+
shuttingDown = true;
|
|
635
|
+
flushPersistAndExit();
|
|
636
|
+
void persistToolbarPresetsNow();
|
|
637
|
+
caffeinateManager.shutdown();
|
|
638
|
+
// Give the MP4 muxer a chance to write its trailer before the service exits.
|
|
639
|
+
try {
|
|
640
|
+
await androidRecordings.stopAll();
|
|
641
|
+
}
|
|
642
|
+
finally {
|
|
643
|
+
process.exit(0);
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
process.on('SIGTERM', () => { void shutdownWithRecordings(); });
|
|
647
|
+
process.on('SIGINT', () => { void shutdownWithRecordings(); });
|
|
630
648
|
// 服务启动时从磁盘加载(带去重,防止历史累积的重复条目复活)
|
|
631
649
|
void (async () => {
|
|
632
650
|
await Promise.all([loadGlobalSessionStateFromDisk(), loadTmuxRecoveryStateFromDisk()]);
|
|
@@ -6258,6 +6276,16 @@ router.post('/update/restart', async (_req, res) => {
|
|
|
6258
6276
|
router.get('/server-health', (_req, res) => {
|
|
6259
6277
|
res.json(buildServerHealthState());
|
|
6260
6278
|
});
|
|
6279
|
+
router.post('/server-health/enable-supervision', async (_req, res) => {
|
|
6280
|
+
try {
|
|
6281
|
+
const commit = await prepareSupervisionEnable();
|
|
6282
|
+
res.once('finish', commit);
|
|
6283
|
+
res.status(202).json({ restarting: true });
|
|
6284
|
+
}
|
|
6285
|
+
catch (error) {
|
|
6286
|
+
res.status(409).json({ error: error instanceof Error ? error.message : String(error) });
|
|
6287
|
+
}
|
|
6288
|
+
});
|
|
6261
6289
|
router.post('/server-health/dismiss', (_req, res) => {
|
|
6262
6290
|
res.status(202).json(dismissServerHealth());
|
|
6263
6291
|
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** The prepared process becomes the supervisor once the old service has exited. */
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { runSupervisor } from './supervisor.js';
|
|
4
|
+
import { isProcessRunning } from './utils/termdockState.js';
|
|
5
|
+
const { parentPid, config } = JSON.parse(process.argv[2]);
|
|
6
|
+
if (!Number.isSafeInteger(parentPid) || parentPid <= 1 || !process.connected)
|
|
7
|
+
process.exit(1);
|
|
8
|
+
fs.accessSync(config.childEntry, fs.constants.R_OK);
|
|
9
|
+
if (config.healthCaPath)
|
|
10
|
+
fs.accessSync(config.healthCaPath, fs.constants.R_OK);
|
|
11
|
+
let committed = false;
|
|
12
|
+
const expiry = setTimeout(() => process.exit(1), 10_000);
|
|
13
|
+
process.on('disconnect', () => { if (!committed)
|
|
14
|
+
process.exit(1); });
|
|
15
|
+
process.once('message', (message) => {
|
|
16
|
+
if (message?.type !== 'handoff-commit')
|
|
17
|
+
process.exit(1);
|
|
18
|
+
committed = true;
|
|
19
|
+
clearTimeout(expiry);
|
|
20
|
+
const deadline = Date.now() + 30_000;
|
|
21
|
+
const timer = setInterval(() => {
|
|
22
|
+
if (isProcessRunning(parentPid)) {
|
|
23
|
+
if (Date.now() >= deadline) {
|
|
24
|
+
console.error('[supervisor] old service did not exit; handoff cancelled');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
clearInterval(timer);
|
|
30
|
+
runSupervisor(config);
|
|
31
|
+
}, 100);
|
|
32
|
+
});
|
|
33
|
+
process.send?.({ type: 'handoff-ready' });
|
|
@@ -29,7 +29,7 @@ import { backoffDelayMs } from './utils/backoff.js';
|
|
|
29
29
|
import { installCrashForensics, isOomSuspect, readRuntimeTail, readServerLogTail } from './utils/crashForensics.js';
|
|
30
30
|
import { probeHealthOnce, HEALTH_PROBE_TIMEOUT_MS } from './utils/healthProbe.js';
|
|
31
31
|
import { writeJsonLogSync } from './utils/serverLogger.js';
|
|
32
|
-
import { SUPERVISOR_STATE_VERSION, classifyChildExit, isReadyMessage, isServerIntentMessage, shouldGiveUp, } from './utils/supervisorProtocol.js';
|
|
32
|
+
import { SUPERVISOR_STATE_VERSION, classifyChildExit, isReadyMessage, isStartupFailedMessage, isServerIntentMessage, shouldGiveUp, } from './utils/supervisorProtocol.js';
|
|
33
33
|
import { SUPERVISOR_STATE_PATH, STOP_GRACE_MS, isProcessRunning, removeJsonState, writeJsonStateAtomic, } from './utils/termdockState.js';
|
|
34
34
|
export const DEFAULT_SUPERVISOR_TIMING = {
|
|
35
35
|
readyTimeoutMs: 30_000,
|
|
@@ -189,6 +189,10 @@ export function createSupervisor(config, deps) {
|
|
|
189
189
|
deps.notifyLauncher({ type: 'termdock-ready' });
|
|
190
190
|
return;
|
|
191
191
|
}
|
|
192
|
+
if (isStartupFailedMessage(message) && !becameReady) {
|
|
193
|
+
portConflict = message.reason === 'port-conflict';
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
192
196
|
if (isServerIntentMessage(message)) {
|
|
193
197
|
intent = message.intent;
|
|
194
198
|
deps.log(`[supervisor] server declared intent: ${message.intent}`);
|
|
@@ -356,7 +360,6 @@ export function createSupervisor(config, deps) {
|
|
|
356
360
|
return;
|
|
357
361
|
}
|
|
358
362
|
if (shouldGiveUp(consecutiveCrashes, timing.maxConsecutiveCrashes)) {
|
|
359
|
-
lastIncident.detail = `${lastIncident.detail} — gave up after ${consecutiveCrashes} consecutive crashes`;
|
|
360
363
|
deps.log(`[supervisor] ${consecutiveCrashes} consecutive crashes; giving up. Service is NOT running.`);
|
|
361
364
|
recordApplicationGaveUp();
|
|
362
365
|
setPhase('gave-up');
|
|
@@ -380,7 +383,7 @@ export function createSupervisor(config, deps) {
|
|
|
380
383
|
deps.recordIncident({
|
|
381
384
|
role: 'supervisor',
|
|
382
385
|
event: 'gave-up',
|
|
383
|
-
detail: `gave up after ${consecutiveCrashes} consecutive
|
|
386
|
+
detail: `gave up after ${consecutiveCrashes} consecutive failures: ${lastIncident?.detail ?? 'unknown cause'}`,
|
|
384
387
|
version: config.version ?? null,
|
|
385
388
|
restarts,
|
|
386
389
|
lastIncident,
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { getSupervisorStatus } from './supervisorClient.js';
|
|
5
|
+
import { SERVER_LOG_PATH } from './termdockState.js';
|
|
6
|
+
let config = null;
|
|
7
|
+
let pending = false;
|
|
8
|
+
// Only the production CLI registers a launch recipe. Desktop and development
|
|
9
|
+
// runtimes must remain owned by their original launcher.
|
|
10
|
+
export function configureSupervisionEnable(value) {
|
|
11
|
+
config = value;
|
|
12
|
+
}
|
|
13
|
+
export function canEnableSupervision() {
|
|
14
|
+
return config !== null && !(process.env.TERMDOCK_SUPERVISED === '1' && process.connected)
|
|
15
|
+
&& !process.env.TERMDOCK_DESKTOP && !process.env.TERMDOCK_DESKTOP_OWNER_SOCKET
|
|
16
|
+
&& !process.env.INVOCATION_ID && !process.env.NOTIFY_SOCKET && !process.env.PM2_HOME
|
|
17
|
+
&& !getSupervisorStatus()?.alive;
|
|
18
|
+
}
|
|
19
|
+
/** Prepare the replacement before stopping anything; commit after HTTP flush. */
|
|
20
|
+
export async function prepareSupervisionEnable() {
|
|
21
|
+
if (pending)
|
|
22
|
+
throw new Error('Automatic recovery is already being enabled.');
|
|
23
|
+
if (!canEnableSupervision() || !config)
|
|
24
|
+
throw new Error('Enable automatic recovery through the service launcher.');
|
|
25
|
+
pending = true;
|
|
26
|
+
try {
|
|
27
|
+
const script = fileURLToPath(new URL('../supervisionHandoff.js', import.meta.url));
|
|
28
|
+
fs.accessSync(script, fs.constants.R_OK);
|
|
29
|
+
fs.accessSync(config.childEntry, fs.constants.R_OK);
|
|
30
|
+
const fd = fs.openSync(SERVER_LOG_PATH, 'a', 0o600);
|
|
31
|
+
let child;
|
|
32
|
+
try {
|
|
33
|
+
child = spawn(process.execPath, [script, JSON.stringify({ parentPid: process.pid, config })], {
|
|
34
|
+
detached: true,
|
|
35
|
+
stdio: ['ignore', fd, fd, 'ipc'],
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
fs.closeSync(fd);
|
|
40
|
+
}
|
|
41
|
+
await new Promise((resolve, reject) => {
|
|
42
|
+
const timer = setTimeout(() => {
|
|
43
|
+
child.kill();
|
|
44
|
+
reject(new Error('Automatic recovery did not become ready.'));
|
|
45
|
+
}, 5000);
|
|
46
|
+
child.once('error', (error) => { clearTimeout(timer); reject(error); });
|
|
47
|
+
child.once('exit', () => {
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
pending = false;
|
|
50
|
+
reject(new Error('Automatic recovery could not start.'));
|
|
51
|
+
});
|
|
52
|
+
child.once('message', (message) => {
|
|
53
|
+
if (message?.type !== 'handoff-ready')
|
|
54
|
+
return;
|
|
55
|
+
clearTimeout(timer);
|
|
56
|
+
resolve();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
let committed = false;
|
|
60
|
+
return () => {
|
|
61
|
+
if (committed)
|
|
62
|
+
return;
|
|
63
|
+
committed = true;
|
|
64
|
+
// Never terminate the working service if the prepared process vanished.
|
|
65
|
+
child.send({ type: 'handoff-commit' }, (error) => {
|
|
66
|
+
if (error) {
|
|
67
|
+
pending = false;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
child.disconnect();
|
|
71
|
+
child.unref();
|
|
72
|
+
setTimeout(() => process.kill(process.pid, 'SIGTERM'), 750).unref();
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
pending = false;
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { INCIDENT_DISMISSED_PATH, readJsonFile, writeJsonStateAtomic, } from './termdockState.js';
|
|
13
13
|
import { readCrashLogTail } from './crashForensics.js';
|
|
14
14
|
import { getSupervisorStatus } from './supervisorClient.js';
|
|
15
|
+
import { canEnableSupervision } from './enableSupervision.js';
|
|
15
16
|
/**
|
|
16
17
|
* 值得用户知道的事件。刻意排除 `stop`(是用户自己停的)、
|
|
17
18
|
* `update-restart` / `manual-restart`(我们自己发起的,成功了就没什么可说)。
|
|
@@ -60,8 +61,31 @@ export function toIncident(entry) {
|
|
|
60
61
|
export function findLatestNotableIncident(entries) {
|
|
61
62
|
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
62
63
|
const incident = toIncident(entries[index]);
|
|
63
|
-
if (incident
|
|
64
|
-
|
|
64
|
+
if (!incident || !NOTABLE_EVENTS.has(incident.event))
|
|
65
|
+
continue;
|
|
66
|
+
if (incident.event === 'gave-up') {
|
|
67
|
+
// Old logs store the final failure separately. Match the supervisor, then
|
|
68
|
+
// its exact child PID; never borrow an unrelated process's port conflict.
|
|
69
|
+
const summary = entries[index];
|
|
70
|
+
const failure = entries.slice(0, index).reverse().find((entry) => entry.role === 'supervisor' && entry.pid === summary.pid
|
|
71
|
+
&& entry.event !== 'gave-up' && NOTABLE_EVENTS.has(String(entry.event)));
|
|
72
|
+
const nested = summary.lastIncident;
|
|
73
|
+
const cause = nested && typeof nested === 'object' ? nested : failure;
|
|
74
|
+
const portConflict = failure && typeof failure.serverPid === 'number'
|
|
75
|
+
? entries.slice(0, index).reverse().find((entry) => entry.role === 'server'
|
|
76
|
+
&& entry.pid === failure.serverPid && entry.event === 'port-conflict'
|
|
77
|
+
&& typeof entry.ts === 'string' && Date.parse(entry.ts) <= incident.at
|
|
78
|
+
&& incident.at - Date.parse(entry.ts) < 60_000)
|
|
79
|
+
: undefined;
|
|
80
|
+
const causeEvent = portConflict ? 'port-conflict' : pickString(cause?.event);
|
|
81
|
+
if (causeEvent)
|
|
82
|
+
incident.causeEvent = causeEvent;
|
|
83
|
+
if (portConflict) {
|
|
84
|
+
const port = pickNumber(portConflict.port);
|
|
85
|
+
incident.detail = port === null ? 'EADDRINUSE' : `Port ${port} is already in use (EADDRINUSE).`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return incident;
|
|
65
89
|
}
|
|
66
90
|
return null;
|
|
67
91
|
}
|
|
@@ -101,7 +125,8 @@ export function buildServerHealthState(options = {}) {
|
|
|
101
125
|
}
|
|
102
126
|
const dismissedAt = readDismissal(dismissedPath);
|
|
103
127
|
return {
|
|
104
|
-
supervised: process.env.TERMDOCK_SUPERVISED === '1',
|
|
128
|
+
supervised: process.env.TERMDOCK_SUPERVISED === '1' && process.connected === true,
|
|
129
|
+
canEnableSupervision: canEnableSupervision(),
|
|
105
130
|
supervisor,
|
|
106
131
|
incident,
|
|
107
132
|
dismissedAt,
|
|
@@ -108,7 +108,7 @@ function normalizeAndroidQuality(value) {
|
|
|
108
108
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
109
109
|
return null;
|
|
110
110
|
const item = value;
|
|
111
|
-
if (item.id !== 'low' && item.id !== 'medium' && item.id !== 'high' && item.id !== 'custom')
|
|
111
|
+
if (item.id !== 'auto' && item.id !== 'low' && item.id !== 'medium' && item.id !== 'high' && item.id !== 'custom')
|
|
112
112
|
return null;
|
|
113
113
|
const maxSize = typeof item.maxSize === 'number' ? Math.max(360, Math.min(2160, Math.round(item.maxSize))) : 1080;
|
|
114
114
|
const bitRate = typeof item.bitRate === 'number' ? Math.max(300_000, Math.min(30_000_000, Math.round(item.bitRate))) : 4_000_000;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Flush the failure to the supervisor before exiting; a log entry alone is not IPC. */
|
|
2
|
+
export function exitWithStartupFailure(reason, detail) {
|
|
3
|
+
if (!process.connected || !process.send)
|
|
4
|
+
process.exit(1);
|
|
5
|
+
const timeout = setTimeout(() => process.exit(1), 1_000);
|
|
6
|
+
const finish = () => {
|
|
7
|
+
clearTimeout(timeout);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
};
|
|
10
|
+
try {
|
|
11
|
+
process.send({ type: 'termdock-startup-failed', reason, detail }, finish);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
finish();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
* 否则唯一验证手段就只剩"手动 kill 一下看看"。
|
|
6
6
|
*/
|
|
7
7
|
export const SUPERVISOR_STATE_VERSION = 1;
|
|
8
|
+
export function isStartupFailedMessage(value) {
|
|
9
|
+
return isRecord(value) && value.type === 'termdock-startup-failed'
|
|
10
|
+
&& typeof value.reason === 'string'
|
|
11
|
+
&& (value.detail === undefined || typeof value.detail === 'string');
|
|
12
|
+
}
|
|
8
13
|
function isRecord(value) {
|
|
9
14
|
return typeof value === 'object' && value !== null;
|
|
10
15
|
}
|
package/package.json
CHANGED
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.265",
|
|
5
5
|
"runtimeProtocolVersion": 1,
|
|
6
6
|
"minimumDesktopVersion": "1.4.46",
|
|
7
7
|
"nodeMajor": 22,
|
|
8
8
|
"dependencyHash": "sha256-K4KyYJuVoQDpZsBM8ZX1Rw3MddOxAzVdp/cPm0iGZz0=",
|
|
9
|
-
"serverBundleHash": "sha256-
|
|
10
|
-
"clientBundleHash": "sha256-
|
|
9
|
+
"serverBundleHash": "sha256-J2E5faoECqRyYnXPzSDHcV9tXUuUih+LDtG464f/dHI=",
|
|
10
|
+
"clientBundleHash": "sha256-FJtbhUlN3+7dITPffcvTDidMmywkNOsNa+E+7ow3+SY=",
|
|
11
11
|
"entrypoint": "dist/server/cli.js",
|
|
12
12
|
"clientEntrypoint": "dist/client/index.html"
|
|
13
13
|
}
|