termdock 1.4.320 → 1.4.321
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-BF6YvbKL.js → App-VAvoVlm2.js} +27 -27
- package/dist/client/assets/App-VAvoVlm2.js.br +0 -0
- package/dist/client/assets/App-VAvoVlm2.js.gz +0 -0
- package/dist/client/assets/{ArchitecturePanel-D1Jca05w.js → ArchitecturePanel-BIlIOGx7.js} +2 -2
- package/dist/client/assets/ArchitecturePanel-BIlIOGx7.js.br +0 -0
- package/dist/client/assets/ArchitecturePanel-BIlIOGx7.js.gz +0 -0
- package/dist/client/assets/{ChangeWalkthroughPanel-B59JwhzK.js → ChangeWalkthroughPanel-BtXqyUzD.js} +1 -1
- package/dist/client/assets/ChangeWalkthroughPanel-BtXqyUzD.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-BtXqyUzD.js.gz +0 -0
- package/dist/client/assets/{CollaborationMainWorkspace-CS_o2iYt.js → CollaborationMainWorkspace-DUw3cqW-.js} +1 -1
- package/dist/client/assets/CollaborationMainWorkspace-DUw3cqW-.js.br +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-DUw3cqW-.js.gz +0 -0
- package/dist/client/assets/CollaborationTaskContent-C2sQQp6K.js +2 -0
- package/dist/client/assets/{ComputerControlView-CRquP12U.js → ComputerControlView-D81udDZO.js} +2 -2
- package/dist/client/assets/ComputerControlView-D81udDZO.js.br +0 -0
- package/dist/client/assets/ComputerControlView-D81udDZO.js.gz +0 -0
- package/dist/client/assets/{DagPlayground-CAfziHw_.js → DagPlayground-B3hTlIFu.js} +1 -1
- package/dist/client/assets/DagPlayground-B3hTlIFu.js.br +0 -0
- package/dist/client/assets/DagPlayground-B3hTlIFu.js.gz +0 -0
- package/dist/client/assets/{DiffLab-CPlA_7PJ.js → DiffLab-C5sDPAZ5.js} +1 -1
- package/dist/client/assets/DiffLab-C5sDPAZ5.js.br +0 -0
- package/dist/client/assets/DiffLab-C5sDPAZ5.js.gz +0 -0
- package/dist/client/assets/{DiffReview-CjEi6PCy.js → DiffReview-DQFgOJPF.js} +1 -1
- package/dist/client/assets/DiffReview-DQFgOJPF.js.br +0 -0
- package/dist/client/assets/DiffReview-DQFgOJPF.js.gz +0 -0
- package/dist/client/assets/{DiffReviewLab-BFRqRotl.js → DiffReviewLab-CZvBmujD.js} +1 -1
- package/dist/client/assets/DiffReviewLab-CZvBmujD.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-CZvBmujD.js.gz +0 -0
- package/dist/client/assets/{DiffViewer-Bh6lvUYN.js → DiffViewer-DOvGC9bh.js} +1 -1
- package/dist/client/assets/DiffViewer-DOvGC9bh.js.br +0 -0
- package/dist/client/assets/DiffViewer-DOvGC9bh.js.gz +0 -0
- package/dist/client/assets/{ModelPreview-D_WFk4yX.js → ModelPreview-ClKH4BQ7.js} +1 -1
- package/dist/client/assets/ModelPreview-ClKH4BQ7.js.br +0 -0
- package/dist/client/assets/ModelPreview-ClKH4BQ7.js.gz +0 -0
- package/dist/client/assets/{RightSidebar-7C9-PfhA.js → RightSidebar-BeegDfBO.js} +3 -3
- package/dist/client/assets/RightSidebar-BeegDfBO.js.br +0 -0
- package/dist/client/assets/RightSidebar-BeegDfBO.js.gz +0 -0
- package/dist/client/assets/{abnfDiagram-VCTEODGH-DDAdRY3H.js → abnfDiagram-VCTEODGH-CHUZIHQo.js} +1 -1
- package/dist/client/assets/abnfDiagram-VCTEODGH-CHUZIHQo.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-CHUZIHQo.js.gz +0 -0
- package/dist/client/assets/{app-BRESmgxW.js → app-Bj0N393t.js} +3 -3
- package/dist/client/assets/app-Bj0N393t.js.br +0 -0
- package/dist/client/assets/app-Bj0N393t.js.gz +0 -0
- package/dist/client/assets/{arc-CV9RqbOa.js → arc-CIJEXYV7.js} +1 -1
- package/dist/client/assets/arc-CIJEXYV7.js.br +0 -0
- package/dist/client/assets/arc-CIJEXYV7.js.gz +0 -0
- package/dist/client/assets/{architectureDiagram-5GKGNRK7-Ct8CtmBh.js → architectureDiagram-5GKGNRK7-CcX1UBXG.js} +1 -1
- package/dist/client/assets/architectureDiagram-5GKGNRK7-CcX1UBXG.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-CcX1UBXG.js.gz +0 -0
- package/dist/client/assets/{blockDiagram-I7D4REHJ-CVjuOZ0h.js → blockDiagram-I7D4REHJ-gDLrIBDk.js} +1 -1
- package/dist/client/assets/blockDiagram-I7D4REHJ-gDLrIBDk.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-gDLrIBDk.js.gz +0 -0
- package/dist/client/assets/{c4Diagram-7LVT6UL2-CSKcN0J-.js → c4Diagram-7LVT6UL2-BQA7WLEL.js} +1 -1
- package/dist/client/assets/{c4Diagram-7LVT6UL2-CSKcN0J-.js.br → c4Diagram-7LVT6UL2-BQA7WLEL.js.br} +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-BQA7WLEL.js.gz +0 -0
- package/dist/client/assets/channel-OHMJip5O.js +1 -0
- package/dist/client/assets/{chunk-2Q5K7J3B-CF6SP9Cv.js → chunk-2Q5K7J3B-CPCY618J.js} +1 -1
- package/dist/client/assets/{chunk-5VM5RSS4-DZhLGwG4.js → chunk-5VM5RSS4-Cc3Czx6A.js} +1 -1
- package/dist/client/assets/{chunk-F27PBJKO-CwqjUNpz.js → chunk-F27PBJKO-3scxqZTK.js} +1 -1
- package/dist/client/assets/chunk-F27PBJKO-3scxqZTK.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-3scxqZTK.js.gz +0 -0
- package/dist/client/assets/{chunk-IMKFNOWR-C9WCfeN9.js → chunk-IMKFNOWR-BOCOE1VY.js} +1 -1
- package/dist/client/assets/chunk-IMKFNOWR-BOCOE1VY.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-BOCOE1VY.js.gz +0 -0
- package/dist/client/assets/{chunk-JWPE2WC7-DUIVW6rN.js → chunk-JWPE2WC7-DX2Onu68.js} +1 -1
- package/dist/client/assets/{chunk-POPQ4Y6H-YgwJ3iH4.js → chunk-POPQ4Y6H-C4MN3QRd.js} +1 -1
- package/dist/client/assets/{chunk-SVP7TREG-A-vVSOuv.js → chunk-SVP7TREG-DOKo3BNt.js} +1 -1
- package/dist/client/assets/chunk-SVP7TREG-DOKo3BNt.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-DOKo3BNt.js.gz +0 -0
- package/dist/client/assets/{chunk-TICWLB2K-akdXuwgx.js → chunk-TICWLB2K-CPpFFmO9.js} +1 -1
- package/dist/client/assets/chunk-TICWLB2K-CPpFFmO9.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-CPpFFmO9.js.gz +0 -0
- package/dist/client/assets/{chunk-XXDRQBXY-Da273BkJ.js → chunk-XXDRQBXY-Zp_XOFU2.js} +1 -1
- package/dist/client/assets/classDiagram-ZZMXUADV-DwA5mGyC.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-DwA5mGyC.js +1 -0
- package/dist/client/assets/{cose-bilkent-JH36ORCC-CGfQhg7T.js → cose-bilkent-JH36ORCC-iYXdWZMG.js} +1 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-iYXdWZMG.js.br +0 -0
- package/dist/client/assets/{cose-bilkent-JH36ORCC-CGfQhg7T.js.gz → cose-bilkent-JH36ORCC-iYXdWZMG.js.gz} +0 -0
- package/dist/client/assets/{cynefin-OW5HDTMX-C9RaJCMn.js → cynefin-OW5HDTMX-CXRpxmcA.js} +1 -1
- package/dist/client/assets/cynefin-OW5HDTMX-CXRpxmcA.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-CXRpxmcA.js.gz +0 -0
- package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-C6SWqaZK.js → cynefinDiagram-5FMLGOSQ-CH1TQhgO.js} +1 -1
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CH1TQhgO.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CH1TQhgO.js.gz +0 -0
- package/dist/client/assets/{dagre-GXQ25YYZ-DTMtzPmS.js → dagre-GXQ25YYZ-BdshuKJr.js} +1 -1
- package/dist/client/assets/dagre-GXQ25YYZ-BdshuKJr.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-BdshuKJr.js.gz +0 -0
- package/dist/client/assets/{diagram-S7CK7UJ4-CRalzYBW.js → diagram-S7CK7UJ4-VbNBimIR.js} +1 -1
- package/dist/client/assets/diagram-S7CK7UJ4-VbNBimIR.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-VbNBimIR.js.gz +0 -0
- package/dist/client/assets/{diagram-UQ7AKVKN-B5qxEH5p.js → diagram-UQ7AKVKN-D_NUFcq3.js} +1 -1
- package/dist/client/assets/diagram-UQ7AKVKN-D_NUFcq3.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-D_NUFcq3.js.gz +0 -0
- package/dist/client/assets/{diagram-VSXAHHWV-CPSmBWU-.js → diagram-VSXAHHWV-CfYRQ4mq.js} +1 -1
- package/dist/client/assets/diagram-VSXAHHWV-CfYRQ4mq.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-CfYRQ4mq.js.gz +0 -0
- package/dist/client/assets/{diagram-VX7I27RA-CU8A_voC.js → diagram-VX7I27RA-YHy6vMjY.js} +1 -1
- package/dist/client/assets/diagram-VX7I27RA-YHy6vMjY.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-YHy6vMjY.js.gz +0 -0
- package/dist/client/assets/{diagram-Z3DM3KII-CtT4QOY-.js → diagram-Z3DM3KII-DvHqYL0O.js} +1 -1
- package/dist/client/assets/diagram-Z3DM3KII-DvHqYL0O.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-DvHqYL0O.js.gz +0 -0
- package/dist/client/assets/{ebnfDiagram-PWID7BFC-Cvk6Y8JV.js → ebnfDiagram-PWID7BFC-Bl9bDxAP.js} +1 -1
- package/dist/client/assets/ebnfDiagram-PWID7BFC-Bl9bDxAP.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-Bl9bDxAP.js.gz +0 -0
- package/dist/client/assets/{erDiagram-RLTQ6QDP-_9Ct2AHs.js → erDiagram-RLTQ6QDP-DauNoBZZ.js} +1 -1
- package/dist/client/assets/erDiagram-RLTQ6QDP-DauNoBZZ.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-DauNoBZZ.js.gz +0 -0
- package/dist/client/assets/{flowDiagram-HODETNUW-BR29aDF_.js → flowDiagram-HODETNUW-D6eDWfJY.js} +1 -1
- package/dist/client/assets/flowDiagram-HODETNUW-D6eDWfJY.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-D6eDWfJY.js.gz +0 -0
- package/dist/client/assets/{ganttDiagram-EL5Y4UJY-BvVG7ism.js → ganttDiagram-EL5Y4UJY-CWHSwTR6.js} +1 -1
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-CWHSwTR6.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-CWHSwTR6.js.gz +0 -0
- package/dist/client/assets/{gestureArbiter-DalDKZKj.js → gestureArbiter-nU4jhK3S.js} +1 -1
- package/dist/client/assets/gestureArbiter-nU4jhK3S.js.br +0 -0
- package/dist/client/assets/gestureArbiter-nU4jhK3S.js.gz +0 -0
- package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-BHOjoasY.js → gitGraphDiagram-WWUBYQGX-BHYt5-_X.js} +1 -1
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BHYt5-_X.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BHYt5-_X.js.gz +0 -0
- package/dist/client/assets/{infoDiagram-27XIBGKW-DgmnLtPV.js → infoDiagram-27XIBGKW-DPmlcUaZ.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-DoiUx_u1.js → ishikawaDiagram-5VMMS53U-DAn65XKZ.js} +1 -1
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-DAn65XKZ.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-DAn65XKZ.js.gz +0 -0
- package/dist/client/assets/{journeyDiagram-3NMN7TZE-sz2KwGQ4.js → journeyDiagram-3NMN7TZE-B2c5x9jb.js} +1 -1
- package/dist/client/assets/journeyDiagram-3NMN7TZE-B2c5x9jb.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-B2c5x9jb.js.gz +0 -0
- package/dist/client/assets/{kanban-definition-UXKFOSKX-CdAnN6NF.js → kanban-definition-UXKFOSKX-CMeEp_9r.js} +1 -1
- package/dist/client/assets/kanban-definition-UXKFOSKX-CMeEp_9r.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-CMeEp_9r.js.gz +0 -0
- package/dist/client/assets/{layout-7mCqPnQ2.js → layout-Db99ysGT.js} +1 -1
- package/dist/client/assets/layout-Db99ysGT.js.br +0 -0
- package/dist/client/assets/layout-Db99ysGT.js.gz +0 -0
- package/dist/client/assets/{linear-CtGxEwoA.js → linear-B6mREmTG.js} +1 -1
- package/dist/client/assets/linear-B6mREmTG.js.br +0 -0
- package/dist/client/assets/linear-B6mREmTG.js.gz +0 -0
- package/dist/client/assets/{mermaid.core-BxJ2mx92.js → mermaid.core-DndzUmju.js} +5 -5
- package/dist/client/assets/mermaid.core-DndzUmju.js.br +0 -0
- package/dist/client/assets/mermaid.core-DndzUmju.js.gz +0 -0
- package/dist/client/assets/{mindmap-definition-YA3MSWOX-Ck2pdDVb.js → mindmap-definition-YA3MSWOX-qYAlDvc4.js} +1 -1
- package/dist/client/assets/mindmap-definition-YA3MSWOX-qYAlDvc4.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-qYAlDvc4.js.gz +0 -0
- package/dist/client/assets/{passwordBootstrap-gTJ9KuKa.js → passwordBootstrap-DaJXVcdB.js} +1 -1
- package/dist/client/assets/passwordBootstrap-DaJXVcdB.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-DaJXVcdB.js.gz +0 -0
- package/dist/client/assets/{pegDiagram-XKGWAZYB-CYBdOhd0.js → pegDiagram-XKGWAZYB-Dg5DCFIn.js} +1 -1
- package/dist/client/assets/pegDiagram-XKGWAZYB-Dg5DCFIn.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-Dg5DCFIn.js.gz +0 -0
- package/dist/client/assets/{pieDiagram-E7YTZNPT-IxFUaefz.js → pieDiagram-E7YTZNPT-dje1AAFI.js} +1 -1
- package/dist/client/assets/pieDiagram-E7YTZNPT-dje1AAFI.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-dje1AAFI.js.gz +0 -0
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-CSirkHeE.js → quadrantDiagram-AXDQQJYC-DLXI6hrS.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-CSirkHeE.js.br → quadrantDiagram-AXDQQJYC-DLXI6hrS.js.br} +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-DLXI6hrS.js.gz +0 -0
- package/dist/client/assets/{railroadDiagram-O6MQD6OU-CYoi1Ctl.js → railroadDiagram-O6MQD6OU-DcY-P8Q_.js} +1 -1
- package/dist/client/assets/railroadDiagram-O6MQD6OU-DcY-P8Q_.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-DcY-P8Q_.js.gz +0 -0
- package/dist/client/assets/{rdpSession-BQ_xI5BI.js → rdpSession-JkZuPKb3.js} +1 -1
- package/dist/client/assets/rdpSession-JkZuPKb3.js.br +0 -0
- package/dist/client/assets/rdpSession-JkZuPKb3.js.gz +0 -0
- package/dist/client/assets/{referenceLongPress-DfQ5jnsk.js → referenceLongPress-CR3uo3V0.js} +1 -1
- package/dist/client/assets/referenceLongPress-CR3uo3V0.js.br +0 -0
- package/dist/client/assets/referenceLongPress-CR3uo3V0.js.gz +0 -0
- package/dist/client/assets/{requirementDiagram-BXWQKSXE-BCoG9aBY.js → requirementDiagram-BXWQKSXE-B-GLzS7h.js} +1 -1
- package/dist/client/assets/requirementDiagram-BXWQKSXE-B-GLzS7h.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-B-GLzS7h.js.gz +0 -0
- package/dist/client/assets/{sankeyDiagram-P5KCCOFB-BM0bKWHQ.js → sankeyDiagram-P5KCCOFB-CINtGjgu.js} +1 -1
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-CINtGjgu.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-CINtGjgu.js.gz +0 -0
- package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-CVc-3QVK.js → sequenceDiagram-WJ2MYXX4-BRE-_raI.js} +1 -1
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-BRE-_raI.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-BRE-_raI.js.gz +0 -0
- package/dist/client/assets/{sizeCapture-INFHLROL-70GusSOh.js → sizeCapture-INFHLROL-v2bGYNk3.js} +1 -1
- package/dist/client/assets/sizeCapture-INFHLROL-v2bGYNk3.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-v2bGYNk3.js.gz +0 -0
- package/dist/client/assets/{sparkles-DbcgKKVd.js → sparkles-Dx518Xui.js} +1 -1
- package/dist/client/assets/{stateDiagram-D77RDMKH-BCw-OQPL.js → stateDiagram-D77RDMKH-CIQ1zGkb.js} +1 -1
- package/dist/client/assets/stateDiagram-D77RDMKH-CIQ1zGkb.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-CIQ1zGkb.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-DCGuhzdh.js +1 -0
- package/dist/client/assets/{swimlanes-42K2YHIH--yebjz0I.js → swimlanes-42K2YHIH-DEjGaJr6.js} +1 -1
- package/dist/client/assets/swimlanes-42K2YHIH-DEjGaJr6.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-DEjGaJr6.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-Bj14fTzZ.js +8 -0
- package/dist/client/assets/{timeline-definition-24CTP7MA-B9_XXo4h.js → timeline-definition-24CTP7MA-BPbZrudq.js} +1 -1
- package/dist/client/assets/timeline-definition-24CTP7MA-BPbZrudq.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-BPbZrudq.js.gz +0 -0
- package/dist/client/assets/{triangle-alert-DG_BJhJY.js → triangle-alert-CVm2qdGE.js} +1 -1
- package/dist/client/assets/{vennDiagram-4TSXK5OY-BjYW4tQw.js → vennDiagram-4TSXK5OY-CAsKNSfN.js} +1 -1
- package/dist/client/assets/vennDiagram-4TSXK5OY-CAsKNSfN.js.br +0 -0
- package/dist/client/assets/{vennDiagram-4TSXK5OY-BjYW4tQw.js.gz → vennDiagram-4TSXK5OY-CAsKNSfN.js.gz} +0 -0
- package/dist/client/assets/{videoCompression-DrYmE1Ed.js → videoCompression-CCOgxfhm.js} +1 -1
- package/dist/client/assets/videoCompression-CCOgxfhm.js.br +0 -0
- package/dist/client/assets/videoCompression-CCOgxfhm.js.gz +0 -0
- package/dist/client/assets/{wardleyDiagram-VM6X3IG4-DNVW8Yot.js → wardleyDiagram-VM6X3IG4-EeabO9yU.js} +1 -1
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-EeabO9yU.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-EeabO9yU.js.gz +0 -0
- package/dist/client/assets/{xychartDiagram-S5SC5T6Z-l7gJBKpK.js → xychartDiagram-S5SC5T6Z-MSUoQl2z.js} +1 -1
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-MSUoQl2z.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-MSUoQl2z.js.gz +0 -0
- package/dist/client/index.html +1 -1
- 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 +25 -2
- package/dist/server/agent/collaborationDeliveryWorker.js +27 -8
- package/dist/server/agent/collaborationPeerTransport.js +3 -2
- package/dist/server/agent/collaborationRoutes.js +12 -1
- package/dist/server/agent/collaborationRouting.js +32 -0
- package/dist/server/agent/collaborationStore.js +27 -1
- package/dist/server/agent/sessionBindingRecovery.js +1 -1
- package/dist/server/routes/terminal.js +80 -13
- package/docs/integrations.md +73 -0
- package/package.json +1 -1
- package/runtime-manifest.json +3 -3
- package/dist/client/assets/App-BF6YvbKL.js.br +0 -0
- package/dist/client/assets/App-BF6YvbKL.js.gz +0 -0
- package/dist/client/assets/ArchitecturePanel-D1Jca05w.js.br +0 -0
- package/dist/client/assets/ArchitecturePanel-D1Jca05w.js.gz +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-B59JwhzK.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-B59JwhzK.js.gz +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-CS_o2iYt.js.br +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-CS_o2iYt.js.gz +0 -0
- package/dist/client/assets/CollaborationTaskContent-WQ5CC-0d.js +0 -2
- package/dist/client/assets/ComputerControlView-CRquP12U.js.br +0 -0
- package/dist/client/assets/ComputerControlView-CRquP12U.js.gz +0 -0
- package/dist/client/assets/DagPlayground-CAfziHw_.js.br +0 -0
- package/dist/client/assets/DagPlayground-CAfziHw_.js.gz +0 -0
- package/dist/client/assets/DiffLab-CPlA_7PJ.js.br +0 -0
- package/dist/client/assets/DiffLab-CPlA_7PJ.js.gz +0 -0
- package/dist/client/assets/DiffReview-CjEi6PCy.js.br +0 -0
- package/dist/client/assets/DiffReview-CjEi6PCy.js.gz +0 -0
- package/dist/client/assets/DiffReviewLab-BFRqRotl.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-BFRqRotl.js.gz +0 -0
- package/dist/client/assets/DiffViewer-Bh6lvUYN.js.br +0 -0
- package/dist/client/assets/DiffViewer-Bh6lvUYN.js.gz +0 -0
- package/dist/client/assets/ModelPreview-D_WFk4yX.js.br +0 -0
- package/dist/client/assets/ModelPreview-D_WFk4yX.js.gz +0 -0
- package/dist/client/assets/RightSidebar-7C9-PfhA.js.br +0 -0
- package/dist/client/assets/RightSidebar-7C9-PfhA.js.gz +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-DDAdRY3H.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-DDAdRY3H.js.gz +0 -0
- package/dist/client/assets/app-BRESmgxW.js.br +0 -0
- package/dist/client/assets/app-BRESmgxW.js.gz +0 -0
- package/dist/client/assets/arc-CV9RqbOa.js.br +0 -0
- package/dist/client/assets/arc-CV9RqbOa.js.gz +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-Ct8CtmBh.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-Ct8CtmBh.js.gz +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-CVjuOZ0h.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-CVjuOZ0h.js.gz +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-CSKcN0J-.js.gz +0 -0
- package/dist/client/assets/channel-BDjp8qZS.js +0 -1
- package/dist/client/assets/chunk-F27PBJKO-CwqjUNpz.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-CwqjUNpz.js.gz +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-C9WCfeN9.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-C9WCfeN9.js.gz +0 -0
- package/dist/client/assets/chunk-SVP7TREG-A-vVSOuv.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-A-vVSOuv.js.gz +0 -0
- package/dist/client/assets/chunk-TICWLB2K-akdXuwgx.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-akdXuwgx.js.gz +0 -0
- package/dist/client/assets/classDiagram-ZZMXUADV-CkFBQKLs.js +0 -1
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-CkFBQKLs.js +0 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-CGfQhg7T.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-C9RaJCMn.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-C9RaJCMn.js.gz +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-C6SWqaZK.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-C6SWqaZK.js.gz +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-DTMtzPmS.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-DTMtzPmS.js.gz +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-CRalzYBW.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-CRalzYBW.js.gz +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-B5qxEH5p.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-B5qxEH5p.js.gz +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-CPSmBWU-.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-CPSmBWU-.js.gz +0 -0
- package/dist/client/assets/diagram-VX7I27RA-CU8A_voC.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-CU8A_voC.js.gz +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-CtT4QOY-.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-CtT4QOY-.js.gz +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-Cvk6Y8JV.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-Cvk6Y8JV.js.gz +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-_9Ct2AHs.js.br +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-_9Ct2AHs.js.gz +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-BR29aDF_.js.br +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-BR29aDF_.js.gz +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-BvVG7ism.js.br +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-BvVG7ism.js.gz +0 -0
- package/dist/client/assets/gestureArbiter-DalDKZKj.js.br +0 -0
- package/dist/client/assets/gestureArbiter-DalDKZKj.js.gz +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BHOjoasY.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BHOjoasY.js.gz +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-DoiUx_u1.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-DoiUx_u1.js.gz +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-sz2KwGQ4.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-sz2KwGQ4.js.gz +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-CdAnN6NF.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-CdAnN6NF.js.gz +0 -0
- package/dist/client/assets/layout-7mCqPnQ2.js.br +0 -0
- package/dist/client/assets/layout-7mCqPnQ2.js.gz +0 -0
- package/dist/client/assets/linear-CtGxEwoA.js.br +0 -0
- package/dist/client/assets/linear-CtGxEwoA.js.gz +0 -0
- package/dist/client/assets/mermaid.core-BxJ2mx92.js.br +0 -0
- package/dist/client/assets/mermaid.core-BxJ2mx92.js.gz +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-Ck2pdDVb.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-Ck2pdDVb.js.gz +0 -0
- package/dist/client/assets/passwordBootstrap-gTJ9KuKa.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-gTJ9KuKa.js.gz +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-CYBdOhd0.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-CYBdOhd0.js.gz +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-IxFUaefz.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-IxFUaefz.js.gz +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-CSirkHeE.js.gz +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-CYoi1Ctl.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-CYoi1Ctl.js.gz +0 -0
- package/dist/client/assets/rdpSession-BQ_xI5BI.js.br +0 -0
- package/dist/client/assets/rdpSession-BQ_xI5BI.js.gz +0 -0
- package/dist/client/assets/referenceLongPress-DfQ5jnsk.js.br +0 -0
- package/dist/client/assets/referenceLongPress-DfQ5jnsk.js.gz +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-BCoG9aBY.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-BCoG9aBY.js.gz +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BM0bKWHQ.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-BM0bKWHQ.js.gz +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-CVc-3QVK.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-CVc-3QVK.js.gz +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-70GusSOh.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-70GusSOh.js.gz +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-BCw-OQPL.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-BCw-OQPL.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-C2WqSO6X.js +0 -1
- package/dist/client/assets/swimlanes-42K2YHIH--yebjz0I.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH--yebjz0I.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-Cyxi7gqq.js +0 -8
- package/dist/client/assets/timeline-definition-24CTP7MA-B9_XXo4h.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-B9_XXo4h.js.gz +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-BjYW4tQw.js.br +0 -0
- package/dist/client/assets/videoCompression-DrYmE1Ed.js.br +0 -0
- package/dist/client/assets/videoCompression-DrYmE1Ed.js.gz +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-DNVW8Yot.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-DNVW8Yot.js.gz +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-l7gJBKpK.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-l7gJBKpK.js.gz +0 -0
|
@@ -10,7 +10,7 @@ import { COLLAB_LIMITS, CollaborationError, MIN_ID_PREFIX_LENGTH, ambiguousIdMes
|
|
|
10
10
|
export function cleanMemberName(value) {
|
|
11
11
|
return value.replace(/[\u0000-\u001f\u007f]/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 80);
|
|
12
12
|
}
|
|
13
|
-
export function collaborationRoutes({ store, resolveSession, deliver, rebind, resolveNames, renameSession }) {
|
|
13
|
+
export function collaborationRoutes({ store, resolveSession, deliver, rebind, diagnoseRoute, resolveNames, renameSession }) {
|
|
14
14
|
const router = Router();
|
|
15
15
|
const run = (handler) => async (req, res) => {
|
|
16
16
|
try {
|
|
@@ -96,6 +96,16 @@ export function collaborationRoutes({ store, resolveSession, deliver, rebind, re
|
|
|
96
96
|
}
|
|
97
97
|
res.json({ ok: true, route: await rebind(sessionId, pane ?? null) });
|
|
98
98
|
}));
|
|
99
|
+
router.get('/route/:id', run(async (req, res, sessionId) => {
|
|
100
|
+
const id = String(req.params.id);
|
|
101
|
+
if (id !== sessionId && !store.groupsForSession(sessionId).some(group => group.sessionIds.includes(id)))
|
|
102
|
+
throw new CollaborationError('NOT_A_GROUP_MEMBER', 'Route diagnostics require a shared group', 403);
|
|
103
|
+
if (id.startsWith('remote:'))
|
|
104
|
+
throw new CollaborationError('REMOTE_ROUTE_DIAGNOSTICS_UNSUPPORTED', 'Query the owning service for the current runtime evidence', 409);
|
|
105
|
+
if (!diagnoseRoute)
|
|
106
|
+
throw new CollaborationError('ROUTE_DIAGNOSTICS_UNAVAILABLE', 'The running service does not support route diagnostics (minimum 1.4.321)', 409);
|
|
107
|
+
res.json({ ok: true, route: await diagnoseRoute(id) });
|
|
108
|
+
}));
|
|
99
109
|
/** Accepts the short id a terminal shows as well as the full one; an
|
|
100
110
|
* ambiguous prefix is refused rather than guessed, so a reply can never
|
|
101
111
|
* land on the wrong thread. */
|
|
@@ -152,6 +162,7 @@ export function collaborationRoutes({ store, resolveSession, deliver, rebind, re
|
|
|
152
162
|
};
|
|
153
163
|
router.get('/capabilities', run((_req, res) => {
|
|
154
164
|
res.json({ protocol_version: 2, server_version: getTermdockVersion(), limits: COLLAB_LIMITS,
|
|
165
|
+
route_diagnostics: !!diagnoseRoute, route_identity_recovery: !!diagnoseRoute, route_identity_recovery_min_version: '1.4.321',
|
|
155
166
|
task_workflow: { version: 2, command: 'td collab task', single_authority: true, explicit_reports: true,
|
|
156
167
|
managed_goals: true, automatic_review: true, dependency_dispatch: true, isolated_worktrees: true, encrypted_commit_transfer: true,
|
|
157
168
|
durable_questions: true, user_acceptance: true, versioned_artifacts: true, independent_reviews: true,
|
|
@@ -17,6 +17,11 @@ export class CollaborationRoutingStore {
|
|
|
17
17
|
|| !/^%\d+$/.test(binding.pane.paneId) || !/^\$\d+$/.test(binding.pane.sessionId) || typeof binding.pane.agentSlug !== 'string'))) {
|
|
18
18
|
throw new Error('Invalid collaboration binding');
|
|
19
19
|
}
|
|
20
|
+
if (binding.routeRevision !== undefined && (typeof binding.routeRevision !== 'string' || !/^[a-zA-Z0-9-]{1,80}$/.test(binding.routeRevision)))
|
|
21
|
+
throw new Error('Invalid route revision');
|
|
22
|
+
if (binding.lastRecovery !== undefined && (!binding.lastRecovery || !['native-identity', 'owner-confirmed'].includes(binding.lastRecovery.kind)
|
|
23
|
+
|| !Number.isSafeInteger(binding.lastRecovery.at)))
|
|
24
|
+
throw new Error('Invalid route recovery record');
|
|
20
25
|
this.bindings.set(binding.sessionId, binding);
|
|
21
26
|
}
|
|
22
27
|
}
|
|
@@ -38,6 +43,10 @@ export class CollaborationRoutingStore {
|
|
|
38
43
|
ownerOfBackend(id) {
|
|
39
44
|
return [...this.bindings.values()].find((binding) => binding.backendSessionId === id)?.sessionId ?? null;
|
|
40
45
|
}
|
|
46
|
+
hasOtherPaneOwner(id, pane) {
|
|
47
|
+
return [...this.bindings.values()].some(binding => binding.sessionId !== id && binding.pane
|
|
48
|
+
&& binding.pane.serverPid === pane.serverPid && binding.pane.sessionId === pane.sessionId && binding.pane.paneId === pane.paneId);
|
|
49
|
+
}
|
|
41
50
|
bind(binding) {
|
|
42
51
|
this.assertReadable();
|
|
43
52
|
const owner = binding.backendSessionId ? this.ownerOfBackend(binding.backendSessionId) : null;
|
|
@@ -65,6 +74,29 @@ export class CollaborationRoutingStore {
|
|
|
65
74
|
this.bindings = next;
|
|
66
75
|
}
|
|
67
76
|
}
|
|
77
|
+
export function assessCollaborationRouteIdentity(binding, panes, ownershipConfirmed, unconfirmedWrite) {
|
|
78
|
+
const selected = selectCollaborationPane(binding, panes);
|
|
79
|
+
const metadata = (pane) => ({ serverPid: pane.serverPid, sessionId: pane.sessionId,
|
|
80
|
+
paneId: pane.paneId, panePid: pane.panePid, agentSlug: pane.agentSlug, nativeSessionId: pane.nativeSessionId });
|
|
81
|
+
const diagnostics = { expected: binding.pane ? { ...binding.pane } : null,
|
|
82
|
+
observed: panes.slice(0, 20).map(pane => ({ ...metadata(pane), nativeIdentitySource: pane.nativeIdentitySource ?? null, nativeIdentityFailure: pane.nativeIdentityFailure ?? null, nativeIdentityVerified: pane.nativeIdentityVerified === true })),
|
|
83
|
+
truncated: panes.length > 20, recovery: 'unchanged', reason: null,
|
|
84
|
+
rebind_command: `td collab --session ${binding.sessionId} rebind${panes.length === 1 ? ` --pane ${panes[0].paneId}` : ''}` };
|
|
85
|
+
if (selected.state !== 'identity-mismatch')
|
|
86
|
+
return { ...selected, diagnostics };
|
|
87
|
+
const nativeId = binding.pane?.nativeSessionId ?? binding.nativeSessionId;
|
|
88
|
+
const slug = binding.pane?.agentSlug || binding.agentSlug;
|
|
89
|
+
const matching = panes.filter(pane => !pane.isShell && pane.agentSlug === slug && pane.nativeSessionId === nativeId
|
|
90
|
+
&& !pane.nativeIdentityFailure && pane.nativeIdentityVerified === true);
|
|
91
|
+
diagnostics.recovery = 'confirmation-required';
|
|
92
|
+
diagnostics.reason = unconfirmedWrite ? 'DELIVERY_OUTCOME_UNCONFIRMED' : !ownershipConfirmed ? 'ROUTE_OWNERSHIP_UNCONFIRMED'
|
|
93
|
+
: !nativeId || !slug ? 'NATIVE_IDENTITY_UNCONFIRMED' : matching.length > 1 ? 'MULTIPLE_NATIVE_IDENTITY_MATCHES'
|
|
94
|
+
: matching.length !== 1 ? 'NATIVE_IDENTITY_UNCONFIRMED' : null;
|
|
95
|
+
if (diagnostics.reason)
|
|
96
|
+
return { ...selected, diagnostics };
|
|
97
|
+
diagnostics.recovery = 'automatic';
|
|
98
|
+
return { state: 'ready', pane: matching[0], diagnostics };
|
|
99
|
+
}
|
|
68
100
|
// Once pinned, changing the active pane cannot change the recipient. A reused
|
|
69
101
|
// tmux name/pane after a server restart must not inherit an old peer's inbox.
|
|
70
102
|
export function selectCollaborationPane(binding, panes) {
|
|
@@ -584,6 +584,10 @@ export class CollaborationStore {
|
|
|
584
584
|
this.expire();
|
|
585
585
|
return [...new Set(this.document.messages.filter((message) => message.status === 'pending').map((message) => message.toSessionId))];
|
|
586
586
|
}
|
|
587
|
+
hasUnconfirmedDelivery(sessionId) {
|
|
588
|
+
return this.document.messages.some(message => message.toSessionId === sessionId && message.status === 'pending'
|
|
589
|
+
&& (this.document.transport?.[message.id]?.attempt_count ?? 0) > 0);
|
|
590
|
+
}
|
|
587
591
|
confirmShell(messageId) {
|
|
588
592
|
const message = this.getMessage(messageId);
|
|
589
593
|
if (!message || message.status !== 'pending')
|
|
@@ -773,6 +777,25 @@ export class CollaborationStore {
|
|
|
773
777
|
(this.document.transport ??= {})[id] = diagnostic;
|
|
774
778
|
this.persist();
|
|
775
779
|
}
|
|
780
|
+
/** A route blocks the whole recipient queue, not just its first message. */
|
|
781
|
+
recordRecipientTransport(sessionId, patch) {
|
|
782
|
+
let changed = false;
|
|
783
|
+
for (const message of this.document.messages) {
|
|
784
|
+
if (message.toSessionId !== sessionId || message.status !== 'pending')
|
|
785
|
+
continue;
|
|
786
|
+
const previous = this.document.transport?.[message.id];
|
|
787
|
+
if ((previous?.checked_at ?? 0) > patch.checked_at)
|
|
788
|
+
continue;
|
|
789
|
+
const next = { relay_online: null, peer_reachable: null, next_retry_at: null, last_error: null,
|
|
790
|
+
...previous, ...patch, attempt_count: previous?.attempt_count ?? 0 };
|
|
791
|
+
if (JSON.stringify(previous) === JSON.stringify(next))
|
|
792
|
+
continue;
|
|
793
|
+
(this.document.transport ??= {})[message.id] = next;
|
|
794
|
+
changed = true;
|
|
795
|
+
}
|
|
796
|
+
if (changed)
|
|
797
|
+
this.persist();
|
|
798
|
+
}
|
|
776
799
|
receipt(id, raw = false) {
|
|
777
800
|
const message = this.getMessage(id);
|
|
778
801
|
if (!message)
|
|
@@ -788,7 +811,10 @@ export class CollaborationStore {
|
|
|
788
811
|
failure_reason: message.failureReason ?? null, delivery_semantics: message.status === 'stored' ? 'durable_storage' : facts.deliverySource ?? (facts.deliveredAt === null ? 'not_delivered' : 'legacy_or_unspecified'),
|
|
789
812
|
snapshot: message.snapshot ? (raw ? message.snapshot : plainCollaborationSnapshot(message.snapshot)) : null,
|
|
790
813
|
delivery: { status: facts.status,
|
|
791
|
-
stage: message.status === 'stored' ? 'stored' : facts.deliveredAt !== null ? 'terminal_written' : diagnostic?.remote_received_at ? 'remote_received' : 'queued',
|
|
814
|
+
stage: message.status === 'stored' ? 'stored' : facts.deliveredAt !== null ? 'terminal_written' : diagnostic?.route_state === 'identity-mismatch' || diagnostic?.last_error === 'TMUX_PANE_CHANGED' ? 'blocked' : diagnostic?.remote_received_at ? 'remote_received' : 'queued',
|
|
815
|
+
...(!diagnostic?.route_diagnostics && diagnostic?.last_error === 'TMUX_PANE_CHANGED' ? { requires_confirmation: true } : {}),
|
|
816
|
+
...(diagnostic?.route_diagnostics ? { route: diagnostic.route_diagnostics, route_state: diagnostic.route_state,
|
|
817
|
+
requires_confirmation: diagnostic.route_diagnostics.recovery === 'confirmation-required' } : {}),
|
|
792
818
|
remote_received_at: diagnostic?.remote_received_at ?? null, delivered_at: facts.deliveredAt, error: message.failureReason ?? diagnostic?.last_error ?? null },
|
|
793
819
|
reply: { status: replies.length ? 'received' : 'pending', ack_at: replies.find(reply => reply.responseKind === 'ack')?.createdAt ?? null, reply_ids: replies.map(reply => reply.id) },
|
|
794
820
|
idempotency_key: message.idempotencyKey ?? null,
|
|
@@ -39,7 +39,7 @@ export function resolveCollaborationBackend(record, records, backends, routing)
|
|
|
39
39
|
return null;
|
|
40
40
|
if (records.some((other) => other.sessionId !== record.sessionId && other.backendSessionId === id))
|
|
41
41
|
return null;
|
|
42
|
-
routing.bind({ sessionId: record.sessionId, backendSessionId: id, mode: backend.mode,
|
|
42
|
+
routing.bind({ ...binding, sessionId: record.sessionId, backendSessionId: id, mode: backend.mode,
|
|
43
43
|
tmuxSessionName: backend.tmuxSessionName,
|
|
44
44
|
agentSlug: binding?.agentSlug ?? backend.agent?.slug ?? record.agentResume?.slug ?? null,
|
|
45
45
|
nativeSessionId: binding?.nativeSessionId ?? backend.agentSession?.sessionId ?? record.agentResume?.sessionId ?? null,
|
|
@@ -66,7 +66,7 @@ import { SessionSearchStore } from '../agent/sessionSearchStore.js';
|
|
|
66
66
|
import { NativeSessionSearch } from '../agent/nativeSessionSearch.js';
|
|
67
67
|
import { CollaborationError } from '../agent/collaborationProtocol.js';
|
|
68
68
|
import { resolveCollaborationBackend, resolveCollaborationSessionId } from '../agent/sessionBindingRecovery.js';
|
|
69
|
-
import { CollaborationRoutingStore, selectCollaborationPane, selectDrivePane } from '../agent/collaborationRouting.js';
|
|
69
|
+
import { CollaborationRoutingStore, selectCollaborationPane, selectDrivePane, assessCollaborationRouteIdentity } from '../agent/collaborationRouting.js';
|
|
70
70
|
import { CollaborationDeliveryWorker } from '../agent/collaborationDeliveryWorker.js';
|
|
71
71
|
import { approveCollaborationDialog, captureTmuxPaneHistory, captureTmuxPaneText, sendTmuxPaneKey, writeCollaborationTmuxPane } from '../agent/collaborationTmuxDelivery.js';
|
|
72
72
|
import { listAllHookAgents, refreshStaleHooksAtLaunch, installHooksForSlug, uninstallHooksForSlug, } from '../agent/installers.js';
|
|
@@ -678,6 +678,9 @@ process.on('SIGINT', () => { void shutdownWithRecordings(); });
|
|
|
678
678
|
// 服务启动时从磁盘加载(带去重,防止历史累积的重复条目复活)
|
|
679
679
|
void (async () => {
|
|
680
680
|
await Promise.all([loadGlobalSessionStateFromDisk(), loadTmuxRecoveryStateFromDisk()]);
|
|
681
|
+
// Delivery needs the loaded inventory, not optional PTY adoption/metadata backfill.
|
|
682
|
+
// Those steps must not leave durable messages without a background scheduler.
|
|
683
|
+
collaborationDeliveryWorker.start();
|
|
681
684
|
await watchGlobalSessionStateFile();
|
|
682
685
|
// pty-host adoption runs after the state load (its record upserts must not
|
|
683
686
|
// be clobbered) and before pruning (surviving shell records' backends are
|
|
@@ -687,7 +690,6 @@ void (async () => {
|
|
|
687
690
|
});
|
|
688
691
|
pruneOrphanSessions();
|
|
689
692
|
await backfillPersistedTmuxMetadata();
|
|
690
|
-
collaborationDeliveryWorker.start();
|
|
691
693
|
})();
|
|
692
694
|
caffeinateManager.startNetworkMonitor();
|
|
693
695
|
// 清理磁盘恢复后后端已不存在的 session 引用。
|
|
@@ -1483,13 +1485,15 @@ function terminalInputGuard(record) {
|
|
|
1483
1485
|
const frontendSessionId = record.sessionId;
|
|
1484
1486
|
const backendSessionId = record.backendSessionId;
|
|
1485
1487
|
const launchId = record.agentLaunchGeneration ?? null;
|
|
1488
|
+
const routeRevision = collaborationRouting.get(frontendSessionId)?.routeRevision ?? null;
|
|
1486
1489
|
const backend = backendSessionId ? terminalSessions.get(backendSessionId) : undefined;
|
|
1487
1490
|
return () => {
|
|
1488
1491
|
const latest = globalSessionState.sessions.find(candidate => candidate.sessionId === frontendSessionId);
|
|
1489
1492
|
if (!latest)
|
|
1490
1493
|
throw new Error('SESSION_REMOVED');
|
|
1491
1494
|
const instanceMatches = !backendSessionId || terminalSessions.get(backendSessionId) === backend;
|
|
1492
|
-
if ((
|
|
1495
|
+
if ((collaborationRouting.get(frontendSessionId)?.routeRevision ?? null) !== routeRevision
|
|
1496
|
+
|| (latest.agentLaunchGeneration ?? null) !== launchId || latest.backendSessionId !== backendSessionId || !instanceMatches) {
|
|
1493
1497
|
throw new TerminalInputTargetChangedError({ expected_backend_session_id: backendSessionId, current_backend_session_id: latest.backendSessionId,
|
|
1494
1498
|
expected_launch_id: launchId, current_launch_id: latest.agentLaunchGeneration ?? null, backend_instance_matches: instanceMatches });
|
|
1495
1499
|
}
|
|
@@ -1612,6 +1616,7 @@ export function resolveStableFederationSessionId(id) {
|
|
|
1612
1616
|
}
|
|
1613
1617
|
function collaborationRemoteSessions() {
|
|
1614
1618
|
return Array.from(new Map(collaborationStore.list().flatMap((group) => group.remoteSessions ?? [])
|
|
1619
|
+
.filter(session => session.sessionId.startsWith('remote:'))
|
|
1615
1620
|
.map((session) => {
|
|
1616
1621
|
const facts = collaborationStore.sessionFacts(session.sessionId, false);
|
|
1617
1622
|
const { currentTask: _currentTask, ...terminalSession } = session;
|
|
@@ -1622,8 +1627,7 @@ function collaborationRemoteSessions() {
|
|
|
1622
1627
|
})).values());
|
|
1623
1628
|
}
|
|
1624
1629
|
function tryDeliverCollaborationInbox(frontendSessionId) {
|
|
1625
|
-
|
|
1626
|
-
if (remote) {
|
|
1630
|
+
if (frontendSessionId.startsWith('remote:')) {
|
|
1627
1631
|
return { delivered: [], pending: collaborationStore.pendingCount(frontendSessionId), waitable: true,
|
|
1628
1632
|
reason: '跨服务消息已入队,服务后台正在投递;使用 message get 查看送达回执或注册、重试原因。' };
|
|
1629
1633
|
}
|
|
@@ -1669,7 +1673,7 @@ function formatLocalCollaborationMessages(frontendSessionId, messages) {
|
|
|
1669
1673
|
* agent-keyed selector can never reach it. Delivery still needs an agent (the
|
|
1670
1674
|
* confirm gate and prompt formatting assume a TUI); driving a terminal —
|
|
1671
1675
|
* run/capture — is a shell operation and works on any pane. */
|
|
1672
|
-
async function inspectCollaborationTmux(binding, requestedPane, allowPlainPane = false, nativeProcessIdentity = false, freshProcess = false) {
|
|
1676
|
+
async function inspectCollaborationTmux(binding, requestedPane, allowPlainPane = false, nativeProcessIdentity = false, freshProcess = false, describeNativeFailure = false) {
|
|
1673
1677
|
if (!binding.tmuxSessionName)
|
|
1674
1678
|
return { state: 'offline', reason: 'TMUX_BINDING_MISSING' };
|
|
1675
1679
|
const name = `=${binding.tmuxSessionName}`;
|
|
@@ -1696,14 +1700,16 @@ async function inspectCollaborationTmux(binding, requestedPane, allowPlainPane =
|
|
|
1696
1700
|
const program = await resolveTmuxPaneProgram(pane, true, nativeProcessIdentity || freshProcess);
|
|
1697
1701
|
const agent = detectAgentFromCommand(program?.rawArgs ?? program?.command ?? '', agentCustomCommands());
|
|
1698
1702
|
const identity = nativeProcessIdentity ? await observeProgramNativeIdentity(agent, program)
|
|
1699
|
-
: { nativeId: agent && program?.rawArgs ? inferResumeSessionId(agent, splitCommandToArgv(program.rawArgs)) : null, failure: null };
|
|
1700
|
-
if (identity.failure)
|
|
1703
|
+
: { nativeId: agent && program?.rawArgs ? inferResumeSessionId(agent, splitCommandToArgv(program.rawArgs)) : null, failure: null, source: null };
|
|
1704
|
+
if (identity.failure && !describeNativeFailure)
|
|
1701
1705
|
integrationError(identity.failure === 'NATIVE_SESSION_IDENTITY_CONFLICT'
|
|
1702
1706
|
? 'NATIVE_SESSION_ID_MISMATCH' : 'NATIVE_SESSION_OWNER_UNCONFIRMED', 'Current process native identity evidence conflicts or cannot be uniquely verified', 409);
|
|
1703
1707
|
const nativeSessionId = identity.nativeId;
|
|
1704
1708
|
return { serverPid, sessionId: layout.sessionId, paneId: pane.id, panePid: pane.pid,
|
|
1705
1709
|
agentSlug: agent?.slug ?? '', nativeSessionId, cwd: pane.currentPath,
|
|
1706
|
-
isShell: shellNamesBackend.has(normalizeProgramName(program?.command ?? '')?.toLowerCase() ?? '')
|
|
1710
|
+
isShell: shellNamesBackend.has(normalizeProgramName(program?.command ?? '')?.toLowerCase() ?? ''),
|
|
1711
|
+
...(nativeProcessIdentity ? { nativeIdentitySource: identity.source, nativeIdentityFailure: identity.failure,
|
|
1712
|
+
nativeIdentityVerified: identity.source === 'linux-flock-owner' && !identity.failure } : {}) };
|
|
1707
1713
|
}));
|
|
1708
1714
|
const candidates = requestedPane ? panes.filter((pane) => pane.paneId === requestedPane) : panes;
|
|
1709
1715
|
if (allowPlainPane && !binding.pane) {
|
|
@@ -1711,24 +1717,56 @@ async function inspectCollaborationTmux(binding, requestedPane, allowPlainPane =
|
|
|
1711
1717
|
// pane so a plain shell member is drivable (run/capture are shell ops).
|
|
1712
1718
|
return selectDrivePane(binding, candidates, layout.activePaneId);
|
|
1713
1719
|
}
|
|
1714
|
-
return selectCollaborationPane(binding, candidates);
|
|
1720
|
+
return { ...selectCollaborationPane(binding, candidates), candidates };
|
|
1721
|
+
}
|
|
1722
|
+
function routeOwnershipConfirmed(frontendSessionId, binding, panes) {
|
|
1723
|
+
const record = globalSessionState.sessions.find(candidate => candidate.sessionId === frontendSessionId);
|
|
1724
|
+
return !!record && record.mode === 'tmux' && record.tmuxSessionName === binding.tmuxSessionName
|
|
1725
|
+
&& !globalSessionState.sessions.some(other => other.sessionId !== frontendSessionId && (other.tmuxSessionName === binding.tmuxSessionName
|
|
1726
|
+
|| !!binding.backendSessionId && other.backendSessionId === binding.backendSessionId))
|
|
1727
|
+
&& (!binding.backendSessionId || [null, frontendSessionId].includes(collaborationRouting.ownerOfBackend(binding.backendSessionId)))
|
|
1728
|
+
&& panes.every(pane => !collaborationRouting.hasOtherPaneOwner(frontendSessionId, pane));
|
|
1729
|
+
}
|
|
1730
|
+
function routeHasUnconfirmedWrite(frontendSessionId) {
|
|
1731
|
+
return collaborationStore.hasUnconfirmedDelivery(frontendSessionId);
|
|
1732
|
+
}
|
|
1733
|
+
async function describeCollaborationRoute(frontendSessionId) {
|
|
1734
|
+
const record = globalSessionState.sessions.find(candidate => candidate.sessionId === frontendSessionId);
|
|
1735
|
+
if (!record)
|
|
1736
|
+
throw new Error('SESSION_REMOVED');
|
|
1737
|
+
const binding = collaborationRouting.get(frontendSessionId);
|
|
1738
|
+
if (!binding || binding.mode !== 'tmux')
|
|
1739
|
+
return { session_id: frontendSessionId, binding,
|
|
1740
|
+
worker: collaborationDeliveryWorker.diagnostics(frontendSessionId), identity: null };
|
|
1741
|
+
const inspected = await inspectCollaborationTmux(binding, null, false, true, true, true);
|
|
1742
|
+
const assessment = assessCollaborationRouteIdentity(binding, inspected.candidates ?? [], routeOwnershipConfirmed(frontendSessionId, binding, inspected.candidates ?? []), routeHasUnconfirmedWrite(frontendSessionId));
|
|
1743
|
+
return { session_id: frontendSessionId, binding, worker: collaborationDeliveryWorker.diagnostics(frontendSessionId),
|
|
1744
|
+
observed_at: Date.now(), state: inspected.state, error: inspected.reason ?? null, identity: assessment.diagnostics,
|
|
1745
|
+
integration_managed: record.tmuxSessionName?.startsWith('wt-integration-') ?? false };
|
|
1715
1746
|
}
|
|
1716
1747
|
async function rebindCollaborationRoute(frontendSessionId, paneId) {
|
|
1717
1748
|
await collaborationDeliveryWorker.reconfigure(frontendSessionId, async () => {
|
|
1718
1749
|
const record = globalSessionState.sessions.find((candidate) => candidate.sessionId === frontendSessionId);
|
|
1719
1750
|
if (!record)
|
|
1720
1751
|
throw new Error('SESSION_REMOVED');
|
|
1752
|
+
if (record.tmuxSessionName?.startsWith('wt-integration-'))
|
|
1753
|
+
throw new Error('INTEGRATION_SESSION_RESTORE_REQUIRED: use the owning principal session restore lifecycle');
|
|
1721
1754
|
const previous = collaborationRouting.get(frontendSessionId);
|
|
1755
|
+
if (routeHasUnconfirmedWrite(frontendSessionId))
|
|
1756
|
+
throw new Error('ROUTE_DELIVERY_OUTCOME_UNCONFIRMED: inspect prior write outcome before rebinding; the body is not replayed');
|
|
1722
1757
|
const binding = {
|
|
1723
1758
|
sessionId: frontendSessionId, backendSessionId: previous?.backendSessionId ?? record.backendSessionId,
|
|
1724
1759
|
mode: record.mode, tmuxSessionName: record.tmuxSessionName ?? previous?.tmuxSessionName ?? null,
|
|
1725
1760
|
agentSlug: null, nativeSessionId: null, pane: null,
|
|
1761
|
+
routeRevision: crypto.randomUUID(), lastRecovery: { kind: 'owner-confirmed', at: Date.now(), previousPane: previous?.pane ?? null },
|
|
1726
1762
|
};
|
|
1727
1763
|
if (binding.mode === 'tmux') {
|
|
1728
1764
|
const inspected = await inspectCollaborationTmux(binding, paneId);
|
|
1729
1765
|
if (inspected.state !== 'ready' || !inspected.pane)
|
|
1730
1766
|
throw new Error(inspected.reason ?? 'AGENT_NOT_RUNNING');
|
|
1731
1767
|
const pane = inspected.pane;
|
|
1768
|
+
if (!routeOwnershipConfirmed(frontendSessionId, binding, [pane]))
|
|
1769
|
+
throw new Error('ROUTE_OWNERSHIP_UNCONFIRMED');
|
|
1732
1770
|
binding.pane = { serverPid: pane.serverPid, sessionId: pane.sessionId, paneId: pane.paneId, panePid: pane.panePid,
|
|
1733
1771
|
agentSlug: pane.agentSlug, nativeSessionId: pane.nativeSessionId };
|
|
1734
1772
|
binding.agentSlug = pane.agentSlug;
|
|
@@ -1759,6 +1797,7 @@ async function rebindCollaborationRoute(frontendSessionId, paneId) {
|
|
|
1759
1797
|
* snapshot of the recipient after the write, and the sender judges from that.
|
|
1760
1798
|
*/
|
|
1761
1799
|
async function resolveCollaborationRoute(frontendSessionId) {
|
|
1800
|
+
let recoveredNativeIdentity = false;
|
|
1762
1801
|
let record = globalSessionState.sessions.find((candidate) => candidate.sessionId === frontendSessionId);
|
|
1763
1802
|
if (!record)
|
|
1764
1803
|
return { state: 'offline', reason: 'SESSION_REMOVED' };
|
|
@@ -1774,7 +1813,26 @@ async function resolveCollaborationRoute(frontendSessionId) {
|
|
|
1774
1813
|
agentSlug: record.agentResume?.slug ?? null, nativeSessionId: record.agentResume?.sessionId ?? null, pane: null,
|
|
1775
1814
|
};
|
|
1776
1815
|
if (binding.mode === 'tmux') {
|
|
1777
|
-
|
|
1816
|
+
let inspected = await inspectCollaborationTmux(binding, undefined, false, Boolean(record.agentLaunchCheck?.nativeSessionId), Boolean(record.agentLaunchCheck));
|
|
1817
|
+
if (inspected.state === 'identity-mismatch' && !record.tmuxSessionName?.startsWith('wt-integration-')) {
|
|
1818
|
+
const observed = await inspectCollaborationTmux(binding, null, false, true, true, true);
|
|
1819
|
+
const assessment = assessCollaborationRouteIdentity(binding, observed.candidates ?? [], routeOwnershipConfirmed(frontendSessionId, binding, observed.candidates ?? []), routeHasUnconfirmedWrite(frontendSessionId));
|
|
1820
|
+
if (assessment.diagnostics.recovery !== 'automatic' || !assessment.pane)
|
|
1821
|
+
return { state: 'identity-mismatch', reason: 'TMUX_PANE_CHANGED', diagnostics: assessment.diagnostics };
|
|
1822
|
+
const previous = collaborationRouting.get(frontendSessionId);
|
|
1823
|
+
if (JSON.stringify(previous) !== JSON.stringify(binding))
|
|
1824
|
+
return { state: 'recovering', reason: 'ROUTE_CHANGED_DURING_RECOVERY' };
|
|
1825
|
+
const verify = await inspectCollaborationTmux(binding, null, false, true, true, true);
|
|
1826
|
+
const confirmed = assessCollaborationRouteIdentity(binding, verify.candidates ?? [], routeOwnershipConfirmed(frontendSessionId, binding, verify.candidates ?? []), routeHasUnconfirmedWrite(frontendSessionId));
|
|
1827
|
+
if (confirmed.diagnostics.recovery !== 'automatic' || !confirmed.pane || JSON.stringify(confirmed.pane) !== JSON.stringify(assessment.pane)) {
|
|
1828
|
+
return { state: 'identity-mismatch', reason: 'ROUTE_CHANGED_DURING_RECOVERY', diagnostics: confirmed.diagnostics };
|
|
1829
|
+
}
|
|
1830
|
+
binding = { ...binding, pane: confirmed.pane, routeRevision: crypto.randomUUID(),
|
|
1831
|
+
lastRecovery: { kind: 'native-identity', at: Date.now(), previousPane: binding.pane } };
|
|
1832
|
+
collaborationRouting.bind(binding);
|
|
1833
|
+
inspected = { state: 'ready', pane: confirmed.pane };
|
|
1834
|
+
recoveredNativeIdentity = true;
|
|
1835
|
+
}
|
|
1778
1836
|
assertGeneration();
|
|
1779
1837
|
if (inspected.state !== 'ready' || !inspected.pane)
|
|
1780
1838
|
return inspected;
|
|
@@ -1816,6 +1874,14 @@ async function resolveCollaborationRoute(frontendSessionId) {
|
|
|
1816
1874
|
return { state: 'ready', isShell: pane.isShell, capture: async () => captureTmuxPaneText(runTmux, pinned), write: async (messages) => {
|
|
1817
1875
|
if (!globalSessionState.sessions.some((candidate) => candidate.sessionId === frontendSessionId))
|
|
1818
1876
|
throw new Error('SESSION_REMOVED');
|
|
1877
|
+
if (recoveredNativeIdentity) {
|
|
1878
|
+
const current = await inspectCollaborationTmux(binding, null, false, true, true, true);
|
|
1879
|
+
const proof = current.candidates?.find(candidate => candidate.serverPid === pinned.serverPid && candidate.sessionId === pinned.sessionId
|
|
1880
|
+
&& candidate.paneId === pinned.paneId && candidate.panePid === pinned.panePid);
|
|
1881
|
+
if (!proof?.nativeIdentityVerified || proof.nativeIdentityFailure || proof.nativeSessionId !== pinned.nativeSessionId
|
|
1882
|
+
|| proof.agentSlug !== pinned.agentSlug || !routeOwnershipConfirmed(frontendSessionId, binding, [proof]))
|
|
1883
|
+
throw new Error('ROUTE_NATIVE_IDENTITY_CHANGED_BEFORE_WRITE');
|
|
1884
|
+
}
|
|
1819
1885
|
await writeCollaborationTmuxPane(runTmux, pinned, formatLocalCollaborationMessages(frontendSessionId, messages), runTmuxStdin, () => { assertGeneration(); assertCurrent(); });
|
|
1820
1886
|
backend.lastActivity = Date.now();
|
|
1821
1887
|
} };
|
|
@@ -6474,7 +6540,8 @@ router.get('/operations/collaboration-groups/:groupId/messages', (req, res) => {
|
|
|
6474
6540
|
return ambiguousGroupResponse(res, ambiguous);
|
|
6475
6541
|
if (!group)
|
|
6476
6542
|
return res.status(404).json({ error: '协作组不存在' });
|
|
6477
|
-
res.json({ messages: collaborationStore.listMessages(group.id, Number(req.query.limit) || 200)
|
|
6543
|
+
res.json({ messages: collaborationStore.listMessages(group.id, Number(req.query.limit) || 200)
|
|
6544
|
+
.map(message => ({ ...message, delivery: collaborationStore.receipt(message.id).delivery })) });
|
|
6478
6545
|
});
|
|
6479
6546
|
router.post('/operations/collaboration-groups/:groupId/messages', (req, res) => {
|
|
6480
6547
|
try {
|
|
@@ -6789,7 +6856,7 @@ router.post('/operations/orchestration/drive', async (req, res) => {
|
|
|
6789
6856
|
}
|
|
6790
6857
|
});
|
|
6791
6858
|
router.use('/operations/orchestration', collaborationRoutes({ store: collaborationStore, resolveSession: resolveFrontendSessionId,
|
|
6792
|
-
deliver: tryDeliverCollaborationInbox, rebind: rebindCollaborationRoute,
|
|
6859
|
+
deliver: tryDeliverCollaborationInbox, rebind: rebindCollaborationRoute, diagnoseRoute: describeCollaborationRoute,
|
|
6793
6860
|
resolveNames: (ids) => {
|
|
6794
6861
|
const names = new Map([...collaborationRemoteSessions(),
|
|
6795
6862
|
...globalSessionState.sessions.map(orchestrationSessionSnapshot)].map((session) => [session.sessionId, session.name]));
|
package/docs/integrations.md
CHANGED
|
@@ -1169,3 +1169,76 @@ TD/native session ID、消息/reply、事件/consumer 历史。没有 Agent 启
|
|
|
1169
1169
|
并发不同键竞争/同键重放、删除/跨服务、管理员 Unix 路由/CLI 权限及 JSON、网页列表
|
|
1170
1170
|
回读和旧网页表单版本冲突。DevBox 业务组及真实 macOS/iOS 显示尚待接入方实机验收,
|
|
1171
1171
|
不以源码/模拟回归代替其运行现场。
|
|
1172
|
+
|
|
1173
|
+
## 1.4.321:普通协作会话的承载变化、阻断诊断与恢复
|
|
1174
|
+
|
|
1175
|
+
最低 CLI/实际服务均为 **1.4.321**;普通协作协议仍为 2,integration protocol 仍为 1。
|
|
1176
|
+
当前 CLI 版本不能替代实际服务版本;普通成员使用
|
|
1177
|
+
`td collab --session <自身ID> capabilities --json` 回读 `server_version`、
|
|
1178
|
+
`route_diagnostics=true`、`route_identity_recovery=true`、
|
|
1179
|
+
`route_identity_recovery_min_version=1.4.321`。
|
|
1180
|
+
|
|
1181
|
+
```sh
|
|
1182
|
+
td collab --session <自身ID> route get <精确本地目标ID> --json
|
|
1183
|
+
td collab --session <自身ID> message get <原消息ID> --receipt-only --json
|
|
1184
|
+
# 只有目标拥有者在自己的真实终端确认“当前承载就是目标”后执行:
|
|
1185
|
+
td collab --session <目标自身ID> rebind --pane <当前pane-ID> --json
|
|
1186
|
+
```
|
|
1187
|
+
|
|
1188
|
+
`route get` 为只读 `GET /operations/orchestration/route/:id`,只允许自身或共享组的本地
|
|
1189
|
+
成员;不解析前缀/名称,不替远端拥有者查询其当前进程。旧服务缺能力时 CLI 明确拒绝。
|
|
1190
|
+
返回 `route.session_id/binding/worker/observed_at/state/error/identity`:worker 包括
|
|
1191
|
+
`started/tick_in_progress/recipient_in_progress/last_tick_at/route/pending_count`;identity
|
|
1192
|
+
包括原 `expected`、当前 `observed`(最多 20 项、`truncated`)、`recovery/reason` 和
|
|
1193
|
+
拥有者正式 `rebind_command`。只导出承载标识、Agent 类型及原生身份证据元数据,
|
|
1194
|
+
没有终端正文、argv、环境或凭据。证据未知即未知,不使用旧缓存 UUID 替代当前身份。
|
|
1195
|
+
只读查询不启动/恢复 Agent、改绑或补键,不把进程/身份正确称为输入已就绪。
|
|
1196
|
+
|
|
1197
|
+
已绑定的 tmux server/session/pane/PID 变化时,原物理身份保护仍拒绝直接写入。
|
|
1198
|
+
消息维持 `status=pending`,诊断会给 `delivery.stage=blocked`、`error=TMUX_PANE_CHANGED`、
|
|
1199
|
+
`route_state`、`requires_confirmation` 及 `route` 差异/建议;`attempt_count=0` 表示尚未
|
|
1200
|
+
尝试写入,不等于失败后可重发。现有 `message.delivery` 主动事件携带该 receipt;
|
|
1201
|
+
网页协作记录也展示绑定变化和投递暂停,保留原正文。跨服务交换在状态不变但错误变化
|
|
1202
|
+
时仍同步错误,不因 pending 状态相同而隐去新的阻断。运行服务未采集过的历史差异
|
|
1203
|
+
不能由新版本凭空补出;`worker.started` 等字段用于确认当前调度事实。
|
|
1204
|
+
|
|
1205
|
+
本地/远端目标依据稳定 `remote:` 地址区分,组是否 federated 不影响组内本地消息进入
|
|
1206
|
+
本地 worker。后台 worker 在会话登记加载完成后启动,不等待额外 PTY adoption 或
|
|
1207
|
+
tmux 元数据 backfill;订阅消息存储变化并保留定时重试。缺绑定/进程/权限时仍保留原
|
|
1208
|
+
消息,诊断拒绝原因,不依赖网页维持投递。此加固不能替代旧现场的运行证据,也不能
|
|
1209
|
+
从过去缺少 transport 条目推断唯一内部根因。
|
|
1210
|
+
|
|
1211
|
+
承载变化后的**自动**更新仅用于普通 tmux 会话,并同时要求:原生 ID/Agent 类型已知,
|
|
1212
|
+
当前可信 provider 独立核验同一原生 ID、同一 Agent,唯一匹配且原逻辑记录/后端/pane
|
|
1213
|
+
归属无冲突,没有原待投递消息的未确认写入尝试。对账前再次核验当前候选和登记,
|
|
1214
|
+
首次继续写入前再次核验当前原生身份。只改绑定,不启动/恢复/切换原生 Agent。
|
|
1215
|
+
当前独立证据 provider 是已配置的 Linux flock-owner 核验;核心不按 Agent 名称或
|
|
1216
|
+
TUI 展示字符串分支。argv 的 resume ID 只能作为启动意图元数据,单独不满足自动更新。
|
|
1217
|
+
因此没有可靠 provider 的 Mac 冷启动 Codex 等场景需要明确拥有者确认,不能宣称跨
|
|
1218
|
+
平台自动身份恢复已通过。独立证据的能力/适用平台由 provider 决定。
|
|
1219
|
+
|
|
1220
|
+
原生身份缺失/不同、多匹配、归属不明或此前写入结果不明时,保留原消息并显示
|
|
1221
|
+
`confirmation-required` 及对应原因(`NATIVE_IDENTITY_UNCONFIRMED`、
|
|
1222
|
+
`MULTIPLE_NATIVE_IDENTITY_MATCHES`、`ROUTE_OWNERSHIP_UNCONFIRMED`、
|
|
1223
|
+
`DELIVERY_OUTCOME_UNCONFIRMED`)。拥有者确认当前承载后可用现有 rebind 明确接受当前
|
|
1224
|
+
Agent/原生身份;这不是承诺精确恢复旧原生历史,也不要求猜 UUID 或编辑私有记录。
|
|
1225
|
+
无运行 tmux 的情况须先通过原会话恢复入口恢复承载,不能靠 rebind 新建。
|
|
1226
|
+
|
|
1227
|
+
重新绑定与投递按该逻辑成员的 worker 屏障串行,持久保存 `routeRevision` 和
|
|
1228
|
+
`lastRecovery={kind,at,previousPane}`,后者只记录最近一次自动/显式绑定恢复。
|
|
1229
|
+
绑定以 routing 文件原子替换提交;失败不采用新绑定。输入队列同时核验 routeRevision,
|
|
1230
|
+
旧队列不能在新绑定上继续粘贴/提交。待处理消息已经记录尝试(`attempt_count>0`)而结果
|
|
1231
|
+
未确认时,显式 rebind 返回 `ROUTE_DELIVERY_OUTCOME_UNCONFIRMED`,先对账,不能借修复
|
|
1232
|
+
重发正文。记录不承诺永久审计或跨掉电的恰好一次输入;原终端传输的写入语义/保留
|
|
1233
|
+
边界不变。
|
|
1234
|
+
|
|
1235
|
+
`IntegrationSession` 不通过普通 rebind 绕过其代次/精确 UUID/配置与所有者保护,须继续
|
|
1236
|
+
用受限 principal 的 `session get/restore`;普通 rebind 对此返回
|
|
1237
|
+
`INTEGRATION_SESSION_RESTORE_REQUIRED`。当前修复不改变业务任务、principal、组、
|
|
1238
|
+
message/thread/幂等键或历史,不自动补 Enter、不用屏幕文字识别消费;delivered 仍只
|
|
1239
|
+
表示终端写入,完成须明确回复。
|
|
1240
|
+
|
|
1241
|
+
回归覆盖同组本地消息处于 federated 组、存储变化唤醒/后台阻断、修复后原消息单次
|
|
1242
|
+
投递、不同/缺失/弱原生证据、多匹配/归属/未知旧写入拒绝、绑定持久化和失败、
|
|
1243
|
+
只读路由权限/CLI、网页暂停提示及加密传输边界。Mac 实际现场的当前原生身份尚未独立确认,原消息尚待拥有者确认及接入方实际服务
|
|
1244
|
+
升级/回读后继续投递;不以维护机回归冒充该现场已恢复。
|
package/package.json
CHANGED
package/runtime-manifest.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"packageName": "termdock",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.321",
|
|
5
5
|
"runtimeProtocolVersion": 1,
|
|
6
6
|
"minimumDesktopVersion": "1.4.46",
|
|
7
7
|
"nodeMajor": 22,
|
|
8
8
|
"dependencyHash": "sha256-oaGYi/P5ob8sd6VnNBOwshKozjhdV+hYiCmLAsn5x00=",
|
|
9
|
-
"serverBundleHash": "sha256-
|
|
10
|
-
"clientBundleHash": "sha256
|
|
9
|
+
"serverBundleHash": "sha256-o36V1OU5HWHaYRXX3y2vcIKrppx0O4wtdbCRN90DifI=",
|
|
10
|
+
"clientBundleHash": "sha256-rMB/XxqqSbnbT1KeX2KqTnR82mLyuW/NFSb1X7Y6BRE=",
|
|
11
11
|
"entrypoint": "dist/server/cli.js",
|
|
12
12
|
"clientEntrypoint": "dist/client/index.html"
|
|
13
13
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{by as r}from"./app-BRESmgxW.js";import{b as m}from"./dnd-BCFAPC0L.js";import{b as n}from"./RightSidebar-7C9-PfhA.js";import"./react-XDCjal2T.js";import"./terminal-C7X98Amf.js";import"./App-BF6YvbKL.js";import"./gestureArbiter-DalDKZKj.js";import"./triangle-alert-DG_BJhJY.js";import"./referenceLongPress-DfQ5jnsk.js";import"./DiffReview-CjEi6PCy.js";import"./sparkles-DbcgKKVd.js";import"./DiffViewer-Bh6lvUYN.js";import"./ChangeWalkthroughPanel-B59JwhzK.js";function g({content:o}){const e=m.useMemo(()=>n(o.split(`
|
|
2
|
-
`),null,null),[o]);return r.jsx("div",{className:"min-w-0 space-y-3 break-words text-sm leading-6 text-foreground [&_h1]:text-lg [&_h2]:text-base [&_h3]:text-sm [&_pre]:max-w-full [&_table]:text-xs",children:e.map((t,i)=>r.jsx("div",{className:"min-w-0",children:typeof t.content=="function"?t.content(null):t.content},i))})}export{g as default};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{c as a,C as n}from"./mermaid.core-BxJ2mx92.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,a as s,c as t,C as e}from"./chunk-TICWLB2K-akdXuwgx.js";import{d as i}from"./mermaid.core-BxJ2mx92.js";import"./chunk-5VM5RSS4-DZhLGwG4.js";import"./chunk-XXDRQBXY-Da273BkJ.js";import"./chunk-POPQ4Y6H-YgwJ3iH4.js";import"./chunk-F27PBJKO-CwqjUNpz.js";import"./purify.es-4eNOHKSq.js";import"./app-BRESmgxW.js";import"./react-XDCjal2T.js";import"./dnd-BCFAPC0L.js";import"./terminal-C7X98Amf.js";var g={parser:t,get db(){return new e},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{g as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,a as s,c as t,C as e}from"./chunk-TICWLB2K-akdXuwgx.js";import{d as i}from"./mermaid.core-BxJ2mx92.js";import"./chunk-5VM5RSS4-DZhLGwG4.js";import"./chunk-XXDRQBXY-Da273BkJ.js";import"./chunk-POPQ4Y6H-YgwJ3iH4.js";import"./chunk-F27PBJKO-CwqjUNpz.js";import"./purify.es-4eNOHKSq.js";import"./app-BRESmgxW.js";import"./react-XDCjal2T.js";import"./dnd-BCFAPC0L.js";import"./terminal-C7X98Amf.js";var g={parser:t,get db(){return new e},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{g as diagram};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|