termdock 1.4.173 → 1.4.175

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 (357) hide show
  1. package/.desktop-dist/main.js +204 -7
  2. package/dist/client/assets/App-BXYZyI_k.js +150 -0
  3. package/dist/client/assets/App-BXYZyI_k.js.br +0 -0
  4. package/dist/client/assets/App-BXYZyI_k.js.gz +0 -0
  5. package/dist/client/assets/ChangeWalkthroughPanel-DeVtCf73.js +2 -0
  6. package/dist/client/assets/ChangeWalkthroughPanel-DeVtCf73.js.br +0 -0
  7. package/dist/client/assets/ChangeWalkthroughPanel-DeVtCf73.js.gz +0 -0
  8. package/dist/client/assets/DagPlayground-ZIqLZoMo.js +1 -0
  9. package/dist/client/assets/DagPlayground-ZIqLZoMo.js.br +0 -0
  10. package/dist/client/assets/DagPlayground-ZIqLZoMo.js.gz +0 -0
  11. package/dist/client/assets/{DiffLab-xuS6rtpv.js → DiffLab-CSMf8So2.js} +2 -2
  12. package/dist/client/assets/DiffLab-CSMf8So2.js.br +0 -0
  13. package/dist/client/assets/DiffLab-CSMf8So2.js.gz +0 -0
  14. package/dist/client/assets/DiffReview-CE5lW1zQ.js +1 -0
  15. package/dist/client/assets/DiffReview-CE5lW1zQ.js.br +0 -0
  16. package/dist/client/assets/DiffReview-CE5lW1zQ.js.gz +0 -0
  17. package/dist/client/assets/DiffReviewLab-CpUW75fZ.js +2 -0
  18. package/dist/client/assets/DiffReviewLab-CpUW75fZ.js.br +0 -0
  19. package/dist/client/assets/DiffReviewLab-CpUW75fZ.js.gz +0 -0
  20. package/dist/client/assets/{DiffViewer-BQGXUr8t.js → DiffViewer-BomvZ4kq.js} +5 -5
  21. package/dist/client/assets/DiffViewer-BomvZ4kq.js.br +0 -0
  22. package/dist/client/assets/DiffViewer-BomvZ4kq.js.gz +0 -0
  23. package/dist/client/assets/{ModelPreview-BfZzS1_d.js → ModelPreview-BWdZFyhh.js} +3 -3
  24. package/dist/client/assets/ModelPreview-BWdZFyhh.js.br +0 -0
  25. package/dist/client/assets/ModelPreview-BWdZFyhh.js.gz +0 -0
  26. package/dist/client/assets/RightSidebar-CYVwFbOc.js +79 -0
  27. package/dist/client/assets/RightSidebar-CYVwFbOc.js.br +0 -0
  28. package/dist/client/assets/RightSidebar-CYVwFbOc.js.gz +0 -0
  29. package/dist/client/assets/{abnfDiagram-VCTEODGH-Dn_lmPcC.js → abnfDiagram-VCTEODGH-BIPsLStE.js} +1 -1
  30. package/dist/client/assets/abnfDiagram-VCTEODGH-BIPsLStE.js.br +0 -0
  31. package/dist/client/assets/abnfDiagram-VCTEODGH-BIPsLStE.js.gz +0 -0
  32. package/dist/client/assets/app-D6KzR8B3.js +34 -0
  33. package/dist/client/assets/app-D6KzR8B3.js.br +0 -0
  34. package/dist/client/assets/app-D6KzR8B3.js.gz +0 -0
  35. package/dist/client/assets/{arc-DUybtKGZ.js → arc-DzeT6hBj.js} +1 -1
  36. package/dist/client/assets/arc-DzeT6hBj.js.br +0 -0
  37. package/dist/client/assets/arc-DzeT6hBj.js.gz +0 -0
  38. package/dist/client/assets/{architectureDiagram-5GKGNRK7-CLEmOHBp.js → architectureDiagram-5GKGNRK7-B1qsxd_5.js} +1 -1
  39. package/dist/client/assets/architectureDiagram-5GKGNRK7-B1qsxd_5.js.br +0 -0
  40. package/dist/client/assets/architectureDiagram-5GKGNRK7-B1qsxd_5.js.gz +0 -0
  41. package/dist/client/assets/{blockDiagram-I7D4REHJ-O_XM5b9_.js → blockDiagram-I7D4REHJ-NLsa29Jp.js} +1 -1
  42. package/dist/client/assets/blockDiagram-I7D4REHJ-NLsa29Jp.js.br +0 -0
  43. package/dist/client/assets/blockDiagram-I7D4REHJ-NLsa29Jp.js.gz +0 -0
  44. package/dist/client/assets/{c4Diagram-7LVT6UL2-DlUEslcV.js → c4Diagram-7LVT6UL2-DBAUvou3.js} +1 -1
  45. package/dist/client/assets/c4Diagram-7LVT6UL2-DBAUvou3.js.br +0 -0
  46. package/dist/client/assets/c4Diagram-7LVT6UL2-DBAUvou3.js.gz +0 -0
  47. package/dist/client/assets/channel-BhwBAWhq.js +1 -0
  48. package/dist/client/assets/{chunk-2Q5K7J3B-DCrP6W79.js → chunk-2Q5K7J3B-BsVAXGLa.js} +1 -1
  49. package/dist/client/assets/{chunk-5VM5RSS4-Zm6_pYQv.js → chunk-5VM5RSS4-BKtILsst.js} +1 -1
  50. package/dist/client/assets/{chunk-F27PBJKO-DkyD-X9z.js → chunk-F27PBJKO-Dn9zcQZG.js} +1 -1
  51. package/dist/client/assets/chunk-F27PBJKO-Dn9zcQZG.js.br +0 -0
  52. package/dist/client/assets/chunk-F27PBJKO-Dn9zcQZG.js.gz +0 -0
  53. package/dist/client/assets/{chunk-IMKFNOWR-UvWxXAkh.js → chunk-IMKFNOWR-MVtVQeTr.js} +1 -1
  54. package/dist/client/assets/chunk-IMKFNOWR-MVtVQeTr.js.br +0 -0
  55. package/dist/client/assets/chunk-IMKFNOWR-MVtVQeTr.js.gz +0 -0
  56. package/dist/client/assets/{chunk-JWPE2WC7-BjeBAFYM.js → chunk-JWPE2WC7-DliIIMe7.js} +1 -1
  57. package/dist/client/assets/{chunk-POPQ4Y6H-CnqrQdZC.js → chunk-POPQ4Y6H-XBSus3IC.js} +1 -1
  58. package/dist/client/assets/{chunk-SVP7TREG-C4a1s0v4.js → chunk-SVP7TREG-wleSQcJR.js} +1 -1
  59. package/dist/client/assets/chunk-SVP7TREG-wleSQcJR.js.br +0 -0
  60. package/dist/client/assets/chunk-SVP7TREG-wleSQcJR.js.gz +0 -0
  61. package/dist/client/assets/{chunk-TICWLB2K-hnmjYAl_.js → chunk-TICWLB2K-Dq6LdswN.js} +1 -1
  62. package/dist/client/assets/chunk-TICWLB2K-Dq6LdswN.js.br +0 -0
  63. package/dist/client/assets/chunk-TICWLB2K-Dq6LdswN.js.gz +0 -0
  64. package/dist/client/assets/{chunk-XXDRQBXY-xR4LOz28.js → chunk-XXDRQBXY-xafyKlM-.js} +1 -1
  65. package/dist/client/assets/classDiagram-ZZMXUADV-slQB0ns2.js +1 -0
  66. package/dist/client/assets/classDiagram-v2-VYDZK3BY-slQB0ns2.js +1 -0
  67. package/dist/client/assets/{cose-bilkent-JH36ORCC-CqY84fFp.js → cose-bilkent-JH36ORCC-BR7Ohnm_.js} +1 -1
  68. package/dist/client/assets/cose-bilkent-JH36ORCC-BR7Ohnm_.js.br +0 -0
  69. package/dist/client/assets/cose-bilkent-JH36ORCC-BR7Ohnm_.js.gz +0 -0
  70. package/dist/client/assets/{cynefin-OW5HDTMX-Bd14zuaD.js → cynefin-OW5HDTMX-CmPjQgER.js} +1 -1
  71. package/dist/client/assets/cynefin-OW5HDTMX-CmPjQgER.js.br +0 -0
  72. package/dist/client/assets/cynefin-OW5HDTMX-CmPjQgER.js.gz +0 -0
  73. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-DSHcNXDs.js → cynefinDiagram-5FMLGOSQ-CFyR9RvM.js} +1 -1
  74. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CFyR9RvM.js.br +0 -0
  75. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CFyR9RvM.js.gz +0 -0
  76. package/dist/client/assets/{dagre-GXQ25YYZ-CIGWQYeP.js → dagre-GXQ25YYZ-D_RVMRO1.js} +1 -1
  77. package/dist/client/assets/dagre-GXQ25YYZ-D_RVMRO1.js.br +0 -0
  78. package/dist/client/assets/dagre-GXQ25YYZ-D_RVMRO1.js.gz +0 -0
  79. package/dist/client/assets/{diagram-S7CK7UJ4-C9Fg7OLN.js → diagram-S7CK7UJ4-6fr-ZoPj.js} +1 -1
  80. package/dist/client/assets/diagram-S7CK7UJ4-6fr-ZoPj.js.br +0 -0
  81. package/dist/client/assets/diagram-S7CK7UJ4-6fr-ZoPj.js.gz +0 -0
  82. package/dist/client/assets/{diagram-UQ7AKVKN-DoRhl7Fd.js → diagram-UQ7AKVKN-CgwiUtz0.js} +1 -1
  83. package/dist/client/assets/diagram-UQ7AKVKN-CgwiUtz0.js.br +0 -0
  84. package/dist/client/assets/diagram-UQ7AKVKN-CgwiUtz0.js.gz +0 -0
  85. package/dist/client/assets/{diagram-VSXAHHWV-CI83g3iM.js → diagram-VSXAHHWV-CLxzTB9k.js} +1 -1
  86. package/dist/client/assets/diagram-VSXAHHWV-CLxzTB9k.js.br +0 -0
  87. package/dist/client/assets/diagram-VSXAHHWV-CLxzTB9k.js.gz +0 -0
  88. package/dist/client/assets/{diagram-VX7I27RA-Dp2kP4PB.js → diagram-VX7I27RA-DjxDAvdZ.js} +1 -1
  89. package/dist/client/assets/diagram-VX7I27RA-DjxDAvdZ.js.br +0 -0
  90. package/dist/client/assets/diagram-VX7I27RA-DjxDAvdZ.js.gz +0 -0
  91. package/dist/client/assets/{diagram-Z3DM3KII-KtLMCM-V.js → diagram-Z3DM3KII-CDPOjiz4.js} +1 -1
  92. package/dist/client/assets/diagram-Z3DM3KII-CDPOjiz4.js.br +0 -0
  93. package/dist/client/assets/diagram-Z3DM3KII-CDPOjiz4.js.gz +0 -0
  94. package/dist/client/assets/{ebnfDiagram-PWID7BFC-D_zseu1m.js → ebnfDiagram-PWID7BFC-BLbwyF1O.js} +1 -1
  95. package/dist/client/assets/ebnfDiagram-PWID7BFC-BLbwyF1O.js.br +0 -0
  96. package/dist/client/assets/ebnfDiagram-PWID7BFC-BLbwyF1O.js.gz +0 -0
  97. package/dist/client/assets/{erDiagram-RLTQ6QDP-DaWUl_Kz.js → erDiagram-RLTQ6QDP-DbjtZnJx.js} +1 -1
  98. package/dist/client/assets/{erDiagram-RLTQ6QDP-DaWUl_Kz.js.br → erDiagram-RLTQ6QDP-DbjtZnJx.js.br} +0 -0
  99. package/dist/client/assets/erDiagram-RLTQ6QDP-DbjtZnJx.js.gz +0 -0
  100. package/dist/client/assets/{flowDiagram-HODETNUW-BMoJ46zJ.js → flowDiagram-HODETNUW-BirJInAN.js} +1 -1
  101. package/dist/client/assets/flowDiagram-HODETNUW-BirJInAN.js.br +0 -0
  102. package/dist/client/assets/flowDiagram-HODETNUW-BirJInAN.js.gz +0 -0
  103. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-lV_iVmoW.js → ganttDiagram-EL5Y4UJY-d6Q9vSbv.js} +1 -1
  104. package/dist/client/assets/ganttDiagram-EL5Y4UJY-d6Q9vSbv.js.br +0 -0
  105. package/dist/client/assets/ganttDiagram-EL5Y4UJY-d6Q9vSbv.js.gz +0 -0
  106. package/dist/client/assets/gestureArbiter-C2J0D0kV.css +1 -0
  107. package/dist/client/assets/gestureArbiter-C2J0D0kV.css.br +0 -0
  108. package/dist/client/assets/gestureArbiter-C2J0D0kV.css.gz +0 -0
  109. package/dist/client/assets/gestureArbiter-D1SNS_gK.js +1 -0
  110. package/dist/client/assets/gestureArbiter-D1SNS_gK.js.br +0 -0
  111. package/dist/client/assets/gestureArbiter-D1SNS_gK.js.gz +0 -0
  112. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-BVCT9Btd.js → gitGraphDiagram-WWUBYQGX-BWBoIeS6.js} +1 -1
  113. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BWBoIeS6.js.br +0 -0
  114. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BWBoIeS6.js.gz +0 -0
  115. package/dist/client/assets/{index-CnKSUg74.css → index-DUI8KRf6.css} +1 -1
  116. package/dist/client/assets/index-DUI8KRf6.css.br +0 -0
  117. package/dist/client/assets/index-DUI8KRf6.css.gz +0 -0
  118. package/dist/client/assets/{infoDiagram-27XIBGKW-BVhXOx1S.js → infoDiagram-27XIBGKW-BH4AynkM.js} +1 -1
  119. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-Cyzfuoys.js → ishikawaDiagram-5VMMS53U-BQw90AKR.js} +1 -1
  120. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BQw90AKR.js.br +0 -0
  121. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BQw90AKR.js.gz +0 -0
  122. package/dist/client/assets/{journeyDiagram-3NMN7TZE-CEIPDhQF.js → journeyDiagram-3NMN7TZE-DISkQocf.js} +1 -1
  123. package/dist/client/assets/journeyDiagram-3NMN7TZE-DISkQocf.js.br +0 -0
  124. package/dist/client/assets/journeyDiagram-3NMN7TZE-DISkQocf.js.gz +0 -0
  125. package/dist/client/assets/{kanban-definition-UXKFOSKX-C8OulEOF.js → kanban-definition-UXKFOSKX-Qg2LyEVy.js} +1 -1
  126. package/dist/client/assets/kanban-definition-UXKFOSKX-Qg2LyEVy.js.br +0 -0
  127. package/dist/client/assets/kanban-definition-UXKFOSKX-Qg2LyEVy.js.gz +0 -0
  128. package/dist/client/assets/{layout-YN93qRzb.js → layout-Cd7-4_Vr.js} +1 -1
  129. package/dist/client/assets/layout-Cd7-4_Vr.js.br +0 -0
  130. package/dist/client/assets/layout-Cd7-4_Vr.js.gz +0 -0
  131. package/dist/client/assets/{linear-D9T4dYh7.js → linear-DFTi2fTn.js} +1 -1
  132. package/dist/client/assets/linear-DFTi2fTn.js.br +0 -0
  133. package/dist/client/assets/linear-DFTi2fTn.js.gz +0 -0
  134. package/dist/client/assets/{mermaid.core-BdCvvCGV.js → mermaid.core-2v726lUU.js} +5 -5
  135. package/dist/client/assets/mermaid.core-2v726lUU.js.br +0 -0
  136. package/dist/client/assets/mermaid.core-2v726lUU.js.gz +0 -0
  137. package/dist/client/assets/{mindmap-definition-YA3MSWOX-CSpES3Jh.js → mindmap-definition-YA3MSWOX-_FpwteCy.js} +4 -4
  138. package/dist/client/assets/mindmap-definition-YA3MSWOX-_FpwteCy.js.br +0 -0
  139. package/dist/client/assets/mindmap-definition-YA3MSWOX-_FpwteCy.js.gz +0 -0
  140. package/dist/client/assets/passwordBootstrap-D9Ffc7NY.js +2 -0
  141. package/dist/client/assets/passwordBootstrap-D9Ffc7NY.js.br +0 -0
  142. package/dist/client/assets/passwordBootstrap-D9Ffc7NY.js.gz +0 -0
  143. package/dist/client/assets/{pegDiagram-XKGWAZYB-6f4vAA1Q.js → pegDiagram-XKGWAZYB-DLFf-HmZ.js} +1 -1
  144. package/dist/client/assets/pegDiagram-XKGWAZYB-DLFf-HmZ.js.br +0 -0
  145. package/dist/client/assets/pegDiagram-XKGWAZYB-DLFf-HmZ.js.gz +0 -0
  146. package/dist/client/assets/{pieDiagram-E7YTZNPT-BC4Jd-I8.js → pieDiagram-E7YTZNPT-DqTnfXHG.js} +1 -1
  147. package/dist/client/assets/pieDiagram-E7YTZNPT-DqTnfXHG.js.br +0 -0
  148. package/dist/client/assets/pieDiagram-E7YTZNPT-DqTnfXHG.js.gz +0 -0
  149. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-B0pnPaEN.js → quadrantDiagram-AXDQQJYC-B_oBH52Q.js} +1 -1
  150. package/dist/client/assets/quadrantDiagram-AXDQQJYC-B_oBH52Q.js.br +0 -0
  151. package/dist/client/assets/quadrantDiagram-AXDQQJYC-B_oBH52Q.js.gz +0 -0
  152. package/dist/client/assets/{railroadDiagram-O6MQD6OU-B-oOamZT.js → railroadDiagram-O6MQD6OU-HxFQ7Pce.js} +1 -1
  153. package/dist/client/assets/railroadDiagram-O6MQD6OU-HxFQ7Pce.js.br +0 -0
  154. package/dist/client/assets/railroadDiagram-O6MQD6OU-HxFQ7Pce.js.gz +0 -0
  155. package/dist/client/assets/referenceLongPress-B3NGIjvv.js +1 -0
  156. package/dist/client/assets/referenceLongPress-B3NGIjvv.js.br +0 -0
  157. package/dist/client/assets/referenceLongPress-B3NGIjvv.js.gz +0 -0
  158. package/dist/client/assets/{requirementDiagram-BXWQKSXE-DBSyxt0k.js → requirementDiagram-BXWQKSXE-NZdfaZFk.js} +1 -1
  159. package/dist/client/assets/requirementDiagram-BXWQKSXE-NZdfaZFk.js.br +0 -0
  160. package/dist/client/assets/requirementDiagram-BXWQKSXE-NZdfaZFk.js.gz +0 -0
  161. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-CcohzEZE.js → sankeyDiagram-P5KCCOFB-BgCctv6X.js} +1 -1
  162. package/dist/client/assets/sankeyDiagram-P5KCCOFB-BgCctv6X.js.br +0 -0
  163. package/dist/client/assets/sankeyDiagram-P5KCCOFB-BgCctv6X.js.gz +0 -0
  164. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-D7KS6rq_.js → sequenceDiagram-WJ2MYXX4-Br42Za1R.js} +1 -1
  165. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-Br42Za1R.js.br +0 -0
  166. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-Br42Za1R.js.gz +0 -0
  167. package/dist/client/assets/{sizeCapture-INFHLROL-CaRXtn4g.js → sizeCapture-INFHLROL-FT4z4S1b.js} +1 -1
  168. package/dist/client/assets/sizeCapture-INFHLROL-FT4z4S1b.js.br +0 -0
  169. package/dist/client/assets/sizeCapture-INFHLROL-FT4z4S1b.js.gz +0 -0
  170. package/dist/client/assets/sparkles-BaGaevME.js +1 -0
  171. package/dist/client/assets/{stateDiagram-D77RDMKH-Dz836LqY.js → stateDiagram-D77RDMKH-DD0t9f84.js} +1 -1
  172. package/dist/client/assets/stateDiagram-D77RDMKH-DD0t9f84.js.br +0 -0
  173. package/dist/client/assets/stateDiagram-D77RDMKH-DD0t9f84.js.gz +0 -0
  174. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-BhvVVB56.js +1 -0
  175. package/dist/client/assets/{swimlanes-42K2YHIH-BK4KAY00.js → swimlanes-42K2YHIH-DcC8pGLx.js} +1 -1
  176. package/dist/client/assets/swimlanes-42K2YHIH-DcC8pGLx.js.br +0 -0
  177. package/dist/client/assets/swimlanes-42K2YHIH-DcC8pGLx.js.gz +0 -0
  178. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DSC5lz0i.js +8 -0
  179. package/dist/client/assets/{timeline-definition-24CTP7MA-DWgxTDhO.js → timeline-definition-24CTP7MA-DnwO_Pxd.js} +1 -1
  180. package/dist/client/assets/timeline-definition-24CTP7MA-DnwO_Pxd.js.br +0 -0
  181. package/dist/client/assets/timeline-definition-24CTP7MA-DnwO_Pxd.js.gz +0 -0
  182. package/dist/client/assets/triangle-alert-BCQO9Ap9.js +1 -0
  183. package/dist/client/assets/{vennDiagram-4TSXK5OY-BV1TIfOp.js → vennDiagram-4TSXK5OY-IVNSrZDM.js} +1 -1
  184. package/dist/client/assets/vennDiagram-4TSXK5OY-IVNSrZDM.js.br +0 -0
  185. package/dist/client/assets/vennDiagram-4TSXK5OY-IVNSrZDM.js.gz +0 -0
  186. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-GYClC5F0.js → wardleyDiagram-VM6X3IG4-BnGetaQL.js} +1 -1
  187. package/dist/client/assets/wardleyDiagram-VM6X3IG4-BnGetaQL.js.br +0 -0
  188. package/dist/client/assets/wardleyDiagram-VM6X3IG4-BnGetaQL.js.gz +0 -0
  189. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-D1oKV5W0.js → xychartDiagram-S5SC5T6Z-C01eBN-W.js} +1 -1
  190. package/dist/client/assets/xychartDiagram-S5SC5T6Z-C01eBN-W.js.br +0 -0
  191. package/dist/client/assets/xychartDiagram-S5SC5T6Z-C01eBN-W.js.gz +0 -0
  192. package/dist/client/index.html +2 -2
  193. package/dist/client/index.html.br +0 -0
  194. package/dist/client/index.html.gz +0 -0
  195. package/dist/client/preview-shell.html +1 -0
  196. package/dist/client/preview-shell.js +20 -0
  197. package/dist/client/preview-shell.js.br +0 -0
  198. package/dist/client/preview-shell.js.gz +0 -0
  199. package/dist/client/sw-secure-api.js +132 -0
  200. package/dist/client/sw-secure-api.js.br +0 -0
  201. package/dist/client/sw-secure-api.js.gz +0 -0
  202. package/dist/client/sw.js +1 -1
  203. package/dist/client/sw.js.br +0 -0
  204. package/dist/client/sw.js.gz +0 -0
  205. package/dist/server/agent/collaborationCli.js +298 -0
  206. package/dist/server/agent/collaborationPrompt.js +12 -3
  207. package/dist/server/agent/collaborationProtocol.js +50 -0
  208. package/dist/server/agent/collaborationRoutes.js +86 -0
  209. package/dist/server/agent/collaborationStore.js +311 -20
  210. package/dist/server/cli.js +28 -163
  211. package/dist/server/entry.js +114 -51
  212. package/dist/server/federation/accessPolicy.js +122 -0
  213. package/dist/server/federation/authorization.js +226 -0
  214. package/dist/server/federation/bootstrapCors.js +23 -0
  215. package/dist/server/federation/cli.js +185 -0
  216. package/dist/server/federation/deviceNames.js +29 -0
  217. package/dist/server/federation/directRoutes.js +72 -0
  218. package/dist/server/federation/invitations.js +123 -0
  219. package/dist/server/federation/openAccess.js +25 -0
  220. package/dist/server/federation/originPolicy.js +19 -0
  221. package/dist/server/federation/packets.js +116 -0
  222. package/dist/server/federation/passwordBootstrap.js +86 -0
  223. package/dist/server/federation/passwordLoginRoutes.js +98 -0
  224. package/dist/server/federation/relay.js +346 -0
  225. package/dist/server/federation/requestContext.js +4 -0
  226. package/dist/server/federation/routeAccess.js +124 -0
  227. package/dist/server/federation/routeInvitations.js +160 -0
  228. package/dist/server/federation/runtime.js +537 -0
  229. package/dist/server/federation/secureProtocol.js +223 -0
  230. package/dist/server/federation/socketDuplex.js +42 -0
  231. package/dist/server/federation/streamLimits.js +5 -0
  232. package/dist/server/routes/filesystem.js +2 -1
  233. package/dist/server/routes/terminal.js +89 -79
  234. package/dist/server/utils/authProtection.js +13 -0
  235. package/dist/server/utils/csrfProtection.js +3 -0
  236. package/dist/server/utils/publicSecurity.js +8 -3
  237. package/package.json +10 -3
  238. package/runtime-manifest.json +4 -4
  239. package/dist/client/assets/ChangeWalkthroughPanel-DKj7F0ex.js +0 -2
  240. package/dist/client/assets/ChangeWalkthroughPanel-DKj7F0ex.js.br +0 -0
  241. package/dist/client/assets/ChangeWalkthroughPanel-DKj7F0ex.js.gz +0 -0
  242. package/dist/client/assets/DagPlayground-D2Wui4jd.js +0 -1
  243. package/dist/client/assets/DagPlayground-D2Wui4jd.js.br +0 -0
  244. package/dist/client/assets/DagPlayground-D2Wui4jd.js.gz +0 -0
  245. package/dist/client/assets/DiffLab-xuS6rtpv.js.br +0 -0
  246. package/dist/client/assets/DiffLab-xuS6rtpv.js.gz +0 -0
  247. package/dist/client/assets/DiffReview-CAwpqM_w.js +0 -1
  248. package/dist/client/assets/DiffReview-CAwpqM_w.js.br +0 -0
  249. package/dist/client/assets/DiffReview-CAwpqM_w.js.gz +0 -0
  250. package/dist/client/assets/DiffReviewLab-BM_uGdyI.js +0 -2
  251. package/dist/client/assets/DiffReviewLab-BM_uGdyI.js.br +0 -0
  252. package/dist/client/assets/DiffReviewLab-BM_uGdyI.js.gz +0 -0
  253. package/dist/client/assets/DiffViewer-BQGXUr8t.js.br +0 -0
  254. package/dist/client/assets/DiffViewer-BQGXUr8t.js.gz +0 -0
  255. package/dist/client/assets/ModelPreview-BfZzS1_d.js.br +0 -0
  256. package/dist/client/assets/ModelPreview-BfZzS1_d.js.gz +0 -0
  257. package/dist/client/assets/RightSidebar-Cdqt3C7V.js +0 -55
  258. package/dist/client/assets/RightSidebar-Cdqt3C7V.js.br +0 -0
  259. package/dist/client/assets/RightSidebar-Cdqt3C7V.js.gz +0 -0
  260. package/dist/client/assets/abnfDiagram-VCTEODGH-Dn_lmPcC.js.br +0 -0
  261. package/dist/client/assets/abnfDiagram-VCTEODGH-Dn_lmPcC.js.gz +0 -0
  262. package/dist/client/assets/app-DDCkFsNe.js +0 -175
  263. package/dist/client/assets/app-DDCkFsNe.js.br +0 -0
  264. package/dist/client/assets/app-DDCkFsNe.js.gz +0 -0
  265. package/dist/client/assets/arc-DUybtKGZ.js.br +0 -0
  266. package/dist/client/assets/arc-DUybtKGZ.js.gz +0 -0
  267. package/dist/client/assets/architectureDiagram-5GKGNRK7-CLEmOHBp.js.br +0 -0
  268. package/dist/client/assets/architectureDiagram-5GKGNRK7-CLEmOHBp.js.gz +0 -0
  269. package/dist/client/assets/blockDiagram-I7D4REHJ-O_XM5b9_.js.br +0 -0
  270. package/dist/client/assets/blockDiagram-I7D4REHJ-O_XM5b9_.js.gz +0 -0
  271. package/dist/client/assets/c4Diagram-7LVT6UL2-DlUEslcV.js.br +0 -0
  272. package/dist/client/assets/c4Diagram-7LVT6UL2-DlUEslcV.js.gz +0 -0
  273. package/dist/client/assets/channel-Bk1VkYvd.js +0 -1
  274. package/dist/client/assets/chunk-F27PBJKO-DkyD-X9z.js.br +0 -0
  275. package/dist/client/assets/chunk-F27PBJKO-DkyD-X9z.js.gz +0 -0
  276. package/dist/client/assets/chunk-IMKFNOWR-UvWxXAkh.js.br +0 -0
  277. package/dist/client/assets/chunk-IMKFNOWR-UvWxXAkh.js.gz +0 -0
  278. package/dist/client/assets/chunk-SVP7TREG-C4a1s0v4.js.br +0 -0
  279. package/dist/client/assets/chunk-SVP7TREG-C4a1s0v4.js.gz +0 -0
  280. package/dist/client/assets/chunk-TICWLB2K-hnmjYAl_.js.br +0 -0
  281. package/dist/client/assets/chunk-TICWLB2K-hnmjYAl_.js.gz +0 -0
  282. package/dist/client/assets/classDiagram-ZZMXUADV-_tUz3Cxt.js +0 -1
  283. package/dist/client/assets/classDiagram-v2-VYDZK3BY-_tUz3Cxt.js +0 -1
  284. package/dist/client/assets/cose-bilkent-JH36ORCC-CqY84fFp.js.br +0 -0
  285. package/dist/client/assets/cose-bilkent-JH36ORCC-CqY84fFp.js.gz +0 -0
  286. package/dist/client/assets/cynefin-OW5HDTMX-Bd14zuaD.js.br +0 -0
  287. package/dist/client/assets/cynefin-OW5HDTMX-Bd14zuaD.js.gz +0 -0
  288. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-DSHcNXDs.js.br +0 -0
  289. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-DSHcNXDs.js.gz +0 -0
  290. package/dist/client/assets/dagre-GXQ25YYZ-CIGWQYeP.js.br +0 -0
  291. package/dist/client/assets/dagre-GXQ25YYZ-CIGWQYeP.js.gz +0 -0
  292. package/dist/client/assets/diagram-S7CK7UJ4-C9Fg7OLN.js.br +0 -0
  293. package/dist/client/assets/diagram-S7CK7UJ4-C9Fg7OLN.js.gz +0 -0
  294. package/dist/client/assets/diagram-UQ7AKVKN-DoRhl7Fd.js.br +0 -0
  295. package/dist/client/assets/diagram-UQ7AKVKN-DoRhl7Fd.js.gz +0 -0
  296. package/dist/client/assets/diagram-VSXAHHWV-CI83g3iM.js.br +0 -0
  297. package/dist/client/assets/diagram-VSXAHHWV-CI83g3iM.js.gz +0 -0
  298. package/dist/client/assets/diagram-VX7I27RA-Dp2kP4PB.js.br +0 -0
  299. package/dist/client/assets/diagram-VX7I27RA-Dp2kP4PB.js.gz +0 -0
  300. package/dist/client/assets/diagram-Z3DM3KII-KtLMCM-V.js.br +0 -0
  301. package/dist/client/assets/diagram-Z3DM3KII-KtLMCM-V.js.gz +0 -0
  302. package/dist/client/assets/ebnfDiagram-PWID7BFC-D_zseu1m.js.br +0 -0
  303. package/dist/client/assets/ebnfDiagram-PWID7BFC-D_zseu1m.js.gz +0 -0
  304. package/dist/client/assets/erDiagram-RLTQ6QDP-DaWUl_Kz.js.gz +0 -0
  305. package/dist/client/assets/flowDiagram-HODETNUW-BMoJ46zJ.js.br +0 -0
  306. package/dist/client/assets/flowDiagram-HODETNUW-BMoJ46zJ.js.gz +0 -0
  307. package/dist/client/assets/ganttDiagram-EL5Y4UJY-lV_iVmoW.js.br +0 -0
  308. package/dist/client/assets/ganttDiagram-EL5Y4UJY-lV_iVmoW.js.gz +0 -0
  309. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BVCT9Btd.js.br +0 -0
  310. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BVCT9Btd.js.gz +0 -0
  311. package/dist/client/assets/index-CnKSUg74.css.br +0 -0
  312. package/dist/client/assets/index-CnKSUg74.css.gz +0 -0
  313. package/dist/client/assets/ishikawaDiagram-5VMMS53U-Cyzfuoys.js.br +0 -0
  314. package/dist/client/assets/ishikawaDiagram-5VMMS53U-Cyzfuoys.js.gz +0 -0
  315. package/dist/client/assets/journeyDiagram-3NMN7TZE-CEIPDhQF.js.br +0 -0
  316. package/dist/client/assets/journeyDiagram-3NMN7TZE-CEIPDhQF.js.gz +0 -0
  317. package/dist/client/assets/kanban-definition-UXKFOSKX-C8OulEOF.js.br +0 -0
  318. package/dist/client/assets/kanban-definition-UXKFOSKX-C8OulEOF.js.gz +0 -0
  319. package/dist/client/assets/layout-YN93qRzb.js.br +0 -0
  320. package/dist/client/assets/layout-YN93qRzb.js.gz +0 -0
  321. package/dist/client/assets/linear-D9T4dYh7.js.br +0 -0
  322. package/dist/client/assets/linear-D9T4dYh7.js.gz +0 -0
  323. package/dist/client/assets/mermaid.core-BdCvvCGV.js.br +0 -0
  324. package/dist/client/assets/mermaid.core-BdCvvCGV.js.gz +0 -0
  325. package/dist/client/assets/mindmap-definition-YA3MSWOX-CSpES3Jh.js.br +0 -0
  326. package/dist/client/assets/mindmap-definition-YA3MSWOX-CSpES3Jh.js.gz +0 -0
  327. package/dist/client/assets/pegDiagram-XKGWAZYB-6f4vAA1Q.js.br +0 -0
  328. package/dist/client/assets/pegDiagram-XKGWAZYB-6f4vAA1Q.js.gz +0 -0
  329. package/dist/client/assets/pieDiagram-E7YTZNPT-BC4Jd-I8.js.br +0 -0
  330. package/dist/client/assets/pieDiagram-E7YTZNPT-BC4Jd-I8.js.gz +0 -0
  331. package/dist/client/assets/quadrantDiagram-AXDQQJYC-B0pnPaEN.js.br +0 -0
  332. package/dist/client/assets/quadrantDiagram-AXDQQJYC-B0pnPaEN.js.gz +0 -0
  333. package/dist/client/assets/railroadDiagram-O6MQD6OU-B-oOamZT.js.br +0 -0
  334. package/dist/client/assets/railroadDiagram-O6MQD6OU-B-oOamZT.js.gz +0 -0
  335. package/dist/client/assets/requirementDiagram-BXWQKSXE-DBSyxt0k.js.br +0 -0
  336. package/dist/client/assets/requirementDiagram-BXWQKSXE-DBSyxt0k.js.gz +0 -0
  337. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CcohzEZE.js.br +0 -0
  338. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CcohzEZE.js.gz +0 -0
  339. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D7KS6rq_.js.br +0 -0
  340. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D7KS6rq_.js.gz +0 -0
  341. package/dist/client/assets/sizeCapture-INFHLROL-CaRXtn4g.js.br +0 -0
  342. package/dist/client/assets/sizeCapture-INFHLROL-CaRXtn4g.js.gz +0 -0
  343. package/dist/client/assets/sparkles-CUdUt4qy.js +0 -1
  344. package/dist/client/assets/stateDiagram-D77RDMKH-Dz836LqY.js.br +0 -0
  345. package/dist/client/assets/stateDiagram-D77RDMKH-Dz836LqY.js.gz +0 -0
  346. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-5V5Y3wwn.js +0 -1
  347. package/dist/client/assets/swimlanes-42K2YHIH-BK4KAY00.js.br +0 -0
  348. package/dist/client/assets/swimlanes-42K2YHIH-BK4KAY00.js.gz +0 -0
  349. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-Sj-7YK2P.js +0 -8
  350. package/dist/client/assets/timeline-definition-24CTP7MA-DWgxTDhO.js.br +0 -0
  351. package/dist/client/assets/timeline-definition-24CTP7MA-DWgxTDhO.js.gz +0 -0
  352. package/dist/client/assets/vennDiagram-4TSXK5OY-BV1TIfOp.js.br +0 -0
  353. package/dist/client/assets/vennDiagram-4TSXK5OY-BV1TIfOp.js.gz +0 -0
  354. package/dist/client/assets/wardleyDiagram-VM6X3IG4-GYClC5F0.js.br +0 -0
  355. package/dist/client/assets/wardleyDiagram-VM6X3IG4-GYClC5F0.js.gz +0 -0
  356. package/dist/client/assets/xychartDiagram-S5SC5T6Z-D1oKV5W0.js.br +0 -0
  357. package/dist/client/assets/xychartDiagram-S5SC5T6Z-D1oKV5W0.js.gz +0 -0
@@ -0,0 +1,298 @@
1
+ import fs from 'node:fs';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { COLLAB_LIMITS, CollaborationError } from './collaborationProtocol.js';
4
+ export const COLLAB_HELP = `td collab — durable messages; no agent-specific hooks required
5
+ status | capabilities
6
+ send <session-id> <message> | reply <message-id> <message> | handoff <session-id> <message>
7
+ --group <id> --thread <id> --idempotency-key <key>
8
+ --file <path> | --stdin (instead of inline body; -- ends option parsing)
9
+ --wait-until queued|delivered|read --timeout 30s
10
+ --expect-reply ack|result|any
11
+ --response-kind ack|progress|result --metadata '<JSON object>'
12
+ --task-envelope '<JSON: task_id,status,progress?,evidence?,blocker?>'
13
+ --expires-at <ISO timestamp or epoch milliseconds>
14
+ message get <message-id> [--receipt-only]
15
+ message read <message-id> (explicit consumption; not application ACK)
16
+ message watch <message-id> [--wait-until delivered|read] [--timeout 30s]
17
+ inbox [--unread] [--since <ISO or epoch-ms>] [--after-id <id>]
18
+ [--cursor <token>] [--consumer <name>] [--limit 1..200]
19
+ [--from <id>] [--group <id>] [--thread <id>] [--kind <kind>]
20
+ [--response-kind ack|progress|result] [--follow] [--timeout 30s]
21
+ cursor commit <token> --consumer <name> (commit after processing the page)
22
+ add|remove <group-id> <session-id>
23
+ spawn <group-id> <agent-slug> [--name <name>] [--cwd <path>] [--task <text>]
24
+ --json (default) | --jsonl | --text
25
+ Exit codes: 0 requested condition met; 1 invalid request/network error;
26
+ 2 wait timeout (message may still deliver); 3 failed/expired.
27
+ Message limit: ${COLLAB_LIMITS.message_bytes} UTF-8 bytes; metadata: ${COLLAB_LIMITS.metadata_bytes} bytes.
28
+ Idempotency retention: 7 days. read/ACK/result never imply each other.
29
+ Inbox defaults to unread first, newest 50; cursor/consumer mode reads oldest unseen first.
30
+ Reading never advances a consumer or marks messages read automatically.`;
31
+ const BOOLEAN_OPTIONS = new Set(['json', 'jsonl', 'text', 'unread', 'follow', 'stdin', 'receipt-only', 'help']);
32
+ const VALUE_OPTIONS = new Set(['group', 'thread', 'idempotency-key', 'file', 'wait-until', 'timeout', 'expect-reply', 'response-kind', 'metadata', 'task-envelope', 'expires-at', 'since', 'after-id', 'cursor', 'consumer', 'limit', 'from', 'kind', 'name', 'cwd', 'task']);
33
+ export function parseCollaborationCommand(argv) {
34
+ const options = {};
35
+ const positional = [];
36
+ let literal = false;
37
+ for (let index = 0; index < argv.length; index++) {
38
+ const value = argv[index];
39
+ if (value === '--' && !literal) {
40
+ literal = true;
41
+ continue;
42
+ }
43
+ if (!literal && value.startsWith('--')) {
44
+ const [flag, ...inline] = value.slice(2).split('=');
45
+ if (BOOLEAN_OPTIONS.has(flag)) {
46
+ if (inline.length)
47
+ throw new Error(`--${flag} takes no value`);
48
+ options[flag] = true;
49
+ }
50
+ else if (VALUE_OPTIONS.has(flag)) {
51
+ const next = inline.length ? inline.join('=') : argv[++index];
52
+ if (!next || (!inline.length && next.startsWith('--')))
53
+ throw new Error(`--${flag} requires a value`);
54
+ options[flag] = next;
55
+ }
56
+ else
57
+ throw new Error(`Unknown collaboration option: --${flag}`);
58
+ }
59
+ else
60
+ positional.push(value);
61
+ }
62
+ const action = (options.help ? 'help' : positional.shift() ?? 'status');
63
+ if (!['status', 'inbox', 'send', 'handoff', 'reply', 'add', 'remove', 'spawn', 'message', 'cursor', 'capabilities', 'help'].includes(action))
64
+ throw new Error('Unknown collaboration command; see td collab --help');
65
+ if (['json', 'jsonl', 'text'].filter((key) => options[key]).length > 1)
66
+ throw new Error('Choose one output format');
67
+ if (options['wait-until'] && !['queued', 'delivered', 'read'].includes(String(options['wait-until'])))
68
+ throw new Error('wait-until must be queued, delivered or read');
69
+ if (options['expect-reply'] && !['ack', 'result', 'any'].includes(String(options['expect-reply'])))
70
+ throw new Error('expect-reply must be ack, result or any');
71
+ if (options.timeout)
72
+ duration(String(options.timeout));
73
+ const command = { action, json: !options.text, options };
74
+ if (['send', 'reply', 'handoff'].includes(action)) {
75
+ command.target = positional.shift();
76
+ command.message = positional.join(' ');
77
+ if (!command.target || (!command.message && !options.file && !options.stdin))
78
+ throw new Error(`${action} requires a target and message`);
79
+ if ([Boolean(command.message), Boolean(options.file), Boolean(options.stdin)].filter(Boolean).length !== 1)
80
+ throw new Error('Choose inline body, --file, or --stdin');
81
+ }
82
+ else if (action === 'message') {
83
+ command.operation = positional.shift();
84
+ command.target = positional.shift();
85
+ if (!['get', 'watch', 'read'].includes(command.operation ?? '') || !command.target || positional.length)
86
+ throw new Error('Usage: td collab message get|watch|read <id>');
87
+ }
88
+ else if (action === 'cursor') {
89
+ command.operation = positional.shift();
90
+ command.target = positional.shift();
91
+ if (command.operation !== 'commit' || !command.target || !options.consumer || positional.length)
92
+ throw new Error('Usage: td collab cursor commit <token> --consumer <name>');
93
+ }
94
+ else if (action === 'add' || action === 'remove' || action === 'spawn') {
95
+ command.groupId = positional.shift();
96
+ if (action === 'spawn')
97
+ command.agentSlug = positional.shift();
98
+ else
99
+ command.sessionId = positional.shift();
100
+ if (!command.groupId || !(command.agentSlug || command.sessionId) || positional.length)
101
+ throw new Error(`${action} requires two identifiers`);
102
+ command.name = options.name;
103
+ command.cwd = options.cwd;
104
+ command.task = options.task;
105
+ }
106
+ else if (positional.length && action !== 'help')
107
+ throw new Error(`Unexpected arguments for ${action}`);
108
+ const allowed = new Set(['json', 'jsonl', 'text', 'help']);
109
+ const byAction = {
110
+ status: [], capabilities: [], help: [...BOOLEAN_OPTIONS, ...VALUE_OPTIONS],
111
+ send: ['group', 'thread', 'idempotency-key', 'file', 'stdin', 'wait-until', 'timeout', 'expect-reply', 'response-kind', 'metadata', 'task-envelope', 'expires-at', 'kind'],
112
+ handoff: ['group', 'thread', 'idempotency-key', 'file', 'stdin', 'wait-until', 'timeout', 'expect-reply', 'response-kind', 'metadata', 'task-envelope', 'expires-at'],
113
+ reply: ['idempotency-key', 'file', 'stdin', 'wait-until', 'timeout', 'expect-reply', 'response-kind', 'metadata', 'task-envelope', 'expires-at'],
114
+ inbox: ['unread', 'since', 'after-id', 'cursor', 'consumer', 'limit', 'from', 'group', 'thread', 'kind', 'response-kind', 'follow', 'timeout'],
115
+ message: ['receipt-only', 'follow', 'wait-until', 'timeout', 'expect-reply'], cursor: ['consumer'],
116
+ add: [], remove: [], spawn: ['name', 'cwd', 'task'],
117
+ };
118
+ for (const option of byAction[action])
119
+ allowed.add(option);
120
+ for (const option of Object.keys(options))
121
+ if (!allowed.has(option))
122
+ throw new Error(`--${option} is not supported by ${action}`);
123
+ if (action === 'message' && command.operation === 'read' && Object.keys(options).some((option) => !['json', 'jsonl', 'text', 'help'].includes(option)))
124
+ throw new Error('message read does not accept wait or filtering options');
125
+ return command;
126
+ }
127
+ export function duration(value) {
128
+ const match = /^(\d+(?:\.\d+)?)(ms|s|m)?$/.exec(value);
129
+ const result = match ? Number(match[1]) * (match[2] === 'm' ? 60000 : match[2] === 's' ? 1000 : 1) : NaN;
130
+ if (!Number.isFinite(result) || result < 1 || result > 86_400_000)
131
+ throw new Error('timeout must be 1ms–24h, e.g. 30s (plain numbers are milliseconds)');
132
+ return result;
133
+ }
134
+ export function waitSatisfied(receipt, stage, reply) {
135
+ const reached = stage === 'queued' || (stage === 'delivered' && ['delivered', 'read'].includes(receipt.status)) || (stage === 'read' && receipt.status === 'read');
136
+ return reached && (!reply || (reply === 'ack' ? receipt.ack_at != null : reply === 'result' ? receipt.result_ids?.length > 0 : receipt.reply_ids?.length > 0));
137
+ }
138
+ export async function executeCollaborationCommand(command, context, io) {
139
+ const o = command.options;
140
+ const now = io.now ?? Date.now;
141
+ const sleep = io.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
142
+ let deadline = now() + duration(String(o.timeout ?? '30s'));
143
+ const query = new URLSearchParams(context);
144
+ const request = async (method, route, body) => {
145
+ const response = await io.request(method, `/api/terminal/operations/orchestration${route}${method === 'GET' ? `${route.includes('?') ? '&' : '?'}${query}` : ''}`, method === 'POST' ? { ...context, ...body } : undefined, Math.max(1, Math.min(10000, deadline - now())));
146
+ let parsed;
147
+ try {
148
+ parsed = JSON.parse(response.body);
149
+ }
150
+ catch {
151
+ throw new CollaborationError('INVALID_RESPONSE', 'Service returned a non-JSON response');
152
+ }
153
+ if (response.statusCode < 200 || response.statusCode >= 300)
154
+ throw new CollaborationError(parsed.code ?? 'REQUEST_FAILED', parsed.error ?? 'Collaboration request failed', response.statusCode);
155
+ return parsed;
156
+ };
157
+ const output = (value) => {
158
+ if (o.text) {
159
+ if (Array.isArray(value.messages))
160
+ for (const message of value.messages)
161
+ io.write(`[${message.responseKind ?? message.kind}] ${message.id} from ${message.fromSessionId ?? 'user'}\n${message.content}`);
162
+ else if (value.message)
163
+ io.write(`[${value.status}] ${value.message_id}\n${value.message.content}`);
164
+ else if (value.message_id)
165
+ io.write(`${value.status} ${value.message_id} thread=${value.thread_id}${value.code ? ` ${value.code}` : ''}${value.failure_reason ? ` ${value.failure_reason}` : ''}`);
166
+ else
167
+ io.write(JSON.stringify(value, null, 2));
168
+ if (value.next_cursor)
169
+ io.write(`next_cursor=${value.next_cursor} has_more=${value.has_more}`);
170
+ }
171
+ else if (o.jsonl && Array.isArray(value.messages) && command.action === 'inbox') {
172
+ for (const message of value.messages)
173
+ io.write(JSON.stringify({ type: 'message', ...message }));
174
+ io.write(JSON.stringify({ type: 'cursor', next_cursor: value.next_cursor, has_more: value.has_more, retention_gap: value.retention_gap ?? false, consumer: value.consumer }));
175
+ }
176
+ else
177
+ io.write(JSON.stringify(value, null, o.jsonl || o.follow || command.operation === 'watch' ? undefined : 2));
178
+ };
179
+ let receipt;
180
+ let idempotencyKey;
181
+ try {
182
+ if (command.action === 'help') {
183
+ io.write(COLLAB_HELP);
184
+ return 0;
185
+ }
186
+ if (command.action === 'capabilities' || command.action === 'status') {
187
+ output(await request('GET', command.action === 'status' ? '/peers' : '/capabilities'));
188
+ return 0;
189
+ }
190
+ if (command.action === 'inbox') {
191
+ let cursor = o.cursor;
192
+ do {
193
+ const params = new URLSearchParams();
194
+ for (const key of ['unread', 'since', 'after-id', 'consumer', 'limit', 'from', 'group', 'thread', 'kind', 'response-kind'])
195
+ if (o[key])
196
+ params.set(key.replaceAll('-', '_'), String(o[key]));
197
+ if (cursor) {
198
+ params.set('cursor', cursor);
199
+ params.delete('after_id');
200
+ }
201
+ const page = await request('GET', `/inbox?${params}`);
202
+ if (!o.follow || page.messages?.length || page.retention_gap)
203
+ output(page);
204
+ cursor = page.next_cursor;
205
+ if (!o.follow)
206
+ return 0;
207
+ if (!page.has_more)
208
+ await sleep(Math.min(1000, Math.max(0, deadline - now())));
209
+ } while (now() < deadline);
210
+ return 0;
211
+ }
212
+ if (command.action === 'cursor') {
213
+ output(await request('POST', '/cursor/commit', { cursor: command.target, consumer: o.consumer }));
214
+ return 0;
215
+ }
216
+ if (command.action === 'message') {
217
+ const route = `/message/${encodeURIComponent(command.target)}`;
218
+ if (command.operation === 'read') {
219
+ output(await request('POST', `${route}/read`));
220
+ return 0;
221
+ }
222
+ receipt = await request('GET', `${route}${o['receipt-only'] || command.operation === 'watch' ? '?receipt_only=true' : ''}`);
223
+ if (command.operation === 'get' && !o.follow && !o['wait-until'] && !o['expect-reply']) {
224
+ output(receipt);
225
+ return 0;
226
+ }
227
+ }
228
+ else if (['send', 'reply', 'handoff'].includes(command.action)) {
229
+ let content = command.message ?? '';
230
+ if (o.file) {
231
+ if (fs.statSync(String(o.file)).size > COLLAB_LIMITS.message_bytes)
232
+ throw new Error('Message file exceeds 1 MiB');
233
+ content = fs.readFileSync(String(o.file), 'utf8');
234
+ }
235
+ if (o.stdin) {
236
+ if (!io.stdin)
237
+ throw new Error('stdin is unavailable');
238
+ content = await io.stdin();
239
+ }
240
+ if (Buffer.byteLength(content) > COLLAB_LIMITS.message_bytes)
241
+ throw new Error('Message exceeds 1 MiB');
242
+ const expiresAt = o['expires-at'] ? /^\d+$/.test(String(o['expires-at'])) ? Number(o['expires-at']) : Date.parse(String(o['expires-at'])) : undefined;
243
+ if (expiresAt !== undefined && !Number.isFinite(expiresAt))
244
+ throw new Error('Invalid expires-at timestamp');
245
+ idempotencyKey = String(o['idempotency-key'] ?? randomUUID());
246
+ const extras = { group_id: o.group, thread_id: o.thread, idempotency_key: idempotencyKey, response_kind: o['response-kind'],
247
+ metadata: o.metadata ? JSON.parse(String(o.metadata)) : undefined, task: o['task-envelope'] ? JSON.parse(String(o['task-envelope'])) : undefined, expires_at: expiresAt };
248
+ deadline = now() + duration(String(o.timeout ?? '30s'));
249
+ receipt = await request('POST', command.action === 'reply' ? '/reply' : '/send', command.action === 'reply'
250
+ ? { ...extras, messageId: command.target, content } : { ...extras, targetSessionId: command.target, message: content, kind: command.action === 'handoff' ? 'handoff' : o.kind ?? 'message' });
251
+ // CLI receipts stay small even when the message is a large evidence package.
252
+ delete receipt.messages;
253
+ receipt.idempotency_key = idempotencyKey;
254
+ }
255
+ else {
256
+ const body = command.action === 'spawn' ? { groupId: command.groupId, agentSlug: command.agentSlug, name: command.name, cwd: command.cwd, task: command.task }
257
+ : { groupId: command.groupId, targetSessionId: command.sessionId, action: command.action };
258
+ output(await request('POST', command.action === 'spawn' ? '/spawn' : '/members', body));
259
+ return 0;
260
+ }
261
+ const stage = String(o['wait-until'] ?? (command.action === 'message' ? 'read' : 'queued'));
262
+ let previous = '';
263
+ for (;;) {
264
+ if (['failed', 'expired'].includes(receipt.status)) {
265
+ output(receipt);
266
+ return 3;
267
+ }
268
+ if (waitSatisfied(receipt, stage, o['expect-reply'])) {
269
+ output(receipt);
270
+ return 0;
271
+ }
272
+ if (o.follow || command.operation === 'watch') {
273
+ const serialized = JSON.stringify(receipt);
274
+ if (serialized !== previous) {
275
+ output(receipt);
276
+ previous = serialized;
277
+ }
278
+ }
279
+ if (now() >= deadline) {
280
+ output({ ...receipt, ok: false, code: 'WAIT_TIMEOUT', wait_until: stage, expect_reply: o['expect-reply'] ?? null, delivery_continues: true });
281
+ return 2;
282
+ }
283
+ await sleep(Math.min(500, deadline - now()));
284
+ if (now() >= deadline)
285
+ continue;
286
+ receipt = { ...await request('GET', `/message/${encodeURIComponent(receipt.message_id)}?receipt_only=true`), ...(idempotencyKey ? { idempotency_key: idempotencyKey } : {}) };
287
+ }
288
+ }
289
+ catch (error) {
290
+ if (receipt && now() >= deadline) {
291
+ output({ ...receipt, ok: false, code: 'WAIT_TIMEOUT', delivery_continues: true, last_error: error instanceof Error ? error.message : String(error) });
292
+ return 2;
293
+ }
294
+ output({ ...(receipt ?? {}), ok: false, code: error instanceof CollaborationError ? error.code : 'COLLABORATION_ERROR',
295
+ error: error instanceof Error ? error.message : String(error), ...(idempotencyKey ? { idempotency_key: idempotencyKey } : {}), ...(receipt ? { delivery_continues: true } : {}) });
296
+ return 1;
297
+ }
298
+ }
@@ -24,8 +24,12 @@ export function formatCollaborationDelivery(input) {
24
24
  `来自:${source}`,
25
25
  `协作组:${group}`,
26
26
  '--- 消息内容 ---',
27
- message.content,
27
+ Buffer.byteLength(message.content) > 8_192
28
+ ? `大消息已完整保存(${Buffer.byteLength(message.content)} 字节)。使用 td collab message get ${message.id} --json 获取正文;不要把这条提示当作任务正文。`
29
+ : message.content,
28
30
  '--- 消息结束 ---',
31
+ ...(message.responseKind ? [`回复类型:${message.responseKind}(ack=收到,progress=进展,result=结果;结果不保证成功)`] : []),
32
+ ...(message.task ? [`任务上报:${JSON.stringify(message.task)}`] : []),
29
33
  ].join('\n');
30
34
  });
31
35
  const peerIds = Array.from(new Set(input.groups.flatMap((group) => group.sessionIds)))
@@ -33,7 +37,7 @@ export function formatCollaborationDelivery(input) {
33
37
  const peers = peerIds.map((sessionId) => {
34
38
  const session = sessionsById.get(sessionId);
35
39
  return [
36
- `- ${session?.name ?? '离线会话'} · ${session?.status ?? 'offline'}`,
40
+ `- ${session?.name ?? '离线会话'} · ${session?.status === 'service-unreachable' ? '服务不可达,消息无法送达;仅可排队等待服务重连' : session?.status ?? 'offline'}`,
37
41
  ...(session?.agentNativeSessionId ? [` Agent 原生 Session ID:${session.agentNativeSessionId}`] : []),
38
42
  ` Termdock 会话 ID:${sessionId}`,
39
43
  ].join('\n');
@@ -49,12 +53,17 @@ export function formatCollaborationDelivery(input) {
49
53
  '- 如果没有这种内建能力,则使用下方 Termdock 收件箱命令;命令中的 <会话ID> 指 Termdock 会话 ID。',
50
54
  ...(hasUserMessage ? ['- 用户消息:直接在当前会话回答或执行(无来源 Agent,不能运行 `td collab reply`)。'] : []),
51
55
  ...(hasAgentMessage ? ['- 回复:`td collab reply <消息ID> "回复内容"`'] : []),
56
+ ...(peerIds.some((id) => id.startsWith('remote:')) ? ['- 跨服务成员必须使用 td collab 通信;服务不可达时消息尚未送达,不要把 pending 当作成功,也不要假定对方已收到任务。Mac 客户端须保持运行以转发消息。'] : []),
52
57
  '- 发消息:`td collab send <会话ID> "消息内容"`',
53
58
  '- 交接:`td collab handoff <会话ID> "交接摘要"`',
54
59
  '- 加成员:`td collab add <协作组ID> <会话ID>`',
55
60
  '- 移成员:`td collab remove <协作组ID> <会话ID>`',
56
61
  '- 新建 Agent:`td collab spawn <协作组ID> <agent-slug> --name "名称" --task "初始任务"`',
57
- '- 查看:`td collab status` / `td collab inbox`',
62
+ '- 查看:`td collab status` / `td collab inbox`;完整选项:`td collab --help`。默认 JSON,pending 只表示已入队。',
63
+ '- 确认投递:`td collab message get <消息ID> --receipt-only`;send/reply 可加 `--wait-until delivered --timeout 30s`。超时不会取消消息,重试使用同一 `--idempotency-key`。',
64
+ '- 只取新回复:`td collab inbox --consumer <名称> --limit 20`;处理完成后用返回的 next_cursor 执行 `td collab cursor commit <游标> --consumer <名称>`。需要明确标记读取时用 `td collab message read <消息ID>`。',
65
+ '- 回复应明确类型:reply 加 `--response-kind ack|progress|result`;可附 `--task-envelope` JSON(task_id、status、progress、evidence、blocker)。不要把 ACK 或 turn done 汇报为任务完成。',
66
+ '- Agent 状态与工具活动只作可选提示;任意接入方都可通过收件箱主动读取、确认和回复,无需专用 hooks。',
58
67
  ];
59
68
  return [
60
69
  `[Termdock 协作收件箱 · ${input.messages.length} 条]`,
@@ -0,0 +1,50 @@
1
+ /** Transport facts and application reports deliberately remain separate. */
2
+ export const COLLAB_LIMITS = {
3
+ message_bytes: 1_048_576,
4
+ metadata_bytes: 16_384,
5
+ wire_bytes: 1_572_864,
6
+ fragment_bytes: 32_768,
7
+ fragment_ttl_ms: 86_400_000,
8
+ idempotency_retention_ms: 7 * 86_400_000,
9
+ default_page_size: 50,
10
+ max_page_size: 200,
11
+ };
12
+ export class CollaborationError extends Error {
13
+ code;
14
+ httpStatus;
15
+ constructor(code, message, httpStatus = 400) {
16
+ super(message);
17
+ this.code = code;
18
+ this.httpStatus = httpStatus;
19
+ }
20
+ }
21
+ export function validateExtras(input) {
22
+ if (input.idempotencyKey !== undefined && (typeof input.idempotencyKey !== 'string' || !input.idempotencyKey.trim() || input.idempotencyKey.length > 256)) {
23
+ throw new CollaborationError('INVALID_IDEMPOTENCY_KEY', 'idempotency key must contain 1–256 characters');
24
+ }
25
+ if (input.responseKind !== undefined && !['ack', 'progress', 'result'].includes(input.responseKind))
26
+ throw new CollaborationError('INVALID_RESPONSE_KIND', 'response_kind must be ack, progress or result');
27
+ if (input.metadata !== undefined && (!input.metadata || typeof input.metadata !== 'object' || Array.isArray(input.metadata)))
28
+ throw new CollaborationError('INVALID_METADATA', 'metadata must be a JSON object');
29
+ const task = input.task;
30
+ if (task !== undefined && (!task || typeof task.task_id !== 'string' || !task.task_id.trim() || task.task_id.length > 256
31
+ || !['ack', 'working', 'blocked', 'complete', 'failed'].includes(task.status)
32
+ || (task.progress !== undefined && (!Number.isFinite(task.progress) || task.progress < 0 || task.progress > 100))
33
+ || (task.blocker !== undefined && typeof task.blocker !== 'string')))
34
+ throw new CollaborationError('INVALID_TASK', 'task requires task_id and status; progress is 0–100');
35
+ const inferred = task ? task.status === 'ack' ? 'ack' : ['complete', 'failed'].includes(task.status) ? 'result' : 'progress' : undefined;
36
+ if (inferred && input.responseKind && inferred !== input.responseKind)
37
+ throw new CollaborationError('TASK_KIND_CONFLICT', 'response_kind conflicts with task.status');
38
+ if (input.expiresAt != null && (!Number.isFinite(input.expiresAt) || input.expiresAt <= 0))
39
+ throw new CollaborationError('INVALID_EXPIRY', 'expires_at must be an epoch millisecond timestamp');
40
+ const extras = { idempotencyKey: input.idempotencyKey, responseKind: input.responseKind ?? inferred, metadata: input.metadata, task: input.task, expiresAt: input.expiresAt };
41
+ if (Buffer.byteLength(JSON.stringify(extras)) > COLLAB_LIMITS.metadata_bytes)
42
+ throw new CollaborationError('METADATA_TOO_LARGE', `metadata and task envelope exceed ${COLLAB_LIMITS.metadata_bytes} bytes`, 413);
43
+ return extras;
44
+ }
45
+ export function extrasFromBody(body) {
46
+ return validateExtras({ idempotencyKey: body.idempotency_key,
47
+ responseKind: body.response_kind, metadata: body.metadata,
48
+ task: body.task, expiresAt: body.expires_at });
49
+ }
50
+ export const STATUS_RANK = { pending: 0, failed: 1, expired: 1, delivered: 2, read: 3 };
@@ -0,0 +1,86 @@
1
+ import { Router } from 'express';
2
+ import { COLLAB_LIMITS, CollaborationError, extrasFromBody } from './collaborationProtocol.js';
3
+ export function collaborationRoutes({ store, resolveSession, deliver }) {
4
+ const router = Router();
5
+ const run = (handler) => (req, res) => {
6
+ try {
7
+ const sessionId = resolveSession((req.method === 'GET' ? req.query : req.body) ?? {});
8
+ if (!sessionId)
9
+ throw new CollaborationError('SESSION_NOT_FOUND', 'Run inside a Termdock managed session', 404);
10
+ handler(req, res, sessionId);
11
+ }
12
+ catch (error) {
13
+ res.status(error instanceof CollaborationError ? error.httpStatus : 400).json({ ok: false,
14
+ code: error instanceof CollaborationError ? error.code : 'COLLABORATION_ERROR', error: error instanceof Error ? error.message : String(error) });
15
+ }
16
+ };
17
+ const ownMessage = (id, sessionId, recipientOnly = false) => {
18
+ const message = store.getMessage(id);
19
+ if (!message || (message.toSessionId !== sessionId && (recipientOnly || message.fromSessionId !== sessionId)))
20
+ throw new CollaborationError('MESSAGE_NOT_FOUND', 'Message does not belong to this session', 404);
21
+ return message;
22
+ };
23
+ const sent = (res, ids) => {
24
+ const messages = ids.map((id) => store.getMessage(id));
25
+ const receipts = ids.map((id) => store.receipt(id));
26
+ res.json({ ok: true, ...receipts[0], messages, receipts });
27
+ };
28
+ router.get('/capabilities', run((_req, res) => {
29
+ res.json({ protocol_version: 2, limits: COLLAB_LIMITS,
30
+ statuses: ['pending', 'delivered', 'read', 'failed', 'expired'], queued_status: 'pending',
31
+ semantics: { delivered: 'written to terminal; no application acknowledgement implied', read: 'explicit consumer acknowledgement',
32
+ ack: 'explicit response_kind=ack', result: 'explicit response_kind=result; inspect task.status and evidence',
33
+ done: 'adapter reports turn ended, never proof of task completion', heartbeat: 'null unless explicitly observed',
34
+ timeout: 'stops waiting, does not cancel delivery' } });
35
+ }));
36
+ router.post('/send', run((req, res, sessionId) => {
37
+ const target = typeof req.body.targetSessionId === 'string' ? req.body.targetSessionId.trim() : '';
38
+ const groups = store.groupsForSession(sessionId).filter((group) => group.sessionIds.includes(target) && (!req.body.group_id || group.id === req.body.group_id));
39
+ if (!groups.length)
40
+ throw new CollaborationError('GROUP_NOT_FOUND', 'Sender and recipient must share the specified group');
41
+ if (groups.length > 1 && !req.body.group_id)
42
+ throw new CollaborationError('AMBIGUOUS_GROUP', 'Multiple shared groups; specify --group');
43
+ const messages = store.send({ ...extrasFromBody(req.body), groupId: groups[0].id, fromSessionId: sessionId, toSessionIds: [target],
44
+ kind: (req.body.kind ?? 'message'), content: typeof req.body.message === 'string' ? req.body.message : '',
45
+ threadId: typeof req.body.thread_id === 'string' ? req.body.thread_id : undefined });
46
+ deliver(target);
47
+ sent(res, messages.map((message) => message.id));
48
+ }));
49
+ router.post('/reply', run((req, res, sessionId) => {
50
+ const original = ownMessage(String(req.body.messageId ?? ''), sessionId, true);
51
+ if (!original.fromSessionId)
52
+ throw new CollaborationError('NO_REPLY_TARGET', 'User messages have no agent reply target');
53
+ const messages = store.send({ ...extrasFromBody(req.body), groupId: original.groupId, fromSessionId: sessionId,
54
+ toSessionIds: [original.fromSessionId], kind: 'reply', content: typeof req.body.content === 'string' ? req.body.content : '',
55
+ replyTo: original.id, threadId: original.threadId });
56
+ // Reply is explicit consumption; only mark after successful validation/persistence.
57
+ store.markRead([original.id]);
58
+ deliver(original.fromSessionId);
59
+ sent(res, messages.map((message) => message.id));
60
+ }));
61
+ router.get('/message/:id', run((req, res, sessionId) => {
62
+ const message = ownMessage(String(req.params.id), sessionId);
63
+ res.json({ ok: true, ...store.receipt(message.id), ...(req.query.receipt_only === 'true' ? {} : { message }) });
64
+ }));
65
+ router.post('/message/:id/read', run((req, res, sessionId) => {
66
+ const message = ownMessage(String(req.params.id), sessionId, true);
67
+ store.markRead([message.id]);
68
+ res.json({ ok: true, ...store.receipt(message.id) });
69
+ }));
70
+ router.get('/inbox', run((req, res, sessionId) => {
71
+ const string = (key) => typeof req.query[key] === 'string' ? req.query[key] : undefined;
72
+ const sinceText = string('since');
73
+ const since = sinceText === undefined ? undefined : /^\d+$/.test(sinceText) ? Number(sinceText) : Date.parse(sinceText);
74
+ if (since !== undefined && !Number.isFinite(since))
75
+ throw new CollaborationError('INVALID_SINCE', 'since must be an ISO timestamp or epoch milliseconds');
76
+ const page = store.page(sessionId, { unread: string('unread') === 'true', since, afterId: string('after_id'), cursor: string('cursor'),
77
+ consumer: string('consumer'), limit: string('limit') ? Number(string('limit')) : undefined,
78
+ from: string('from'), group: string('group'), thread: string('thread'), kind: string('kind'), responseKind: string('response_kind'), order: string('order') });
79
+ res.json({ ok: true, ...page });
80
+ }));
81
+ router.post('/cursor/commit', run((req, res, sessionId) => {
82
+ store.commitCursor(sessionId, String(req.body.cursor ?? ''), String(req.body.consumer ?? ''));
83
+ res.json({ ok: true, consumer: req.body.consumer, cursor: req.body.cursor });
84
+ }));
85
+ return router;
86
+ }