termdock 1.4.264 → 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-xq2AwXOA.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-C3ljSBdz.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-Ducnm_Zp.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-zTuUIB7N.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-CBlF880M.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-BPPustvB.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-BaDQ7Gpm.js → RightSidebar-CeHCLhLy.js} +45 -45
- 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-CqyKSrWN.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-CacB_zmS.js → app-L3gaEB1i.js} +9 -9
- 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-BgwdpkOZ.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-N1kpYkPE.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-Dw81yows.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-D32t58M4.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-C9UvOdT5.js → chunk-2Q5K7J3B-CUFYwTko.js} +1 -1
- package/dist/client/assets/{chunk-5VM5RSS4-CFC27MFf.js → chunk-5VM5RSS4-COcgIAqN.js} +1 -1
- package/dist/client/assets/{chunk-F27PBJKO-B4-9Xrnz.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-CsBaOmDp.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-Ck04aXnz.js → chunk-JWPE2WC7-DjNz0bcc.js} +1 -1
- package/dist/client/assets/{chunk-POPQ4Y6H-BqcqNVVk.js → chunk-POPQ4Y6H-TT5BNkJr.js} +1 -1
- package/dist/client/assets/{chunk-SVP7TREG-OpdssCsG.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-CDexR7sW.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-DNtcUYbk.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-cTbTSxj8.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-Rm2aJeBM.js → cynefin-OW5HDTMX-uC7egYG5.js} +1 -1
- package/dist/client/assets/cynefin-OW5HDTMX-uC7egYG5.js.br +0 -0
- package/dist/client/assets/{cynefin-OW5HDTMX-Rm2aJeBM.js.gz → cynefin-OW5HDTMX-uC7egYG5.js.gz} +0 -0
- package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-CBBrWwPa.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-srDwDfcU.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-CTwLQY9V.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-BT_rALfG.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-BKsGk0lY.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-BYbtwhbM.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-Db0I7mu4.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-BWizg7gn.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-BwUS8fPZ.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-MAzdNa6g.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-C8VaA5zH.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-BkdwKXjM.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-BX2iDm_R.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-BbK6xNAN.css → index-BOv8uqyA.css} +1 -1
- package/dist/client/assets/index-BOv8uqyA.css.br +0 -0
- package/dist/client/assets/{index-BbK6xNAN.css.gz → index-BOv8uqyA.css.gz} +0 -0
- package/dist/client/assets/{infoDiagram-27XIBGKW-Ns3hP0eV.js → infoDiagram-27XIBGKW-0ylnBr_8.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-Bv4pVCgQ.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-CjrSMq_a.js.gz +0 -0
- package/dist/client/assets/{journeyDiagram-3NMN7TZE-DRRi377b.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-B7L-csMZ.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-BxSxAk6Q.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-BXjh9BXc.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-5r_1zWs_.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-DUhDC9wQ.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-Cwjat0qO.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-C-SLAJDe.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-qRG_HAda.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-Cx85SpAC.js → quadrantDiagram-AXDQQJYC-BUHd3sQq.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-Cx85SpAC.js.br → quadrantDiagram-AXDQQJYC-BUHd3sQq.js.br} +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-BUHd3sQq.js.gz +0 -0
- package/dist/client/assets/{railroadDiagram-O6MQD6OU-CHUzbbuc.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-CkmKcttc.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-BMLDFHF4.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-BWS5I_IL.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-BPdGEV61.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-oxQ5oK3g.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-MZp-tT_G.js → sparkles-CT3DLxs9.js} +1 -1
- package/dist/client/assets/{stateDiagram-D77RDMKH-DtSfST46.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-BqUlkZ_F.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-B__ZTuwu.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-DN7qGh3M.js → triangle-alert-C6No3Q8u.js} +1 -1
- package/dist/client/assets/{vennDiagram-4TSXK5OY-C6JudjQT.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-BHt61gtN.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-C0rZbFNo.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/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-C-sArfYM.js +0 -156
- package/dist/client/assets/App-C-sArfYM.js.br +0 -0
- package/dist/client/assets/App-C-sArfYM.js.gz +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-xq2AwXOA.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-xq2AwXOA.js.gz +0 -0
- package/dist/client/assets/DagPlayground-C3ljSBdz.js.br +0 -0
- package/dist/client/assets/DagPlayground-C3ljSBdz.js.gz +0 -0
- package/dist/client/assets/DiffLab-Ducnm_Zp.js.br +0 -0
- package/dist/client/assets/DiffLab-Ducnm_Zp.js.gz +0 -0
- package/dist/client/assets/DiffReview-zTuUIB7N.js.br +0 -0
- package/dist/client/assets/DiffReview-zTuUIB7N.js.gz +0 -0
- package/dist/client/assets/DiffReviewLab-CBlF880M.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-CBlF880M.js.gz +0 -0
- package/dist/client/assets/DiffViewer-D4UreLzY.js +0 -36
- package/dist/client/assets/DiffViewer-D4UreLzY.js.br +0 -0
- package/dist/client/assets/DiffViewer-D4UreLzY.js.gz +0 -0
- package/dist/client/assets/ModelPreview-BPPustvB.js.br +0 -0
- package/dist/client/assets/ModelPreview-BPPustvB.js.gz +0 -0
- package/dist/client/assets/RightSidebar-BaDQ7Gpm.js.br +0 -0
- package/dist/client/assets/RightSidebar-BaDQ7Gpm.js.gz +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-CqyKSrWN.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-CqyKSrWN.js.gz +0 -0
- package/dist/client/assets/app-CacB_zmS.js.br +0 -0
- package/dist/client/assets/app-CacB_zmS.js.gz +0 -0
- package/dist/client/assets/arc-BgwdpkOZ.js.br +0 -0
- package/dist/client/assets/arc-BgwdpkOZ.js.gz +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-N1kpYkPE.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-N1kpYkPE.js.gz +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-Dw81yows.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-Dw81yows.js.gz +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-D32t58M4.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-D32t58M4.js.gz +0 -0
- package/dist/client/assets/channel-DhLuwycJ.js +0 -1
- package/dist/client/assets/chunk-F27PBJKO-B4-9Xrnz.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-B4-9Xrnz.js.gz +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-CsBaOmDp.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-CsBaOmDp.js.gz +0 -0
- package/dist/client/assets/chunk-SVP7TREG-OpdssCsG.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-OpdssCsG.js.gz +0 -0
- package/dist/client/assets/chunk-TICWLB2K-CDexR7sW.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-CDexR7sW.js.gz +0 -0
- package/dist/client/assets/classDiagram-ZZMXUADV-WqsEmR1Y.js +0 -1
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-WqsEmR1Y.js +0 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-cTbTSxj8.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-cTbTSxj8.js.gz +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-Rm2aJeBM.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CBBrWwPa.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CBBrWwPa.js.gz +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-srDwDfcU.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-srDwDfcU.js.gz +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-CTwLQY9V.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-CTwLQY9V.js.gz +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-BT_rALfG.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-BT_rALfG.js.gz +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-BKsGk0lY.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-BKsGk0lY.js.gz +0 -0
- package/dist/client/assets/diagram-VX7I27RA-BYbtwhbM.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-BYbtwhbM.js.gz +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-Db0I7mu4.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-Db0I7mu4.js.gz +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-BWizg7gn.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-BWizg7gn.js.gz +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-BwUS8fPZ.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-BwUS8fPZ.js.gz +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-MAzdNa6g.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-MAzdNa6g.js.gz +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-C8VaA5zH.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-C8VaA5zH.js.gz +0 -0
- package/dist/client/assets/gestureArbiter-BkdwKXjM.js.br +0 -0
- package/dist/client/assets/gestureArbiter-BkdwKXjM.js.gz +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BX2iDm_R.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BX2iDm_R.js.gz +0 -0
- package/dist/client/assets/index-BbK6xNAN.css.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-Bv4pVCgQ.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-Bv4pVCgQ.js.gz +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DRRi377b.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DRRi377b.js.gz +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-B7L-csMZ.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-B7L-csMZ.js.gz +0 -0
- package/dist/client/assets/layout-BxSxAk6Q.js.br +0 -0
- package/dist/client/assets/layout-BxSxAk6Q.js.gz +0 -0
- package/dist/client/assets/linear-BXjh9BXc.js.br +0 -0
- package/dist/client/assets/linear-BXjh9BXc.js.gz +0 -0
- package/dist/client/assets/mermaid.core-5r_1zWs_.js.br +0 -0
- package/dist/client/assets/mermaid.core-5r_1zWs_.js.gz +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-DUhDC9wQ.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-DUhDC9wQ.js.gz +0 -0
- package/dist/client/assets/passwordBootstrap-Cwjat0qO.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-Cwjat0qO.js.gz +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-C-SLAJDe.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-C-SLAJDe.js.gz +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-qRG_HAda.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-qRG_HAda.js.gz +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-Cx85SpAC.js.gz +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-CHUzbbuc.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-CHUzbbuc.js.gz +0 -0
- package/dist/client/assets/referenceLongPress-CkmKcttc.js.br +0 -0
- package/dist/client/assets/referenceLongPress-CkmKcttc.js.gz +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-BMLDFHF4.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-BMLDFHF4.js.gz +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BWS5I_IL.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BWS5I_IL.js.gz +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-BPdGEV61.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-BPdGEV61.js.gz +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-oxQ5oK3g.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-oxQ5oK3g.js.gz +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-DtSfST46.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-DtSfST46.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-BF_rwi5O.js +0 -1
- package/dist/client/assets/swimlanes-42K2YHIH-BqUlkZ_F.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-BqUlkZ_F.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DP9kFtCd.js +0 -8
- package/dist/client/assets/timeline-definition-24CTP7MA-B__ZTuwu.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-B__ZTuwu.js.gz +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-C6JudjQT.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-C6JudjQT.js.gz +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-BHt61gtN.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-BHt61gtN.js.gz +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-C0rZbFNo.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-C0rZbFNo.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))
|
|
@@ -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
|
}
|