termdock 1.4.295 → 1.4.296
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-BiLjlrk-.js +171 -0
- package/dist/client/assets/App-BiLjlrk-.js.br +0 -0
- package/dist/client/assets/App-BiLjlrk-.js.gz +0 -0
- package/dist/client/assets/{ChangeWalkthroughPanel-Dv5XRtRh.js → ChangeWalkthroughPanel-DXprT-7m.js} +1 -1
- package/dist/client/assets/ChangeWalkthroughPanel-DXprT-7m.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-DXprT-7m.js.gz +0 -0
- package/dist/client/assets/{DagPlayground-mq69dKyr.js → DagPlayground-DZcUunT5.js} +1 -1
- package/dist/client/assets/DagPlayground-DZcUunT5.js.br +0 -0
- package/dist/client/assets/DagPlayground-DZcUunT5.js.gz +0 -0
- package/dist/client/assets/{DiffLab-BqdHYGi5.js → DiffLab-Brv4DCTb.js} +1 -1
- package/dist/client/assets/DiffLab-Brv4DCTb.js.br +0 -0
- package/dist/client/assets/DiffLab-Brv4DCTb.js.gz +0 -0
- package/dist/client/assets/{DiffReview-BvzGxpuc.js → DiffReview-BuLu1qCi.js} +1 -1
- package/dist/client/assets/DiffReview-BuLu1qCi.js.br +0 -0
- package/dist/client/assets/DiffReview-BuLu1qCi.js.gz +0 -0
- package/dist/client/assets/{DiffReviewLab-DrfddB7x.js → DiffReviewLab-DSGamuAD.js} +1 -1
- package/dist/client/assets/DiffReviewLab-DSGamuAD.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-DSGamuAD.js.gz +0 -0
- package/dist/client/assets/{DiffViewer-3bJV_A5s.js → DiffViewer-BUCYxg27.js} +1 -1
- package/dist/client/assets/DiffViewer-BUCYxg27.js.br +0 -0
- package/dist/client/assets/DiffViewer-BUCYxg27.js.gz +0 -0
- package/dist/client/assets/{ModelPreview-CX7VtoJB.js → ModelPreview-Bnlo-oVE.js} +1 -1
- package/dist/client/assets/ModelPreview-Bnlo-oVE.js.br +0 -0
- package/dist/client/assets/ModelPreview-Bnlo-oVE.js.gz +0 -0
- package/dist/client/assets/{RightSidebar-BK6vWNw3.js → RightSidebar-r_3Lk5Rp.js} +45 -45
- package/dist/client/assets/RightSidebar-r_3Lk5Rp.js.br +0 -0
- package/dist/client/assets/RightSidebar-r_3Lk5Rp.js.gz +0 -0
- package/dist/client/assets/{abnfDiagram-VCTEODGH-PJwhLTPH.js → abnfDiagram-VCTEODGH-K6Ppkrbt.js} +1 -1
- package/dist/client/assets/abnfDiagram-VCTEODGH-K6Ppkrbt.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-K6Ppkrbt.js.gz +0 -0
- package/dist/client/assets/{app-C7pXMvSE.js → app-CATnTUZF.js} +8 -8
- package/dist/client/assets/app-CATnTUZF.js.br +0 -0
- package/dist/client/assets/app-CATnTUZF.js.gz +0 -0
- package/dist/client/assets/{arc-l3FXjCEl.js → arc-Co2OQqtH.js} +1 -1
- package/dist/client/assets/arc-Co2OQqtH.js.br +0 -0
- package/dist/client/assets/arc-Co2OQqtH.js.gz +0 -0
- package/dist/client/assets/{architectureDiagram-5GKGNRK7-DdNbKi-4.js → architectureDiagram-5GKGNRK7-BQnl7tVF.js} +1 -1
- package/dist/client/assets/architectureDiagram-5GKGNRK7-BQnl7tVF.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-BQnl7tVF.js.gz +0 -0
- package/dist/client/assets/{blockDiagram-I7D4REHJ-Cu63oaxR.js → blockDiagram-I7D4REHJ-Bm5D5-qq.js} +1 -1
- package/dist/client/assets/blockDiagram-I7D4REHJ-Bm5D5-qq.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-Bm5D5-qq.js.gz +0 -0
- package/dist/client/assets/{c4Diagram-7LVT6UL2-DQiV_yk6.js → c4Diagram-7LVT6UL2-B9oPpey8.js} +1 -1
- package/dist/client/assets/c4Diagram-7LVT6UL2-B9oPpey8.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-B9oPpey8.js.gz +0 -0
- package/dist/client/assets/channel-Czv2W4qA.js +1 -0
- package/dist/client/assets/{chunk-2Q5K7J3B-COKJ79Ld.js → chunk-2Q5K7J3B-TMaWHH0U.js} +1 -1
- package/dist/client/assets/{chunk-5VM5RSS4-BfV-m7oa.js → chunk-5VM5RSS4-CH7XpknV.js} +1 -1
- package/dist/client/assets/{chunk-F27PBJKO-sLDCEnU8.js → chunk-F27PBJKO-CJ1rotBe.js} +1 -1
- package/dist/client/assets/chunk-F27PBJKO-CJ1rotBe.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-CJ1rotBe.js.gz +0 -0
- package/dist/client/assets/{chunk-IMKFNOWR-DYu5qS7g.js → chunk-IMKFNOWR-UYKZ5uOG.js} +1 -1
- package/dist/client/assets/chunk-IMKFNOWR-UYKZ5uOG.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-UYKZ5uOG.js.gz +0 -0
- package/dist/client/assets/{chunk-JWPE2WC7-DixkILcl.js → chunk-JWPE2WC7-BYL8aXjQ.js} +1 -1
- package/dist/client/assets/{chunk-POPQ4Y6H-CfW5Vm_-.js → chunk-POPQ4Y6H-C3E8yfU2.js} +1 -1
- package/dist/client/assets/{chunk-SVP7TREG-nJnbUFzs.js → chunk-SVP7TREG-DCTDYa1E.js} +1 -1
- package/dist/client/assets/chunk-SVP7TREG-DCTDYa1E.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-DCTDYa1E.js.gz +0 -0
- package/dist/client/assets/{chunk-TICWLB2K-BwyiSQgx.js → chunk-TICWLB2K-wHiaOsBh.js} +1 -1
- package/dist/client/assets/chunk-TICWLB2K-wHiaOsBh.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-wHiaOsBh.js.gz +0 -0
- package/dist/client/assets/{chunk-XXDRQBXY-TCk4c2XN.js → chunk-XXDRQBXY-D_d479hK.js} +1 -1
- package/dist/client/assets/classDiagram-ZZMXUADV-BdvOOL9k.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-BdvOOL9k.js +1 -0
- package/dist/client/assets/{cose-bilkent-JH36ORCC-rroo-EOb.js → cose-bilkent-JH36ORCC-DnhlPBLr.js} +1 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-DnhlPBLr.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-DnhlPBLr.js.gz +0 -0
- package/dist/client/assets/{cynefin-OW5HDTMX-CkFeV85k.js → cynefin-OW5HDTMX-BsjzNqJZ.js} +1 -1
- package/dist/client/assets/cynefin-OW5HDTMX-BsjzNqJZ.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-BsjzNqJZ.js.gz +0 -0
- package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-hBwpU_bW.js → cynefinDiagram-5FMLGOSQ-sVUb0zY5.js} +1 -1
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-sVUb0zY5.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-sVUb0zY5.js.gz +0 -0
- package/dist/client/assets/{dagre-GXQ25YYZ-B321-hdp.js → dagre-GXQ25YYZ-YErk8S-c.js} +1 -1
- package/dist/client/assets/dagre-GXQ25YYZ-YErk8S-c.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-YErk8S-c.js.gz +0 -0
- package/dist/client/assets/{diagram-S7CK7UJ4-bY87_ptA.js → diagram-S7CK7UJ4-BaHbV5ho.js} +1 -1
- package/dist/client/assets/diagram-S7CK7UJ4-BaHbV5ho.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-BaHbV5ho.js.gz +0 -0
- package/dist/client/assets/{diagram-UQ7AKVKN--cez0H_o.js → diagram-UQ7AKVKN-BocCYx3V.js} +1 -1
- package/dist/client/assets/diagram-UQ7AKVKN-BocCYx3V.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-BocCYx3V.js.gz +0 -0
- package/dist/client/assets/{diagram-VSXAHHWV-BupH_VRK.js → diagram-VSXAHHWV-ZMTYwWOQ.js} +1 -1
- package/dist/client/assets/diagram-VSXAHHWV-ZMTYwWOQ.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-ZMTYwWOQ.js.gz +0 -0
- package/dist/client/assets/{diagram-VX7I27RA-DewqaxvF.js → diagram-VX7I27RA-xmk_EY1h.js} +1 -1
- package/dist/client/assets/diagram-VX7I27RA-xmk_EY1h.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-xmk_EY1h.js.gz +0 -0
- package/dist/client/assets/{diagram-Z3DM3KII-wDumcTuR.js → diagram-Z3DM3KII-DKDY_cG6.js} +1 -1
- package/dist/client/assets/diagram-Z3DM3KII-DKDY_cG6.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-DKDY_cG6.js.gz +0 -0
- package/dist/client/assets/{ebnfDiagram-PWID7BFC-C0OY91We.js → ebnfDiagram-PWID7BFC-C_0z-Jx9.js} +1 -1
- package/dist/client/assets/ebnfDiagram-PWID7BFC-C_0z-Jx9.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-C_0z-Jx9.js.gz +0 -0
- package/dist/client/assets/{erDiagram-RLTQ6QDP-Cw9aNqvJ.js → erDiagram-RLTQ6QDP-DHUaG7mt.js} +1 -1
- package/dist/client/assets/erDiagram-RLTQ6QDP-DHUaG7mt.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-DHUaG7mt.js.gz +0 -0
- package/dist/client/assets/{flowDiagram-HODETNUW-BC7XUXeI.js → flowDiagram-HODETNUW-BMNsdMBD.js} +1 -1
- package/dist/client/assets/flowDiagram-HODETNUW-BMNsdMBD.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-BMNsdMBD.js.gz +0 -0
- package/dist/client/assets/{ganttDiagram-EL5Y4UJY-DovhJIz5.js → ganttDiagram-EL5Y4UJY-BH1AiKuF.js} +1 -1
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-BH1AiKuF.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-BH1AiKuF.js.gz +0 -0
- package/dist/client/assets/{gestureArbiter-wjVok2Lg.js → gestureArbiter-DvupkPra.js} +1 -1
- package/dist/client/assets/gestureArbiter-DvupkPra.js.br +0 -0
- package/dist/client/assets/gestureArbiter-DvupkPra.js.gz +0 -0
- package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-BmrbbyW1.js → gitGraphDiagram-WWUBYQGX-DAgV0MV-.js} +1 -1
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DAgV0MV-.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DAgV0MV-.js.gz +0 -0
- package/dist/client/assets/{index-BeD4iJ6L.css → index-Bi9A6QUP.css} +1 -1
- package/dist/client/assets/index-Bi9A6QUP.css.br +0 -0
- package/dist/client/assets/index-Bi9A6QUP.css.gz +0 -0
- package/dist/client/assets/{infoDiagram-27XIBGKW-CQEu4Jwy.js → infoDiagram-27XIBGKW-C7iSg0cB.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-BPqibqsm.js → ishikawaDiagram-5VMMS53U-BpZwsQvw.js} +1 -1
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-BpZwsQvw.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-BpZwsQvw.js.gz +0 -0
- package/dist/client/assets/{journeyDiagram-3NMN7TZE-DIkhubnf.js → journeyDiagram-3NMN7TZE-DXEeFLvw.js} +1 -1
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DXEeFLvw.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DXEeFLvw.js.gz +0 -0
- package/dist/client/assets/{kanban-definition-UXKFOSKX-CBT0DIUR.js → kanban-definition-UXKFOSKX-CV9ivL5u.js} +1 -1
- package/dist/client/assets/kanban-definition-UXKFOSKX-CV9ivL5u.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-CV9ivL5u.js.gz +0 -0
- package/dist/client/assets/{layout-C1CMlOIU.js → layout-DsKKsJKX.js} +1 -1
- package/dist/client/assets/layout-DsKKsJKX.js.br +0 -0
- package/dist/client/assets/layout-DsKKsJKX.js.gz +0 -0
- package/dist/client/assets/{linear-C4gyqor0.js → linear-Dl9MDNV3.js} +1 -1
- package/dist/client/assets/linear-Dl9MDNV3.js.br +0 -0
- package/dist/client/assets/linear-Dl9MDNV3.js.gz +0 -0
- package/dist/client/assets/{mermaid.core-CMfa4ncd.js → mermaid.core-CxZFe3as.js} +5 -5
- package/dist/client/assets/mermaid.core-CxZFe3as.js.br +0 -0
- package/dist/client/assets/mermaid.core-CxZFe3as.js.gz +0 -0
- package/dist/client/assets/{mindmap-definition-YA3MSWOX-C-JmgKOI.js → mindmap-definition-YA3MSWOX-C3ormYdL.js} +1 -1
- package/dist/client/assets/mindmap-definition-YA3MSWOX-C3ormYdL.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-C3ormYdL.js.gz +0 -0
- package/dist/client/assets/{passwordBootstrap-BmUG2IwA.js → passwordBootstrap-a8z6jJNY.js} +2 -2
- package/dist/client/assets/passwordBootstrap-a8z6jJNY.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-a8z6jJNY.js.gz +0 -0
- package/dist/client/assets/{pegDiagram-XKGWAZYB-IY-AEKQa.js → pegDiagram-XKGWAZYB-CG0wNylH.js} +1 -1
- package/dist/client/assets/pegDiagram-XKGWAZYB-CG0wNylH.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-CG0wNylH.js.gz +0 -0
- package/dist/client/assets/{pieDiagram-E7YTZNPT-9Qq43qED.js → pieDiagram-E7YTZNPT-D2-ydqyX.js} +1 -1
- package/dist/client/assets/pieDiagram-E7YTZNPT-D2-ydqyX.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-D2-ydqyX.js.gz +0 -0
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-BjQncx5i.js → quadrantDiagram-AXDQQJYC-CK3fRC18.js} +1 -1
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-CK3fRC18.js.br +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-CK3fRC18.js.gz +0 -0
- package/dist/client/assets/{railroadDiagram-O6MQD6OU-Cr1rL0wZ.js → railroadDiagram-O6MQD6OU-V4EFlydu.js} +1 -1
- package/dist/client/assets/railroadDiagram-O6MQD6OU-V4EFlydu.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-V4EFlydu.js.gz +0 -0
- package/dist/client/assets/{referenceLongPress-ConC5-ym.js → referenceLongPress-BjmYd1vB.js} +1 -1
- package/dist/client/assets/referenceLongPress-BjmYd1vB.js.br +0 -0
- package/dist/client/assets/referenceLongPress-BjmYd1vB.js.gz +0 -0
- package/dist/client/assets/{requirementDiagram-BXWQKSXE-DU2q_iZg.js → requirementDiagram-BXWQKSXE-Di1_tyAX.js} +1 -1
- package/dist/client/assets/requirementDiagram-BXWQKSXE-Di1_tyAX.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-Di1_tyAX.js.gz +0 -0
- package/dist/client/assets/{sankeyDiagram-P5KCCOFB-BYlx9kXC.js → sankeyDiagram-P5KCCOFB-D-qpWNza.js} +1 -1
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-D-qpWNza.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-D-qpWNza.js.gz +0 -0
- package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-D_uAKme-.js → sequenceDiagram-WJ2MYXX4-DmIxafrB.js} +1 -1
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DmIxafrB.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DmIxafrB.js.gz +0 -0
- package/dist/client/assets/{sizeCapture-INFHLROL-H_uqscf4.js → sizeCapture-INFHLROL-4MTh3tTt.js} +1 -1
- package/dist/client/assets/sizeCapture-INFHLROL-4MTh3tTt.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-4MTh3tTt.js.gz +0 -0
- package/dist/client/assets/{sparkles-D2z4Ue6G.js → sparkles-Dk93lHg0.js} +1 -1
- package/dist/client/assets/{stateDiagram-D77RDMKH-BvsQjIIW.js → stateDiagram-D77RDMKH-CgYgneIv.js} +1 -1
- package/dist/client/assets/stateDiagram-D77RDMKH-CgYgneIv.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-CgYgneIv.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-CvPf0fxf.js +1 -0
- package/dist/client/assets/{swimlanes-42K2YHIH-LmUJag-p.js → swimlanes-42K2YHIH-OWA9HFVf.js} +1 -1
- package/dist/client/assets/swimlanes-42K2YHIH-OWA9HFVf.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-OWA9HFVf.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-CZ_OauyW.js +8 -0
- package/dist/client/assets/{timeline-definition-24CTP7MA-DZ5n0Pim.js → timeline-definition-24CTP7MA-BAzx5DyO.js} +1 -1
- package/dist/client/assets/timeline-definition-24CTP7MA-BAzx5DyO.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-BAzx5DyO.js.gz +0 -0
- package/dist/client/assets/{triangle-alert-Ct6iIBmv.js → triangle-alert-CUIBOwqW.js} +1 -1
- package/dist/client/assets/{vennDiagram-4TSXK5OY-BkTA_Ciz.js → vennDiagram-4TSXK5OY-CBZ-PhTQ.js} +1 -1
- package/dist/client/assets/vennDiagram-4TSXK5OY-CBZ-PhTQ.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-CBZ-PhTQ.js.gz +0 -0
- package/dist/client/assets/{videoCompression-VZIoFnyJ.js → videoCompression-BCnqCkRK.js} +1 -1
- package/dist/client/assets/videoCompression-BCnqCkRK.js.br +0 -0
- package/dist/client/assets/videoCompression-BCnqCkRK.js.gz +0 -0
- package/dist/client/assets/{wardleyDiagram-VM6X3IG4-7hzU176j.js → wardleyDiagram-VM6X3IG4-DbWzC6l5.js} +1 -1
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-DbWzC6l5.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-DbWzC6l5.js.gz +0 -0
- package/dist/client/assets/{xychartDiagram-S5SC5T6Z-Bx4P96Bb.js → xychartDiagram-S5SC5T6Z-BmApnTWE.js} +1 -1
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-BmApnTWE.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-BmApnTWE.js.gz +0 -0
- package/dist/client/index.html +2 -2
- package/dist/client/index.html.br +0 -0
- package/dist/client/index.html.gz +0 -0
- package/dist/client/sw.js +1 -1
- package/dist/client/sw.js.br +0 -0
- package/dist/client/sw.js.gz +0 -0
- package/dist/server/agent/collaborationCli.js +45 -4
- package/dist/server/agent/collaborationDeliveryWorker.js +1 -1
- package/dist/server/agent/collaborationPeerTransport.js +8 -2
- package/dist/server/agent/collaborationRoutes.js +18 -2
- package/dist/server/agent/collaborationService.js +43 -1
- package/dist/server/agent/collaborationTaskBundles.js +121 -0
- package/dist/server/agent/collaborationTaskCli.js +54 -0
- package/dist/server/agent/collaborationTaskRoutes.js +58 -0
- package/dist/server/agent/collaborationTaskService.js +355 -0
- package/dist/server/agent/collaborationTaskStore.js +773 -0
- package/dist/server/agent/collaborationTaskTypes.js +1 -0
- package/dist/server/agent/collaborationTaskWorkspace.js +100 -0
- package/dist/server/entry.js +11 -1
- package/dist/server/federation/runtime.js +6 -1
- package/dist/server/routes/terminal.js +66 -2
- package/package.json +1 -1
- package/runtime-manifest.json +3 -3
- package/dist/client/assets/App-D-cerXsD.js +0 -158
- package/dist/client/assets/App-D-cerXsD.js.br +0 -0
- package/dist/client/assets/App-D-cerXsD.js.gz +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-Dv5XRtRh.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-Dv5XRtRh.js.gz +0 -0
- package/dist/client/assets/DagPlayground-mq69dKyr.js.br +0 -0
- package/dist/client/assets/DagPlayground-mq69dKyr.js.gz +0 -0
- package/dist/client/assets/DiffLab-BqdHYGi5.js.br +0 -0
- package/dist/client/assets/DiffLab-BqdHYGi5.js.gz +0 -0
- package/dist/client/assets/DiffReview-BvzGxpuc.js.br +0 -0
- package/dist/client/assets/DiffReview-BvzGxpuc.js.gz +0 -0
- package/dist/client/assets/DiffReviewLab-DrfddB7x.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-DrfddB7x.js.gz +0 -0
- package/dist/client/assets/DiffViewer-3bJV_A5s.js.br +0 -0
- package/dist/client/assets/DiffViewer-3bJV_A5s.js.gz +0 -0
- package/dist/client/assets/ModelPreview-CX7VtoJB.js.br +0 -0
- package/dist/client/assets/ModelPreview-CX7VtoJB.js.gz +0 -0
- package/dist/client/assets/RightSidebar-BK6vWNw3.js.br +0 -0
- package/dist/client/assets/RightSidebar-BK6vWNw3.js.gz +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-PJwhLTPH.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-PJwhLTPH.js.gz +0 -0
- package/dist/client/assets/app-C7pXMvSE.js.br +0 -0
- package/dist/client/assets/app-C7pXMvSE.js.gz +0 -0
- package/dist/client/assets/arc-l3FXjCEl.js.br +0 -0
- package/dist/client/assets/arc-l3FXjCEl.js.gz +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-DdNbKi-4.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-DdNbKi-4.js.gz +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-Cu63oaxR.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-Cu63oaxR.js.gz +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-DQiV_yk6.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-DQiV_yk6.js.gz +0 -0
- package/dist/client/assets/channel-CwC957gi.js +0 -1
- package/dist/client/assets/chunk-F27PBJKO-sLDCEnU8.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-sLDCEnU8.js.gz +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-DYu5qS7g.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-DYu5qS7g.js.gz +0 -0
- package/dist/client/assets/chunk-SVP7TREG-nJnbUFzs.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-nJnbUFzs.js.gz +0 -0
- package/dist/client/assets/chunk-TICWLB2K-BwyiSQgx.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-BwyiSQgx.js.gz +0 -0
- package/dist/client/assets/classDiagram-ZZMXUADV-CmoJ7-rE.js +0 -1
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-CmoJ7-rE.js +0 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-rroo-EOb.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-rroo-EOb.js.gz +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-CkFeV85k.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-CkFeV85k.js.gz +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-hBwpU_bW.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-hBwpU_bW.js.gz +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-B321-hdp.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-B321-hdp.js.gz +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-bY87_ptA.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-bY87_ptA.js.gz +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN--cez0H_o.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN--cez0H_o.js.gz +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-BupH_VRK.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-BupH_VRK.js.gz +0 -0
- package/dist/client/assets/diagram-VX7I27RA-DewqaxvF.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-DewqaxvF.js.gz +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-wDumcTuR.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-wDumcTuR.js.gz +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-C0OY91We.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-C0OY91We.js.gz +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-Cw9aNqvJ.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-Cw9aNqvJ.js.gz +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-BC7XUXeI.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-BC7XUXeI.js.gz +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-DovhJIz5.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-DovhJIz5.js.gz +0 -0
- package/dist/client/assets/gestureArbiter-wjVok2Lg.js.br +0 -0
- package/dist/client/assets/gestureArbiter-wjVok2Lg.js.gz +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BmrbbyW1.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BmrbbyW1.js.gz +0 -0
- package/dist/client/assets/index-BeD4iJ6L.css.br +0 -0
- package/dist/client/assets/index-BeD4iJ6L.css.gz +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-BPqibqsm.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-BPqibqsm.js.gz +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DIkhubnf.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-DIkhubnf.js.gz +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-CBT0DIUR.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-CBT0DIUR.js.gz +0 -0
- package/dist/client/assets/layout-C1CMlOIU.js.br +0 -0
- package/dist/client/assets/layout-C1CMlOIU.js.gz +0 -0
- package/dist/client/assets/linear-C4gyqor0.js.br +0 -0
- package/dist/client/assets/linear-C4gyqor0.js.gz +0 -0
- package/dist/client/assets/mermaid.core-CMfa4ncd.js.br +0 -0
- package/dist/client/assets/mermaid.core-CMfa4ncd.js.gz +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-C-JmgKOI.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-C-JmgKOI.js.gz +0 -0
- package/dist/client/assets/passwordBootstrap-BmUG2IwA.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-BmUG2IwA.js.gz +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-IY-AEKQa.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-IY-AEKQa.js.gz +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-9Qq43qED.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-9Qq43qED.js.gz +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-BjQncx5i.js.br +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-BjQncx5i.js.gz +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-Cr1rL0wZ.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-Cr1rL0wZ.js.gz +0 -0
- package/dist/client/assets/referenceLongPress-ConC5-ym.js.br +0 -0
- package/dist/client/assets/referenceLongPress-ConC5-ym.js.gz +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-DU2q_iZg.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-DU2q_iZg.js.gz +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BYlx9kXC.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BYlx9kXC.js.gz +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D_uAKme-.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D_uAKme-.js.gz +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-H_uqscf4.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-H_uqscf4.js.gz +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-BvsQjIIW.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-BvsQjIIW.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-DNgoExtD.js +0 -1
- package/dist/client/assets/swimlanes-42K2YHIH-LmUJag-p.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-LmUJag-p.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-BRuArMR5.js +0 -8
- package/dist/client/assets/timeline-definition-24CTP7MA-DZ5n0Pim.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-DZ5n0Pim.js.gz +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-BkTA_Ciz.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-BkTA_Ciz.js.gz +0 -0
- package/dist/client/assets/videoCompression-VZIoFnyJ.js.br +0 -0
- package/dist/client/assets/videoCompression-VZIoFnyJ.js.gz +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-7hzU176j.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-7hzU176j.js.gz +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-Bx4P96Bb.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-Bx4P96Bb.js.gz +0 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { CollaborationError } from './collaborationProtocol.js';
|
|
2
|
+
import { captureTaskCommit } from './collaborationTaskWorkspace.js';
|
|
3
|
+
import { taskBundleChunk } from './collaborationTaskBundles.js';
|
|
4
|
+
import { taskMemberKey } from './collaborationTaskTypes.js';
|
|
5
|
+
/** One authority per task; replicas are records, never competing decision writers. */
|
|
6
|
+
export class CollaborationTaskService {
|
|
7
|
+
tasks;
|
|
8
|
+
messages;
|
|
9
|
+
peers;
|
|
10
|
+
deliver;
|
|
11
|
+
prepareWorker;
|
|
12
|
+
timer;
|
|
13
|
+
running = false;
|
|
14
|
+
preparing = new Map();
|
|
15
|
+
constructor(tasks, messages, peers, deliver, prepareWorker) {
|
|
16
|
+
this.tasks = tasks;
|
|
17
|
+
this.messages = messages;
|
|
18
|
+
this.peers = peers;
|
|
19
|
+
this.deliver = deliver;
|
|
20
|
+
this.prepareWorker = prepareWorker;
|
|
21
|
+
}
|
|
22
|
+
get self() { return this.peers.descriptor().serviceId; }
|
|
23
|
+
group(groupId, actor, peer) {
|
|
24
|
+
const group = this.messages.getGroup(groupId);
|
|
25
|
+
if (!group || group.deleted)
|
|
26
|
+
throw new CollaborationError('TASK_GROUP_NOT_FOUND', '协作组不存在或无权访问', 404);
|
|
27
|
+
if (actor && !group.sessionIds.includes(this.peers.taskSession(actor)))
|
|
28
|
+
throw new CollaborationError('TASK_PERMISSION_DENIED', '成员不在该协作组', 403);
|
|
29
|
+
if (peer) {
|
|
30
|
+
const scope = this.peers.effectiveScope(peer.serviceId);
|
|
31
|
+
if (!group.federated || !group.sessionIds.some(s => s.startsWith(`remote:${encodeURIComponent(peer.origin)}:`))
|
|
32
|
+
|| scope && !group.sessionIds.every(s => s.startsWith('remote:') || scope.includes(s))) {
|
|
33
|
+
throw new CollaborationError('TASK_PERMISSION_DENIED', '来源服务无权访问此任务', 403);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return group;
|
|
37
|
+
}
|
|
38
|
+
validateMembers(groupId, input) {
|
|
39
|
+
for (const member of [input.assignee, input.coordinator, ...('reviewers' in input ? input.reviewers ?? [] : [])])
|
|
40
|
+
if (member)
|
|
41
|
+
this.group(groupId, member);
|
|
42
|
+
}
|
|
43
|
+
view(task, summary = false) {
|
|
44
|
+
const members = [...task.attempts.map(a => a.assignee), ...task.artifacts.map(a => a.actor),
|
|
45
|
+
...task.events.flatMap(e => [...(e.actor ? [e.actor] : []), ...(e.target ? [e.target] : [])]), ...(task.coordinator ? [task.coordinator] : []), ...(task.workflow?.reviewers ?? [])];
|
|
46
|
+
const memberSessions = {};
|
|
47
|
+
for (const member of members)
|
|
48
|
+
try {
|
|
49
|
+
memberSessions[taskMemberKey(member)] = this.peers.taskSession(member);
|
|
50
|
+
}
|
|
51
|
+
catch { /* Removed peer stays identifiable in history. */ }
|
|
52
|
+
const children = this.tasks.children(task.id);
|
|
53
|
+
const group = this.messages.getGroup(task.groupId);
|
|
54
|
+
const roster = summary ? undefined : group?.sessionIds.map(sessionId => {
|
|
55
|
+
const member = this.peers.taskMember(sessionId);
|
|
56
|
+
const template = task.workflow?.reviewers.some(m => taskMemberKey(m) === taskMemberKey(member));
|
|
57
|
+
return { member, sessionId, role: `${template ? '此目标的执行成员模板;' : ''}${group.roles?.[sessionId] ?? ''}` };
|
|
58
|
+
});
|
|
59
|
+
return { ...task, children, roster, memberSessions, replica: task.ownerServiceId !== this.self, summaryOnly: summary, outbox: (summary ? [] : this.tasks.pending(task.id))
|
|
60
|
+
.map(({ id, attemptId, messageId, lastError }) => ({ id, attemptId, messageId, lastError })) };
|
|
61
|
+
}
|
|
62
|
+
list(groupId, actor) {
|
|
63
|
+
this.group(groupId, actor);
|
|
64
|
+
return this.tasks.list([groupId], true).map(task => this.view(task, true));
|
|
65
|
+
}
|
|
66
|
+
async get(taskId, actor) {
|
|
67
|
+
const task = this.tasks.get(taskId);
|
|
68
|
+
if (!task)
|
|
69
|
+
throw new CollaborationError('TASK_NOT_FOUND', '任务不存在', 404);
|
|
70
|
+
this.group(task.groupId, actor);
|
|
71
|
+
return this.view(task);
|
|
72
|
+
}
|
|
73
|
+
async create(input, actor) {
|
|
74
|
+
this.group(input.groupId, actor);
|
|
75
|
+
this.validateMembers(input.groupId, input);
|
|
76
|
+
const dependencies = [...(input.dependsOn ?? []), ...(input.parentTaskId ? [input.parentTaskId] : [])];
|
|
77
|
+
const authority = dependencies.length ? this.tasks.get(dependencies[0])?.ownerServiceId : this.self;
|
|
78
|
+
if (!authority)
|
|
79
|
+
throw new CollaborationError('TASK_DEPENDENCY_NOT_FOUND', '父任务或依赖任务不存在', 404);
|
|
80
|
+
for (const dependency of [...(input.dependsOn ?? []), ...(input.parentTaskId ? [input.parentTaskId] : [])]) {
|
|
81
|
+
if (this.tasks.get(dependency)?.ownerServiceId !== authority)
|
|
82
|
+
throw new CollaborationError('DEPENDENCY_AUTHORITY_REQUIRED', '依赖与父任务需在同一来源服务创建', 409);
|
|
83
|
+
}
|
|
84
|
+
if (authority !== this.self) {
|
|
85
|
+
const result = await this.peers.requestTasks(authority, { op: 'create', input, actorSessionId: actor?.sessionId ?? null });
|
|
86
|
+
const task = result.task;
|
|
87
|
+
this.tasks.merge(task, authority);
|
|
88
|
+
return this.view(task);
|
|
89
|
+
}
|
|
90
|
+
const task = this.tasks.create(this.self, input, actor);
|
|
91
|
+
void this.flush();
|
|
92
|
+
return this.view(task);
|
|
93
|
+
}
|
|
94
|
+
async apply(taskId, input, actor) {
|
|
95
|
+
const task = this.tasks.get(taskId);
|
|
96
|
+
if (!task)
|
|
97
|
+
throw new CollaborationError('TASK_NOT_FOUND', '任务不存在', 404);
|
|
98
|
+
this.group(task.groupId, actor);
|
|
99
|
+
this.validateMembers(task.groupId, input);
|
|
100
|
+
if (task.ownerServiceId !== this.self) {
|
|
101
|
+
const result = await this.peers.requestTasks(task.ownerServiceId, { op: 'apply', taskId, input, actorSessionId: actor?.sessionId ?? null });
|
|
102
|
+
this.tasks.merge(result.task, task.ownerServiceId);
|
|
103
|
+
return this.view(this.tasks.get(taskId));
|
|
104
|
+
}
|
|
105
|
+
if (input.kind === 'report' && input.status === 'complete' && task.workspace && task.workflow?.kind === 'step') {
|
|
106
|
+
const attempt = task.attempts.find(a => a.id === input.attemptId);
|
|
107
|
+
if (!actor || !attempt || taskMemberKey(attempt.assignee) !== taskMemberKey(actor) || attempt.id !== task.activeAttemptId)
|
|
108
|
+
throw new CollaborationError('ATTEMPT_PERMISSION_DENIED', '只有当前执行成员可以提交完成报告', 403);
|
|
109
|
+
const commit = actor.serviceId === this.self ? await captureTaskCommit(task.workspace)
|
|
110
|
+
: (await this.peers.requestTasks(actor.serviceId, { op: 'commit', taskId: task.id })).commit;
|
|
111
|
+
if (!commit || !/^[a-f0-9]{40,64}$/.test(commit.commit) || commit.cwd !== task.workspace.cwd || commit.branch !== task.workspace.branch)
|
|
112
|
+
throw new CollaborationError('INVALID_COMMIT_RECEIPT', '交付提交凭证与执行目录不符');
|
|
113
|
+
input = { ...input, evidence: { memberEvidence: input.evidence, ...commit } };
|
|
114
|
+
}
|
|
115
|
+
if (input.kind === 'review' && input.verdict === 'pass' && task.workspace && task.workflow) {
|
|
116
|
+
const artifact = task.artifacts.find(a => a.id === input.artifactId);
|
|
117
|
+
const source = task.attempts.find(a => a.id === task.activeAttemptId).assignee.serviceId;
|
|
118
|
+
const commit = source === this.self ? await captureTaskCommit(task.workspace)
|
|
119
|
+
: (await this.peers.requestTasks(source, { op: 'commit', taskId: task.id })).commit;
|
|
120
|
+
if (commit?.commit !== artifact?.evidence?.commit)
|
|
121
|
+
throw new CollaborationError('RESULT_CHANGED', '代码在交付后发生变化,请执行成员重新提交结果再评审', 409);
|
|
122
|
+
}
|
|
123
|
+
if (input.kind === 'report' && input.status === 'complete' && task.workflow?.kind === 'goal') {
|
|
124
|
+
const children = this.tasks.list([task.groupId]).filter(t => t.workflow?.rootTaskId === task.id && t.status === 'accepted');
|
|
125
|
+
input = { ...input, evidence: { memberEvidence: input.evidence, deliveries: children.map(child => ({ taskId: child.id, title: child.title,
|
|
126
|
+
artifactId: child.acceptedArtifactId, integration: child.workflow?.integration === true,
|
|
127
|
+
commit: child.artifacts.find(a => a.id === child.acceptedArtifactId)?.evidence?.commit })) } };
|
|
128
|
+
}
|
|
129
|
+
const updated = this.tasks.apply(taskId, input, actor);
|
|
130
|
+
void this.flush();
|
|
131
|
+
return this.view(updated);
|
|
132
|
+
}
|
|
133
|
+
heads(groupIds) { return this.tasks.heads(groupIds, this.self); }
|
|
134
|
+
async dependencyChunk(taskId, dependencyId, offset, targetService = this.self) {
|
|
135
|
+
const current = this.tasks.get(taskId), dependency = this.tasks.get(dependencyId);
|
|
136
|
+
const target = current?.scheduledAssignee ?? current?.attempts.find(a => a.id === current.activeAttemptId)?.assignee;
|
|
137
|
+
if (!current || current.ownerServiceId !== this.self || target?.serviceId !== targetService || !dependency
|
|
138
|
+
|| dependency.status !== 'accepted' || dependency.ownerServiceId !== this.self || !current.dependsOn.includes(dependency.id))
|
|
139
|
+
throw new CollaborationError('TASK_PERMISSION_DENIED', '仅执行服务可以读取此任务依赖的已评审提交', 403);
|
|
140
|
+
const source = dependency.attempts.find(a => a.id === dependency.activeAttemptId).assignee.serviceId;
|
|
141
|
+
return source === this.self ? { chunk: await taskBundleChunk(dependency, offset) }
|
|
142
|
+
: this.peers.requestTasks(source, { op: 'bundle-chunk', task: dependency, offset });
|
|
143
|
+
}
|
|
144
|
+
async sync(peer, heads) {
|
|
145
|
+
if (heads.length > 2000)
|
|
146
|
+
throw new CollaborationError('INVALID_TASK_SNAPSHOT', '远端任务列表过长');
|
|
147
|
+
let fetched = 0;
|
|
148
|
+
for (const raw of heads) {
|
|
149
|
+
const head = raw;
|
|
150
|
+
if (!head || !/^[a-f0-9]{32}$/.test(head.id) || !Number.isSafeInteger(head.revision))
|
|
151
|
+
continue;
|
|
152
|
+
const current = this.tasks.get(head.id);
|
|
153
|
+
if (current && current.revision >= head.revision)
|
|
154
|
+
continue;
|
|
155
|
+
if (++fetched > 8)
|
|
156
|
+
break;
|
|
157
|
+
try {
|
|
158
|
+
const result = await this.peers.requestTasks(peer.serviceId, { op: 'get', taskId: head.id });
|
|
159
|
+
const task = result.task;
|
|
160
|
+
this.group(task.groupId, null, peer);
|
|
161
|
+
this.tasks.merge(task, peer.serviceId);
|
|
162
|
+
}
|
|
163
|
+
catch { /* A failed task fetch must not turn a reachable terminal directory offline. */ }
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
async receive(peer, packet) {
|
|
167
|
+
const actor = packet.actorSessionId === null || packet.actorSessionId === undefined ? null : { serviceId: peer.serviceId, sessionId: String(packet.actorSessionId) };
|
|
168
|
+
if (packet.op === 'create') {
|
|
169
|
+
const input = packet.input;
|
|
170
|
+
this.group(input.groupId, actor, peer);
|
|
171
|
+
this.validateMembers(input.groupId, input);
|
|
172
|
+
const dependencies = [...(input.dependsOn ?? []), ...(input.parentTaskId ? [input.parentTaskId] : [])];
|
|
173
|
+
if (!dependencies.length || dependencies.some(id => this.tasks.get(id)?.ownerServiceId !== this.self))
|
|
174
|
+
throw new CollaborationError('DEPENDENCY_AUTHORITY_REQUIRED', '来源服务必须拥有父任务或依赖任务', 409);
|
|
175
|
+
const created = this.tasks.create(this.self, input, actor);
|
|
176
|
+
void this.flush();
|
|
177
|
+
return { task: created };
|
|
178
|
+
}
|
|
179
|
+
if (packet.op === 'deliver') {
|
|
180
|
+
const task = packet.task;
|
|
181
|
+
if (!task || task.ownerServiceId !== peer.serviceId)
|
|
182
|
+
throw new CollaborationError('INVALID_TASK_OWNER', '只有任务来源服务可以投递');
|
|
183
|
+
const group = this.group(task.groupId, null, peer);
|
|
184
|
+
const recipient = { serviceId: this.self, sessionId: String(packet.target ?? '') };
|
|
185
|
+
this.group(task.groupId, recipient, peer);
|
|
186
|
+
const attempt = task.attempts.find(a => a.id === packet.attemptId);
|
|
187
|
+
if (packet.kind === 'task' ? !attempt || taskMemberKey(attempt.assignee) !== taskMemberKey(recipient) : packet.attemptId !== null && !attempt)
|
|
188
|
+
throw new CollaborationError('INVALID_ATTEMPT', '投递对象与执行尝试不符');
|
|
189
|
+
this.tasks.merge(task, peer.serviceId);
|
|
190
|
+
const previous = typeof packet.messageId === 'string' ? this.messages.getMessage(packet.messageId) : null;
|
|
191
|
+
if (previous && previous.groupId === task.groupId && previous.toSessionId === recipient.sessionId
|
|
192
|
+
&& previous.fromSessionId === null && previous.content === packet.content && previous.metadata?.taskOutboxId === packet.outboxId) {
|
|
193
|
+
this.deliver(recipient.sessionId);
|
|
194
|
+
return { receipt: this.receipt(previous.id) };
|
|
195
|
+
}
|
|
196
|
+
const queued = this.messages.send({ groupId: group.id, fromSessionId: null, toSessionIds: [recipient.sessionId],
|
|
197
|
+
kind: packet.kind === 'task' ? 'task' : 'message', content: String(packet.content ?? ''), threadId: attempt?.threadId ?? task.id,
|
|
198
|
+
idempotencyKey: `task:${peer.serviceId}:${String(packet.outboxId)}`,
|
|
199
|
+
metadata: { taskOutboxId: packet.outboxId, termdockTask: { taskId: task.id, attemptId: attempt?.id ?? null, ownerServiceId: peer.serviceId } } });
|
|
200
|
+
this.deliver(recipient.sessionId);
|
|
201
|
+
return { receipt: this.receipt(queued[0].id) };
|
|
202
|
+
}
|
|
203
|
+
if (packet.op === 'prepare') {
|
|
204
|
+
const task = packet.task;
|
|
205
|
+
if (!task || task.ownerServiceId !== peer.serviceId || !task.workflow?.isolated || !task.scheduledAssignee || task.scheduledAssignee.serviceId !== this.self)
|
|
206
|
+
throw new CollaborationError('INVALID_TASK_OWNER', '执行准备请求来源或成员无效');
|
|
207
|
+
this.group(task.groupId, task.scheduledAssignee, peer);
|
|
208
|
+
this.tasks.merge(task, peer.serviceId);
|
|
209
|
+
if (this.peers.effectiveScope(peer.serviceId) !== undefined)
|
|
210
|
+
throw new CollaborationError('SESSION_SCOPE_DENIED', '会话范围授权不能自动创建新成员,请使用现有会话或完整协作授权', 403);
|
|
211
|
+
if (!this.prepareWorker)
|
|
212
|
+
throw new CollaborationError('WORKSPACE_UNAVAILABLE', '目标服务不支持独立执行目录');
|
|
213
|
+
const dependencies = Array.isArray(packet.dependencies) ? packet.dependencies : [];
|
|
214
|
+
if (dependencies.length > 32 || dependencies.length !== task.dependsOn.length || dependencies.some(d => d.ownerServiceId !== peer.serviceId || d.groupId !== task.groupId || d.status !== 'accepted' || !task.dependsOn.includes(d.id)))
|
|
215
|
+
throw new CollaborationError('INVALID_DEPENDENCIES', '依赖交付记录无效');
|
|
216
|
+
for (const dependency of dependencies)
|
|
217
|
+
this.tasks.merge(dependency, peer.serviceId);
|
|
218
|
+
const prepared = await this.prepareWorker(task, task.scheduledAssignee, dependencies);
|
|
219
|
+
return { ...prepared, member: { serviceId: this.self, sessionId: prepared.sessionId } };
|
|
220
|
+
}
|
|
221
|
+
if (packet.op === 'commit') {
|
|
222
|
+
const task = this.tasks.get(String(packet.taskId));
|
|
223
|
+
if (!task || task.ownerServiceId !== peer.serviceId || !task.workspace)
|
|
224
|
+
throw new CollaborationError('TASK_NOT_FOUND', '执行目录记录不存在', 404);
|
|
225
|
+
this.group(task.groupId, null, peer);
|
|
226
|
+
return { commit: await captureTaskCommit(task.workspace) };
|
|
227
|
+
}
|
|
228
|
+
if (packet.op === 'bundle-chunk') {
|
|
229
|
+
const task = packet.task;
|
|
230
|
+
const previous = task && this.tasks.get(task.id);
|
|
231
|
+
if (!task || task.ownerServiceId !== peer.serviceId || !task.workspace || previous?.workspace?.cwd !== task.workspace.cwd
|
|
232
|
+
|| task.attempts.find(a => a.id === task.activeAttemptId)?.assignee.serviceId !== this.self)
|
|
233
|
+
throw new CollaborationError('INVALID_TASK_OWNER', '只能导出此服务执行的已评审交付');
|
|
234
|
+
this.group(task.groupId, null, peer);
|
|
235
|
+
this.tasks.merge(task, peer.serviceId);
|
|
236
|
+
return { chunk: await taskBundleChunk(task, packet.offset) };
|
|
237
|
+
}
|
|
238
|
+
if (packet.op === 'dependency-bundle') {
|
|
239
|
+
const current = this.tasks.get(String(packet.taskId));
|
|
240
|
+
if (!current)
|
|
241
|
+
throw new CollaborationError('TASK_NOT_FOUND', '执行任务不存在', 404);
|
|
242
|
+
this.group(current.groupId, null, peer);
|
|
243
|
+
return this.dependencyChunk(current.id, String(packet.dependencyId), packet.offset, peer.serviceId);
|
|
244
|
+
}
|
|
245
|
+
const task = this.tasks.get(String(packet.taskId ?? ''));
|
|
246
|
+
if (!task || task.ownerServiceId !== this.self)
|
|
247
|
+
throw new CollaborationError('TASK_NOT_FOUND', '来源任务不存在', 404);
|
|
248
|
+
this.group(task.groupId, actor, peer);
|
|
249
|
+
if (packet.op === 'get')
|
|
250
|
+
return { task: this.view(task) };
|
|
251
|
+
if (packet.op === 'apply') {
|
|
252
|
+
const input = packet.input;
|
|
253
|
+
this.validateMembers(task.groupId, input);
|
|
254
|
+
return { task: await this.apply(task.id, input, actor) };
|
|
255
|
+
}
|
|
256
|
+
throw new CollaborationError('INVALID_TASK_OPERATION', '不支持的远端任务操作');
|
|
257
|
+
}
|
|
258
|
+
receipt(messageId) {
|
|
259
|
+
const receipt = this.messages.receipt(messageId);
|
|
260
|
+
return { messageId, status: receipt.status, deliveredAt: receipt.delivered_at, error: receipt.delivery.error };
|
|
261
|
+
}
|
|
262
|
+
start() { this.timer = setInterval(() => void this.flush(), 1500); this.timer.unref(); void this.flush(); }
|
|
263
|
+
close() { clearInterval(this.timer); }
|
|
264
|
+
async flush() {
|
|
265
|
+
if (this.running)
|
|
266
|
+
return;
|
|
267
|
+
this.running = true;
|
|
268
|
+
try {
|
|
269
|
+
this.tasks.advance(this.self);
|
|
270
|
+
const owned = this.tasks.owned(this.self);
|
|
271
|
+
const slots = new Map(owned.filter(t => t.workflow?.kind === 'goal').map(root => [root.id,
|
|
272
|
+
Math.max(0, (root.workflow.maxParallel ?? 2) - owned.filter(t => t.workflow?.rootTaskId === root.id && t.status === 'open' && (!!t.activeAttemptId || this.preparing.has(t.id))).length)]));
|
|
273
|
+
for (const task of this.tasks.scheduled(this.self)) {
|
|
274
|
+
if (this.preparing.has(task.id) || this.preparing.size >= 4 || (slots.get(task.workflow.rootTaskId) ?? 0) <= 0)
|
|
275
|
+
continue;
|
|
276
|
+
slots.set(task.workflow.rootTaskId, slots.get(task.workflow.rootTaskId) - 1);
|
|
277
|
+
const prepare = Promise.resolve().then(async () => {
|
|
278
|
+
try {
|
|
279
|
+
this.group(task.groupId, task.scheduledAssignee);
|
|
280
|
+
let assignee = task.scheduledAssignee, workspace;
|
|
281
|
+
if (task.workflow.isolated) {
|
|
282
|
+
const dependencies = task.dependsOn.map(id => this.tasks.get(id));
|
|
283
|
+
if (assignee.serviceId === this.self) {
|
|
284
|
+
if (!this.prepareWorker)
|
|
285
|
+
throw new Error('此服务不支持独立执行目录');
|
|
286
|
+
const prepared = await this.prepareWorker(task, assignee, dependencies);
|
|
287
|
+
assignee = { serviceId: this.self, sessionId: prepared.sessionId };
|
|
288
|
+
workspace = prepared.workspace;
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
const prepared = await this.peers.requestTasks(assignee.serviceId, { op: 'prepare', task, dependencies });
|
|
292
|
+
assignee = prepared.member;
|
|
293
|
+
workspace = prepared.workspace;
|
|
294
|
+
if (!assignee || assignee.serviceId !== task.scheduledAssignee.serviceId || !workspace)
|
|
295
|
+
throw new Error('远端执行目录准备记录无效');
|
|
296
|
+
await this.peers.refresh();
|
|
297
|
+
}
|
|
298
|
+
this.group(task.groupId, assignee);
|
|
299
|
+
}
|
|
300
|
+
this.tasks.activateScheduled(task.id, task.revision, assignee, workspace);
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
this.tasks.automationFailed(task.id, error instanceof Error ? error.message : String(error));
|
|
304
|
+
}
|
|
305
|
+
finally {
|
|
306
|
+
this.preparing.delete(task.id);
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
this.preparing.set(task.id, prepare);
|
|
310
|
+
}
|
|
311
|
+
const ready = this.tasks.pending(undefined, true).filter(outbox => {
|
|
312
|
+
const task = this.tasks.get(outbox.taskId);
|
|
313
|
+
if (!task?.workflow)
|
|
314
|
+
return true;
|
|
315
|
+
const root = task.workflow.rootTaskId ? this.tasks.get(task.workflow.rootTaskId) : task;
|
|
316
|
+
return !task.workflow.paused && !root?.workflow?.paused && root?.status === 'open';
|
|
317
|
+
}).slice(0, 16);
|
|
318
|
+
for (const outbox of ready) {
|
|
319
|
+
try {
|
|
320
|
+
const task = this.tasks.get(outbox.taskId);
|
|
321
|
+
this.group(task.groupId, outbox.target);
|
|
322
|
+
const root = task.workflow?.rootTaskId ? this.tasks.get(task.workflow.rootTaskId) : task;
|
|
323
|
+
if (task.workflow && (task.workflow.paused || root?.workflow?.paused || root?.status !== 'open'))
|
|
324
|
+
continue;
|
|
325
|
+
if (outbox.target.serviceId === this.self) {
|
|
326
|
+
if (outbox.messageId && this.messages.getMessage(outbox.messageId)) {
|
|
327
|
+
this.deliver(outbox.target.sessionId);
|
|
328
|
+
this.tasks.delivered(outbox.id, this.receipt(outbox.messageId));
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
const queued = this.messages.send({ groupId: task.groupId, fromSessionId: null, toSessionIds: [outbox.target.sessionId],
|
|
332
|
+
kind: outbox.kind, content: outbox.content, threadId: outbox.threadId, idempotencyKey: `task:${this.self}:${outbox.id}`,
|
|
333
|
+
metadata: { termdockTask: { taskId: task.id, attemptId: outbox.attemptId, ownerServiceId: this.self } } });
|
|
334
|
+
this.deliver(outbox.target.sessionId);
|
|
335
|
+
this.tasks.delivered(outbox.id, this.receipt(queued[0].id));
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
const result = await this.peers.requestTasks(outbox.target.serviceId, { op: 'deliver', task, target: outbox.target.sessionId,
|
|
339
|
+
attemptId: outbox.attemptId, content: outbox.content, kind: outbox.kind, outboxId: outbox.id, messageId: outbox.messageId });
|
|
340
|
+
this.tasks.delivered(outbox.id, result.receipt);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
this.tasks.failed(outbox.id, error instanceof Error ? error.message : String(error));
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
catch (error) {
|
|
349
|
+
console.error('[collaboration-tasks] queue persistence failed:', error instanceof Error ? error.message : String(error));
|
|
350
|
+
}
|
|
351
|
+
finally {
|
|
352
|
+
this.running = false;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|