termdock 1.4.299 → 1.4.301
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +1 -1
- package/README.md +2 -1
- package/dist/client/assets/App-BziVLy1b.js +179 -0
- package/dist/client/assets/App-BziVLy1b.js.br +0 -0
- package/dist/client/assets/App-BziVLy1b.js.gz +0 -0
- package/dist/client/assets/ArchitecturePanel-CARNBEqQ.js +12 -0
- package/dist/client/assets/ArchitecturePanel-CARNBEqQ.js.br +0 -0
- package/dist/client/assets/ArchitecturePanel-CARNBEqQ.js.gz +0 -0
- package/dist/client/assets/{ChangeWalkthroughPanel-2lXfrgk4.js → ChangeWalkthroughPanel-00oa0z6w.js} +2 -2
- package/dist/client/assets/ChangeWalkthroughPanel-00oa0z6w.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-00oa0z6w.js.gz +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-DuEeKQKZ.js +1 -0
- package/dist/client/assets/CollaborationMainWorkspace-DuEeKQKZ.js.br +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-DuEeKQKZ.js.gz +0 -0
- package/dist/client/assets/CollaborationTaskContent-B_mzpNuw.js +2 -0
- package/dist/client/assets/ComputerControlView-C9v1Ooc9.js +5 -0
- package/dist/client/assets/ComputerControlView-C9v1Ooc9.js.br +0 -0
- package/dist/client/assets/ComputerControlView-C9v1Ooc9.js.gz +0 -0
- package/dist/client/assets/{DagPlayground-EFUb9S3u.js → DagPlayground-DfUpMALj.js} +1 -1
- package/dist/client/assets/DagPlayground-DfUpMALj.js.br +0 -0
- package/dist/client/assets/DagPlayground-DfUpMALj.js.gz +0 -0
- package/dist/client/assets/{DiffLab-CXWjSE2q.js → DiffLab-Cf_URhQt.js} +1 -1
- package/dist/client/assets/DiffLab-Cf_URhQt.js.br +0 -0
- package/dist/client/assets/DiffLab-Cf_URhQt.js.gz +0 -0
- package/dist/client/assets/{DiffReview-ByMkBaD9.js → DiffReview-DjG9vCpH.js} +1 -1
- package/dist/client/assets/DiffReview-DjG9vCpH.js.br +0 -0
- package/dist/client/assets/DiffReview-DjG9vCpH.js.gz +0 -0
- package/dist/client/assets/{DiffReviewLab-DoWaKm94.js → DiffReviewLab-BKOvHdJY.js} +2 -2
- package/dist/client/assets/DiffReviewLab-BKOvHdJY.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-BKOvHdJY.js.gz +0 -0
- package/dist/client/assets/{DiffViewer-B4hn9z0k.js → DiffViewer-6n3tgsdc.js} +8 -8
- package/dist/client/assets/DiffViewer-6n3tgsdc.js.br +0 -0
- package/dist/client/assets/DiffViewer-6n3tgsdc.js.gz +0 -0
- package/dist/client/assets/{ModelPreview-C-LJZ8so.js → ModelPreview-BNs2sRct.js} +1 -1
- package/dist/client/assets/ModelPreview-BNs2sRct.js.br +0 -0
- package/dist/client/assets/ModelPreview-BNs2sRct.js.gz +0 -0
- package/dist/client/assets/RightSidebar-CcMSU1v8.js +1677 -0
- package/dist/client/assets/RightSidebar-CcMSU1v8.js.br +0 -0
- package/dist/client/assets/RightSidebar-CcMSU1v8.js.gz +0 -0
- package/dist/client/assets/{abnfDiagram-VCTEODGH-BY-pfYKk.js → abnfDiagram-VCTEODGH-DogjvRKp.js} +1 -1
- package/dist/client/assets/abnfDiagram-VCTEODGH-DogjvRKp.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-DogjvRKp.js.gz +0 -0
- package/dist/client/assets/app-D6vN8PW-.js +35 -0
- package/dist/client/assets/app-D6vN8PW-.js.br +0 -0
- package/dist/client/assets/app-D6vN8PW-.js.gz +0 -0
- package/dist/client/assets/{arc-DIENgCZn.js → arc-Cqel4Ted.js} +1 -1
- package/dist/client/assets/arc-Cqel4Ted.js.br +0 -0
- package/dist/client/assets/arc-Cqel4Ted.js.gz +0 -0
- package/dist/client/assets/{architectureDiagram-5GKGNRK7-C1h4e4az.js → architectureDiagram-5GKGNRK7-DgvPtgNb.js} +1 -1
- package/dist/client/assets/architectureDiagram-5GKGNRK7-DgvPtgNb.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-DgvPtgNb.js.gz +0 -0
- package/dist/client/assets/{blockDiagram-I7D4REHJ-B_yOr54K.js → blockDiagram-I7D4REHJ-BxbWO4x4.js} +1 -1
- package/dist/client/assets/blockDiagram-I7D4REHJ-BxbWO4x4.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-BxbWO4x4.js.gz +0 -0
- package/dist/client/assets/{c4Diagram-7LVT6UL2-DRD4zxIo.js → c4Diagram-7LVT6UL2-gsA37gjL.js} +1 -1
- package/dist/client/assets/c4Diagram-7LVT6UL2-gsA37gjL.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-gsA37gjL.js.gz +0 -0
- package/dist/client/assets/channel-CBc8-n7y.js +1 -0
- package/dist/client/assets/{chunk-2Q5K7J3B-CXytnjmD.js → chunk-2Q5K7J3B-ChC9yYOd.js} +1 -1
- package/dist/client/assets/{chunk-5VM5RSS4-Bjmajkf7.js → chunk-5VM5RSS4-Bi4Hc8yL.js} +1 -1
- package/dist/client/assets/{chunk-F27PBJKO-CQCL8mJG.js → chunk-F27PBJKO-DvVWvQEk.js} +1 -1
- package/dist/client/assets/chunk-F27PBJKO-DvVWvQEk.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-DvVWvQEk.js.gz +0 -0
- package/dist/client/assets/{chunk-IMKFNOWR-ruHGCADe.js → chunk-IMKFNOWR-BnwQLR5S.js} +1 -1
- package/dist/client/assets/chunk-IMKFNOWR-BnwQLR5S.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-BnwQLR5S.js.gz +0 -0
- package/dist/client/assets/{chunk-JWPE2WC7-U18S7rxZ.js → chunk-JWPE2WC7-BkNnaDiR.js} +1 -1
- package/dist/client/assets/{chunk-POPQ4Y6H-DWnwssfL.js → chunk-POPQ4Y6H-BRzm6Uzi.js} +1 -1
- package/dist/client/assets/{chunk-SVP7TREG-DMHj3NSq.js → chunk-SVP7TREG-CDYm-dzk.js} +1 -1
- package/dist/client/assets/chunk-SVP7TREG-CDYm-dzk.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-CDYm-dzk.js.gz +0 -0
- package/dist/client/assets/{chunk-TICWLB2K-Dh_ekvFW.js → chunk-TICWLB2K-BKaW9Z9i.js} +1 -1
- package/dist/client/assets/chunk-TICWLB2K-BKaW9Z9i.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-BKaW9Z9i.js.gz +0 -0
- package/dist/client/assets/{chunk-XXDRQBXY-Bq5wD6iJ.js → chunk-XXDRQBXY-DcHZ_FHb.js} +1 -1
- package/dist/client/assets/classDiagram-ZZMXUADV-CNFc2dOc.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-CNFc2dOc.js +1 -0
- package/dist/client/assets/{cose-bilkent-JH36ORCC-CsySWhYg.js → cose-bilkent-JH36ORCC-DCbbTNc6.js} +1 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-DCbbTNc6.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-DCbbTNc6.js.gz +0 -0
- package/dist/client/assets/{cynefin-OW5HDTMX-9DKE5wV7.js → cynefin-OW5HDTMX-i23hD0Z2.js} +1 -1
- package/dist/client/assets/cynefin-OW5HDTMX-i23hD0Z2.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-i23hD0Z2.js.gz +0 -0
- package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-B_8fvr9c.js → cynefinDiagram-5FMLGOSQ-CbyLYcqc.js} +1 -1
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CbyLYcqc.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CbyLYcqc.js.gz +0 -0
- package/dist/client/assets/{dagre-GXQ25YYZ-BOdsFNFT.js → dagre-GXQ25YYZ-iJ4VKzZm.js} +1 -1
- package/dist/client/assets/dagre-GXQ25YYZ-iJ4VKzZm.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-iJ4VKzZm.js.gz +0 -0
- package/dist/client/assets/{diagram-S7CK7UJ4-6v_qvAvi.js → diagram-S7CK7UJ4-BNVZcdsO.js} +1 -1
- package/dist/client/assets/diagram-S7CK7UJ4-BNVZcdsO.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-BNVZcdsO.js.gz +0 -0
- package/dist/client/assets/{diagram-UQ7AKVKN-c03oOGhD.js → diagram-UQ7AKVKN-1ghTvPiu.js} +1 -1
- package/dist/client/assets/diagram-UQ7AKVKN-1ghTvPiu.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-1ghTvPiu.js.gz +0 -0
- package/dist/client/assets/{diagram-VSXAHHWV-MMIhRYp_.js → diagram-VSXAHHWV-Ce_0nMd3.js} +1 -1
- package/dist/client/assets/diagram-VSXAHHWV-Ce_0nMd3.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-Ce_0nMd3.js.gz +0 -0
- package/dist/client/assets/{diagram-VX7I27RA-B_l-uebl.js → diagram-VX7I27RA-CLHEkhUt.js} +1 -1
- package/dist/client/assets/diagram-VX7I27RA-CLHEkhUt.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-CLHEkhUt.js.gz +0 -0
- package/dist/client/assets/{diagram-Z3DM3KII-DKoBC5gn.js → diagram-Z3DM3KII-iyb5DkP6.js} +1 -1
- package/dist/client/assets/diagram-Z3DM3KII-iyb5DkP6.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-iyb5DkP6.js.gz +0 -0
- package/dist/client/assets/{ebnfDiagram-PWID7BFC-Bs3wu8Az.js → ebnfDiagram-PWID7BFC-Dxh2TzXm.js} +1 -1
- package/dist/client/assets/ebnfDiagram-PWID7BFC-Dxh2TzXm.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-Dxh2TzXm.js.gz +0 -0
- package/dist/client/assets/{erDiagram-RLTQ6QDP-mYnHYbKl.js → erDiagram-RLTQ6QDP-Cr8IkdCC.js} +1 -1
- package/dist/client/assets/erDiagram-RLTQ6QDP-Cr8IkdCC.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-Cr8IkdCC.js.gz +0 -0
- package/dist/client/assets/{flowDiagram-HODETNUW-CwCLWbib.js → flowDiagram-HODETNUW-B8ZF1bwr.js} +1 -1
- package/dist/client/assets/flowDiagram-HODETNUW-B8ZF1bwr.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-B8ZF1bwr.js.gz +0 -0
- package/dist/client/assets/{ganttDiagram-EL5Y4UJY-mse8c-ni.js → ganttDiagram-EL5Y4UJY-zhdL10eM.js} +1 -1
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-zhdL10eM.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-zhdL10eM.js.gz +0 -0
- package/dist/client/assets/{gestureArbiter-BviL29ps.js → gestureArbiter-CXYHfU__.js} +1 -1
- package/dist/client/assets/gestureArbiter-CXYHfU__.js.br +0 -0
- package/dist/client/assets/gestureArbiter-CXYHfU__.js.gz +0 -0
- package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-BVUfLjAX.js → gitGraphDiagram-WWUBYQGX-BQf2fHBo.js} +1 -1
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BQf2fHBo.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BQf2fHBo.js.gz +0 -0
- package/dist/client/assets/{index-C6ftfFlG.css → index-CNY7CTVa.css} +1 -1
- package/dist/client/assets/index-CNY7CTVa.css.br +0 -0
- package/dist/client/assets/index-CNY7CTVa.css.gz +0 -0
- package/dist/client/assets/{infoDiagram-27XIBGKW-XjoFF4BC.js → infoDiagram-27XIBGKW-BT8xey7S.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-bH299bWL.js → ishikawaDiagram-5VMMS53U-DunPdwW9.js} +1 -1
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-DunPdwW9.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-DunPdwW9.js.gz +0 -0
- package/dist/client/assets/{journeyDiagram-3NMN7TZE-BG0u_X1A.js → journeyDiagram-3NMN7TZE-B0y75iIg.js} +1 -1
- package/dist/client/assets/journeyDiagram-3NMN7TZE-B0y75iIg.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-B0y75iIg.js.gz +0 -0
- package/dist/client/assets/{kanban-definition-UXKFOSKX-DRoc9N-i.js → kanban-definition-UXKFOSKX-BfgA5WLo.js} +1 -1
- package/dist/client/assets/kanban-definition-UXKFOSKX-BfgA5WLo.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-BfgA5WLo.js.gz +0 -0
- package/dist/client/assets/{layout-mh0t6JpE.js → layout-BvjABLff.js} +1 -1
- package/dist/client/assets/layout-BvjABLff.js.br +0 -0
- package/dist/client/assets/layout-BvjABLff.js.gz +0 -0
- package/dist/client/assets/{linear-B9KTRuUV.js → linear-DgeFRliF.js} +1 -1
- package/dist/client/assets/linear-DgeFRliF.js.br +0 -0
- package/dist/client/assets/linear-DgeFRliF.js.gz +0 -0
- package/dist/client/assets/{mermaid.core-Bu2G9zhK.js → mermaid.core-DM6Rlal9.js} +5 -5
- package/dist/client/assets/mermaid.core-DM6Rlal9.js.br +0 -0
- package/dist/client/assets/mermaid.core-DM6Rlal9.js.gz +0 -0
- package/dist/client/assets/{mindmap-definition-YA3MSWOX-Go6Bg5xm.js → mindmap-definition-YA3MSWOX-DhEiABv6.js} +1 -1
- package/dist/client/assets/mindmap-definition-YA3MSWOX-DhEiABv6.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-DhEiABv6.js.gz +0 -0
- package/dist/client/assets/{passwordBootstrap-C7-MUAHQ.js → passwordBootstrap-Dxv0I4wM.js} +1 -1
- package/dist/client/assets/passwordBootstrap-Dxv0I4wM.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-Dxv0I4wM.js.gz +0 -0
- package/dist/client/assets/{pegDiagram-XKGWAZYB-DKUIl_U6.js → pegDiagram-XKGWAZYB-LTlVaJfm.js} +1 -1
- package/dist/client/assets/pegDiagram-XKGWAZYB-LTlVaJfm.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-LTlVaJfm.js.gz +0 -0
- package/dist/client/assets/{pieDiagram-E7YTZNPT-aoDNlV7J.js → pieDiagram-E7YTZNPT-9bnryna3.js} +1 -1
- package/dist/client/assets/pieDiagram-E7YTZNPT-9bnryna3.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-9bnryna3.js.gz +0 -0
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-BKuuaF2s.js → quadrantDiagram-AXDQQJYC-ZBmgIpsJ.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-BKuuaF2s.js.br → quadrantDiagram-AXDQQJYC-ZBmgIpsJ.js.br} +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-ZBmgIpsJ.js.gz +0 -0
- package/dist/client/assets/{railroadDiagram-O6MQD6OU-BwfCW2bp.js → railroadDiagram-O6MQD6OU-DTtXvKOu.js} +1 -1
- package/dist/client/assets/railroadDiagram-O6MQD6OU-DTtXvKOu.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-DTtXvKOu.js.gz +0 -0
- package/dist/client/assets/rdpSession-Ggo3N5s5.js +1 -0
- package/dist/client/assets/rdpSession-Ggo3N5s5.js.br +0 -0
- package/dist/client/assets/rdpSession-Ggo3N5s5.js.gz +0 -0
- package/dist/client/assets/referenceLongPress-Df8W2cyP.js +1 -0
- package/dist/client/assets/referenceLongPress-Df8W2cyP.js.br +0 -0
- package/dist/client/assets/referenceLongPress-Df8W2cyP.js.gz +0 -0
- package/dist/client/assets/{requirementDiagram-BXWQKSXE-DbpU9Uig.js → requirementDiagram-BXWQKSXE-BNia9zI0.js} +1 -1
- package/dist/client/assets/requirementDiagram-BXWQKSXE-BNia9zI0.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-BNia9zI0.js.gz +0 -0
- package/dist/client/assets/{sankeyDiagram-P5KCCOFB-Bxa22XVM.js → sankeyDiagram-P5KCCOFB-uvg5npfK.js} +1 -1
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-uvg5npfK.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-uvg5npfK.js.gz +0 -0
- package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-C4GvzT9z.js → sequenceDiagram-WJ2MYXX4-DpJNf2MD.js} +1 -1
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DpJNf2MD.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DpJNf2MD.js.gz +0 -0
- package/dist/client/assets/{sizeCapture-INFHLROL-B9zJJwQw.js → sizeCapture-INFHLROL-CkWB2AnF.js} +1 -1
- package/dist/client/assets/sizeCapture-INFHLROL-CkWB2AnF.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-CkWB2AnF.js.gz +0 -0
- package/dist/client/assets/{sparkles-BJbfT-v-.js → sparkles-DOuEtn62.js} +1 -1
- package/dist/client/assets/{stateDiagram-D77RDMKH-fqbw6LZa.js → stateDiagram-D77RDMKH-CeMzMQq-.js} +1 -1
- package/dist/client/assets/stateDiagram-D77RDMKH-CeMzMQq-.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-CeMzMQq-.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-CNYUpLxt.js +1 -0
- package/dist/client/assets/{swimlanes-42K2YHIH-Hpc28YZY.js → swimlanes-42K2YHIH-Bo9GejWo.js} +1 -1
- package/dist/client/assets/swimlanes-42K2YHIH-Bo9GejWo.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-Bo9GejWo.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-EB7zBRFR.js +8 -0
- package/dist/client/assets/{timeline-definition-24CTP7MA-qDieK7Re.js → timeline-definition-24CTP7MA-cvWXYEZ4.js} +1 -1
- package/dist/client/assets/timeline-definition-24CTP7MA-cvWXYEZ4.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-cvWXYEZ4.js.gz +0 -0
- package/dist/client/assets/{triangle-alert-YOCAWhtT.js → triangle-alert-DzV0gQXz.js} +1 -1
- package/dist/client/assets/{vennDiagram-4TSXK5OY-BJpZlHao.js → vennDiagram-4TSXK5OY-CzleWcmk.js} +1 -1
- package/dist/client/assets/{vennDiagram-4TSXK5OY-BJpZlHao.js.br → vennDiagram-4TSXK5OY-CzleWcmk.js.br} +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-CzleWcmk.js.gz +0 -0
- package/dist/client/assets/{videoCompression-DI9vP0dm.js → videoCompression-DCnzjEfU.js} +1 -1
- package/dist/client/assets/videoCompression-DCnzjEfU.js.br +0 -0
- package/dist/client/assets/videoCompression-DCnzjEfU.js.gz +0 -0
- package/dist/client/assets/{wardleyDiagram-VM6X3IG4-CQJfj6Ns.js → wardleyDiagram-VM6X3IG4-Cir1iutR.js} +1 -1
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-Cir1iutR.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-Cir1iutR.js.gz +0 -0
- package/dist/client/assets/{xychartDiagram-S5SC5T6Z-Cy-lkWBX.js → xychartDiagram-S5SC5T6Z-pNPcVJ1C.js} +1 -1
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-pNPcVJ1C.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-pNPcVJ1C.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 +56 -10
- package/dist/server/agent/collaborationGroupRoutes.js +10 -5
- package/dist/server/agent/collaborationLaunchProfiles.js +43 -0
- package/dist/server/agent/collaborationRoutes.js +6 -2
- package/dist/server/agent/collaborationService.js +8 -2
- package/dist/server/agent/collaborationStore.js +32 -1
- package/dist/server/agent/collaborationTaskCli.js +11 -3
- package/dist/server/agent/collaborationTaskService.js +16 -10
- package/dist/server/agent/collaborationTaskStore.js +70 -25
- package/dist/server/agent/collaborationTeam.js +3 -3
- package/dist/server/agent/integrationCli.js +243 -0
- package/dist/server/agent/integrationServer.js +331 -0
- package/dist/server/agent/integrationSessions.js +344 -0
- package/dist/server/agent/integrationStore.js +222 -0
- package/dist/server/cli.js +29 -0
- package/dist/server/entry.js +26 -7
- package/dist/server/routes/filesystem.js +120 -87
- package/dist/server/routes/terminal.js +196 -13
- package/dist/server/utils/localAccess.js +27 -7
- package/dist/server/utils/sessionDisplayName.js +53 -0
- package/docs/integrations.md +304 -0
- package/package.json +3 -2
- package/runtime-manifest.json +3 -3
- package/dist/client/assets/App-DzuUkEI_.js +0 -179
- package/dist/client/assets/App-DzuUkEI_.js.br +0 -0
- package/dist/client/assets/App-DzuUkEI_.js.gz +0 -0
- package/dist/client/assets/ArchitecturePanel-QodxiiCc.js +0 -7
- package/dist/client/assets/ArchitecturePanel-QodxiiCc.js.br +0 -0
- package/dist/client/assets/ArchitecturePanel-QodxiiCc.js.gz +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-2lXfrgk4.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-2lXfrgk4.js.gz +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-05-Py9N8.js +0 -1
- package/dist/client/assets/CollaborationMainWorkspace-05-Py9N8.js.br +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-05-Py9N8.js.gz +0 -0
- package/dist/client/assets/CollaborationTaskContent-BJe9TUtZ.js +0 -2
- package/dist/client/assets/ComputerControlView-B5vigCoW.js +0 -5
- package/dist/client/assets/ComputerControlView-B5vigCoW.js.br +0 -0
- package/dist/client/assets/ComputerControlView-B5vigCoW.js.gz +0 -0
- package/dist/client/assets/DagPlayground-EFUb9S3u.js.br +0 -0
- package/dist/client/assets/DagPlayground-EFUb9S3u.js.gz +0 -0
- package/dist/client/assets/DiffLab-CXWjSE2q.js.br +0 -0
- package/dist/client/assets/DiffLab-CXWjSE2q.js.gz +0 -0
- package/dist/client/assets/DiffReview-ByMkBaD9.js.br +0 -0
- package/dist/client/assets/DiffReview-ByMkBaD9.js.gz +0 -0
- package/dist/client/assets/DiffReviewLab-DoWaKm94.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-DoWaKm94.js.gz +0 -0
- package/dist/client/assets/DiffViewer-B4hn9z0k.js.br +0 -0
- package/dist/client/assets/DiffViewer-B4hn9z0k.js.gz +0 -0
- package/dist/client/assets/ModelPreview-C-LJZ8so.js.br +0 -0
- package/dist/client/assets/ModelPreview-C-LJZ8so.js.gz +0 -0
- package/dist/client/assets/RightSidebar-EaMm4prW.js +0 -1678
- package/dist/client/assets/RightSidebar-EaMm4prW.js.br +0 -0
- package/dist/client/assets/RightSidebar-EaMm4prW.js.gz +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-BY-pfYKk.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-BY-pfYKk.js.gz +0 -0
- package/dist/client/assets/app-Ch0UDtJ-.js +0 -35
- package/dist/client/assets/app-Ch0UDtJ-.js.br +0 -0
- package/dist/client/assets/app-Ch0UDtJ-.js.gz +0 -0
- package/dist/client/assets/arc-DIENgCZn.js.br +0 -0
- package/dist/client/assets/arc-DIENgCZn.js.gz +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-C1h4e4az.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-C1h4e4az.js.gz +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-B_yOr54K.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-B_yOr54K.js.gz +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-DRD4zxIo.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-DRD4zxIo.js.gz +0 -0
- package/dist/client/assets/channel-MOXuUKM7.js +0 -1
- package/dist/client/assets/chunk-F27PBJKO-CQCL8mJG.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-CQCL8mJG.js.gz +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-ruHGCADe.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-ruHGCADe.js.gz +0 -0
- package/dist/client/assets/chunk-SVP7TREG-DMHj3NSq.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-DMHj3NSq.js.gz +0 -0
- package/dist/client/assets/chunk-TICWLB2K-Dh_ekvFW.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-Dh_ekvFW.js.gz +0 -0
- package/dist/client/assets/classDiagram-ZZMXUADV-CEXMdudw.js +0 -1
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-CEXMdudw.js +0 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-CsySWhYg.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-CsySWhYg.js.gz +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-9DKE5wV7.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-9DKE5wV7.js.gz +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-B_8fvr9c.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-B_8fvr9c.js.gz +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-BOdsFNFT.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-BOdsFNFT.js.gz +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-6v_qvAvi.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-6v_qvAvi.js.gz +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-c03oOGhD.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-c03oOGhD.js.gz +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-MMIhRYp_.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-MMIhRYp_.js.gz +0 -0
- package/dist/client/assets/diagram-VX7I27RA-B_l-uebl.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-B_l-uebl.js.gz +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-DKoBC5gn.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-DKoBC5gn.js.gz +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-Bs3wu8Az.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-Bs3wu8Az.js.gz +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-mYnHYbKl.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-mYnHYbKl.js.gz +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-CwCLWbib.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-CwCLWbib.js.gz +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-mse8c-ni.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-mse8c-ni.js.gz +0 -0
- package/dist/client/assets/gestureArbiter-BviL29ps.js.br +0 -0
- package/dist/client/assets/gestureArbiter-BviL29ps.js.gz +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BVUfLjAX.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BVUfLjAX.js.gz +0 -0
- package/dist/client/assets/index-C6ftfFlG.css.br +0 -0
- package/dist/client/assets/index-C6ftfFlG.css.gz +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-bH299bWL.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-bH299bWL.js.gz +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-BG0u_X1A.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-BG0u_X1A.js.gz +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-DRoc9N-i.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-DRoc9N-i.js.gz +0 -0
- package/dist/client/assets/layout-mh0t6JpE.js.br +0 -0
- package/dist/client/assets/layout-mh0t6JpE.js.gz +0 -0
- package/dist/client/assets/linear-B9KTRuUV.js.br +0 -0
- package/dist/client/assets/linear-B9KTRuUV.js.gz +0 -0
- package/dist/client/assets/mermaid.core-Bu2G9zhK.js.br +0 -0
- package/dist/client/assets/mermaid.core-Bu2G9zhK.js.gz +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-Go6Bg5xm.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-Go6Bg5xm.js.gz +0 -0
- package/dist/client/assets/passwordBootstrap-C7-MUAHQ.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-C7-MUAHQ.js.gz +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-DKUIl_U6.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-DKUIl_U6.js.gz +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-aoDNlV7J.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-aoDNlV7J.js.gz +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-BKuuaF2s.js.gz +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-BwfCW2bp.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-BwfCW2bp.js.gz +0 -0
- package/dist/client/assets/rdpSession--y6Q98uo.js +0 -1
- package/dist/client/assets/rdpSession--y6Q98uo.js.br +0 -0
- package/dist/client/assets/rdpSession--y6Q98uo.js.gz +0 -0
- package/dist/client/assets/referenceLongPress-BeG1PAdI.js +0 -1
- package/dist/client/assets/referenceLongPress-BeG1PAdI.js.br +0 -0
- package/dist/client/assets/referenceLongPress-BeG1PAdI.js.gz +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-DbpU9Uig.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-DbpU9Uig.js.gz +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-Bxa22XVM.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-Bxa22XVM.js.gz +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-C4GvzT9z.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-C4GvzT9z.js.gz +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-B9zJJwQw.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-B9zJJwQw.js.gz +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-fqbw6LZa.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-fqbw6LZa.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-BO23Pbrn.js +0 -1
- package/dist/client/assets/swimlanes-42K2YHIH-Hpc28YZY.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-Hpc28YZY.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-BLS7y4Di.js +0 -8
- package/dist/client/assets/timeline-definition-24CTP7MA-qDieK7Re.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-qDieK7Re.js.gz +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-BJpZlHao.js.gz +0 -0
- package/dist/client/assets/videoCompression-DI9vP0dm.js.br +0 -0
- package/dist/client/assets/videoCompression-DI9vP0dm.js.gz +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-CQJfj6Ns.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-CQJfj6Ns.js.gz +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-Cy-lkWBX.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-Cy-lkWBX.js.gz +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import { CollaborationError } from './collaborationProtocol.js';
|
|
3
3
|
import { COLLAB_NAME_FORBIDDEN } from './collaborationPrompt.js';
|
|
4
|
+
import { validateLaunchProfiles } from './collaborationLaunchProfiles.js';
|
|
4
5
|
/** The current service owns group membership, including retained offline members. */
|
|
5
6
|
export function collaborationGroupRoutes(options) {
|
|
6
7
|
const router = Router();
|
|
@@ -11,15 +12,15 @@ export function collaborationGroupRoutes(options) {
|
|
|
11
12
|
router.post('/collaboration-groups', async (req, res) => {
|
|
12
13
|
try {
|
|
13
14
|
const body = req.body ?? {};
|
|
14
|
-
const { id, name, sessionIds, expectedUpdatedAt } = body;
|
|
15
|
+
const { id, name, sessionIds, expectedUpdatedAt, launchProfiles, defaultLaunchProfileId } = body;
|
|
15
16
|
// Unknown fields used to be dropped silently while the save still
|
|
16
17
|
// returned ok — a caller submitting `members` to rename someone got a
|
|
17
18
|
// success and no rename. Reject them and route the common case (member
|
|
18
19
|
// renames) to the command that actually does it.
|
|
19
|
-
const unknownKeys = Object.keys(body).filter((key) => !['id', 'name', 'sessionIds', 'expectedUpdatedAt'].includes(key));
|
|
20
|
+
const unknownKeys = Object.keys(body).filter((key) => !['id', 'name', 'sessionIds', 'expectedUpdatedAt', 'launchProfiles', 'defaultLaunchProfileId'].includes(key));
|
|
20
21
|
if (unknownKeys.length) {
|
|
21
22
|
const hint = unknownKeys.includes('members') ? ';要改成员显示名请用 td collab rename <session-id> <新名字>' : '';
|
|
22
|
-
throw new CollaborationError('INVALID_GROUP', `含未知字段 ${unknownKeys.join('、')}(合法字段:name, sessionIds, id, expectedUpdatedAt)${hint}`, 400);
|
|
23
|
+
throw new CollaborationError('INVALID_GROUP', `含未知字段 ${unknownKeys.join('、')}(合法字段:name, sessionIds, id, expectedUpdatedAt, launchProfiles, defaultLaunchProfileId)${hint}`, 400);
|
|
23
24
|
}
|
|
24
25
|
if ((id !== undefined && (typeof id !== 'string' || !id))
|
|
25
26
|
|| typeof name !== 'string' || !name.trim() || !Array.isArray(sessionIds)
|
|
@@ -36,15 +37,19 @@ export function collaborationGroupRoutes(options) {
|
|
|
36
37
|
throw new CollaborationError('GROUP_CHANGED', `协作组已被修改(当前 updatedAt=${existing?.updatedAt})。请先确认最新成员列表,再以 expectedUpdatedAt=${existing?.updatedAt} 重新提交`, 409, { currentUpdatedAt: existing?.updatedAt });
|
|
37
38
|
}
|
|
38
39
|
const ids = [...new Set(sessionIds)];
|
|
40
|
+
const launch = launchProfiles !== undefined || defaultLaunchProfileId !== undefined ? {
|
|
41
|
+
launchProfiles: validateLaunchProfiles(launchProfiles ?? existing?.launchProfiles ?? [], defaultLaunchProfileId ?? null),
|
|
42
|
+
defaultLaunchProfileId: defaultLaunchProfileId ?? null,
|
|
43
|
+
} : {};
|
|
39
44
|
if (options.save) {
|
|
40
|
-
res.json(await options.save(req, { id, name, sessionIds: ids, expectedUpdatedAt }));
|
|
45
|
+
res.json(await options.save(req, { id, name, sessionIds: ids, expectedUpdatedAt, ...launch }));
|
|
41
46
|
return;
|
|
42
47
|
}
|
|
43
48
|
const known = new Set([...options.sessions().map((session) => session.sessionId), ...(existing?.sessionIds ?? [])]);
|
|
44
49
|
if (ids.some((value) => !known.has(value))) {
|
|
45
50
|
throw new CollaborationError('MEMBERS_CHANGED', '所选会话已变化,请刷新后重新选择;尚未保存任何修改', 409);
|
|
46
51
|
}
|
|
47
|
-
res.json({ group: options.store.save({ id, name, sessionIds: ids }) });
|
|
52
|
+
res.json({ group: options.store.save({ id, name, sessionIds: ids, ...launch }) });
|
|
48
53
|
}
|
|
49
54
|
catch (error) {
|
|
50
55
|
res.status(error instanceof CollaborationError ? error.httpStatus : 500)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { CollaborationError } from './collaborationProtocol.js';
|
|
2
|
+
/** User-authored shell commands; never interpolate coordinator-provided parameters. */
|
|
3
|
+
export function validateLaunchProfiles(profiles, defaultId) {
|
|
4
|
+
const invalid = () => { throw new CollaborationError('INVALID_LAUNCH_PROFILE', '启动方案无效:请填写唯一标识、名称、Agent 和单行启动命令,并选择存在的默认方案', 400); };
|
|
5
|
+
if (!Array.isArray(profiles) || profiles.length > 20)
|
|
6
|
+
return invalid();
|
|
7
|
+
const ids = new Set();
|
|
8
|
+
for (const profile of profiles) {
|
|
9
|
+
if (!profile || typeof profile !== 'object' || Array.isArray(profile)
|
|
10
|
+
|| Object.keys(profile).some(key => !['id', 'name', 'agentSlug', 'command', 'notes'].includes(key))
|
|
11
|
+
|| typeof profile.id !== 'string' || !/^[a-zA-Z0-9_-]{1,64}$/.test(profile.id) || ids.has(profile.id)
|
|
12
|
+
|| typeof profile.name !== 'string' || !profile.name.trim() || profile.name.length > 100
|
|
13
|
+
|| typeof profile.agentSlug !== 'string' || !/^[a-zA-Z0-9_-]{1,64}$/.test(profile.agentSlug)
|
|
14
|
+
|| typeof profile.command !== 'string' || !profile.command.trim() || profile.command.length > 4096
|
|
15
|
+
|| typeof profile.notes !== 'string' || profile.notes.length > 2000
|
|
16
|
+
|| /[\x00-\x1f\x7f]/.test(profile.command + profile.name)
|
|
17
|
+
|| /[\x00-\x08\x0b-\x1f\x7f]/.test(profile.notes))
|
|
18
|
+
return invalid();
|
|
19
|
+
ids.add(profile.id);
|
|
20
|
+
}
|
|
21
|
+
if (defaultId !== undefined && defaultId !== null && (typeof defaultId !== 'string' || !ids.has(defaultId)))
|
|
22
|
+
return invalid();
|
|
23
|
+
return profiles.map(p => ({ id: p.id, name: p.name.trim(), agentSlug: p.agentSlug, command: p.command.trim(), notes: p.notes.trim() }));
|
|
24
|
+
}
|
|
25
|
+
export function resolveCollaborationLaunch(group, input) {
|
|
26
|
+
if (input.launchProfileId !== undefined && typeof input.launchProfileId !== 'string')
|
|
27
|
+
throw new CollaborationError('INVALID_LAUNCH_PROFILE', '启动方案标识必须是文本', 400);
|
|
28
|
+
const slug = typeof input.agentSlug === 'string' ? input.agentSlug.trim().toLowerCase() : '';
|
|
29
|
+
const explicit = typeof input.launchProfileId === 'string' && !!input.launchProfileId;
|
|
30
|
+
const profileId = explicit ? input.launchProfileId : input.launchProfileId === '' ? null : group.defaultLaunchProfileId;
|
|
31
|
+
const candidate = group.launchProfiles?.find(p => p.id === profileId);
|
|
32
|
+
if (explicit && !candidate)
|
|
33
|
+
throw new CollaborationError('LAUNCH_PROFILE_NOT_FOUND', '启动方案已被删除,请读取最新协作组配置', 409);
|
|
34
|
+
if (explicit && slug && candidate.agentSlug !== slug)
|
|
35
|
+
throw new CollaborationError('LAUNCH_PROFILE_AGENT_MISMATCH', '启动方案与所选 Agent 类型不一致', 400);
|
|
36
|
+
const profile = candidate && (!slug || candidate.agentSlug === slug) ? candidate : undefined;
|
|
37
|
+
if (profile)
|
|
38
|
+
validateLaunchProfiles([profile], profile.id);
|
|
39
|
+
return { agentSlug: profile?.agentSlug ?? slug, profile };
|
|
40
|
+
}
|
|
41
|
+
export function launchProfileKey(profile) {
|
|
42
|
+
return profile ? JSON.stringify([profile.id, profile.agentSlug, profile.command]) : '';
|
|
43
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { terminalMessage } from './collaborationStore.js';
|
|
2
|
+
import { getTermdockVersion } from '../utils/version.js';
|
|
2
3
|
import { assertPeerRegistrationAuthority } from './collaborationPeerTransport.js';
|
|
3
4
|
import { Router } from 'express';
|
|
4
5
|
import { COLLAB_LIMITS, CollaborationError, MIN_ID_PREFIX_LENGTH, ambiguousIdMessage, extrasFromBody } from './collaborationProtocol.js';
|
|
@@ -150,10 +151,11 @@ export function collaborationRoutes({ store, resolveSession, deliver, rebind, re
|
|
|
150
151
|
}
|
|
151
152
|
};
|
|
152
153
|
router.get('/capabilities', run((_req, res) => {
|
|
153
|
-
res.json({ protocol_version: 2, limits: COLLAB_LIMITS,
|
|
154
|
+
res.json({ protocol_version: 2, server_version: getTermdockVersion(), limits: COLLAB_LIMITS,
|
|
154
155
|
task_workflow: { version: 2, command: 'td collab task', single_authority: true, explicit_reports: true,
|
|
155
156
|
managed_goals: true, automatic_review: true, dependency_dispatch: true, isolated_worktrees: true, encrypted_commit_transfer: true,
|
|
156
157
|
durable_questions: true, user_acceptance: true, versioned_artifacts: true, independent_reviews: true,
|
|
158
|
+
correlated_responses: true, accepted_comments: true,
|
|
157
159
|
task_reply: 'Replies to task-linked user messages are stored in the task; status=stored is not a terminal delivery receipt' },
|
|
158
160
|
routing: { background_recovery: true, explicit_rebind: Boolean(rebind), fixed_tmux_pane: true },
|
|
159
161
|
statuses: ['pending', 'delivered', 'failed', 'expired'], queued_status: 'pending',
|
|
@@ -211,7 +213,7 @@ export function collaborationRoutes({ store, resolveSession, deliver, rebind, re
|
|
|
211
213
|
const extras = extrasFromBody(req.body);
|
|
212
214
|
const status = extras.task?.status ?? (extras.responseKind === 'ack' ? 'ack' : extras.responseKind === 'result' ? 'complete' : extras.responseKind === 'progress' ? 'working' : null);
|
|
213
215
|
const task = await req.app.locals.collaborationTasks.apply(link.taskId, {
|
|
214
|
-
kind: status ? 'report' : 'comment', status: status ?? undefined, attemptId: link.attemptId,
|
|
216
|
+
kind: status ? 'report' : link.replyToEventId ? 'respond' : 'comment', replyToEventId: link.replyToEventId, status: status ?? undefined, attemptId: link.attemptId,
|
|
215
217
|
content: req.body.content, evidence: extras.task?.evidence, idempotencyKey: extras.idempotencyKey,
|
|
216
218
|
}, req.app.locals.collaborationService.taskMember(sessionId));
|
|
217
219
|
res.json({ ok: true, status: 'stored', task_recorded: true, task_id: task.id, task_revision: task.revision });
|
|
@@ -323,6 +325,8 @@ export function collaborationRoutes({ store, resolveSession, deliver, rebind, re
|
|
|
323
325
|
id: group.id, name: group.name, sessionIds: group.sessionIds,
|
|
324
326
|
members: group.sessionIds.map((sessionId) => ({ sessionId, name: names[sessionId] ?? null })),
|
|
325
327
|
roles: group.roles ?? {},
|
|
328
|
+
launchProfiles: group.launchProfiles ?? [], defaultLaunchProfileId: group.defaultLaunchProfileId ?? null,
|
|
329
|
+
memberLaunchProfiles: group.memberLaunchProfiles ?? {},
|
|
326
330
|
};
|
|
327
331
|
};
|
|
328
332
|
router.get('/rules', run((req, res, sessionId) => {
|
|
@@ -3,6 +3,7 @@ import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
|
3
3
|
import { dirname } from 'node:path';
|
|
4
4
|
import { CollaborationError } from './collaborationProtocol.js';
|
|
5
5
|
import { COLLAB_NAME_FORBIDDEN } from './collaborationPrompt.js';
|
|
6
|
+
import { validateLaunchProfiles } from './collaborationLaunchProfiles.js';
|
|
6
7
|
import { remoteSession, validateCollaborationNode } from './collaborationPeerTransport.js';
|
|
7
8
|
const hash = (value) => createHash('sha256').update(value).digest('hex');
|
|
8
9
|
const address = (id) => { if (!id.startsWith('remote:'))
|
|
@@ -12,6 +13,7 @@ const local = (origin, id) => { const a = address(id); return a?.origin === orig
|
|
|
12
13
|
const mapRoles = (value, map) => value && Object.fromEntries(Object.entries(value).map(([id, item]) => [map(id), item]));
|
|
13
14
|
function mapGroup(group, map) {
|
|
14
15
|
return { ...group, sessionIds: group.sessionIds.map(map), roles: mapRoles(group.roles, map), roleVersions: mapRoles(group.roleVersions, map),
|
|
16
|
+
memberLaunchProfiles: mapRoles(group.memberLaunchProfiles, map),
|
|
15
17
|
instructions: group.instructions && { ...group.instructions, updatedBy: map(group.instructions.updatedBy) } };
|
|
16
18
|
}
|
|
17
19
|
/** Sole owner of peer discovery and group replication. UI and CLI call the same
|
|
@@ -460,10 +462,14 @@ export class CollaborationService {
|
|
|
460
462
|
throw new CollaborationError('GROUP_CHANGED', `协作组已变化(当前 updatedAt=${existing.updatedAt}),请刷新后重试`, 409, { currentUpdatedAt: existing.updatedAt });
|
|
461
463
|
if (typeof input.name !== 'string' || !input.name.trim() || COLLAB_NAME_FORBIDDEN.test(input.name) || !Array.isArray(input.sessionIds) || input.sessionIds.some(id => typeof id !== 'string'))
|
|
462
464
|
throw new Error('INVALID_GROUP');
|
|
465
|
+
const launch = input.launchProfiles !== undefined || input.defaultLaunchProfileId !== undefined ? {
|
|
466
|
+
launchProfiles: validateLaunchProfiles(input.launchProfiles ?? existing?.launchProfiles ?? [], input.defaultLaunchProfileId ?? null),
|
|
467
|
+
defaultLaunchProfileId: input.defaultLaunchProfileId ?? null,
|
|
468
|
+
} : {};
|
|
463
469
|
if (!input.sessionIds.some(id => address(id)) && !existing?.federated) {
|
|
464
470
|
if (input.sessionIds.some(id => !this.options.sessions().some(s => s.sessionId === id) && !existing?.sessionIds.includes(id)))
|
|
465
471
|
throw new Error('GROUP_MEMBER_UNAVAILABLE');
|
|
466
|
-
return { group: this.options.store.save(input) };
|
|
472
|
+
return { group: this.options.store.save({ ...input, ...launch }) };
|
|
467
473
|
}
|
|
468
474
|
if (input.sessionIds.length < 2)
|
|
469
475
|
throw new CollaborationError('INVALID_GROUP', '跨服务组仍需两个成员;修改未保存', 400);
|
|
@@ -477,7 +483,7 @@ export class CollaborationService {
|
|
|
477
483
|
const available = new Set([...this.options.sessions(), ...this.directory().sessions.filter(s => s.serviceConnected)].map(s => s.sessionId));
|
|
478
484
|
if (!Array.isArray(input.sessionIds) || input.sessionIds.some(id => !available.has(id) && !existing?.sessionIds.includes(id)))
|
|
479
485
|
throw new Error('GROUP_MEMBER_UNAVAILABLE');
|
|
480
|
-
const group = { ...existing, id: existing?.federated ? existing.id : `cross-${randomBytes(16).toString('hex')}`, name: input.name,
|
|
486
|
+
const group = { ...existing, ...launch, id: existing?.federated ? existing.id : `cross-${randomBytes(16).toString('hex')}`, name: input.name,
|
|
481
487
|
sessionIds: [...new Set(input.sessionIds)], createdAt: existing?.createdAt ?? Date.now(), updatedAt: Math.max(Date.now(), (existing?.updatedAt ?? 0) + 1), federated: true };
|
|
482
488
|
const canonical = mapGroup(group, id => address(id) ? id : remoteSession(this.node().origin, id));
|
|
483
489
|
if (canonical.sessionIds.some(id => !this.nodes().some(node => node.origin === address(id)?.origin)))
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { plainCollaborationSnapshot } from './collaborationText.js';
|
|
2
|
+
import { validateLaunchProfiles } from './collaborationLaunchProfiles.js';
|
|
2
3
|
import fs from 'node:fs';
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
import crypto from 'node:crypto';
|
|
@@ -43,6 +44,9 @@ export class CollaborationStore {
|
|
|
43
44
|
filePath;
|
|
44
45
|
drawId;
|
|
45
46
|
onMessageQueued;
|
|
47
|
+
changeListeners = new Set();
|
|
48
|
+
subscribe(listener) { this.changeListeners.add(listener); return () => { this.changeListeners.delete(listener); }; }
|
|
49
|
+
snapshotMessages() { return structuredClone(this.document.messages); }
|
|
46
50
|
peerActivity = new Map();
|
|
47
51
|
recordPeerActivity(sessionId, outputAt, observedAt) {
|
|
48
52
|
if (this.peerActivity.size >= 2000 && !this.peerActivity.has(sessionId))
|
|
@@ -122,9 +126,14 @@ export class CollaborationStore {
|
|
|
122
126
|
const existing = input.id ? this.document.groups.find((group) => group.id === input.id) : null;
|
|
123
127
|
if (input.id && (!existing || existing.deleted))
|
|
124
128
|
throw new CollaborationError('GROUP_NOT_FOUND', '协作组已删除,请刷新列表', 404);
|
|
129
|
+
const launchProfiles = input.launchProfiles === undefined ? existing?.launchProfiles : validateLaunchProfiles(input.launchProfiles, input.defaultLaunchProfileId ?? null);
|
|
130
|
+
const defaultLaunchProfileId = input.defaultLaunchProfileId !== undefined ? input.defaultLaunchProfileId : input.launchProfiles !== undefined ? null : existing?.defaultLaunchProfileId;
|
|
131
|
+
if (launchProfiles || defaultLaunchProfileId)
|
|
132
|
+
validateLaunchProfiles(launchProfiles ?? [], defaultLaunchProfileId);
|
|
125
133
|
const sessionIds = Array.from(new Set(input.sessionIds.map((id) => id.trim()).filter(Boolean)));
|
|
126
134
|
const group = pruneRoles({
|
|
127
135
|
...existing,
|
|
136
|
+
launchProfiles, defaultLaunchProfileId,
|
|
128
137
|
...(existing?.remoteSessions ? { remoteSessions: existing.remoteSessions.filter((session) => sessionIds.includes(session.sessionId)) } : {}),
|
|
129
138
|
id: existing?.id ?? newCollaborationId(this.takenIds(), this.drawId),
|
|
130
139
|
name: input.name.trim(),
|
|
@@ -138,6 +147,15 @@ export class CollaborationStore {
|
|
|
138
147
|
this.persist();
|
|
139
148
|
return group;
|
|
140
149
|
}
|
|
150
|
+
setMemberLaunchProfile(groupId, sessionId, profile) {
|
|
151
|
+
const group = this.getGroup(groupId);
|
|
152
|
+
if (!group || group.deleted || !group.sessionIds.includes(sessionId))
|
|
153
|
+
throw new CollaborationError('NOT_A_MEMBER', '会话不在协作组内', 409);
|
|
154
|
+
const [snapshot] = validateLaunchProfiles([profile], profile.id);
|
|
155
|
+
this.document.groups = this.document.groups.map(g => g.id === groupId ? { ...g,
|
|
156
|
+
memberLaunchProfiles: { ...g.memberLaunchProfiles, [sessionId]: snapshot }, updatedAt: Math.max(Date.now(), g.updatedAt + 1) } : g);
|
|
157
|
+
this.persist();
|
|
158
|
+
}
|
|
141
159
|
/** Set or clear a member's role (定位). The target may be any group member —
|
|
142
160
|
* oneself, a peer, or a federated remote session; peers can set each other's
|
|
143
161
|
* roles. Roles ride the group document into federation and are dropped
|
|
@@ -199,7 +217,9 @@ export class CollaborationStore {
|
|
|
199
217
|
...(group.remoteSessions ? { remoteSessions: group.remoteSessions.filter((session) => sourceIds.includes(session.sessionId)) } : {}),
|
|
200
218
|
updatedAt: Math.max(now, group.updatedAt + 1) }, sourceIds)];
|
|
201
219
|
}
|
|
202
|
-
return group.id === target.id ? [{ ...group, sessionIds: [...new Set([...group.sessionIds, input.sessionId])],
|
|
220
|
+
return group.id === target.id ? [{ ...group, sessionIds: [...new Set([...group.sessionIds, input.sessionId])],
|
|
221
|
+
...(source.memberLaunchProfiles?.[input.sessionId] ? { memberLaunchProfiles: { ...group.memberLaunchProfiles, [input.sessionId]: source.memberLaunchProfiles[input.sessionId] } } : {}),
|
|
222
|
+
updatedAt: Math.max(now, group.updatedAt + 1) }] : [group];
|
|
203
223
|
}),
|
|
204
224
|
messages: this.document.messages,
|
|
205
225
|
};
|
|
@@ -727,6 +747,12 @@ export class CollaborationStore {
|
|
|
727
747
|
fs.writeFileSync(temporaryPath, serialized, { mode: 0o600 });
|
|
728
748
|
fs.renameSync(temporaryPath, this.filePath);
|
|
729
749
|
this.persistedDocument = serialized;
|
|
750
|
+
for (const listener of this.changeListeners) {
|
|
751
|
+
try {
|
|
752
|
+
listener();
|
|
753
|
+
}
|
|
754
|
+
catch { /* Journal retries from durable source records. */ }
|
|
755
|
+
}
|
|
730
756
|
}
|
|
731
757
|
catch (error) {
|
|
732
758
|
this.document = JSON.parse(this.persistedDocument);
|
|
@@ -739,6 +765,11 @@ function stableJson(value) {
|
|
|
739
765
|
? Object.fromEntries(Object.entries(entry).sort(([a], [b]) => a.localeCompare(b))) : entry);
|
|
740
766
|
}
|
|
741
767
|
function validateFederatedGroup(group) {
|
|
768
|
+
if (group.launchProfiles !== undefined || group.defaultLaunchProfileId !== undefined)
|
|
769
|
+
validateLaunchProfiles(group.launchProfiles ?? [], group.defaultLaunchProfileId);
|
|
770
|
+
if (group.memberLaunchProfiles)
|
|
771
|
+
for (const profile of Object.values(group.memberLaunchProfiles))
|
|
772
|
+
validateLaunchProfiles([profile], profile.id);
|
|
742
773
|
if (!group.federated || typeof group.id !== 'string' || !group.id.startsWith('cross-') || typeof group.name !== 'string' || !group.name.trim()
|
|
743
774
|
|| !Number.isFinite(group.updatedAt) || !Number.isFinite(group.createdAt)
|
|
744
775
|
|| !Array.isArray(group.sessionIds) || group.sessionIds.some((id) => typeof id !== 'string')
|
|
@@ -3,8 +3,12 @@ import { randomUUID } from 'node:crypto';
|
|
|
3
3
|
export async function executeTaskCommand(command, request, io) {
|
|
4
4
|
const o = command.options, operation = command.operation;
|
|
5
5
|
const bodyOptions = ['content', 'file', 'stdin', 'idempotency-key'];
|
|
6
|
+
const originOptions = ['source', 'external-actor', 'external-message-id', 'metadata'];
|
|
7
|
+
if (originOptions.some(key => o[key]) && !o.principal)
|
|
8
|
+
throw new Error('External source metadata requires --principal');
|
|
6
9
|
const allowed = {
|
|
7
10
|
list: ['group'], get: [], create: [...bodyOptions, 'group', 'title', 'constraints', 'acceptance', 'assignee', 'coordinator', 'parent', 'depends-on', 'managed', 'reviewers', 'shared-directory', 'integration', 'work-type'],
|
|
11
|
+
answer: [...bodyOptions, 'decision'], respond: [...bodyOptions, 'attempt', 'to-event', 'evidence'],
|
|
8
12
|
assign: [...bodyOptions, 'assignee', 'revision'], report: [...bodyOptions, 'attempt', 'status', 'evidence', 'summary'], ask: [...bodyOptions, 'attempt', 'options'],
|
|
9
13
|
plan: [...bodyOptions, 'attempt', 'evidence'], review: [...bodyOptions, 'artifact', 'evidence', 'verdict'], comment: bodyOptions,
|
|
10
14
|
'request-review': [...bodyOptions, 'artifact', 'assignee', 'revision'],
|
|
@@ -12,7 +16,7 @@ export async function executeTaskCommand(command, request, io) {
|
|
|
12
16
|
coordinate: [...bodyOptions, 'revision'], pause: [...bodyOptions, 'revision'], resume: [...bodyOptions, 'revision'], retry: [...bodyOptions, 'revision'],
|
|
13
17
|
};
|
|
14
18
|
for (const flag of Object.keys(o))
|
|
15
|
-
if (![...allowed[operation], 'session', 'json', 'jsonl', 'text', 'help'].includes(flag))
|
|
19
|
+
if (![...allowed[operation], ...(o.principal ? originOptions : []), 'principal', 'session', 'json', 'jsonl', 'text', 'help'].includes(flag))
|
|
16
20
|
throw new Error(`--${flag} is not supported by task ${operation}`);
|
|
17
21
|
if (operation === 'list')
|
|
18
22
|
return request('GET', `/tasks${o.group ? `?group=${encodeURIComponent(String(o.group))}` : ''}`);
|
|
@@ -32,8 +36,12 @@ export async function executeTaskCommand(command, request, io) {
|
|
|
32
36
|
throw new Error('Read task get first, then supply --revision to avoid overwriting another decision');
|
|
33
37
|
if (['assign', 'request-review'].includes(operation) && !o.assignee)
|
|
34
38
|
throw new Error('This task operation requires --assignee');
|
|
35
|
-
if (['report', 'ask', 'plan'].includes(operation) && !o.attempt)
|
|
39
|
+
if (['report', 'respond', 'ask', 'plan'].includes(operation) && !o.attempt)
|
|
36
40
|
throw new Error('Use --attempt from the dispatch message; never guess the current attempt');
|
|
41
|
+
if (operation === 'respond' && !o['to-event'])
|
|
42
|
+
throw new Error('respond requires --to-event <comment-event-id>');
|
|
43
|
+
if (operation === 'answer' && !o.decision)
|
|
44
|
+
throw new Error('answer requires --decision <question-id>');
|
|
37
45
|
if (operation === 'create') {
|
|
38
46
|
if (!o.title || !o.group)
|
|
39
47
|
throw new Error('task create requires --title and --group');
|
|
@@ -47,7 +55,7 @@ export async function executeTaskCommand(command, request, io) {
|
|
|
47
55
|
if (options !== undefined && (!Array.isArray(options) || options.some(v => typeof v !== 'string')))
|
|
48
56
|
throw new Error('--options must be a JSON array of strings');
|
|
49
57
|
return request('POST', `/tasks/${encodeURIComponent(command.target)}`, { input: {
|
|
50
|
-
kind: operation === 'plan' ? 'submit-plan' : operation, idempotencyKey, expectedRevision, content,
|
|
58
|
+
replyToEventId: o['to-event'], decisionId: o.decision, kind: operation === 'plan' ? 'submit-plan' : operation, idempotencyKey, expectedRevision, content,
|
|
51
59
|
assigneeSessionId: o.assignee, attemptId: o.attempt, status: o.status, artifactId: o.artifact, options, verdict: o.verdict,
|
|
52
60
|
evidence: o.evidence ? JSON.parse(String(o.evidence)) : undefined, summary: o.summary,
|
|
53
61
|
} });
|
|
@@ -54,9 +54,9 @@ export class CollaborationTaskService {
|
|
|
54
54
|
const roster = summary ? undefined : group?.sessionIds.map(sessionId => {
|
|
55
55
|
const member = this.peers.taskMember(sessionId);
|
|
56
56
|
const template = task.workflow?.reviewers.some(m => taskMemberKey(m) === taskMemberKey(member));
|
|
57
|
-
return { member, sessionId, role: `${template ? '此目标的执行成员模板;' : ''}${group.roles?.[sessionId] ?? ''}` };
|
|
57
|
+
return { member, sessionId, launchProfile: group.memberLaunchProfiles?.[sessionId], role: `${template ? '此目标的执行成员模板;' : ''}${group.roles?.[sessionId] ?? ''}` };
|
|
58
58
|
});
|
|
59
|
-
return { ...task, children, roster, memberSessions, replica: task.ownerServiceId !== this.self, summaryOnly: summary, outbox: (summary ? [] : this.tasks.pending(task.id))
|
|
59
|
+
return { ...task, children, roster, launchProfiles: summary ? undefined : group?.launchProfiles, defaultLaunchProfileId: summary ? undefined : group?.defaultLaunchProfileId, memberSessions, replica: task.ownerServiceId !== this.self, summaryOnly: summary, outbox: (summary ? [] : this.tasks.pending(task.id))
|
|
60
60
|
.map(({ id, attemptId, messageId, lastError }) => ({ id, attemptId, messageId, lastError })) };
|
|
61
61
|
}
|
|
62
62
|
list(groupId, actor) {
|
|
@@ -70,7 +70,7 @@ export class CollaborationTaskService {
|
|
|
70
70
|
this.group(task.groupId, actor);
|
|
71
71
|
return this.view(task);
|
|
72
72
|
}
|
|
73
|
-
async create(input, actor) {
|
|
73
|
+
async create(input, actor, origin) {
|
|
74
74
|
this.group(input.groupId, actor);
|
|
75
75
|
this.validateMembers(input.groupId, input);
|
|
76
76
|
const dependencies = [...(input.dependsOn ?? []), ...(input.parentTaskId ? [input.parentTaskId] : [])];
|
|
@@ -81,22 +81,26 @@ export class CollaborationTaskService {
|
|
|
81
81
|
if (this.tasks.get(dependency)?.ownerServiceId !== authority)
|
|
82
82
|
throw new CollaborationError('DEPENDENCY_AUTHORITY_REQUIRED', '依赖与父任务需在同一来源服务创建', 409);
|
|
83
83
|
}
|
|
84
|
+
if (origin && authority !== this.self)
|
|
85
|
+
throw new CollaborationError('INTEGRATION_LOCAL_ONLY', '首版集成任务须由本机服务保存', 409);
|
|
84
86
|
if (authority !== this.self) {
|
|
85
87
|
const result = await this.peers.requestTasks(authority, { op: 'create', input, actorSessionId: actor?.sessionId ?? null });
|
|
86
88
|
const task = result.task;
|
|
87
89
|
this.tasks.merge(task, authority);
|
|
88
90
|
return this.view(task);
|
|
89
91
|
}
|
|
90
|
-
const task = this.tasks.create(this.self, input, actor);
|
|
92
|
+
const task = this.tasks.create(this.self, input, actor, origin);
|
|
91
93
|
void this.flush();
|
|
92
94
|
return this.view(task);
|
|
93
95
|
}
|
|
94
|
-
async apply(taskId, input, actor) {
|
|
96
|
+
async apply(taskId, input, actor, origin) {
|
|
95
97
|
const task = this.tasks.get(taskId);
|
|
96
98
|
if (!task)
|
|
97
99
|
throw new CollaborationError('TASK_NOT_FOUND', '任务不存在', 404);
|
|
98
100
|
this.group(task.groupId, actor);
|
|
99
101
|
this.validateMembers(task.groupId, input);
|
|
102
|
+
if (origin && task.ownerServiceId !== this.self)
|
|
103
|
+
throw new CollaborationError('INTEGRATION_LOCAL_ONLY', '首版集成任务须由本机服务保存', 409);
|
|
100
104
|
if (task.ownerServiceId !== this.self) {
|
|
101
105
|
const result = await this.peers.requestTasks(task.ownerServiceId, { op: 'apply', taskId, input, actorSessionId: actor?.sessionId ?? null });
|
|
102
106
|
this.tasks.merge(result.task, task.ownerServiceId);
|
|
@@ -126,7 +130,7 @@ export class CollaborationTaskService {
|
|
|
126
130
|
artifactId: child.acceptedArtifactId, integration: child.workflow?.integration === true,
|
|
127
131
|
commit: child.artifacts.find(a => a.id === child.acceptedArtifactId)?.evidence?.commit })) } };
|
|
128
132
|
}
|
|
129
|
-
const updated = this.tasks.apply(taskId, input, actor);
|
|
133
|
+
const updated = this.tasks.apply(taskId, input, actor, origin);
|
|
130
134
|
void this.flush();
|
|
131
135
|
return this.view(updated);
|
|
132
136
|
}
|
|
@@ -196,7 +200,7 @@ export class CollaborationTaskService {
|
|
|
196
200
|
const queued = this.messages.send({ groupId: group.id, fromSessionId: null, toSessionIds: [recipient.sessionId],
|
|
197
201
|
kind: packet.kind === 'task' ? 'task' : 'message', content: String(packet.content ?? ''), threadId: attempt?.threadId ?? task.id,
|
|
198
202
|
idempotencyKey: `task:${peer.serviceId}:${String(packet.outboxId)}`,
|
|
199
|
-
metadata: { taskOutboxId: packet.outboxId, termdockTask: { taskId: task.id, attemptId: attempt?.id ?? null, ownerServiceId: peer.serviceId } } });
|
|
203
|
+
metadata: { taskOutboxId: packet.outboxId, termdockTask: { taskId: task.id, attemptId: attempt?.id ?? null, ownerServiceId: peer.serviceId, replyToEventId: task.events.find(e => e.deliveryId === packet.outboxId && e.attemptId === attempt?.id && e.kind === 'comment')?.id } } });
|
|
200
204
|
this.deliver(recipient.sessionId);
|
|
201
205
|
return { receipt: this.receipt(queued[0].id) };
|
|
202
206
|
}
|
|
@@ -313,14 +317,16 @@ export class CollaborationTaskService {
|
|
|
313
317
|
if (!task?.workflow)
|
|
314
318
|
return true;
|
|
315
319
|
const root = task.workflow.rootTaskId ? this.tasks.get(task.workflow.rootTaskId) : task;
|
|
316
|
-
|
|
320
|
+
const consultation = outbox.replyToEventId && task.events.some(e => e.id === outbox.replyToEventId && e.kind === 'comment');
|
|
321
|
+
return consultation || !task.workflow.paused && !root?.workflow?.paused && root?.status === 'open';
|
|
317
322
|
}).slice(0, 16);
|
|
318
323
|
for (const outbox of ready) {
|
|
319
324
|
try {
|
|
320
325
|
const task = this.tasks.get(outbox.taskId);
|
|
321
326
|
this.group(task.groupId, outbox.target);
|
|
322
327
|
const root = task.workflow?.rootTaskId ? this.tasks.get(task.workflow.rootTaskId) : task;
|
|
323
|
-
|
|
328
|
+
const consultation = outbox.replyToEventId && task.events.some(e => e.id === outbox.replyToEventId && e.kind === 'comment');
|
|
329
|
+
if (task.workflow && !consultation && (task.workflow.paused || root?.workflow?.paused || root?.status !== 'open'))
|
|
324
330
|
continue;
|
|
325
331
|
if (outbox.target.serviceId === this.self) {
|
|
326
332
|
if (outbox.messageId && this.messages.getMessage(outbox.messageId)) {
|
|
@@ -330,7 +336,7 @@ export class CollaborationTaskService {
|
|
|
330
336
|
}
|
|
331
337
|
const queued = this.messages.send({ groupId: task.groupId, fromSessionId: null, toSessionIds: [outbox.target.sessionId],
|
|
332
338
|
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 } } });
|
|
339
|
+
metadata: { termdockTask: { taskId: task.id, attemptId: outbox.attemptId, ownerServiceId: this.self, replyToEventId: outbox.replyToEventId } } });
|
|
334
340
|
this.deliver(outbox.target.sessionId);
|
|
335
341
|
this.tasks.delivered(outbox.id, this.receipt(queued[0].id));
|
|
336
342
|
}
|