termdock 1.4.295 → 1.4.296

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (337) hide show
  1. package/dist/client/assets/App-BiLjlrk-.js +171 -0
  2. package/dist/client/assets/App-BiLjlrk-.js.br +0 -0
  3. package/dist/client/assets/App-BiLjlrk-.js.gz +0 -0
  4. package/dist/client/assets/{ChangeWalkthroughPanel-Dv5XRtRh.js → ChangeWalkthroughPanel-DXprT-7m.js} +1 -1
  5. package/dist/client/assets/ChangeWalkthroughPanel-DXprT-7m.js.br +0 -0
  6. package/dist/client/assets/ChangeWalkthroughPanel-DXprT-7m.js.gz +0 -0
  7. package/dist/client/assets/{DagPlayground-mq69dKyr.js → DagPlayground-DZcUunT5.js} +1 -1
  8. package/dist/client/assets/DagPlayground-DZcUunT5.js.br +0 -0
  9. package/dist/client/assets/DagPlayground-DZcUunT5.js.gz +0 -0
  10. package/dist/client/assets/{DiffLab-BqdHYGi5.js → DiffLab-Brv4DCTb.js} +1 -1
  11. package/dist/client/assets/DiffLab-Brv4DCTb.js.br +0 -0
  12. package/dist/client/assets/DiffLab-Brv4DCTb.js.gz +0 -0
  13. package/dist/client/assets/{DiffReview-BvzGxpuc.js → DiffReview-BuLu1qCi.js} +1 -1
  14. package/dist/client/assets/DiffReview-BuLu1qCi.js.br +0 -0
  15. package/dist/client/assets/DiffReview-BuLu1qCi.js.gz +0 -0
  16. package/dist/client/assets/{DiffReviewLab-DrfddB7x.js → DiffReviewLab-DSGamuAD.js} +1 -1
  17. package/dist/client/assets/DiffReviewLab-DSGamuAD.js.br +0 -0
  18. package/dist/client/assets/DiffReviewLab-DSGamuAD.js.gz +0 -0
  19. package/dist/client/assets/{DiffViewer-3bJV_A5s.js → DiffViewer-BUCYxg27.js} +1 -1
  20. package/dist/client/assets/DiffViewer-BUCYxg27.js.br +0 -0
  21. package/dist/client/assets/DiffViewer-BUCYxg27.js.gz +0 -0
  22. package/dist/client/assets/{ModelPreview-CX7VtoJB.js → ModelPreview-Bnlo-oVE.js} +1 -1
  23. package/dist/client/assets/ModelPreview-Bnlo-oVE.js.br +0 -0
  24. package/dist/client/assets/ModelPreview-Bnlo-oVE.js.gz +0 -0
  25. package/dist/client/assets/{RightSidebar-BK6vWNw3.js → RightSidebar-r_3Lk5Rp.js} +45 -45
  26. package/dist/client/assets/RightSidebar-r_3Lk5Rp.js.br +0 -0
  27. package/dist/client/assets/RightSidebar-r_3Lk5Rp.js.gz +0 -0
  28. package/dist/client/assets/{abnfDiagram-VCTEODGH-PJwhLTPH.js → abnfDiagram-VCTEODGH-K6Ppkrbt.js} +1 -1
  29. package/dist/client/assets/abnfDiagram-VCTEODGH-K6Ppkrbt.js.br +0 -0
  30. package/dist/client/assets/abnfDiagram-VCTEODGH-K6Ppkrbt.js.gz +0 -0
  31. package/dist/client/assets/{app-C7pXMvSE.js → app-CATnTUZF.js} +8 -8
  32. package/dist/client/assets/app-CATnTUZF.js.br +0 -0
  33. package/dist/client/assets/app-CATnTUZF.js.gz +0 -0
  34. package/dist/client/assets/{arc-l3FXjCEl.js → arc-Co2OQqtH.js} +1 -1
  35. package/dist/client/assets/arc-Co2OQqtH.js.br +0 -0
  36. package/dist/client/assets/arc-Co2OQqtH.js.gz +0 -0
  37. package/dist/client/assets/{architectureDiagram-5GKGNRK7-DdNbKi-4.js → architectureDiagram-5GKGNRK7-BQnl7tVF.js} +1 -1
  38. package/dist/client/assets/architectureDiagram-5GKGNRK7-BQnl7tVF.js.br +0 -0
  39. package/dist/client/assets/architectureDiagram-5GKGNRK7-BQnl7tVF.js.gz +0 -0
  40. package/dist/client/assets/{blockDiagram-I7D4REHJ-Cu63oaxR.js → blockDiagram-I7D4REHJ-Bm5D5-qq.js} +1 -1
  41. package/dist/client/assets/blockDiagram-I7D4REHJ-Bm5D5-qq.js.br +0 -0
  42. package/dist/client/assets/blockDiagram-I7D4REHJ-Bm5D5-qq.js.gz +0 -0
  43. package/dist/client/assets/{c4Diagram-7LVT6UL2-DQiV_yk6.js → c4Diagram-7LVT6UL2-B9oPpey8.js} +1 -1
  44. package/dist/client/assets/c4Diagram-7LVT6UL2-B9oPpey8.js.br +0 -0
  45. package/dist/client/assets/c4Diagram-7LVT6UL2-B9oPpey8.js.gz +0 -0
  46. package/dist/client/assets/channel-Czv2W4qA.js +1 -0
  47. package/dist/client/assets/{chunk-2Q5K7J3B-COKJ79Ld.js → chunk-2Q5K7J3B-TMaWHH0U.js} +1 -1
  48. package/dist/client/assets/{chunk-5VM5RSS4-BfV-m7oa.js → chunk-5VM5RSS4-CH7XpknV.js} +1 -1
  49. package/dist/client/assets/{chunk-F27PBJKO-sLDCEnU8.js → chunk-F27PBJKO-CJ1rotBe.js} +1 -1
  50. package/dist/client/assets/chunk-F27PBJKO-CJ1rotBe.js.br +0 -0
  51. package/dist/client/assets/chunk-F27PBJKO-CJ1rotBe.js.gz +0 -0
  52. package/dist/client/assets/{chunk-IMKFNOWR-DYu5qS7g.js → chunk-IMKFNOWR-UYKZ5uOG.js} +1 -1
  53. package/dist/client/assets/chunk-IMKFNOWR-UYKZ5uOG.js.br +0 -0
  54. package/dist/client/assets/chunk-IMKFNOWR-UYKZ5uOG.js.gz +0 -0
  55. package/dist/client/assets/{chunk-JWPE2WC7-DixkILcl.js → chunk-JWPE2WC7-BYL8aXjQ.js} +1 -1
  56. package/dist/client/assets/{chunk-POPQ4Y6H-CfW5Vm_-.js → chunk-POPQ4Y6H-C3E8yfU2.js} +1 -1
  57. package/dist/client/assets/{chunk-SVP7TREG-nJnbUFzs.js → chunk-SVP7TREG-DCTDYa1E.js} +1 -1
  58. package/dist/client/assets/chunk-SVP7TREG-DCTDYa1E.js.br +0 -0
  59. package/dist/client/assets/chunk-SVP7TREG-DCTDYa1E.js.gz +0 -0
  60. package/dist/client/assets/{chunk-TICWLB2K-BwyiSQgx.js → chunk-TICWLB2K-wHiaOsBh.js} +1 -1
  61. package/dist/client/assets/chunk-TICWLB2K-wHiaOsBh.js.br +0 -0
  62. package/dist/client/assets/chunk-TICWLB2K-wHiaOsBh.js.gz +0 -0
  63. package/dist/client/assets/{chunk-XXDRQBXY-TCk4c2XN.js → chunk-XXDRQBXY-D_d479hK.js} +1 -1
  64. package/dist/client/assets/classDiagram-ZZMXUADV-BdvOOL9k.js +1 -0
  65. package/dist/client/assets/classDiagram-v2-VYDZK3BY-BdvOOL9k.js +1 -0
  66. package/dist/client/assets/{cose-bilkent-JH36ORCC-rroo-EOb.js → cose-bilkent-JH36ORCC-DnhlPBLr.js} +1 -1
  67. package/dist/client/assets/cose-bilkent-JH36ORCC-DnhlPBLr.js.br +0 -0
  68. package/dist/client/assets/cose-bilkent-JH36ORCC-DnhlPBLr.js.gz +0 -0
  69. package/dist/client/assets/{cynefin-OW5HDTMX-CkFeV85k.js → cynefin-OW5HDTMX-BsjzNqJZ.js} +1 -1
  70. package/dist/client/assets/cynefin-OW5HDTMX-BsjzNqJZ.js.br +0 -0
  71. package/dist/client/assets/cynefin-OW5HDTMX-BsjzNqJZ.js.gz +0 -0
  72. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-hBwpU_bW.js → cynefinDiagram-5FMLGOSQ-sVUb0zY5.js} +1 -1
  73. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-sVUb0zY5.js.br +0 -0
  74. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-sVUb0zY5.js.gz +0 -0
  75. package/dist/client/assets/{dagre-GXQ25YYZ-B321-hdp.js → dagre-GXQ25YYZ-YErk8S-c.js} +1 -1
  76. package/dist/client/assets/dagre-GXQ25YYZ-YErk8S-c.js.br +0 -0
  77. package/dist/client/assets/dagre-GXQ25YYZ-YErk8S-c.js.gz +0 -0
  78. package/dist/client/assets/{diagram-S7CK7UJ4-bY87_ptA.js → diagram-S7CK7UJ4-BaHbV5ho.js} +1 -1
  79. package/dist/client/assets/diagram-S7CK7UJ4-BaHbV5ho.js.br +0 -0
  80. package/dist/client/assets/diagram-S7CK7UJ4-BaHbV5ho.js.gz +0 -0
  81. package/dist/client/assets/{diagram-UQ7AKVKN--cez0H_o.js → diagram-UQ7AKVKN-BocCYx3V.js} +1 -1
  82. package/dist/client/assets/diagram-UQ7AKVKN-BocCYx3V.js.br +0 -0
  83. package/dist/client/assets/diagram-UQ7AKVKN-BocCYx3V.js.gz +0 -0
  84. package/dist/client/assets/{diagram-VSXAHHWV-BupH_VRK.js → diagram-VSXAHHWV-ZMTYwWOQ.js} +1 -1
  85. package/dist/client/assets/diagram-VSXAHHWV-ZMTYwWOQ.js.br +0 -0
  86. package/dist/client/assets/diagram-VSXAHHWV-ZMTYwWOQ.js.gz +0 -0
  87. package/dist/client/assets/{diagram-VX7I27RA-DewqaxvF.js → diagram-VX7I27RA-xmk_EY1h.js} +1 -1
  88. package/dist/client/assets/diagram-VX7I27RA-xmk_EY1h.js.br +0 -0
  89. package/dist/client/assets/diagram-VX7I27RA-xmk_EY1h.js.gz +0 -0
  90. package/dist/client/assets/{diagram-Z3DM3KII-wDumcTuR.js → diagram-Z3DM3KII-DKDY_cG6.js} +1 -1
  91. package/dist/client/assets/diagram-Z3DM3KII-DKDY_cG6.js.br +0 -0
  92. package/dist/client/assets/diagram-Z3DM3KII-DKDY_cG6.js.gz +0 -0
  93. package/dist/client/assets/{ebnfDiagram-PWID7BFC-C0OY91We.js → ebnfDiagram-PWID7BFC-C_0z-Jx9.js} +1 -1
  94. package/dist/client/assets/ebnfDiagram-PWID7BFC-C_0z-Jx9.js.br +0 -0
  95. package/dist/client/assets/ebnfDiagram-PWID7BFC-C_0z-Jx9.js.gz +0 -0
  96. package/dist/client/assets/{erDiagram-RLTQ6QDP-Cw9aNqvJ.js → erDiagram-RLTQ6QDP-DHUaG7mt.js} +1 -1
  97. package/dist/client/assets/erDiagram-RLTQ6QDP-DHUaG7mt.js.br +0 -0
  98. package/dist/client/assets/erDiagram-RLTQ6QDP-DHUaG7mt.js.gz +0 -0
  99. package/dist/client/assets/{flowDiagram-HODETNUW-BC7XUXeI.js → flowDiagram-HODETNUW-BMNsdMBD.js} +1 -1
  100. package/dist/client/assets/flowDiagram-HODETNUW-BMNsdMBD.js.br +0 -0
  101. package/dist/client/assets/flowDiagram-HODETNUW-BMNsdMBD.js.gz +0 -0
  102. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-DovhJIz5.js → ganttDiagram-EL5Y4UJY-BH1AiKuF.js} +1 -1
  103. package/dist/client/assets/ganttDiagram-EL5Y4UJY-BH1AiKuF.js.br +0 -0
  104. package/dist/client/assets/ganttDiagram-EL5Y4UJY-BH1AiKuF.js.gz +0 -0
  105. package/dist/client/assets/{gestureArbiter-wjVok2Lg.js → gestureArbiter-DvupkPra.js} +1 -1
  106. package/dist/client/assets/gestureArbiter-DvupkPra.js.br +0 -0
  107. package/dist/client/assets/gestureArbiter-DvupkPra.js.gz +0 -0
  108. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-BmrbbyW1.js → gitGraphDiagram-WWUBYQGX-DAgV0MV-.js} +1 -1
  109. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DAgV0MV-.js.br +0 -0
  110. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DAgV0MV-.js.gz +0 -0
  111. package/dist/client/assets/{index-BeD4iJ6L.css → index-Bi9A6QUP.css} +1 -1
  112. package/dist/client/assets/index-Bi9A6QUP.css.br +0 -0
  113. package/dist/client/assets/index-Bi9A6QUP.css.gz +0 -0
  114. package/dist/client/assets/{infoDiagram-27XIBGKW-CQEu4Jwy.js → infoDiagram-27XIBGKW-C7iSg0cB.js} +1 -1
  115. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-BPqibqsm.js → ishikawaDiagram-5VMMS53U-BpZwsQvw.js} +1 -1
  116. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BpZwsQvw.js.br +0 -0
  117. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BpZwsQvw.js.gz +0 -0
  118. package/dist/client/assets/{journeyDiagram-3NMN7TZE-DIkhubnf.js → journeyDiagram-3NMN7TZE-DXEeFLvw.js} +1 -1
  119. package/dist/client/assets/journeyDiagram-3NMN7TZE-DXEeFLvw.js.br +0 -0
  120. package/dist/client/assets/journeyDiagram-3NMN7TZE-DXEeFLvw.js.gz +0 -0
  121. package/dist/client/assets/{kanban-definition-UXKFOSKX-CBT0DIUR.js → kanban-definition-UXKFOSKX-CV9ivL5u.js} +1 -1
  122. package/dist/client/assets/kanban-definition-UXKFOSKX-CV9ivL5u.js.br +0 -0
  123. package/dist/client/assets/kanban-definition-UXKFOSKX-CV9ivL5u.js.gz +0 -0
  124. package/dist/client/assets/{layout-C1CMlOIU.js → layout-DsKKsJKX.js} +1 -1
  125. package/dist/client/assets/layout-DsKKsJKX.js.br +0 -0
  126. package/dist/client/assets/layout-DsKKsJKX.js.gz +0 -0
  127. package/dist/client/assets/{linear-C4gyqor0.js → linear-Dl9MDNV3.js} +1 -1
  128. package/dist/client/assets/linear-Dl9MDNV3.js.br +0 -0
  129. package/dist/client/assets/linear-Dl9MDNV3.js.gz +0 -0
  130. package/dist/client/assets/{mermaid.core-CMfa4ncd.js → mermaid.core-CxZFe3as.js} +5 -5
  131. package/dist/client/assets/mermaid.core-CxZFe3as.js.br +0 -0
  132. package/dist/client/assets/mermaid.core-CxZFe3as.js.gz +0 -0
  133. package/dist/client/assets/{mindmap-definition-YA3MSWOX-C-JmgKOI.js → mindmap-definition-YA3MSWOX-C3ormYdL.js} +1 -1
  134. package/dist/client/assets/mindmap-definition-YA3MSWOX-C3ormYdL.js.br +0 -0
  135. package/dist/client/assets/mindmap-definition-YA3MSWOX-C3ormYdL.js.gz +0 -0
  136. package/dist/client/assets/{passwordBootstrap-BmUG2IwA.js → passwordBootstrap-a8z6jJNY.js} +2 -2
  137. package/dist/client/assets/passwordBootstrap-a8z6jJNY.js.br +0 -0
  138. package/dist/client/assets/passwordBootstrap-a8z6jJNY.js.gz +0 -0
  139. package/dist/client/assets/{pegDiagram-XKGWAZYB-IY-AEKQa.js → pegDiagram-XKGWAZYB-CG0wNylH.js} +1 -1
  140. package/dist/client/assets/pegDiagram-XKGWAZYB-CG0wNylH.js.br +0 -0
  141. package/dist/client/assets/pegDiagram-XKGWAZYB-CG0wNylH.js.gz +0 -0
  142. package/dist/client/assets/{pieDiagram-E7YTZNPT-9Qq43qED.js → pieDiagram-E7YTZNPT-D2-ydqyX.js} +1 -1
  143. package/dist/client/assets/pieDiagram-E7YTZNPT-D2-ydqyX.js.br +0 -0
  144. package/dist/client/assets/pieDiagram-E7YTZNPT-D2-ydqyX.js.gz +0 -0
  145. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-BjQncx5i.js → quadrantDiagram-AXDQQJYC-CK3fRC18.js} +1 -1
  146. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CK3fRC18.js.br +0 -0
  147. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CK3fRC18.js.gz +0 -0
  148. package/dist/client/assets/{railroadDiagram-O6MQD6OU-Cr1rL0wZ.js → railroadDiagram-O6MQD6OU-V4EFlydu.js} +1 -1
  149. package/dist/client/assets/railroadDiagram-O6MQD6OU-V4EFlydu.js.br +0 -0
  150. package/dist/client/assets/railroadDiagram-O6MQD6OU-V4EFlydu.js.gz +0 -0
  151. package/dist/client/assets/{referenceLongPress-ConC5-ym.js → referenceLongPress-BjmYd1vB.js} +1 -1
  152. package/dist/client/assets/referenceLongPress-BjmYd1vB.js.br +0 -0
  153. package/dist/client/assets/referenceLongPress-BjmYd1vB.js.gz +0 -0
  154. package/dist/client/assets/{requirementDiagram-BXWQKSXE-DU2q_iZg.js → requirementDiagram-BXWQKSXE-Di1_tyAX.js} +1 -1
  155. package/dist/client/assets/requirementDiagram-BXWQKSXE-Di1_tyAX.js.br +0 -0
  156. package/dist/client/assets/requirementDiagram-BXWQKSXE-Di1_tyAX.js.gz +0 -0
  157. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-BYlx9kXC.js → sankeyDiagram-P5KCCOFB-D-qpWNza.js} +1 -1
  158. package/dist/client/assets/sankeyDiagram-P5KCCOFB-D-qpWNza.js.br +0 -0
  159. package/dist/client/assets/sankeyDiagram-P5KCCOFB-D-qpWNza.js.gz +0 -0
  160. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-D_uAKme-.js → sequenceDiagram-WJ2MYXX4-DmIxafrB.js} +1 -1
  161. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DmIxafrB.js.br +0 -0
  162. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DmIxafrB.js.gz +0 -0
  163. package/dist/client/assets/{sizeCapture-INFHLROL-H_uqscf4.js → sizeCapture-INFHLROL-4MTh3tTt.js} +1 -1
  164. package/dist/client/assets/sizeCapture-INFHLROL-4MTh3tTt.js.br +0 -0
  165. package/dist/client/assets/sizeCapture-INFHLROL-4MTh3tTt.js.gz +0 -0
  166. package/dist/client/assets/{sparkles-D2z4Ue6G.js → sparkles-Dk93lHg0.js} +1 -1
  167. package/dist/client/assets/{stateDiagram-D77RDMKH-BvsQjIIW.js → stateDiagram-D77RDMKH-CgYgneIv.js} +1 -1
  168. package/dist/client/assets/stateDiagram-D77RDMKH-CgYgneIv.js.br +0 -0
  169. package/dist/client/assets/stateDiagram-D77RDMKH-CgYgneIv.js.gz +0 -0
  170. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-CvPf0fxf.js +1 -0
  171. package/dist/client/assets/{swimlanes-42K2YHIH-LmUJag-p.js → swimlanes-42K2YHIH-OWA9HFVf.js} +1 -1
  172. package/dist/client/assets/swimlanes-42K2YHIH-OWA9HFVf.js.br +0 -0
  173. package/dist/client/assets/swimlanes-42K2YHIH-OWA9HFVf.js.gz +0 -0
  174. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-CZ_OauyW.js +8 -0
  175. package/dist/client/assets/{timeline-definition-24CTP7MA-DZ5n0Pim.js → timeline-definition-24CTP7MA-BAzx5DyO.js} +1 -1
  176. package/dist/client/assets/timeline-definition-24CTP7MA-BAzx5DyO.js.br +0 -0
  177. package/dist/client/assets/timeline-definition-24CTP7MA-BAzx5DyO.js.gz +0 -0
  178. package/dist/client/assets/{triangle-alert-Ct6iIBmv.js → triangle-alert-CUIBOwqW.js} +1 -1
  179. package/dist/client/assets/{vennDiagram-4TSXK5OY-BkTA_Ciz.js → vennDiagram-4TSXK5OY-CBZ-PhTQ.js} +1 -1
  180. package/dist/client/assets/vennDiagram-4TSXK5OY-CBZ-PhTQ.js.br +0 -0
  181. package/dist/client/assets/vennDiagram-4TSXK5OY-CBZ-PhTQ.js.gz +0 -0
  182. package/dist/client/assets/{videoCompression-VZIoFnyJ.js → videoCompression-BCnqCkRK.js} +1 -1
  183. package/dist/client/assets/videoCompression-BCnqCkRK.js.br +0 -0
  184. package/dist/client/assets/videoCompression-BCnqCkRK.js.gz +0 -0
  185. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-7hzU176j.js → wardleyDiagram-VM6X3IG4-DbWzC6l5.js} +1 -1
  186. package/dist/client/assets/wardleyDiagram-VM6X3IG4-DbWzC6l5.js.br +0 -0
  187. package/dist/client/assets/wardleyDiagram-VM6X3IG4-DbWzC6l5.js.gz +0 -0
  188. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-Bx4P96Bb.js → xychartDiagram-S5SC5T6Z-BmApnTWE.js} +1 -1
  189. package/dist/client/assets/xychartDiagram-S5SC5T6Z-BmApnTWE.js.br +0 -0
  190. package/dist/client/assets/xychartDiagram-S5SC5T6Z-BmApnTWE.js.gz +0 -0
  191. package/dist/client/index.html +2 -2
  192. package/dist/client/index.html.br +0 -0
  193. package/dist/client/index.html.gz +0 -0
  194. package/dist/client/sw.js +1 -1
  195. package/dist/client/sw.js.br +0 -0
  196. package/dist/client/sw.js.gz +0 -0
  197. package/dist/server/agent/collaborationCli.js +45 -4
  198. package/dist/server/agent/collaborationDeliveryWorker.js +1 -1
  199. package/dist/server/agent/collaborationPeerTransport.js +8 -2
  200. package/dist/server/agent/collaborationRoutes.js +18 -2
  201. package/dist/server/agent/collaborationService.js +43 -1
  202. package/dist/server/agent/collaborationTaskBundles.js +121 -0
  203. package/dist/server/agent/collaborationTaskCli.js +54 -0
  204. package/dist/server/agent/collaborationTaskRoutes.js +58 -0
  205. package/dist/server/agent/collaborationTaskService.js +355 -0
  206. package/dist/server/agent/collaborationTaskStore.js +773 -0
  207. package/dist/server/agent/collaborationTaskTypes.js +1 -0
  208. package/dist/server/agent/collaborationTaskWorkspace.js +100 -0
  209. package/dist/server/entry.js +11 -1
  210. package/dist/server/federation/runtime.js +6 -1
  211. package/dist/server/routes/terminal.js +66 -2
  212. package/package.json +1 -1
  213. package/runtime-manifest.json +3 -3
  214. package/dist/client/assets/App-D-cerXsD.js +0 -158
  215. package/dist/client/assets/App-D-cerXsD.js.br +0 -0
  216. package/dist/client/assets/App-D-cerXsD.js.gz +0 -0
  217. package/dist/client/assets/ChangeWalkthroughPanel-Dv5XRtRh.js.br +0 -0
  218. package/dist/client/assets/ChangeWalkthroughPanel-Dv5XRtRh.js.gz +0 -0
  219. package/dist/client/assets/DagPlayground-mq69dKyr.js.br +0 -0
  220. package/dist/client/assets/DagPlayground-mq69dKyr.js.gz +0 -0
  221. package/dist/client/assets/DiffLab-BqdHYGi5.js.br +0 -0
  222. package/dist/client/assets/DiffLab-BqdHYGi5.js.gz +0 -0
  223. package/dist/client/assets/DiffReview-BvzGxpuc.js.br +0 -0
  224. package/dist/client/assets/DiffReview-BvzGxpuc.js.gz +0 -0
  225. package/dist/client/assets/DiffReviewLab-DrfddB7x.js.br +0 -0
  226. package/dist/client/assets/DiffReviewLab-DrfddB7x.js.gz +0 -0
  227. package/dist/client/assets/DiffViewer-3bJV_A5s.js.br +0 -0
  228. package/dist/client/assets/DiffViewer-3bJV_A5s.js.gz +0 -0
  229. package/dist/client/assets/ModelPreview-CX7VtoJB.js.br +0 -0
  230. package/dist/client/assets/ModelPreview-CX7VtoJB.js.gz +0 -0
  231. package/dist/client/assets/RightSidebar-BK6vWNw3.js.br +0 -0
  232. package/dist/client/assets/RightSidebar-BK6vWNw3.js.gz +0 -0
  233. package/dist/client/assets/abnfDiagram-VCTEODGH-PJwhLTPH.js.br +0 -0
  234. package/dist/client/assets/abnfDiagram-VCTEODGH-PJwhLTPH.js.gz +0 -0
  235. package/dist/client/assets/app-C7pXMvSE.js.br +0 -0
  236. package/dist/client/assets/app-C7pXMvSE.js.gz +0 -0
  237. package/dist/client/assets/arc-l3FXjCEl.js.br +0 -0
  238. package/dist/client/assets/arc-l3FXjCEl.js.gz +0 -0
  239. package/dist/client/assets/architectureDiagram-5GKGNRK7-DdNbKi-4.js.br +0 -0
  240. package/dist/client/assets/architectureDiagram-5GKGNRK7-DdNbKi-4.js.gz +0 -0
  241. package/dist/client/assets/blockDiagram-I7D4REHJ-Cu63oaxR.js.br +0 -0
  242. package/dist/client/assets/blockDiagram-I7D4REHJ-Cu63oaxR.js.gz +0 -0
  243. package/dist/client/assets/c4Diagram-7LVT6UL2-DQiV_yk6.js.br +0 -0
  244. package/dist/client/assets/c4Diagram-7LVT6UL2-DQiV_yk6.js.gz +0 -0
  245. package/dist/client/assets/channel-CwC957gi.js +0 -1
  246. package/dist/client/assets/chunk-F27PBJKO-sLDCEnU8.js.br +0 -0
  247. package/dist/client/assets/chunk-F27PBJKO-sLDCEnU8.js.gz +0 -0
  248. package/dist/client/assets/chunk-IMKFNOWR-DYu5qS7g.js.br +0 -0
  249. package/dist/client/assets/chunk-IMKFNOWR-DYu5qS7g.js.gz +0 -0
  250. package/dist/client/assets/chunk-SVP7TREG-nJnbUFzs.js.br +0 -0
  251. package/dist/client/assets/chunk-SVP7TREG-nJnbUFzs.js.gz +0 -0
  252. package/dist/client/assets/chunk-TICWLB2K-BwyiSQgx.js.br +0 -0
  253. package/dist/client/assets/chunk-TICWLB2K-BwyiSQgx.js.gz +0 -0
  254. package/dist/client/assets/classDiagram-ZZMXUADV-CmoJ7-rE.js +0 -1
  255. package/dist/client/assets/classDiagram-v2-VYDZK3BY-CmoJ7-rE.js +0 -1
  256. package/dist/client/assets/cose-bilkent-JH36ORCC-rroo-EOb.js.br +0 -0
  257. package/dist/client/assets/cose-bilkent-JH36ORCC-rroo-EOb.js.gz +0 -0
  258. package/dist/client/assets/cynefin-OW5HDTMX-CkFeV85k.js.br +0 -0
  259. package/dist/client/assets/cynefin-OW5HDTMX-CkFeV85k.js.gz +0 -0
  260. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-hBwpU_bW.js.br +0 -0
  261. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-hBwpU_bW.js.gz +0 -0
  262. package/dist/client/assets/dagre-GXQ25YYZ-B321-hdp.js.br +0 -0
  263. package/dist/client/assets/dagre-GXQ25YYZ-B321-hdp.js.gz +0 -0
  264. package/dist/client/assets/diagram-S7CK7UJ4-bY87_ptA.js.br +0 -0
  265. package/dist/client/assets/diagram-S7CK7UJ4-bY87_ptA.js.gz +0 -0
  266. package/dist/client/assets/diagram-UQ7AKVKN--cez0H_o.js.br +0 -0
  267. package/dist/client/assets/diagram-UQ7AKVKN--cez0H_o.js.gz +0 -0
  268. package/dist/client/assets/diagram-VSXAHHWV-BupH_VRK.js.br +0 -0
  269. package/dist/client/assets/diagram-VSXAHHWV-BupH_VRK.js.gz +0 -0
  270. package/dist/client/assets/diagram-VX7I27RA-DewqaxvF.js.br +0 -0
  271. package/dist/client/assets/diagram-VX7I27RA-DewqaxvF.js.gz +0 -0
  272. package/dist/client/assets/diagram-Z3DM3KII-wDumcTuR.js.br +0 -0
  273. package/dist/client/assets/diagram-Z3DM3KII-wDumcTuR.js.gz +0 -0
  274. package/dist/client/assets/ebnfDiagram-PWID7BFC-C0OY91We.js.br +0 -0
  275. package/dist/client/assets/ebnfDiagram-PWID7BFC-C0OY91We.js.gz +0 -0
  276. package/dist/client/assets/erDiagram-RLTQ6QDP-Cw9aNqvJ.js.br +0 -0
  277. package/dist/client/assets/erDiagram-RLTQ6QDP-Cw9aNqvJ.js.gz +0 -0
  278. package/dist/client/assets/flowDiagram-HODETNUW-BC7XUXeI.js.br +0 -0
  279. package/dist/client/assets/flowDiagram-HODETNUW-BC7XUXeI.js.gz +0 -0
  280. package/dist/client/assets/ganttDiagram-EL5Y4UJY-DovhJIz5.js.br +0 -0
  281. package/dist/client/assets/ganttDiagram-EL5Y4UJY-DovhJIz5.js.gz +0 -0
  282. package/dist/client/assets/gestureArbiter-wjVok2Lg.js.br +0 -0
  283. package/dist/client/assets/gestureArbiter-wjVok2Lg.js.gz +0 -0
  284. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BmrbbyW1.js.br +0 -0
  285. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BmrbbyW1.js.gz +0 -0
  286. package/dist/client/assets/index-BeD4iJ6L.css.br +0 -0
  287. package/dist/client/assets/index-BeD4iJ6L.css.gz +0 -0
  288. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BPqibqsm.js.br +0 -0
  289. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BPqibqsm.js.gz +0 -0
  290. package/dist/client/assets/journeyDiagram-3NMN7TZE-DIkhubnf.js.br +0 -0
  291. package/dist/client/assets/journeyDiagram-3NMN7TZE-DIkhubnf.js.gz +0 -0
  292. package/dist/client/assets/kanban-definition-UXKFOSKX-CBT0DIUR.js.br +0 -0
  293. package/dist/client/assets/kanban-definition-UXKFOSKX-CBT0DIUR.js.gz +0 -0
  294. package/dist/client/assets/layout-C1CMlOIU.js.br +0 -0
  295. package/dist/client/assets/layout-C1CMlOIU.js.gz +0 -0
  296. package/dist/client/assets/linear-C4gyqor0.js.br +0 -0
  297. package/dist/client/assets/linear-C4gyqor0.js.gz +0 -0
  298. package/dist/client/assets/mermaid.core-CMfa4ncd.js.br +0 -0
  299. package/dist/client/assets/mermaid.core-CMfa4ncd.js.gz +0 -0
  300. package/dist/client/assets/mindmap-definition-YA3MSWOX-C-JmgKOI.js.br +0 -0
  301. package/dist/client/assets/mindmap-definition-YA3MSWOX-C-JmgKOI.js.gz +0 -0
  302. package/dist/client/assets/passwordBootstrap-BmUG2IwA.js.br +0 -0
  303. package/dist/client/assets/passwordBootstrap-BmUG2IwA.js.gz +0 -0
  304. package/dist/client/assets/pegDiagram-XKGWAZYB-IY-AEKQa.js.br +0 -0
  305. package/dist/client/assets/pegDiagram-XKGWAZYB-IY-AEKQa.js.gz +0 -0
  306. package/dist/client/assets/pieDiagram-E7YTZNPT-9Qq43qED.js.br +0 -0
  307. package/dist/client/assets/pieDiagram-E7YTZNPT-9Qq43qED.js.gz +0 -0
  308. package/dist/client/assets/quadrantDiagram-AXDQQJYC-BjQncx5i.js.br +0 -0
  309. package/dist/client/assets/quadrantDiagram-AXDQQJYC-BjQncx5i.js.gz +0 -0
  310. package/dist/client/assets/railroadDiagram-O6MQD6OU-Cr1rL0wZ.js.br +0 -0
  311. package/dist/client/assets/railroadDiagram-O6MQD6OU-Cr1rL0wZ.js.gz +0 -0
  312. package/dist/client/assets/referenceLongPress-ConC5-ym.js.br +0 -0
  313. package/dist/client/assets/referenceLongPress-ConC5-ym.js.gz +0 -0
  314. package/dist/client/assets/requirementDiagram-BXWQKSXE-DU2q_iZg.js.br +0 -0
  315. package/dist/client/assets/requirementDiagram-BXWQKSXE-DU2q_iZg.js.gz +0 -0
  316. package/dist/client/assets/sankeyDiagram-P5KCCOFB-BYlx9kXC.js.br +0 -0
  317. package/dist/client/assets/sankeyDiagram-P5KCCOFB-BYlx9kXC.js.gz +0 -0
  318. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D_uAKme-.js.br +0 -0
  319. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D_uAKme-.js.gz +0 -0
  320. package/dist/client/assets/sizeCapture-INFHLROL-H_uqscf4.js.br +0 -0
  321. package/dist/client/assets/sizeCapture-INFHLROL-H_uqscf4.js.gz +0 -0
  322. package/dist/client/assets/stateDiagram-D77RDMKH-BvsQjIIW.js.br +0 -0
  323. package/dist/client/assets/stateDiagram-D77RDMKH-BvsQjIIW.js.gz +0 -0
  324. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-DNgoExtD.js +0 -1
  325. package/dist/client/assets/swimlanes-42K2YHIH-LmUJag-p.js.br +0 -0
  326. package/dist/client/assets/swimlanes-42K2YHIH-LmUJag-p.js.gz +0 -0
  327. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-BRuArMR5.js +0 -8
  328. package/dist/client/assets/timeline-definition-24CTP7MA-DZ5n0Pim.js.br +0 -0
  329. package/dist/client/assets/timeline-definition-24CTP7MA-DZ5n0Pim.js.gz +0 -0
  330. package/dist/client/assets/vennDiagram-4TSXK5OY-BkTA_Ciz.js.br +0 -0
  331. package/dist/client/assets/vennDiagram-4TSXK5OY-BkTA_Ciz.js.gz +0 -0
  332. package/dist/client/assets/videoCompression-VZIoFnyJ.js.br +0 -0
  333. package/dist/client/assets/videoCompression-VZIoFnyJ.js.gz +0 -0
  334. package/dist/client/assets/wardleyDiagram-VM6X3IG4-7hzU176j.js.br +0 -0
  335. package/dist/client/assets/wardleyDiagram-VM6X3IG4-7hzU176j.js.gz +0 -0
  336. package/dist/client/assets/xychartDiagram-S5SC5T6Z-Bx4P96Bb.js.br +0 -0
  337. package/dist/client/assets/xychartDiagram-S5SC5T6Z-Bx4P96Bb.js.gz +0 -0
@@ -151,6 +151,10 @@ export function collaborationRoutes({ store, resolveSession, deliver, rebind, re
151
151
  };
152
152
  router.get('/capabilities', run((_req, res) => {
153
153
  res.json({ protocol_version: 2, limits: COLLAB_LIMITS,
154
+ task_workflow: { version: 2, command: 'td collab task', single_authority: true, explicit_reports: true,
155
+ managed_goals: true, automatic_review: true, dependency_dispatch: true, isolated_worktrees: true, encrypted_commit_transfer: true,
156
+ durable_questions: true, user_acceptance: true, versioned_artifacts: true, independent_reviews: true,
157
+ task_reply: 'Replies to task-linked user messages are stored in the task; status=stored is not a terminal delivery receipt' },
154
158
  routing: { background_recovery: true, explicit_rebind: Boolean(rebind), fixed_tmux_pane: true },
155
159
  statuses: ['pending', 'delivered', 'failed', 'expired'], queued_status: 'pending',
156
160
  semantics: { delivered: 'written to terminal; no application acknowledgement implied',
@@ -201,8 +205,20 @@ export function collaborationRoutes({ store, resolveSession, deliver, rebind, re
201
205
  }));
202
206
  router.post('/reply', run(async (req, res, sessionId) => {
203
207
  const original = ownMessage(String(req.body.messageId ?? ''), sessionId, true);
204
- if (!original.fromSessionId)
205
- throw new CollaborationError('NO_REPLY_TARGET', 'User messages have no agent reply target');
208
+ if (!original.fromSessionId) {
209
+ const link = original.metadata?.termdockTask;
210
+ if (link?.taskId && req.app.locals.collaborationTasks) {
211
+ const extras = extrasFromBody(req.body);
212
+ const status = extras.task?.status ?? (extras.responseKind === 'ack' ? 'ack' : extras.responseKind === 'result' ? 'complete' : extras.responseKind === 'progress' ? 'working' : null);
213
+ const task = await req.app.locals.collaborationTasks.apply(link.taskId, {
214
+ kind: status ? 'report' : 'comment', status: status ?? undefined, attemptId: link.attemptId,
215
+ content: req.body.content, evidence: extras.task?.evidence, idempotencyKey: extras.idempotencyKey,
216
+ }, req.app.locals.collaborationService.taskMember(sessionId));
217
+ res.json({ ok: true, status: 'stored', task_recorded: true, task_id: task.id, task_revision: task.revision });
218
+ return;
219
+ }
220
+ throw new CollaborationError('NO_REPLY_TARGET', '该消息没有成员回复目标;任务请使用 td collab task report 或 task comment');
221
+ }
206
222
  const messages = store.send({ ...extrasFromBody(req.body), groupId: original.groupId, fromSessionId: sessionId,
207
223
  toSessionIds: [original.fromSessionId], kind: 'reply', content: typeof req.body.content === 'string' ? req.body.content : '',
208
224
  replyTo: original.id, threadId: original.threadId });
@@ -89,6 +89,34 @@ export class CollaborationService {
89
89
  this.persist();
90
90
  }
91
91
  descriptor() { return { ...this.options.node(), ...(this.document.origin ? { origin: this.document.origin } : {}) }; }
92
+ taskMember(sessionId) {
93
+ const parsed = address(sessionId);
94
+ if (!parsed)
95
+ return { serviceId: this.options.node().serviceId, sessionId };
96
+ const peer = this.document.peers.find(node => node.origin === parsed.origin);
97
+ if (!peer)
98
+ throw new CollaborationError('TASK_PEER_UNAVAILABLE', '成员所在服务尚未配对', 409);
99
+ return { serviceId: peer.serviceId, sessionId: parsed.id };
100
+ }
101
+ taskSession(member) {
102
+ if (member.serviceId === this.options.node().serviceId)
103
+ return member.sessionId;
104
+ const peer = this.document.peers.find(node => node.serviceId === member.serviceId);
105
+ if (!peer)
106
+ throw new CollaborationError('TASK_PEER_UNAVAILABLE', '任务所在服务尚未配对', 409);
107
+ return remoteSession(peer.origin, member.sessionId);
108
+ }
109
+ async requestTasks(serviceId, payload) {
110
+ const peer = this.document.peers.find(node => node.serviceId === serviceId);
111
+ if (!peer)
112
+ throw new CollaborationError('TASK_PEER_UNAVAILABLE', '任务来源服务未连接,记录已保留', 409);
113
+ const result = await (await this.client(peer)).request({ type: 'collaboration-service', action: 'tasks', ...payload });
114
+ if (result.taskError) {
115
+ const error = result.taskError;
116
+ throw new CollaborationError(error.code, error.message, error.status);
117
+ }
118
+ return result;
119
+ }
92
120
  /** Called through the existing authenticated administrator connection. No
93
121
  * client key is copied; only pinned public service descriptors are persisted. */
94
122
  connectKnown(origin, nodes) {
@@ -260,6 +288,18 @@ export class CollaborationService {
260
288
  return { ok: true };
261
289
  if (packet.action === 'directory')
262
290
  return this.snapshot(peer);
291
+ if (packet.action === 'tasks' && this.options.tasks) {
292
+ try {
293
+ return Promise.resolve(this.options.tasks.receive(peer, packet)).catch(error => ({ taskError: {
294
+ code: error instanceof CollaborationError ? error.code : 'TASK_ERROR', message: error instanceof Error ? error.message : String(error),
295
+ status: error instanceof CollaborationError ? error.httpStatus : 400
296
+ } }));
297
+ }
298
+ catch (error) {
299
+ return { taskError: { code: error instanceof CollaborationError ? error.code : 'TASK_ERROR',
300
+ message: error instanceof Error ? error.message : String(error), status: error instanceof CollaborationError ? error.httpStatus : 400 } };
301
+ }
302
+ }
263
303
  if (packet.action === 'group') {
264
304
  const canonical = packet.group;
265
305
  if (!canonical?.sessionIds?.some(id => address(id)?.origin === peer.origin) && !this.document.replicas?.[canonical?.id]?.includes(peer.origin))
@@ -281,7 +321,7 @@ export class CollaborationService {
281
321
  .filter(group => scope === undefined || group.sessionIds.every(id => address(id) ? true : scope.includes(id)))
282
322
  .map(group => mapGroup(group, id => address(id) ? id : remoteSession(origin, id)));
283
323
  return { sessions: scope === undefined ? sessions : sessions.filter(session => scope.includes(session.sessionId)),
284
- groups, nodes: scope === undefined ? this.nodes() : [this.node(), peer] };
324
+ groups, taskHeads: this.options.tasks?.heads(groups.map(g => g.id)) ?? [], nodes: scope === undefined ? this.nodes() : [this.node(), peer] };
285
325
  }
286
326
  merge(canonical, nodes, source) {
287
327
  if (!canonical || typeof canonical.id !== 'string' || !canonical.id.startsWith('cross-') || !Array.isArray(canonical.sessionIds)
@@ -377,6 +417,8 @@ export class CollaborationService {
377
417
  this.observations.set(peer.serviceId, { sessions, checkedAt: Date.now() });
378
418
  for (const group of data.groups)
379
419
  this.merge(group, data.nodes, peer);
420
+ if (Array.isArray(data.taskHeads))
421
+ await this.options.tasks?.sync(peer, data.taskHeads);
380
422
  for (const group of this.options.store.federationSnapshot().groups.filter(g => g.federated && (g.sessionIds.some(id => address(id)?.origin === peer.origin) || this.document.replicas?.[g.id]?.includes(peer.origin)))) {
381
423
  const scope = this.effectiveScope(peer.serviceId);
382
424
  // Never push a group to a scoped peer if it involves other local sessions.
@@ -0,0 +1,121 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+ import { createHash } from 'node:crypto';
4
+ import { createReadStream } from 'node:fs';
5
+ import { mkdir, open, readFile, writeFile, rename, stat, unlink } from 'node:fs/promises';
6
+ import path from 'node:path';
7
+ import os from 'node:os';
8
+ const exec = promisify(execFile), chunkSize = 256 * 1024, maxBytes = 128 * 1024 * 1024;
9
+ const directory = path.join(os.homedir(), '.termdock', 'task-bundles');
10
+ const preparing = new Map();
11
+ const git = async (cwd, args) => (await exec('git', ['-C', cwd, ...args], { timeout: 60_000, maxBuffer: 1024 * 1024,
12
+ env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } })).stdout.trim();
13
+ async function digestFile(file) {
14
+ const digest = createHash('sha256');
15
+ for await (const chunk of createReadStream(file))
16
+ digest.update(chunk);
17
+ return digest.digest('hex');
18
+ }
19
+ function acceptedCommit(task) {
20
+ const artifact = task.artifacts.find(a => a.id === task.acceptedArtifactId && a.kind === 'result');
21
+ const commit = artifact?.evidence?.commit;
22
+ if (task.status !== 'accepted' || !artifact || !task.workspace || !commit || !/^[a-f0-9]{40,64}$/.test(commit)
23
+ || !/^[a-f0-9]{40,64}$/.test(task.workspace.base) || !/^[a-f0-9]{32}$/.test(artifact.id))
24
+ throw new Error('依赖没有已评审的代码提交');
25
+ return { artifact, commit, base: task.workspace.base, workspace: task.workspace };
26
+ }
27
+ async function prepareBundle(task) {
28
+ const { artifact, commit, base, workspace } = acceptedCommit(task);
29
+ const existing = preparing.get(artifact.id);
30
+ if (existing)
31
+ return existing;
32
+ const operation = (async () => {
33
+ await mkdir(directory, { recursive: true, mode: 0o700 });
34
+ const file = path.join(directory, `${artifact.id}.bundle`), metadataFile = `${file}.json`;
35
+ try {
36
+ const metadata = JSON.parse(await readFile(metadataFile, 'utf8'));
37
+ if (metadata.commit === commit && metadata.base === base && metadata.bytes === (await stat(file)).size)
38
+ return metadata;
39
+ }
40
+ catch (error) {
41
+ if (error.code !== 'ENOENT')
42
+ throw error;
43
+ }
44
+ // Export the reviewed commit, even if the task branch has since moved.
45
+ const ref = `refs/termdock/exports/${artifact.id}`;
46
+ await git(workspace.cwd, ['update-ref', ref, commit]);
47
+ const temporary = `${file}.${process.pid}.tmp`;
48
+ if (commit === base)
49
+ throw new Error('依赖未产生代码提交,无需传输;请检查项目基线是否一致');
50
+ try {
51
+ await git(workspace.cwd, ['bundle', 'create', temporary, ref, `^${base}`]);
52
+ const bytes = (await stat(temporary)).size;
53
+ if (bytes > maxBytes)
54
+ throw new Error('依赖提交包超过 128 MiB,请通过仓库远端同步后继续');
55
+ const metadata = { bytes, digest: await digestFile(temporary), commit, base, ref };
56
+ await rename(temporary, file);
57
+ await writeFile(`${metadataFile}.${process.pid}.tmp`, JSON.stringify(metadata), { mode: 0o600 });
58
+ await rename(`${metadataFile}.${process.pid}.tmp`, metadataFile);
59
+ return metadata;
60
+ }
61
+ finally {
62
+ await unlink(temporary).catch(() => { });
63
+ }
64
+ })().finally(() => preparing.delete(artifact.id));
65
+ preparing.set(artifact.id, operation);
66
+ return operation;
67
+ }
68
+ /** Chunks travel on the existing Noise RPC. No HTTP upload or repository credentials are introduced. */
69
+ export async function taskBundleChunk(task, offset) {
70
+ if (!Number.isSafeInteger(offset) || Number(offset) < 0 || Number(offset) % chunkSize !== 0)
71
+ throw new Error('提交包偏移无效');
72
+ const metadata = await prepareBundle(task);
73
+ if (Number(offset) >= metadata.bytes)
74
+ throw new Error('提交包偏移超出范围');
75
+ const artifact = acceptedCommit(task).artifact;
76
+ const file = await open(path.join(directory, `${artifact.id}.bundle`), 'r');
77
+ try {
78
+ const buffer = Buffer.alloc(Math.min(chunkSize, metadata.bytes - Number(offset)));
79
+ const { bytesRead } = await file.read(buffer, 0, buffer.length, Number(offset));
80
+ return { ...metadata, offset, data: buffer.subarray(0, bytesRead).toString('base64') };
81
+ }
82
+ finally {
83
+ await file.close();
84
+ }
85
+ }
86
+ export async function importTaskDependency(current, dependency, repository, peers, localRead) {
87
+ const expected = acceptedCommit(dependency);
88
+ await mkdir(directory, { recursive: true, mode: 0o700 });
89
+ const temporary = path.join(directory, `${expected.artifact.id}.incoming.${current.id}.${process.pid}.tmp`);
90
+ const file = await open(temporary, 'w', 0o600);
91
+ let offset = 0, digest = '', total = Infinity, ref = '';
92
+ try {
93
+ do {
94
+ const response = current.ownerServiceId === peers.descriptor().serviceId ? await localRead(current.id, dependency.id, offset)
95
+ : await peers.requestTasks(current.ownerServiceId, { op: 'dependency-bundle', taskId: current.id, dependencyId: dependency.id, offset });
96
+ const chunk = response.chunk;
97
+ if (!chunk || chunk.offset !== offset || chunk.commit !== expected.commit || chunk.base !== expected.base
98
+ || !Number.isSafeInteger(chunk.bytes) || chunk.bytes < 1 || chunk.bytes > maxBytes || typeof chunk.digest !== 'string' || !/^[a-f0-9]{64}$/.test(chunk.digest)
99
+ || chunk.ref !== `refs/termdock/exports/${expected.artifact.id}` || typeof chunk.data !== 'string' || chunk.data.length > 350_000
100
+ || digest && digest !== chunk.digest || offset && total !== chunk.bytes)
101
+ throw new Error('依赖提交包校验信息无效');
102
+ digest = chunk.digest;
103
+ total = chunk.bytes;
104
+ ref = chunk.ref;
105
+ const bytes = Buffer.from(chunk.data, 'base64');
106
+ if (!bytes.length || bytes.length > chunkSize || offset + bytes.length > total)
107
+ throw new Error('依赖提交包分片无效');
108
+ await file.write(bytes, 0, bytes.length, offset);
109
+ offset += bytes.length;
110
+ } while (offset < total);
111
+ await file.close();
112
+ if (await digestFile(temporary) !== digest)
113
+ throw new Error('依赖提交包摘要不匹配,保留任务等待重试');
114
+ await git(repository, ['bundle', 'verify', temporary]);
115
+ await git(repository, ['fetch', '--no-tags', temporary, ref]);
116
+ }
117
+ finally {
118
+ await file.close().catch(() => { });
119
+ await unlink(temporary).catch(() => { });
120
+ }
121
+ }
@@ -0,0 +1,54 @@
1
+ import fs from 'node:fs';
2
+ import { randomUUID } from 'node:crypto';
3
+ export async function executeTaskCommand(command, request, io) {
4
+ const o = command.options, operation = command.operation;
5
+ const bodyOptions = ['content', 'file', 'stdin', 'idempotency-key'];
6
+ const allowed = {
7
+ list: ['group'], get: [], create: [...bodyOptions, 'group', 'title', 'constraints', 'acceptance', 'assignee', 'coordinator', 'parent', 'depends-on', 'managed', 'reviewers', 'shared-directory', 'integration'],
8
+ assign: [...bodyOptions, 'assignee', 'revision'], report: [...bodyOptions, 'attempt', 'status', 'evidence'], ask: [...bodyOptions, 'attempt', 'options'],
9
+ plan: [...bodyOptions, 'attempt', 'evidence'], review: [...bodyOptions, 'artifact', 'evidence', 'verdict'], comment: bodyOptions,
10
+ 'request-review': [...bodyOptions, 'artifact', 'assignee', 'revision'],
11
+ revise: [...bodyOptions, 'revision'], close: [...bodyOptions, 'revision'], reopen: [...bodyOptions, 'revision'],
12
+ coordinate: [...bodyOptions, 'revision'], pause: [...bodyOptions, 'revision'], resume: [...bodyOptions, 'revision'], retry: [...bodyOptions, 'revision'],
13
+ };
14
+ for (const flag of Object.keys(o))
15
+ if (![...allowed[operation], 'session', 'json', 'jsonl', 'text', 'help'].includes(flag))
16
+ throw new Error(`--${flag} is not supported by task ${operation}`);
17
+ if (operation === 'list')
18
+ return request('GET', `/tasks${o.group ? `?group=${encodeURIComponent(String(o.group))}` : ''}`);
19
+ if (operation === 'get')
20
+ return request('GET', `/tasks/${encodeURIComponent(command.target)}`);
21
+ const contentSources = [o.content, o.file, o.stdin].filter(Boolean).length;
22
+ if (contentSources > 1)
23
+ throw new Error('Choose --content, --file or --stdin');
24
+ const content = o.file ? fs.readFileSync(String(o.file), 'utf8') : o.stdin ? await io.stdin?.() : o.content;
25
+ if (!['assign', 'close', 'reopen', 'request-review', 'pause', 'resume', 'retry'].includes(operation) && (typeof content !== 'string' || !content.trim()))
26
+ throw new Error('This task operation requires --content, --file or --stdin');
27
+ const idempotencyKey = String(o['idempotency-key'] ?? randomUUID());
28
+ const expectedRevision = o.revision === undefined ? undefined : Number(o.revision);
29
+ if (expectedRevision !== undefined && (!Number.isSafeInteger(expectedRevision) || expectedRevision < 1))
30
+ throw new Error('--revision must be a positive integer');
31
+ if (['assign', 'revise', 'close', 'reopen', 'request-review', 'coordinate', 'pause', 'resume', 'retry'].includes(operation) && expectedRevision === undefined)
32
+ throw new Error('Read task get first, then supply --revision to avoid overwriting another decision');
33
+ if (['assign', 'request-review'].includes(operation) && !o.assignee)
34
+ throw new Error('This task operation requires --assignee');
35
+ if (['report', 'ask', 'plan'].includes(operation) && !o.attempt)
36
+ throw new Error('Use --attempt from the dispatch message; never guess the current attempt');
37
+ if (operation === 'create') {
38
+ if (!o.title || !o.group)
39
+ throw new Error('task create requires --title and --group');
40
+ return request('POST', '/tasks', { input: { idempotencyKey, groupId: o.group, title: o.title, spec: content,
41
+ constraints: o.constraints, acceptance: o.acceptance, assigneeSessionId: o.assignee, coordinatorSessionId: o.coordinator,
42
+ parentTaskId: o.parent, dependsOn: o['depends-on'] ? String(o['depends-on']).split(',').filter(Boolean) : undefined,
43
+ integration: o.integration === true, managed: o.managed === true, isolated: o['shared-directory'] !== true,
44
+ reviewerSessionIds: o.reviewers ? String(o.reviewers).split(',').filter(Boolean) : undefined } });
45
+ }
46
+ const options = o.options ? JSON.parse(String(o.options)) : undefined;
47
+ if (options !== undefined && (!Array.isArray(options) || options.some(v => typeof v !== 'string')))
48
+ throw new Error('--options must be a JSON array of strings');
49
+ return request('POST', `/tasks/${encodeURIComponent(command.target)}`, { input: {
50
+ kind: operation === 'plan' ? 'submit-plan' : operation, idempotencyKey, expectedRevision, content,
51
+ assigneeSessionId: o.assignee, attemptId: o.attempt, status: o.status, artifactId: o.artifact, options, verdict: o.verdict,
52
+ evidence: o.evidence ? JSON.parse(String(o.evidence)) : undefined,
53
+ } });
54
+ }
@@ -0,0 +1,58 @@
1
+ import { Router } from 'express';
2
+ import { CollaborationError } from './collaborationProtocol.js';
3
+ import { assertPeerRegistrationAuthority } from './collaborationPeerTransport.js';
4
+ export function collaborationTaskRoutes(options) {
5
+ const router = Router();
6
+ const groupId = (value) => {
7
+ const resolved = options.store.resolveGroupId(value);
8
+ if (resolved.status !== 'ok')
9
+ throw new CollaborationError(resolved.status === 'ambiguous' ? 'GROUP_ID_AMBIGUOUS' : 'TASK_GROUP_NOT_FOUND', '请使用存在且唯一的协作组 ID', resolved.status === 'ambiguous' ? 409 : 404);
10
+ return resolved.id;
11
+ };
12
+ const context = (req) => {
13
+ const tasks = req.app.locals.collaborationTasks;
14
+ const peers = req.app.locals.collaborationService;
15
+ if (!tasks || !peers)
16
+ throw new CollaborationError('TASK_SERVICE_STARTING', '任务服务正在启动,请稍后重试', 503);
17
+ if (!options.agent) {
18
+ try {
19
+ assertPeerRegistrationAuthority(req);
20
+ }
21
+ catch {
22
+ throw new CollaborationError('TASK_PERMISSION_DENIED', '当前连接无权处理协作任务', 403);
23
+ }
24
+ return { tasks, peers, actor: null };
25
+ }
26
+ const sessionId = options.resolveSession((req.method === 'GET' ? req.query : req.body) ?? {});
27
+ if (!sessionId || sessionId.startsWith('remote:'))
28
+ throw new CollaborationError('SESSION_NOT_FOUND', '请在 Termdock 管理的本机会话内使用任务命令', 404);
29
+ return { tasks, peers, actor: peers.taskMember(sessionId) };
30
+ };
31
+ const run = (handler) => async (req, res) => {
32
+ try {
33
+ res.json(await handler(req, context(req)));
34
+ }
35
+ catch (error) {
36
+ res.status(error instanceof CollaborationError ? error.httpStatus : 400).json({ ok: false,
37
+ code: error instanceof CollaborationError ? error.code : 'TASK_ERROR', error: error instanceof Error ? error.message : String(error) });
38
+ }
39
+ };
40
+ router.get('/', run((req, { tasks, actor }) => {
41
+ const requested = typeof req.query.group === 'string' ? groupId(req.query.group) : null;
42
+ const groups = requested ? [requested] : actor ? options.store.groupsForSession(actor.sessionId).map(g => g.id) : options.store.list().map(g => g.id);
43
+ return { tasks: groups.flatMap(id => tasks.list(id, actor)) };
44
+ }));
45
+ router.get('/:taskId', run(async (req, { tasks, actor }) => ({ task: await tasks.get(req.params.taskId, actor) })));
46
+ const input = (req, peers) => {
47
+ const body = req.body?.input;
48
+ if (!body || typeof body !== 'object' || Array.isArray(body))
49
+ throw new CollaborationError('INVALID_TASK', '需要任务内容');
50
+ if (body.reviewerSessionIds !== undefined && (!Array.isArray(body.reviewerSessionIds) || body.reviewerSessionIds.length > 32 || body.reviewerSessionIds.some((v) => typeof v !== 'string')))
51
+ throw new CollaborationError('INVALID_REVIEWERS', '执行成员列表无效');
52
+ return { ...body, ...(body.reviewerSessionIds ? { reviewers: body.reviewerSessionIds.map((id) => peers.taskMember(id)) } : {}), ...(typeof body.groupId === 'string' ? { groupId: groupId(body.groupId) } : {}), ...(body.assigneeSessionId ? { assignee: peers.taskMember(String(body.assigneeSessionId)) } : {}),
53
+ ...(body.coordinatorSessionId !== undefined ? { coordinator: body.coordinatorSessionId ? peers.taskMember(String(body.coordinatorSessionId)) : null } : {}) };
54
+ };
55
+ router.post('/', run(async (req, { tasks, peers, actor }) => ({ task: await tasks.create(input(req, peers), actor) })));
56
+ router.post('/:taskId', run(async (req, { tasks, peers, actor }) => ({ task: await tasks.apply(req.params.taskId, input(req, peers), actor) })));
57
+ return router;
58
+ }