termdock 1.4.354 → 1.4.356

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 (430) hide show
  1. package/THIRD_PARTY_NOTICES.md +56 -0
  2. package/dist/client/assets/{AndroidMirrorView-D9CMPmet.js → AndroidMirrorView-DW9oRr0w.js} +3 -3
  3. package/dist/client/assets/AndroidMirrorView-DW9oRr0w.js.br +0 -0
  4. package/dist/client/assets/AndroidMirrorView-DW9oRr0w.js.gz +0 -0
  5. package/dist/client/assets/App-DEZ2i9ZZ.js +178 -0
  6. package/dist/client/assets/App-DEZ2i9ZZ.js.br +0 -0
  7. package/dist/client/assets/App-DEZ2i9ZZ.js.gz +0 -0
  8. package/dist/client/assets/{ArchitecturePanel-Dlnd9PH-.js → ArchitecturePanel-Bf4b-6An.js} +3 -3
  9. package/dist/client/assets/ArchitecturePanel-Bf4b-6An.js.br +0 -0
  10. package/dist/client/assets/ArchitecturePanel-Bf4b-6An.js.gz +0 -0
  11. package/dist/client/assets/ChangeWalkthroughPanel-DO_zJfZr.js +2 -0
  12. package/dist/client/assets/ChangeWalkthroughPanel-DO_zJfZr.js.br +0 -0
  13. package/dist/client/assets/ChangeWalkthroughPanel-DO_zJfZr.js.gz +0 -0
  14. package/dist/client/assets/ChatRichContent-Cu1E1cJ8.js +277 -0
  15. package/dist/client/assets/ChatRichContent-Cu1E1cJ8.js.br +0 -0
  16. package/dist/client/assets/ChatRichContent-Cu1E1cJ8.js.gz +0 -0
  17. package/dist/client/assets/CollaborationMainWorkspace-BhmpSEbf.js +1 -0
  18. package/dist/client/assets/CollaborationMainWorkspace-BhmpSEbf.js.br +0 -0
  19. package/dist/client/assets/CollaborationMainWorkspace-BhmpSEbf.js.gz +0 -0
  20. package/dist/client/assets/{CollaborationTaskContent-GMhtQgeq.js → CollaborationTaskContent-CX0Aqdi2.js} +1 -1
  21. package/dist/client/assets/{ComputerControlView-VNUyl2Gb.js → ComputerControlView-DjQLzn10.js} +4 -4
  22. package/dist/client/assets/ComputerControlView-DjQLzn10.js.br +0 -0
  23. package/dist/client/assets/ComputerControlView-DjQLzn10.js.gz +0 -0
  24. package/dist/client/assets/DagPlayground-CPYwfryM.js +1 -0
  25. package/dist/client/assets/DagPlayground-CPYwfryM.js.br +0 -0
  26. package/dist/client/assets/DagPlayground-CPYwfryM.js.gz +0 -0
  27. package/dist/client/assets/{DiffLab-CKBHu65J.js → DiffLab-ptw96Q_4.js} +1 -1
  28. package/dist/client/assets/DiffLab-ptw96Q_4.js.br +0 -0
  29. package/dist/client/assets/DiffLab-ptw96Q_4.js.gz +0 -0
  30. package/dist/client/assets/DiffReview-12E2zWyL.js +1 -0
  31. package/dist/client/assets/DiffReview-12E2zWyL.js.br +0 -0
  32. package/dist/client/assets/DiffReview-12E2zWyL.js.gz +0 -0
  33. package/dist/client/assets/{DiffReviewLab--PbhIP71.js → DiffReviewLab-eEi3y-0G.js} +2 -2
  34. package/dist/client/assets/DiffReviewLab-eEi3y-0G.js.br +0 -0
  35. package/dist/client/assets/DiffReviewLab-eEi3y-0G.js.gz +0 -0
  36. package/dist/client/assets/{DiffViewer-Cg3GhKcU.js → DiffViewer-DqcQxp4Q.js} +1 -1
  37. package/dist/client/assets/DiffViewer-DqcQxp4Q.js.br +0 -0
  38. package/dist/client/assets/DiffViewer-DqcQxp4Q.js.gz +0 -0
  39. package/dist/client/assets/GitLoadingSkeleton-DYrDIDF1.js +1 -0
  40. package/dist/client/assets/GitLoadingSkeleton-DYrDIDF1.js.br +0 -0
  41. package/dist/client/assets/GitLoadingSkeleton-DYrDIDF1.js.gz +0 -0
  42. package/dist/client/assets/{MarkdownPreview-b_bwDNcY.js → MarkdownPreview-CsJGsDRL.js} +2 -2
  43. package/dist/client/assets/MarkdownPreview-CsJGsDRL.js.br +0 -0
  44. package/dist/client/assets/MarkdownPreview-CsJGsDRL.js.gz +0 -0
  45. package/dist/client/assets/{ModelPreview-C9nka14O.js → ModelPreview-DjtHLlqP.js} +3 -3
  46. package/dist/client/assets/ModelPreview-DjtHLlqP.js.br +0 -0
  47. package/dist/client/assets/ModelPreview-DjtHLlqP.js.gz +0 -0
  48. package/dist/client/assets/{RecordingSaveDialog-1YvzwTzo.js → RecordingSaveDialog-DUtwgIME.js} +1 -1
  49. package/dist/client/assets/RecordingSaveDialog-DUtwgIME.js.br +0 -0
  50. package/dist/client/assets/RecordingSaveDialog-DUtwgIME.js.gz +0 -0
  51. package/dist/client/assets/{RightSidebar-CCk8ovoK.js → RightSidebar-BltjUFwI.js} +20 -20
  52. package/dist/client/assets/RightSidebar-BltjUFwI.js.br +0 -0
  53. package/dist/client/assets/RightSidebar-BltjUFwI.js.gz +0 -0
  54. package/dist/client/assets/SessionChatView-CdKfHRp8.js +13 -0
  55. package/dist/client/assets/SessionChatView-CdKfHRp8.js.br +0 -0
  56. package/dist/client/assets/SessionChatView-CdKfHRp8.js.gz +0 -0
  57. package/dist/client/assets/SessionResourceSidebar-DmQOydhf.js +2 -0
  58. package/dist/client/assets/SessionResourceSidebar-DmQOydhf.js.br +0 -0
  59. package/dist/client/assets/SessionResourceSidebar-DmQOydhf.js.gz +0 -0
  60. package/dist/client/assets/TodoWorkspace-Bh1C035B.js +1 -0
  61. package/dist/client/assets/TodoWorkspace-Bh1C035B.js.br +0 -0
  62. package/dist/client/assets/TodoWorkspace-Bh1C035B.js.gz +0 -0
  63. package/dist/client/assets/{abnfDiagram-VCTEODGH-CTqKSsYV.js → abnfDiagram-VCTEODGH-Cvf_KWZ0.js} +1 -1
  64. package/dist/client/assets/abnfDiagram-VCTEODGH-Cvf_KWZ0.js.br +0 -0
  65. package/dist/client/assets/abnfDiagram-VCTEODGH-Cvf_KWZ0.js.gz +0 -0
  66. package/dist/client/assets/app-DuUnqxq-.js +37 -0
  67. package/dist/client/assets/app-DuUnqxq-.js.br +0 -0
  68. package/dist/client/assets/app-DuUnqxq-.js.gz +0 -0
  69. package/dist/client/assets/{arc-CcvWcKBR.js → arc-UvdowQOf.js} +1 -1
  70. package/dist/client/assets/arc-UvdowQOf.js.br +0 -0
  71. package/dist/client/assets/arc-UvdowQOf.js.gz +0 -0
  72. package/dist/client/assets/{architectureDiagram-5GKGNRK7-B_2ae8Tt.js → architectureDiagram-5GKGNRK7-DotsbCCA.js} +1 -1
  73. package/dist/client/assets/architectureDiagram-5GKGNRK7-DotsbCCA.js.br +0 -0
  74. package/dist/client/assets/architectureDiagram-5GKGNRK7-DotsbCCA.js.gz +0 -0
  75. package/dist/client/assets/{arrow-down-DaWRHIlh.js → arrow-down-FGzRy9D-.js} +1 -1
  76. package/dist/client/assets/{arrow-up-DE9Z7GTI.js → arrow-up-DNkfesW0.js} +1 -1
  77. package/dist/client/assets/{blockDiagram-I7D4REHJ-CGXUOwJg.js → blockDiagram-I7D4REHJ-CoOfSG4k.js} +1 -1
  78. package/dist/client/assets/blockDiagram-I7D4REHJ-CoOfSG4k.js.br +0 -0
  79. package/dist/client/assets/blockDiagram-I7D4REHJ-CoOfSG4k.js.gz +0 -0
  80. package/dist/client/assets/{c4Diagram-7LVT6UL2-BSU3omYQ.js → c4Diagram-7LVT6UL2-BAfjgs8B.js} +1 -1
  81. package/dist/client/assets/c4Diagram-7LVT6UL2-BAfjgs8B.js.br +0 -0
  82. package/dist/client/assets/c4Diagram-7LVT6UL2-BAfjgs8B.js.gz +0 -0
  83. package/dist/client/assets/channel-BzMU9Wks.js +1 -0
  84. package/dist/client/assets/{chevron-left-ZgHOf4aC.js → chevron-left-xqARwD-7.js} +1 -1
  85. package/dist/client/assets/{chunk-2Q5K7J3B-B67WsCJN.js → chunk-2Q5K7J3B-DiiQ7BvG.js} +1 -1
  86. package/dist/client/assets/{chunk-5VM5RSS4-B8k7JXrn.js → chunk-5VM5RSS4-CczSK8wW.js} +1 -1
  87. package/dist/client/assets/{chunk-F27PBJKO-CP85XeHB.js → chunk-F27PBJKO-BI3Di4Ve.js} +1 -1
  88. package/dist/client/assets/chunk-F27PBJKO-BI3Di4Ve.js.br +0 -0
  89. package/dist/client/assets/chunk-F27PBJKO-BI3Di4Ve.js.gz +0 -0
  90. package/dist/client/assets/{chunk-IMKFNOWR-BjTbac0d.js → chunk-IMKFNOWR-Cvvs1wmn.js} +1 -1
  91. package/dist/client/assets/chunk-IMKFNOWR-Cvvs1wmn.js.br +0 -0
  92. package/dist/client/assets/chunk-IMKFNOWR-Cvvs1wmn.js.gz +0 -0
  93. package/dist/client/assets/{chunk-JWPE2WC7-vEdRTCxh.js → chunk-JWPE2WC7-lrJRD9WA.js} +1 -1
  94. package/dist/client/assets/{chunk-POPQ4Y6H-BI8tSW7F.js → chunk-POPQ4Y6H-CnPC9D8B.js} +1 -1
  95. package/dist/client/assets/{chunk-SVP7TREG-Dde8KTpr.js → chunk-SVP7TREG-BZfMhm64.js} +1 -1
  96. package/dist/client/assets/chunk-SVP7TREG-BZfMhm64.js.br +0 -0
  97. package/dist/client/assets/chunk-SVP7TREG-BZfMhm64.js.gz +0 -0
  98. package/dist/client/assets/{chunk-TICWLB2K-DIBgH5zV.js → chunk-TICWLB2K-DmkEaRK3.js} +1 -1
  99. package/dist/client/assets/chunk-TICWLB2K-DmkEaRK3.js.br +0 -0
  100. package/dist/client/assets/chunk-TICWLB2K-DmkEaRK3.js.gz +0 -0
  101. package/dist/client/assets/{chunk-XXDRQBXY-LSjj35mz.js → chunk-XXDRQBXY-BP9Lccpe.js} +1 -1
  102. package/dist/client/assets/circle-DGZOpG8V.js +1 -0
  103. package/dist/client/assets/classDiagram-ZZMXUADV-DtAtEoWU.js +1 -0
  104. package/dist/client/assets/classDiagram-v2-VYDZK3BY-DtAtEoWU.js +1 -0
  105. package/dist/client/assets/{clipboard-BGpbRBdi.js → clipboard-rLx5CzbY.js} +1 -1
  106. package/dist/client/assets/clipboardText-cZXParp1.js +1 -0
  107. package/dist/client/assets/clipboardText-cZXParp1.js.br +0 -0
  108. package/dist/client/assets/clipboardText-cZXParp1.js.gz +0 -0
  109. package/dist/client/assets/{cose-bilkent-JH36ORCC-v4utSIkX.js → cose-bilkent-JH36ORCC-0xPYMc2z.js} +1 -1
  110. package/dist/client/assets/cose-bilkent-JH36ORCC-0xPYMc2z.js.br +0 -0
  111. package/dist/client/assets/cose-bilkent-JH36ORCC-0xPYMc2z.js.gz +0 -0
  112. package/dist/client/assets/{cynefin-OW5HDTMX-BdbtIufa.js → cynefin-OW5HDTMX-BQ7-lCHm.js} +1 -1
  113. package/dist/client/assets/cynefin-OW5HDTMX-BQ7-lCHm.js.br +0 -0
  114. package/dist/client/assets/cynefin-OW5HDTMX-BQ7-lCHm.js.gz +0 -0
  115. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-B9EVx2-N.js → cynefinDiagram-5FMLGOSQ-CazHuSj1.js} +1 -1
  116. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CazHuSj1.js.br +0 -0
  117. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CazHuSj1.js.gz +0 -0
  118. package/dist/client/assets/{dagre-GXQ25YYZ-Do2YjWuC.js → dagre-GXQ25YYZ-CJNgsyHQ.js} +1 -1
  119. package/dist/client/assets/dagre-GXQ25YYZ-CJNgsyHQ.js.br +0 -0
  120. package/dist/client/assets/dagre-GXQ25YYZ-CJNgsyHQ.js.gz +0 -0
  121. package/dist/client/assets/{diagram-S7CK7UJ4-BnJa3bbo.js → diagram-S7CK7UJ4-D4xXIj1P.js} +1 -1
  122. package/dist/client/assets/diagram-S7CK7UJ4-D4xXIj1P.js.br +0 -0
  123. package/dist/client/assets/diagram-S7CK7UJ4-D4xXIj1P.js.gz +0 -0
  124. package/dist/client/assets/{diagram-UQ7AKVKN-C09N8-nE.js → diagram-UQ7AKVKN-BWhpL-35.js} +1 -1
  125. package/dist/client/assets/diagram-UQ7AKVKN-BWhpL-35.js.br +0 -0
  126. package/dist/client/assets/diagram-UQ7AKVKN-BWhpL-35.js.gz +0 -0
  127. package/dist/client/assets/{diagram-VSXAHHWV-mMv3O2zK.js → diagram-VSXAHHWV-DG9A7EgJ.js} +1 -1
  128. package/dist/client/assets/diagram-VSXAHHWV-DG9A7EgJ.js.br +0 -0
  129. package/dist/client/assets/diagram-VSXAHHWV-DG9A7EgJ.js.gz +0 -0
  130. package/dist/client/assets/{diagram-VX7I27RA-B0aepUKS.js → diagram-VX7I27RA-L5PSvynM.js} +1 -1
  131. package/dist/client/assets/diagram-VX7I27RA-L5PSvynM.js.br +0 -0
  132. package/dist/client/assets/diagram-VX7I27RA-L5PSvynM.js.gz +0 -0
  133. package/dist/client/assets/{diagram-Z3DM3KII-BstqsbCO.js → diagram-Z3DM3KII-moBH7ruR.js} +1 -1
  134. package/dist/client/assets/diagram-Z3DM3KII-moBH7ruR.js.br +0 -0
  135. package/dist/client/assets/diagram-Z3DM3KII-moBH7ruR.js.gz +0 -0
  136. package/dist/client/assets/{ebnfDiagram-PWID7BFC-CPINc9LK.js → ebnfDiagram-PWID7BFC-DEiGgcRP.js} +1 -1
  137. package/dist/client/assets/ebnfDiagram-PWID7BFC-DEiGgcRP.js.br +0 -0
  138. package/dist/client/assets/ebnfDiagram-PWID7BFC-DEiGgcRP.js.gz +0 -0
  139. package/dist/client/assets/{erDiagram-RLTQ6QDP-dUgaGLHP.js → erDiagram-RLTQ6QDP-BboIleYi.js} +1 -1
  140. package/dist/client/assets/erDiagram-RLTQ6QDP-BboIleYi.js.br +0 -0
  141. package/dist/client/assets/erDiagram-RLTQ6QDP-BboIleYi.js.gz +0 -0
  142. package/dist/client/assets/external-link-AZ3wjUg5.js +1 -0
  143. package/dist/client/assets/{flowDiagram-HODETNUW-4ottFlnS.js → flowDiagram-HODETNUW-COxz7Rda.js} +1 -1
  144. package/dist/client/assets/flowDiagram-HODETNUW-COxz7Rda.js.br +0 -0
  145. package/dist/client/assets/flowDiagram-HODETNUW-COxz7Rda.js.gz +0 -0
  146. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-CZOkoivd.js → ganttDiagram-EL5Y4UJY-_XdRvgyZ.js} +1 -1
  147. package/dist/client/assets/ganttDiagram-EL5Y4UJY-_XdRvgyZ.js.br +0 -0
  148. package/dist/client/assets/ganttDiagram-EL5Y4UJY-_XdRvgyZ.js.gz +0 -0
  149. package/dist/client/assets/{git-compare-C7n2uha2.js → git-compare-90v75Jal.js} +1 -1
  150. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-kh9xx53r.js → gitGraphDiagram-WWUBYQGX-CBb9xBNW.js} +1 -1
  151. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-CBb9xBNW.js.br +0 -0
  152. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-CBb9xBNW.js.gz +0 -0
  153. package/dist/client/assets/index-ByrWASlZ.js +1 -0
  154. package/dist/client/assets/index-ByrWASlZ.js.br +0 -0
  155. package/dist/client/assets/index-ByrWASlZ.js.gz +0 -0
  156. package/dist/client/assets/{index-bfj9dYEg.css → index-nIgxJ6I3.css} +1 -1
  157. package/dist/client/assets/index-nIgxJ6I3.css.br +0 -0
  158. package/dist/client/assets/{index-bfj9dYEg.css.gz → index-nIgxJ6I3.css.gz} +0 -0
  159. package/dist/client/assets/{infoDiagram-27XIBGKW-zRkMruS-.js → infoDiagram-27XIBGKW-DjLdeNZi.js} +1 -1
  160. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-DPntAz12.js → ishikawaDiagram-5VMMS53U-Bcr-lhIE.js} +1 -1
  161. package/dist/client/assets/ishikawaDiagram-5VMMS53U-Bcr-lhIE.js.br +0 -0
  162. package/dist/client/assets/ishikawaDiagram-5VMMS53U-Bcr-lhIE.js.gz +0 -0
  163. package/dist/client/assets/{journeyDiagram-3NMN7TZE-B074bD6a.js → journeyDiagram-3NMN7TZE-3vK6s9Pq.js} +1 -1
  164. package/dist/client/assets/journeyDiagram-3NMN7TZE-3vK6s9Pq.js.br +0 -0
  165. package/dist/client/assets/journeyDiagram-3NMN7TZE-3vK6s9Pq.js.gz +0 -0
  166. package/dist/client/assets/{kanban-definition-UXKFOSKX-wPbpE7ij.js → kanban-definition-UXKFOSKX-DqDYDca0.js} +1 -1
  167. package/dist/client/assets/kanban-definition-UXKFOSKX-DqDYDca0.js.br +0 -0
  168. package/dist/client/assets/kanban-definition-UXKFOSKX-DqDYDca0.js.gz +0 -0
  169. package/dist/client/assets/{layout-D-nTHjVE.js → layout-C7_WwzCP.js} +1 -1
  170. package/dist/client/assets/layout-C7_WwzCP.js.br +0 -0
  171. package/dist/client/assets/layout-C7_WwzCP.js.gz +0 -0
  172. package/dist/client/assets/{linear-BVxgfw5H.js → linear-BQCRhl6P.js} +1 -1
  173. package/dist/client/assets/linear-BQCRhl6P.js.br +0 -0
  174. package/dist/client/assets/linear-BQCRhl6P.js.gz +0 -0
  175. package/dist/client/assets/{link-D-fkBp5k.js → link-Cq14tNBm.js} +3 -3
  176. package/dist/client/assets/link-Cq14tNBm.js.br +0 -0
  177. package/dist/client/assets/link-Cq14tNBm.js.gz +0 -0
  178. package/dist/client/assets/{list-tree-DKTcSR9r.js → list-tree-C281zrdg.js} +1 -1
  179. package/dist/client/assets/{loader-circle-DZn9iP0u.js → loader-circle-Df0zpx5N.js} +1 -1
  180. package/dist/client/assets/{maximize-2-dFjMEqgh.js → maximize-2-CovPxWdw.js} +1 -1
  181. package/dist/client/assets/{mermaid.core-D89ctjDO.js → mermaid.core-DGsccxt-.js} +5 -5
  182. package/dist/client/assets/mermaid.core-DGsccxt-.js.br +0 -0
  183. package/dist/client/assets/mermaid.core-DGsccxt-.js.gz +0 -0
  184. package/dist/client/assets/{mindmap-definition-YA3MSWOX-1TrbOKNK.js → mindmap-definition-YA3MSWOX-l0eF1PQE.js} +1 -1
  185. package/dist/client/assets/mindmap-definition-YA3MSWOX-l0eF1PQE.js.br +0 -0
  186. package/dist/client/assets/mindmap-definition-YA3MSWOX-l0eF1PQE.js.gz +0 -0
  187. package/dist/client/assets/{passwordBootstrap-8XHlXyYk.js → passwordBootstrap-B5VzheZz.js} +2 -2
  188. package/dist/client/assets/passwordBootstrap-B5VzheZz.js.br +0 -0
  189. package/dist/client/assets/passwordBootstrap-B5VzheZz.js.gz +0 -0
  190. package/dist/client/assets/{pegDiagram-XKGWAZYB-CJYo1Bz4.js → pegDiagram-XKGWAZYB-fRrxGIDM.js} +1 -1
  191. package/dist/client/assets/pegDiagram-XKGWAZYB-fRrxGIDM.js.br +0 -0
  192. package/dist/client/assets/pegDiagram-XKGWAZYB-fRrxGIDM.js.gz +0 -0
  193. package/dist/client/assets/{pieDiagram-E7YTZNPT-DyE6_2FS.js → pieDiagram-E7YTZNPT-B-EBa3qN.js} +1 -1
  194. package/dist/client/assets/pieDiagram-E7YTZNPT-B-EBa3qN.js.br +0 -0
  195. package/dist/client/assets/pieDiagram-E7YTZNPT-B-EBa3qN.js.gz +0 -0
  196. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-OgNN7-oZ.js → quadrantDiagram-AXDQQJYC-Dj4e6f4h.js} +1 -1
  197. package/dist/client/assets/quadrantDiagram-AXDQQJYC-Dj4e6f4h.js.br +0 -0
  198. package/dist/client/assets/quadrantDiagram-AXDQQJYC-Dj4e6f4h.js.gz +0 -0
  199. package/dist/client/assets/{quote-QwQvV6RF.js → quote-COQfrXhi.js} +1 -1
  200. package/dist/client/assets/{railroadDiagram-O6MQD6OU-Dmqw_B10.js → railroadDiagram-O6MQD6OU-CEMppxTC.js} +1 -1
  201. package/dist/client/assets/railroadDiagram-O6MQD6OU-CEMppxTC.js.br +0 -0
  202. package/dist/client/assets/railroadDiagram-O6MQD6OU-CEMppxTC.js.gz +0 -0
  203. package/dist/client/assets/{rdpSession-tgxFIJYE.js → rdpSession-C5rS-ImV.js} +1 -1
  204. package/dist/client/assets/rdpSession-C5rS-ImV.js.br +0 -0
  205. package/dist/client/assets/rdpSession-C5rS-ImV.js.gz +0 -0
  206. package/dist/client/assets/{requirementDiagram-BXWQKSXE-nZK7--1f.js → requirementDiagram-BXWQKSXE-Dri1k4_x.js} +1 -1
  207. package/dist/client/assets/requirementDiagram-BXWQKSXE-Dri1k4_x.js.br +0 -0
  208. package/dist/client/assets/requirementDiagram-BXWQKSXE-Dri1k4_x.js.gz +0 -0
  209. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-Db_TVWjx.js → sankeyDiagram-P5KCCOFB-CMsL_tYL.js} +1 -1
  210. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CMsL_tYL.js.br +0 -0
  211. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CMsL_tYL.js.gz +0 -0
  212. package/dist/client/assets/search-Dg6HWygj.js +1 -0
  213. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-B7TK9j0_.js → sequenceDiagram-WJ2MYXX4-4_4hZtOd.js} +1 -1
  214. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-4_4hZtOd.js.br +0 -0
  215. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-4_4hZtOd.js.gz +0 -0
  216. package/dist/client/assets/{settings-2-9tlRImVo.js → settings-2-iGqzPez0.js} +1 -1
  217. package/dist/client/assets/{sizeCapture-INFHLROL-roX-pGgF.js → sizeCapture-INFHLROL-3QA6qj2j.js} +1 -1
  218. package/dist/client/assets/sizeCapture-INFHLROL-3QA6qj2j.js.br +0 -0
  219. package/dist/client/assets/sizeCapture-INFHLROL-3QA6qj2j.js.gz +0 -0
  220. package/dist/client/assets/{stateDiagram-D77RDMKH-BdBm0h1F.js → stateDiagram-D77RDMKH-90IFPhD9.js} +1 -1
  221. package/dist/client/assets/stateDiagram-D77RDMKH-90IFPhD9.js.br +0 -0
  222. package/dist/client/assets/stateDiagram-D77RDMKH-90IFPhD9.js.gz +0 -0
  223. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-CH-yvmL4.js +1 -0
  224. package/dist/client/assets/sun-BAMMjiA8.js +1 -0
  225. package/dist/client/assets/{swimlanes-42K2YHIH-DUulb0LD.js → swimlanes-42K2YHIH-BuHieVWC.js} +1 -1
  226. package/dist/client/assets/swimlanes-42K2YHIH-BuHieVWC.js.br +0 -0
  227. package/dist/client/assets/swimlanes-42K2YHIH-BuHieVWC.js.gz +0 -0
  228. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-P_rDqbtg.js +8 -0
  229. package/dist/client/assets/{syntaxHighlight-Bgt0lmWx.js → syntaxHighlight-Cz6TPDW9.js} +1 -1
  230. package/dist/client/assets/syntaxHighlight-Cz6TPDW9.js.br +0 -0
  231. package/dist/client/assets/syntaxHighlight-Cz6TPDW9.js.gz +0 -0
  232. package/dist/client/assets/{timeline-definition-24CTP7MA-CIQuxjVB.js → timeline-definition-24CTP7MA-C7FpaNwf.js} +1 -1
  233. package/dist/client/assets/timeline-definition-24CTP7MA-C7FpaNwf.js.br +0 -0
  234. package/dist/client/assets/timeline-definition-24CTP7MA-C7FpaNwf.js.gz +0 -0
  235. package/dist/client/assets/{triangle-alert-LpKfIn7N.js → triangle-alert-Oj-OsZDw.js} +1 -1
  236. package/dist/client/assets/{unplug-CLBg6VOD.js → unplug-DN2SNXUL.js} +1 -1
  237. package/dist/client/assets/{vennDiagram-4TSXK5OY-CMRFApvJ.js → vennDiagram-4TSXK5OY-CxoHHVcs.js} +1 -1
  238. package/dist/client/assets/vennDiagram-4TSXK5OY-CxoHHVcs.js.br +0 -0
  239. package/dist/client/assets/vennDiagram-4TSXK5OY-CxoHHVcs.js.gz +0 -0
  240. package/dist/client/assets/{videoCompression-DjyAuV3i.js → videoCompression-rr2lu3uy.js} +1 -1
  241. package/dist/client/assets/videoCompression-rr2lu3uy.js.br +0 -0
  242. package/dist/client/assets/videoCompression-rr2lu3uy.js.gz +0 -0
  243. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-BEb3x-zl.js → wardleyDiagram-VM6X3IG4-B4Hsh-Ad.js} +1 -1
  244. package/dist/client/assets/wardleyDiagram-VM6X3IG4-B4Hsh-Ad.js.br +0 -0
  245. package/dist/client/assets/wardleyDiagram-VM6X3IG4-B4Hsh-Ad.js.gz +0 -0
  246. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-DUvoeYl2.js → xychartDiagram-S5SC5T6Z-CghzsxQv.js} +1 -1
  247. package/dist/client/assets/xychartDiagram-S5SC5T6Z-CghzsxQv.js.br +0 -0
  248. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-DUvoeYl2.js.gz → xychartDiagram-S5SC5T6Z-CghzsxQv.js.gz} +0 -0
  249. package/dist/client/index.html +2 -2
  250. package/dist/client/index.html.br +0 -0
  251. package/dist/client/index.html.gz +0 -0
  252. package/dist/client/sw.js +1 -1
  253. package/dist/client/sw.js.br +0 -0
  254. package/dist/client/sw.js.gz +0 -0
  255. package/dist/server/agent/chatUIPrompt.js +14 -0
  256. package/dist/server/agent/collaborationCli.js +8 -2
  257. package/dist/server/agent/collaborationPrompt.js +2 -2
  258. package/dist/server/agent/collaborationStore.js +17 -0
  259. package/dist/server/agent/sessionChatRoutes.js +23 -1
  260. package/dist/server/cli.js +5 -0
  261. package/dist/server/federation/accessPolicy.js +3 -0
  262. package/dist/server/federation/authorization.js +7 -3
  263. package/dist/server/federation/invitations.js +14 -7
  264. package/dist/server/federation/routeInvitations.js +5 -1
  265. package/dist/server/federation/runtime.js +8 -1
  266. package/dist/server/shared/chatPresentation.js +36 -0
  267. package/dist/server/shared/chatUILibrary.js +26 -0
  268. package/dist/server/shared/sessionAppearance.js +17 -0
  269. package/package.json +4 -1
  270. package/runtime-manifest.json +4 -4
  271. package/scripts/ensure-node-pty.cjs +22 -7
  272. package/scripts/postinstall.mjs +5 -4
  273. package/dist/client/assets/AndroidMirrorView-D9CMPmet.js.br +0 -0
  274. package/dist/client/assets/AndroidMirrorView-D9CMPmet.js.gz +0 -0
  275. package/dist/client/assets/App-CqLXOAnv.js +0 -178
  276. package/dist/client/assets/App-CqLXOAnv.js.br +0 -0
  277. package/dist/client/assets/App-CqLXOAnv.js.gz +0 -0
  278. package/dist/client/assets/ArchitecturePanel-Dlnd9PH-.js.br +0 -0
  279. package/dist/client/assets/ArchitecturePanel-Dlnd9PH-.js.gz +0 -0
  280. package/dist/client/assets/ChangeWalkthroughPanel-BYb27GTC.js +0 -2
  281. package/dist/client/assets/ChangeWalkthroughPanel-BYb27GTC.js.br +0 -0
  282. package/dist/client/assets/ChangeWalkthroughPanel-BYb27GTC.js.gz +0 -0
  283. package/dist/client/assets/CollaborationMainWorkspace-BJ_pbIlW.js +0 -1
  284. package/dist/client/assets/CollaborationMainWorkspace-BJ_pbIlW.js.br +0 -0
  285. package/dist/client/assets/CollaborationMainWorkspace-BJ_pbIlW.js.gz +0 -0
  286. package/dist/client/assets/ComputerControlView-VNUyl2Gb.js.br +0 -0
  287. package/dist/client/assets/ComputerControlView-VNUyl2Gb.js.gz +0 -0
  288. package/dist/client/assets/DagPlayground-Bzu6gfYW.js +0 -1
  289. package/dist/client/assets/DagPlayground-Bzu6gfYW.js.br +0 -0
  290. package/dist/client/assets/DagPlayground-Bzu6gfYW.js.gz +0 -0
  291. package/dist/client/assets/DiffLab-CKBHu65J.js.br +0 -0
  292. package/dist/client/assets/DiffLab-CKBHu65J.js.gz +0 -0
  293. package/dist/client/assets/DiffReview-DAUBgpsh.js +0 -1
  294. package/dist/client/assets/DiffReview-DAUBgpsh.js.br +0 -0
  295. package/dist/client/assets/DiffReview-DAUBgpsh.js.gz +0 -0
  296. package/dist/client/assets/DiffReviewLab--PbhIP71.js.br +0 -0
  297. package/dist/client/assets/DiffReviewLab--PbhIP71.js.gz +0 -0
  298. package/dist/client/assets/DiffViewer-Cg3GhKcU.js.br +0 -0
  299. package/dist/client/assets/DiffViewer-Cg3GhKcU.js.gz +0 -0
  300. package/dist/client/assets/GitLoadingSkeleton-ieGTuTuO.js +0 -1
  301. package/dist/client/assets/GitLoadingSkeleton-ieGTuTuO.js.br +0 -0
  302. package/dist/client/assets/GitLoadingSkeleton-ieGTuTuO.js.gz +0 -0
  303. package/dist/client/assets/MarkdownPreview-b_bwDNcY.js.br +0 -0
  304. package/dist/client/assets/MarkdownPreview-b_bwDNcY.js.gz +0 -0
  305. package/dist/client/assets/ModelPreview-C9nka14O.js.br +0 -0
  306. package/dist/client/assets/ModelPreview-C9nka14O.js.gz +0 -0
  307. package/dist/client/assets/RecordingSaveDialog-1YvzwTzo.js.br +0 -0
  308. package/dist/client/assets/RecordingSaveDialog-1YvzwTzo.js.gz +0 -0
  309. package/dist/client/assets/RightSidebar-CCk8ovoK.js.br +0 -0
  310. package/dist/client/assets/RightSidebar-CCk8ovoK.js.gz +0 -0
  311. package/dist/client/assets/SessionChatView-DORRzcNq.js +0 -13
  312. package/dist/client/assets/SessionChatView-DORRzcNq.js.br +0 -0
  313. package/dist/client/assets/SessionChatView-DORRzcNq.js.gz +0 -0
  314. package/dist/client/assets/SessionResourceSidebar-De0sHmdG.js +0 -2
  315. package/dist/client/assets/SessionResourceSidebar-De0sHmdG.js.br +0 -0
  316. package/dist/client/assets/SessionResourceSidebar-De0sHmdG.js.gz +0 -0
  317. package/dist/client/assets/TodoWorkspace-BHHT954s.js +0 -1
  318. package/dist/client/assets/TodoWorkspace-BHHT954s.js.br +0 -0
  319. package/dist/client/assets/TodoWorkspace-BHHT954s.js.gz +0 -0
  320. package/dist/client/assets/abnfDiagram-VCTEODGH-CTqKSsYV.js.br +0 -0
  321. package/dist/client/assets/abnfDiagram-VCTEODGH-CTqKSsYV.js.gz +0 -0
  322. package/dist/client/assets/app-stNRNTO-.js +0 -37
  323. package/dist/client/assets/app-stNRNTO-.js.br +0 -0
  324. package/dist/client/assets/app-stNRNTO-.js.gz +0 -0
  325. package/dist/client/assets/arc-CcvWcKBR.js.br +0 -0
  326. package/dist/client/assets/arc-CcvWcKBR.js.gz +0 -0
  327. package/dist/client/assets/architectureDiagram-5GKGNRK7-B_2ae8Tt.js.br +0 -0
  328. package/dist/client/assets/architectureDiagram-5GKGNRK7-B_2ae8Tt.js.gz +0 -0
  329. package/dist/client/assets/blockDiagram-I7D4REHJ-CGXUOwJg.js.br +0 -0
  330. package/dist/client/assets/blockDiagram-I7D4REHJ-CGXUOwJg.js.gz +0 -0
  331. package/dist/client/assets/c4Diagram-7LVT6UL2-BSU3omYQ.js.br +0 -0
  332. package/dist/client/assets/c4Diagram-7LVT6UL2-BSU3omYQ.js.gz +0 -0
  333. package/dist/client/assets/channel-CREmT4wq.js +0 -1
  334. package/dist/client/assets/chunk-F27PBJKO-CP85XeHB.js.br +0 -0
  335. package/dist/client/assets/chunk-F27PBJKO-CP85XeHB.js.gz +0 -0
  336. package/dist/client/assets/chunk-IMKFNOWR-BjTbac0d.js.br +0 -0
  337. package/dist/client/assets/chunk-IMKFNOWR-BjTbac0d.js.gz +0 -0
  338. package/dist/client/assets/chunk-SVP7TREG-Dde8KTpr.js.br +0 -0
  339. package/dist/client/assets/chunk-SVP7TREG-Dde8KTpr.js.gz +0 -0
  340. package/dist/client/assets/chunk-TICWLB2K-DIBgH5zV.js.br +0 -0
  341. package/dist/client/assets/chunk-TICWLB2K-DIBgH5zV.js.gz +0 -0
  342. package/dist/client/assets/classDiagram-ZZMXUADV-CTHA5GVu.js +0 -1
  343. package/dist/client/assets/classDiagram-v2-VYDZK3BY-CTHA5GVu.js +0 -1
  344. package/dist/client/assets/clipboardText-B0NK9NMn.js +0 -1
  345. package/dist/client/assets/clipboardText-B0NK9NMn.js.br +0 -0
  346. package/dist/client/assets/clipboardText-B0NK9NMn.js.gz +0 -0
  347. package/dist/client/assets/cose-bilkent-JH36ORCC-v4utSIkX.js.br +0 -0
  348. package/dist/client/assets/cose-bilkent-JH36ORCC-v4utSIkX.js.gz +0 -0
  349. package/dist/client/assets/cynefin-OW5HDTMX-BdbtIufa.js.br +0 -0
  350. package/dist/client/assets/cynefin-OW5HDTMX-BdbtIufa.js.gz +0 -0
  351. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-B9EVx2-N.js.br +0 -0
  352. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-B9EVx2-N.js.gz +0 -0
  353. package/dist/client/assets/dagre-GXQ25YYZ-Do2YjWuC.js.br +0 -0
  354. package/dist/client/assets/dagre-GXQ25YYZ-Do2YjWuC.js.gz +0 -0
  355. package/dist/client/assets/diagram-S7CK7UJ4-BnJa3bbo.js.br +0 -0
  356. package/dist/client/assets/diagram-S7CK7UJ4-BnJa3bbo.js.gz +0 -0
  357. package/dist/client/assets/diagram-UQ7AKVKN-C09N8-nE.js.br +0 -0
  358. package/dist/client/assets/diagram-UQ7AKVKN-C09N8-nE.js.gz +0 -0
  359. package/dist/client/assets/diagram-VSXAHHWV-mMv3O2zK.js.br +0 -0
  360. package/dist/client/assets/diagram-VSXAHHWV-mMv3O2zK.js.gz +0 -0
  361. package/dist/client/assets/diagram-VX7I27RA-B0aepUKS.js.br +0 -0
  362. package/dist/client/assets/diagram-VX7I27RA-B0aepUKS.js.gz +0 -0
  363. package/dist/client/assets/diagram-Z3DM3KII-BstqsbCO.js.br +0 -0
  364. package/dist/client/assets/diagram-Z3DM3KII-BstqsbCO.js.gz +0 -0
  365. package/dist/client/assets/ebnfDiagram-PWID7BFC-CPINc9LK.js.br +0 -0
  366. package/dist/client/assets/ebnfDiagram-PWID7BFC-CPINc9LK.js.gz +0 -0
  367. package/dist/client/assets/erDiagram-RLTQ6QDP-dUgaGLHP.js.br +0 -0
  368. package/dist/client/assets/erDiagram-RLTQ6QDP-dUgaGLHP.js.gz +0 -0
  369. package/dist/client/assets/flowDiagram-HODETNUW-4ottFlnS.js.br +0 -0
  370. package/dist/client/assets/flowDiagram-HODETNUW-4ottFlnS.js.gz +0 -0
  371. package/dist/client/assets/ganttDiagram-EL5Y4UJY-CZOkoivd.js.br +0 -0
  372. package/dist/client/assets/ganttDiagram-EL5Y4UJY-CZOkoivd.js.gz +0 -0
  373. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-kh9xx53r.js.br +0 -0
  374. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-kh9xx53r.js.gz +0 -0
  375. package/dist/client/assets/index-bfj9dYEg.css.br +0 -0
  376. package/dist/client/assets/ishikawaDiagram-5VMMS53U-DPntAz12.js.br +0 -0
  377. package/dist/client/assets/ishikawaDiagram-5VMMS53U-DPntAz12.js.gz +0 -0
  378. package/dist/client/assets/journeyDiagram-3NMN7TZE-B074bD6a.js.br +0 -0
  379. package/dist/client/assets/journeyDiagram-3NMN7TZE-B074bD6a.js.gz +0 -0
  380. package/dist/client/assets/kanban-definition-UXKFOSKX-wPbpE7ij.js.br +0 -0
  381. package/dist/client/assets/kanban-definition-UXKFOSKX-wPbpE7ij.js.gz +0 -0
  382. package/dist/client/assets/layout-D-nTHjVE.js.br +0 -0
  383. package/dist/client/assets/layout-D-nTHjVE.js.gz +0 -0
  384. package/dist/client/assets/linear-BVxgfw5H.js.br +0 -0
  385. package/dist/client/assets/linear-BVxgfw5H.js.gz +0 -0
  386. package/dist/client/assets/link-D-fkBp5k.js.br +0 -0
  387. package/dist/client/assets/link-D-fkBp5k.js.gz +0 -0
  388. package/dist/client/assets/mermaid.core-D89ctjDO.js.br +0 -0
  389. package/dist/client/assets/mermaid.core-D89ctjDO.js.gz +0 -0
  390. package/dist/client/assets/mindmap-definition-YA3MSWOX-1TrbOKNK.js.br +0 -0
  391. package/dist/client/assets/mindmap-definition-YA3MSWOX-1TrbOKNK.js.gz +0 -0
  392. package/dist/client/assets/passwordBootstrap-8XHlXyYk.js.br +0 -0
  393. package/dist/client/assets/passwordBootstrap-8XHlXyYk.js.gz +0 -0
  394. package/dist/client/assets/pegDiagram-XKGWAZYB-CJYo1Bz4.js.br +0 -0
  395. package/dist/client/assets/pegDiagram-XKGWAZYB-CJYo1Bz4.js.gz +0 -0
  396. package/dist/client/assets/pieDiagram-E7YTZNPT-DyE6_2FS.js.br +0 -0
  397. package/dist/client/assets/pieDiagram-E7YTZNPT-DyE6_2FS.js.gz +0 -0
  398. package/dist/client/assets/quadrantDiagram-AXDQQJYC-OgNN7-oZ.js.br +0 -0
  399. package/dist/client/assets/quadrantDiagram-AXDQQJYC-OgNN7-oZ.js.gz +0 -0
  400. package/dist/client/assets/railroadDiagram-O6MQD6OU-Dmqw_B10.js.br +0 -0
  401. package/dist/client/assets/railroadDiagram-O6MQD6OU-Dmqw_B10.js.gz +0 -0
  402. package/dist/client/assets/rdpSession-tgxFIJYE.js.br +0 -0
  403. package/dist/client/assets/rdpSession-tgxFIJYE.js.gz +0 -0
  404. package/dist/client/assets/requirementDiagram-BXWQKSXE-nZK7--1f.js.br +0 -0
  405. package/dist/client/assets/requirementDiagram-BXWQKSXE-nZK7--1f.js.gz +0 -0
  406. package/dist/client/assets/sankeyDiagram-P5KCCOFB-Db_TVWjx.js.br +0 -0
  407. package/dist/client/assets/sankeyDiagram-P5KCCOFB-Db_TVWjx.js.gz +0 -0
  408. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-B7TK9j0_.js.br +0 -0
  409. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-B7TK9j0_.js.gz +0 -0
  410. package/dist/client/assets/sizeCapture-INFHLROL-roX-pGgF.js.br +0 -0
  411. package/dist/client/assets/sizeCapture-INFHLROL-roX-pGgF.js.gz +0 -0
  412. package/dist/client/assets/sparkles-B64EiCUM.js +0 -1
  413. package/dist/client/assets/stateDiagram-D77RDMKH-BdBm0h1F.js.br +0 -0
  414. package/dist/client/assets/stateDiagram-D77RDMKH-BdBm0h1F.js.gz +0 -0
  415. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-ClZ2Tfz8.js +0 -1
  416. package/dist/client/assets/sun-BFxiDkET.js +0 -1
  417. package/dist/client/assets/swimlanes-42K2YHIH-DUulb0LD.js.br +0 -0
  418. package/dist/client/assets/swimlanes-42K2YHIH-DUulb0LD.js.gz +0 -0
  419. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-CGI6rSok.js +0 -8
  420. package/dist/client/assets/syntaxHighlight-Bgt0lmWx.js.br +0 -0
  421. package/dist/client/assets/syntaxHighlight-Bgt0lmWx.js.gz +0 -0
  422. package/dist/client/assets/timeline-definition-24CTP7MA-CIQuxjVB.js.br +0 -0
  423. package/dist/client/assets/timeline-definition-24CTP7MA-CIQuxjVB.js.gz +0 -0
  424. package/dist/client/assets/vennDiagram-4TSXK5OY-CMRFApvJ.js.br +0 -0
  425. package/dist/client/assets/vennDiagram-4TSXK5OY-CMRFApvJ.js.gz +0 -0
  426. package/dist/client/assets/videoCompression-DjyAuV3i.js.br +0 -0
  427. package/dist/client/assets/videoCompression-DjyAuV3i.js.gz +0 -0
  428. package/dist/client/assets/wardleyDiagram-VM6X3IG4-BEb3x-zl.js.br +0 -0
  429. package/dist/client/assets/wardleyDiagram-VM6X3IG4-BEb3x-zl.js.gz +0 -0
  430. package/dist/client/assets/xychartDiagram-S5SC5T6Z-DUvoeYl2.js.br +0 -0
@@ -1,6 +1,8 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { Router } from 'express';
3
3
  import { encryptedRequestSubject } from '../federation/requestContext.js';
4
+ import { chatPresentation } from '../shared/chatPresentation.js';
5
+ import { CollaborationError } from './collaborationProtocol.js';
4
6
  /** Clients authorized to view this Session share its durable chat history.
5
7
  * Per-device delivery addresses remain stable for retries and explicit replies. */
6
8
  export function sessionChatRoutes(options) {
@@ -27,10 +29,30 @@ export function sessionChatRoutes(options) {
27
29
  return true;
28
30
  const original = message.toPrincipalId && message.replyTo ? options.store.getMessage(message.replyTo) : null;
29
31
  return original?.groupId === group.id && message.toPrincipalId === original.integrationOrigin?.integrationId && canSeeRequest(original);
30
- }).map(m => ({ id: m.id, role: m.toPrincipalId ? 'assistant' : 'user', content: m.content, createdAt: m.createdAt, status: m.status === 'read' ? 'delivered' : m.status, replyTo: m.replyTo, requestId: m.idempotencyKey, responseKind: m.responseKind })) : [];
32
+ }).map(m => ({ id: m.id, role: m.toPrincipalId ? 'assistant' : 'user', ...(m.toPrincipalId ? chatPresentation(m.content, m.metadata) : { content: m.content }), ...(m.uiState ? { uiState: m.uiState } : {}), createdAt: m.createdAt, status: m.status === 'read' ? 'delivered' : m.status, replyTo: m.replyTo, requestId: m.idempotencyKey, responseKind: m.responseKind })) : [];
31
33
  res.setHeader('Cache-Control', 'no-store');
32
34
  res.json({ messages, agentAvailable: !!ctx.session.agent, agent: ctx.session.agent ? { slug: ctx.session.agent.slug, displayName: ctx.session.agent.displayName || ctx.session.agent.slug } : null });
33
35
  });
36
+ router.put('/:sessionId/chat/:messageId/state', (req, res) => {
37
+ const ctx = context(req), body = req.body;
38
+ if (!ctx) {
39
+ res.status(404).json({ error: '会话不可用' });
40
+ return;
41
+ }
42
+ if (!body || typeof body !== 'object' || Object.keys(body).some(key => !['revision', 'values'].includes(key))) {
43
+ res.status(400).json({ error: '填写内容无效' });
44
+ return;
45
+ }
46
+ try {
47
+ res.json(options.store.saveChatUIState(String(req.params.messageId), ctx.session.sessionId, body.values, body.revision));
48
+ }
49
+ catch (error) {
50
+ if (error instanceof CollaborationError)
51
+ res.status(error.httpStatus).json({ error: error.message, ...error.details });
52
+ else
53
+ res.status(500).json({ error: '暂时无法保存,填写内容已保留' });
54
+ }
55
+ });
34
56
  router.post('/:sessionId/chat', (req, res) => {
35
57
  const ctx = context(req);
36
58
  if (!ctx) {
@@ -1461,6 +1461,11 @@ async function runAutomation(command) {
1461
1461
  });
1462
1462
  }
1463
1463
  async function runCollab(command) {
1464
+ if (command.action === 'ui') {
1465
+ const { chatUIPrompt } = await import('./agent/chatUIPrompt.js');
1466
+ console.log(command.options.text ? chatUIPrompt() : JSON.stringify({ version: 1, instructions: chatUIPrompt() }));
1467
+ return;
1468
+ }
1464
1469
  const runningState = getRunningState();
1465
1470
  if (command.options.principal) {
1466
1471
  process.exitCode = await runIntegrationCollab(command, runningState?.port ?? 9834, { write: line => console.log(line), stdin: readStdinText });
@@ -93,6 +93,9 @@ export function resolveAccessRequest(method, path) {
93
93
  const attachment = /^([^/]+)\/chat\/attachments$/.exec(route);
94
94
  if (method === 'POST' && attachment && !reservedSessionIds.has(attachment[1].toLowerCase()))
95
95
  return { action: 'session.input', sessionId: attachment[1] };
96
+ const chatState = /^([^/]+)\/chat\/[^/]+\/state$/.exec(route);
97
+ if (method === 'PUT' && chatState && !reservedSessionIds.has(chatState[1].toLowerCase()))
98
+ return { action: 'session.input', sessionId: chatState[1] };
96
99
  const session = /^([^/]+)(?:\/(health|attach|stream|input|resize|tmux|restart|agent-resume|chat|view-mode))?$/.exec(route);
97
100
  if (session && !reservedSessionIds.has(session[1].toLowerCase())) {
98
101
  const sessionId = session[1];
@@ -2,6 +2,7 @@ import { validShareResources, resourceSubset } from '../shared/shareResources.js
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { mkdirSync, readFileSync, openSync, writeFileSync, fsyncSync, closeSync, renameSync, unlinkSync } from 'node:fs';
4
4
  import { dirname } from 'node:path';
5
+ import { validSessionAppearances, restrictSessionAppearances } from '../shared/sessionAppearance.js';
5
6
  const id = (v) => typeof v === 'string' && v.length > 0 && v.length <= 512 && !/[\s\x00-\x1f]/.test(v);
6
7
  const action = (v) => typeof v === 'string' && (v === 'service:*' || /^[a-z][a-z0-9_-]*\.[a-z][a-z0-9_-]*$/.test(v));
7
8
  const object = (v) => !!v && typeof v === 'object' && !Array.isArray(v);
@@ -20,6 +21,7 @@ function validateInput(v) {
20
21
  keys(v.scope, ['kind', 'sessionIds']);
21
22
  }
22
23
  assert(v.resources === undefined || validShareResources(v.resources), 'shared resources');
24
+ assert(v.sessionAppearance === undefined || validSessionAppearances(v.sessionAppearance, v.scope), 'session appearance');
23
25
  assert(Array.isArray(v.actions) && v.actions.length > 0 && v.actions.length <= 256 && v.actions.every(action) && new Set(v.actions).size === v.actions.length, 'actions');
24
26
  if (v.scope.kind === 'sessions')
25
27
  assert(v.actions.every(a => a.startsWith('session.')), 'session scope cannot grant service or file capabilities');
@@ -88,7 +90,7 @@ export class AuthorizationStore {
88
90
  for (const value of data.grants) {
89
91
  validateInput(value);
90
92
  const g = value;
91
- keys(g, ['id', 'serviceId', 'createdAt', 'parentGrantId', 'revokedAt', 'subjectId', 'scope', 'actions', 'expiresAt', 'canDelegate', 'conditions', 'passwordCredential', 'resources']);
93
+ keys(g, ['id', 'serviceId', 'createdAt', 'parentGrantId', 'revokedAt', 'subjectId', 'scope', 'actions', 'expiresAt', 'canDelegate', 'conditions', 'passwordCredential', 'resources', 'sessionAppearance']);
92
94
  assert(id(g.id) && g.serviceId === this.options.serviceId && Number.isSafeInteger(g.createdAt) && g.createdAt >= 0, 'grant metadata');
93
95
  assert(g.parentGrantId === undefined || id(g.parentGrantId), 'parent identity');
94
96
  assert(g.revokedAt === undefined || (Number.isSafeInteger(g.revokedAt) && g.revokedAt >= 0), 'revocation');
@@ -124,7 +126,7 @@ export class AuthorizationStore {
124
126
  }
125
127
  create(input) {
126
128
  validateInput(input);
127
- keys(input, ['subjectId', 'scope', 'actions', 'expiresAt', 'canDelegate', 'conditions', 'resources']);
129
+ keys(input, ['subjectId', 'scope', 'actions', 'expiresAt', 'canDelegate', 'conditions', 'resources', 'sessionAppearance']);
128
130
  const now = this.now();
129
131
  assert(input.expiresAt === undefined || input.expiresAt > now, 'already expired');
130
132
  return { ...structuredClone(input), id: randomUUID(), serviceId: this.options.serviceId, createdAt: now };
@@ -185,8 +187,10 @@ export class AuthorizationStore {
185
187
  changed++;
186
188
  if (!remaining.length)
187
189
  grant.revokedAt = this.now();
188
- else
190
+ else {
189
191
  grant.scope = { kind: 'sessions', sessionIds: remaining };
192
+ grant.sessionAppearance = restrictSessionAppearances(grant.sessionAppearance, remaining);
193
+ }
190
194
  }
191
195
  if (changed)
192
196
  this.save(grants);
@@ -2,6 +2,7 @@ import { validShareResources } from '../shared/shareResources.js';
2
2
  import { createHash, randomBytes, randomUUID } from 'node:crypto';
3
3
  import { mkdirSync, readFileSync, openSync, writeFileSync, fsyncSync, closeSync, renameSync, unlinkSync, chmodSync } from 'node:fs';
4
4
  import { dirname } from 'node:path';
5
+ import { validSessionAppearances, restrictSessionAppearances } from '../shared/sessionAppearance.js';
5
6
  const TTL = 10 * 60 * 1000;
6
7
  const actions = new Set(['session.view', 'session.input', 'session.resize', 'session.terminate']);
7
8
  const identity = (v) => typeof v === 'string' && v.length > 0 && v.length <= 512 && !/[\s\x00-\x1f]/.test(v);
@@ -9,9 +10,10 @@ const record = (v) => !!v && typeof v === 'object' && !Array.isArray(v);
9
10
  function requireValid(ok) { if (!ok)
10
11
  throw new Error('INVALID_INVITATION'); }
11
12
  export function validateInvitation(input) {
12
- requireValid(record(input) && Object.keys(input).every(k => ['scope', 'actions', 'label', 'expiresAt', 'resources'].includes(k)));
13
+ requireValid(record(input) && Object.keys(input).every(k => ['scope', 'actions', 'label', 'expiresAt', 'resources', 'sessionAppearance'].includes(k)));
13
14
  requireValid(record(input.scope) && Array.isArray(input.actions) && input.actions.length > 0 && new Set(input.actions).size === input.actions.length);
14
15
  requireValid(input.resources === undefined || validShareResources(input.resources));
16
+ requireValid(input.sessionAppearance === undefined || validSessionAppearances(input.sessionAppearance, input.scope));
15
17
  const scope = input.scope;
16
18
  if (scope.kind === 'service') {
17
19
  requireValid(Object.keys(scope).length === 1 && ((input.actions.length === 1 && input.actions[0] === 'service:*') || input.actions.every(a => typeof a === 'string' && actions.has(a))));
@@ -52,9 +54,9 @@ export class InvitationStore {
52
54
  requireValid(record(data) && data.version === 1 && data.serviceId === this.options.serviceId && Array.isArray(data.invitations) && data.invitations.length <= 2048);
53
55
  const seen = new Set();
54
56
  for (const item of data.invitations) {
55
- requireValid(record(item) && Object.keys(item).every(k => ['scope', 'actions', 'label', 'expiresAt', 'hash', 'issuerId', 'createdAt', 'invitationExpiresAt', 'consumedAt', 'consumedBy', 'resources'].includes(k)));
56
- const { scope, actions, resources, label, expiresAt, hash, issuerId, createdAt, invitationExpiresAt, consumedAt, consumedBy } = item;
57
- validateInvitation({ scope, actions, ...(resources === undefined ? {} : { resources }), ...(label === undefined ? {} : { label }), ...(expiresAt === undefined ? {} : { expiresAt }) });
57
+ requireValid(record(item) && Object.keys(item).every(k => ['scope', 'actions', 'label', 'expiresAt', 'hash', 'issuerId', 'createdAt', 'invitationExpiresAt', 'consumedAt', 'consumedBy', 'resources', 'sessionAppearance'].includes(k)));
58
+ const { scope, actions, resources, sessionAppearance, label, expiresAt, hash, issuerId, createdAt, invitationExpiresAt, consumedAt, consumedBy } = item;
59
+ validateInvitation({ scope, actions, ...(resources === undefined ? {} : { resources }), ...(sessionAppearance === undefined ? {} : { sessionAppearance }), ...(label === undefined ? {} : { label }), ...(expiresAt === undefined ? {} : { expiresAt }) });
58
60
  requireValid(typeof hash === 'string' && /^[a-f0-9]{64}$/.test(hash) && !seen.has(hash) && identity(issuerId));
59
61
  seen.add(hash);
60
62
  requireValid(Number.isSafeInteger(createdAt) && Number.isSafeInteger(invitationExpiresAt) && Number(invitationExpiresAt) === Number(createdAt) + TTL);
@@ -89,7 +91,7 @@ export class InvitationStore {
89
91
  listPending() {
90
92
  const now = this.now();
91
93
  return this.read().filter(i => i.consumedAt === undefined && i.invitationExpiresAt > now && (i.expiresAt === undefined || i.expiresAt > now))
92
- .map(({ hash, scope, actions, resources, label, expiresAt, createdAt, invitationExpiresAt }) => ({ id: hash, scope, actions, ...(resources === undefined ? {} : { resources }), ...(label ? { label } : {}), ...(expiresAt === undefined ? {} : { expiresAt }), createdAt, invitationExpiresAt }));
94
+ .map(({ hash, scope, actions, resources, sessionAppearance, label, expiresAt, createdAt, invitationExpiresAt }) => ({ id: hash, scope, actions, ...(resources === undefined ? {} : { resources }), ...(sessionAppearance === undefined ? {} : { sessionAppearance }), ...(label ? { label } : {}), ...(expiresAt === undefined ? {} : { expiresAt }), createdAt, invitationExpiresAt }));
93
95
  }
94
96
  revoke(id) {
95
97
  const current = this.read();
@@ -113,6 +115,7 @@ export class InvitationStore {
113
115
  if (!remaining.length)
114
116
  return false;
115
117
  invitation.scope = { kind: 'sessions', sessionIds: remaining };
118
+ invitation.sessionAppearance = restrictSessionAppearances(invitation.sessionAppearance, remaining);
116
119
  return true;
117
120
  });
118
121
  if (changed)
@@ -145,12 +148,16 @@ export class InvitationStore {
145
148
  throw new Error('PAIRING_DENIED');
146
149
  const current = this.read(), hash = this.hash(code), now = this.now();
147
150
  const invite = current.find(i => i.hash === hash);
148
- if (!invite || invite.consumedAt !== undefined || invite.invitationExpiresAt <= now || (invite.expiresAt !== undefined && invite.expiresAt <= now) || !issuerAllowed(invite.issuerId))
151
+ if (!invite || !issuerAllowed(invite.issuerId))
149
152
  throw new Error('PAIRING_DENIED');
153
+ if (invite.consumedAt !== undefined)
154
+ throw new Error('INVITATION_USED');
155
+ if (invite.invitationExpiresAt <= now || (invite.expiresAt !== undefined && invite.expiresAt <= now))
156
+ throw new Error('INVITATION_EXPIRED');
150
157
  invite.consumedAt = now;
151
158
  invite.consumedBy = subjectId;
152
159
  this.save(current);
153
- return { subjectId, ...(invite.resources ? { resources: structuredClone(invite.resources) } : {}), scope: structuredClone(invite.scope), actions: [...invite.actions], ...(invite.expiresAt === undefined ? {} : { expiresAt: invite.expiresAt }), canDelegate: false };
160
+ return { subjectId, ...(invite.resources ? { resources: structuredClone(invite.resources) } : {}), ...(invite.sessionAppearance ? { sessionAppearance: structuredClone(invite.sessionAppearance) } : {}), scope: structuredClone(invite.scope), actions: [...invite.actions], ...(invite.expiresAt === undefined ? {} : { expiresAt: invite.expiresAt }), canDelegate: false };
154
161
  }
155
162
  subjectLabels() {
156
163
  return Object.fromEntries(this.read().filter(i => i.consumedBy && i.label).map(i => [i.consumedBy, i.label]));
@@ -110,9 +110,13 @@ export class RouteInvitationStore {
110
110
  const invitation = current.find(item => item.hash === hash);
111
111
  if (invitation?.subjectId === actualSubjectId && invitation.revokedAt === undefined && this.available(invitation.issuerId, invitation.targetServiceId))
112
112
  return { serviceId: invitation.targetServiceId };
113
- if (!invitation || invitation.revokedAt !== undefined || invitation.subjectId !== undefined || invitation.createdAt > now || invitation.expiresAt <= now
113
+ if (!invitation || invitation.revokedAt !== undefined || invitation.createdAt > now
114
114
  || !this.available(invitation.issuerId, invitation.targetServiceId))
115
115
  throw new Error('ROUTE_PAIRING_DENIED');
116
+ if (invitation.subjectId !== undefined)
117
+ throw new Error('ROUTE_INVITATION_USED');
118
+ if (invitation.expiresAt <= now)
119
+ throw new Error('ROUTE_INVITATION_EXPIRED');
116
120
  invitation.subjectId = actualSubjectId;
117
121
  invitation.consumedAt = now;
118
122
  this.save(current);
@@ -407,14 +407,18 @@ export async function createFederationRuntime(app, directory, handlers, options
407
407
  }
408
408
  else if (packet.type === 'session-list') {
409
409
  const inventory = await sessionInventory();
410
+ const displayGrants = store.listEffective({ subjectId, serviceId }).filter(grant => grant.actions.includes('session.view')).reverse().sort((a, b) => b.createdAt - a.createdAt);
410
411
  const seen = new Set();
411
412
  const items = inventory.flatMap(session => {
412
413
  const sessionId = session.backendSessionId;
413
414
  if (typeof sessionId !== 'string' || !sessionId || seen.has(sessionId) || !allowed(subjectId, 'session.view', sessionId))
414
415
  return [];
415
416
  seen.add(sessionId);
417
+ const matches = (id) => id === session.sessionId || id === sessionId || stableSessionId(id) === session.sessionId;
418
+ const displayGrant = displayGrants.find(grant => grant.scope.kind === 'service' || grant.scope.sessionIds.some(matches));
419
+ const appearance = Object.entries(displayGrant?.sessionAppearance || {}).find(([id]) => matches(id))?.[1];
416
420
  return [{ sessionId, ...(typeof session.sessionId === 'string' ? { sourceSessionId: session.sessionId } : {}),
417
- name: collaborationSessionDisplayName({ ...session, name: typeof session.name === 'string' ? session.name : sessionId }), live: session.live === true,
421
+ name: appearance?.name || collaborationSessionDisplayName({ ...session, name: typeof session.name === 'string' ? session.name : sessionId }), ...(appearance?.icon ? { icon: appearance.icon } : {}), live: session.live === true,
418
422
  canWrite: allowed(subjectId, 'session.input', sessionId), canResize: allowed(subjectId, 'session.resize', sessionId) }];
419
423
  });
420
424
  send({ type: 'result', id: packet.id, items });
@@ -491,6 +495,7 @@ export async function createFederationRuntime(app, directory, handlers, options
491
495
  else if (packet.type === 'invite-create') {
492
496
  check('authorization.manage');
493
497
  const invitation = { scope: packet.scope, actions: packet.actions, ...(packet.resources === undefined ? {} : { resources: packet.resources }),
498
+ ...(packet.sessionAppearance === undefined ? {} : { sessionAppearance: packet.sessionAppearance }),
494
499
  ...(packet.label === undefined ? {} : { label: packet.label }),
495
500
  ...(packet.expiresAt === undefined ? {} : { expiresAt: packet.expiresAt }) };
496
501
  validateInvitation(invitation);
@@ -514,6 +519,8 @@ export async function createFederationRuntime(app, directory, handlers, options
514
519
  const sessionIds = invitation.scope.sessionIds.map(id => stable.get(id)).filter((id) => typeof id === 'string');
515
520
  if (sessionIds.length !== invitation.scope.sessionIds.length || new Set(sessionIds).size !== sessionIds.length)
516
521
  throw new Error('UNKNOWN_SESSION');
522
+ if (invitation.sessionAppearance)
523
+ invitation.sessionAppearance = Object.fromEntries(Object.entries(invitation.sessionAppearance).map(([id, appearance]) => [stable.get(id), appearance]));
517
524
  invitation.scope = { kind: 'sessions', sessionIds };
518
525
  }
519
526
  check('authorization.manage');
@@ -0,0 +1,36 @@
1
+ /** TD reply body stays readable to old clients; rich content is an explicit,
2
+ * versioned opt-in, never guessed from terminal output or ordinary code fences. */
3
+ export const CHAT_UI_VERSION = 1;
4
+ const record = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
5
+ export function chatPresentation(content, metadata) {
6
+ if (!record(metadata?.openui))
7
+ return { content };
8
+ try {
9
+ const body = JSON.parse(content);
10
+ if (!record(body) || typeof body.text !== 'string' || !body.text.trim() || body.text.length > 32000)
11
+ return { content: '这条回复暂时无法显示,请让对方重新发送文字说明。' };
12
+ if (metadata.openui.version !== CHAT_UI_VERSION || typeof body.ui !== 'string' || !body.ui.trim() || body.ui.length > 64000)
13
+ return { content: body.text };
14
+ return { content: body.text, ui: { version: CHAT_UI_VERSION, code: body.ui } };
15
+ }
16
+ catch {
17
+ return { content: '这条回复暂时无法显示,请让对方重新发送文字说明。' };
18
+ }
19
+ }
20
+ export function validChatUIValues(value) {
21
+ let nodes = 0;
22
+ const valid = (item, depth) => {
23
+ if (++nodes > 2000 || depth > 8)
24
+ return false;
25
+ if (item === null || typeof item === 'boolean')
26
+ return true;
27
+ if (typeof item === 'number')
28
+ return Number.isFinite(item);
29
+ if (typeof item === 'string')
30
+ return item.length <= 8000;
31
+ if (Array.isArray(item))
32
+ return item.length <= 300 && item.every(child => valid(child, depth + 1));
33
+ return record(item) && Object.keys(item).length <= 100 && Object.entries(item).every(([key, child]) => key.length <= 128 && !['__proto__', 'prototype', 'constructor'].includes(key) && valid(child, depth + 1));
34
+ };
35
+ return record(value) && valid(value, 0) && new TextEncoder().encode(JSON.stringify(value)).length <= 32000;
36
+ }
@@ -0,0 +1,26 @@
1
+ import { action, createLibrary, defineComponent } from '@openuidev/lang-core';
2
+ import { z } from 'zod/v4';
3
+ const text = z.string().max(16000), short = z.string().max(160), name = z.string().regex(/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/);
4
+ const cell = z.union([z.string().max(4000), z.number().finite(), z.boolean(), z.null()]);
5
+ export const chatUISchemas = {
6
+ Text: z.object({ content: text }),
7
+ Metric: z.object({ label: short, value: short, detail: short.optional() }),
8
+ Callout: z.object({ title: short, content: text, tone: z.enum(['info', 'success', 'warning']).optional() }),
9
+ Table: z.object({ columns: z.array(short).min(1).max(12), rows: z.array(z.array(cell).max(12)).max(300), caption: short.optional() }),
10
+ Chart: z.object({ title: short, labels: z.array(short).min(1).max(30), series: z.array(z.object({ name: short, values: z.array(z.number().finite()).max(30) })).min(1).max(6), kind: z.enum(['bar', 'line']).optional() }),
11
+ Checklist: z.object({ title: short, items: z.array(z.object({ label: short, detail: short.optional(), done: z.boolean() })).max(30) }),
12
+ Input: z.object({ name, label: short, placeholder: short.optional(), required: z.boolean().optional() }),
13
+ Select: z.object({ name, label: short, options: z.array(short).min(1).max(50), required: z.boolean().optional() }),
14
+ Checkbox: z.object({ name, label: short }),
15
+ Button: z.object({ label: short, action: action().optional() }),
16
+ Resource: z.object({ label: short, kind: z.enum(['file', 'link']), target: z.string().max(4096), description: short.optional() }),
17
+ };
18
+ const components = Object.entries(chatUISchemas).map(([key, props]) => defineComponent({ name: key, props, component: null, description: {
19
+ Text: 'Markdown prose using the shared preview renderer.', Metric: 'A known metric with label, value and optional context.', Callout: 'An important explanation; tone info/success/warning.', Table: 'A comparison table with horizontally scrollable, filterable and sortable rows.', Chart: 'A chart of supplied factual values. Do not invent values.', Checklist: 'Explicitly reported checklist items, never inferred Agent activity.',
20
+ Input: 'Text field inside Form; name must be unique in that form.', Select: 'Selection field inside Form.', Checkbox: 'Checkbox inside Form.', Button: 'Clickable action. @ToAssistant(message) continues this same conversation; inside Form also sends the form values.', Resource: 'User-opened file preview or external web link. Use an authorized absolute path for files.',
21
+ }[key] }));
22
+ const refs = z.union(components.map(component => component.ref));
23
+ const Form = defineComponent({ name: 'Form', description: 'User question form. Include Input/Select/Checkbox and a Button with @ToAssistant. Never nest forms.', props: z.object({ name, title: short, fields: z.array(refs).max(30) }), component: null });
24
+ const Card = defineComponent({ name: 'Card', description: 'A titled result card, with text, metrics, charts, tables or a form.', props: z.object({ title: short, content: z.array(z.union([refs, Form.ref])).max(30) }), component: null });
25
+ const Stack = defineComponent({ name: 'Stack', description: 'Root vertical layout of answer components.', props: z.object({ content: z.array(z.union([refs, Form.ref, Card.ref])).max(40) }), component: null });
26
+ export const chatUILibrary = createLibrary({ id: 'termdock-chat@1', root: 'Stack', components: [...components, Form, Card, Stack] });
@@ -0,0 +1,17 @@
1
+ export const SESSION_ICONS = ['message', 'sparkles', 'bot', 'code', 'file', 'briefcase', 'lightbulb', 'rocket'];
2
+ const record = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
3
+ export function validSessionIcon(value) {
4
+ return typeof value === 'string' && value.length <= 32 && (SESSION_ICONS.includes(value)
5
+ || /^(?:\p{Regional_Indicator}{2}|[#*0-9]\uFE0F?\u20E3|\p{Extended_Pictographic}[\uFE0F\p{Emoji_Modifier}]*(?:\u200D\p{Extended_Pictographic}[\uFE0F\p{Emoji_Modifier}]*)*)$/u.test(value));
6
+ }
7
+ export function validSessionAppearances(value, scope) {
8
+ if (!record(scope) || scope.kind !== 'sessions' || !Array.isArray(scope.sessionIds))
9
+ return false;
10
+ const ids = scope.sessionIds;
11
+ return record(value) && Object.keys(value).length <= 256 && Object.entries(value).every(([id, appearance]) => ids.includes(id) && record(appearance) && Object.keys(appearance).length > 0 && Object.keys(appearance).every(key => ['name', 'icon'].includes(key))
12
+ && (appearance.name === undefined || typeof appearance.name === 'string' && appearance.name.trim().length > 0 && appearance.name.length <= 80 && !/[\x00-\x1f\x7f\u202a-\u202e\u2066-\u2069]/.test(appearance.name))
13
+ && (appearance.icon === undefined || validSessionIcon(appearance.icon)));
14
+ }
15
+ export function restrictSessionAppearances(value, ids) {
16
+ return value && Object.fromEntries(Object.entries(value).filter(([id]) => ids.includes(id)));
17
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "termdock",
3
- "version": "1.4.354",
3
+ "version": "1.4.356",
4
4
  "description": "A complete web-based terminal application with modern UI",
5
5
  "type": "module",
6
6
  "main": ".desktop-dist/main.js",
@@ -66,6 +66,8 @@
66
66
  "@libp2p/utils": "7.0.7",
67
67
  "@noble/hashes": "2.4.0",
68
68
  "@novnc/novnc": "^1.7.0",
69
+ "@openuidev/lang-core": "1.0.1",
70
+ "@openuidev/react-lang": "1.0.1",
69
71
  "@peculiar/x509": "2.2.0",
70
72
  "@serenity-kit/opaque": "1.1.0",
71
73
  "@types/cookie-parser": "^1.4.10",
@@ -111,6 +113,7 @@
111
113
  "web-push": "^3.6.7",
112
114
  "ws": "^8.21.0",
113
115
  "yaml": "^2.9.1",
116
+ "zod": "4.6.7",
114
117
  "zustand": "^4.5.0"
115
118
  },
116
119
  "devDependencies": {
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "packageName": "termdock",
4
- "version": "1.4.354",
4
+ "version": "1.4.356",
5
5
  "runtimeProtocolVersion": 1,
6
6
  "minimumDesktopVersion": "1.4.46",
7
7
  "nodeMajor": 22,
8
- "dependencyHash": "sha256-ObG1OGq7e7fMFQmYoPxPp3jRodEusYHulVNa5mT1aW8=",
9
- "serverBundleHash": "sha256-BytBn+wZV+5Djv9XYLw86ORzRirpOjdtlg/oM+wPdWs=",
10
- "clientBundleHash": "sha256-WZsLgBHIwqpKOiCPDz+7avZBlO8N11O2Nz0xqptny1U=",
8
+ "dependencyHash": "sha256-uodaeckvlR6JDQ73ORIEefAICJ13wyApaFoGn2b0/GA=",
9
+ "serverBundleHash": "sha256-EleaQUnsAD9SVsw4yzpj1baMo/wPvtGD+nxHeqQJMFw=",
10
+ "clientBundleHash": "sha256-JdYvt3n9O/BJP9I3C9SqhKgOGybj4C++jnfeyaQhd5I=",
11
11
  "entrypoint": "dist/server/cli.js",
12
12
  "clientEntrypoint": "dist/client/index.html"
13
13
  }
@@ -6,6 +6,26 @@ const { spawnSync } = require('node:child_process');
6
6
  const hash = data => createHash('sha256').update(data).digest('hex');
7
7
  const upstreamHash = '5e1005d6bdcfbe97b486ee415419fe7adae99035047f07340fbad36419e0bae6';
8
8
 
9
+ function rebuildNodePty(ptyRoot, { timeout = 180_000, patched = false } = {}) {
10
+ // npm install -g passes npm_config_global=true to lifecycle scripts. Do not
11
+ // let it turn npx's temporary dependency installation into a global install.
12
+ const result = spawnSync('npx', ['--global=false', '--yes', 'node-gyp', 'rebuild'], {
13
+ cwd: ptyRoot, stdio: 'inherit', timeout,
14
+ });
15
+ if (result.error || result.status !== 0) {
16
+ const context = [
17
+ `cwd=${ptyRoot}`,
18
+ `exit status=${result.status ?? 'none'}`,
19
+ ...(result.signal ? [`signal=${result.signal}`] : []),
20
+ ...(result.error ? [`${result.error.code || 'spawn error'}: ${result.error.message}`] : []),
21
+ ].join('; ');
22
+ throw new Error(`${patched ? 'Patched node-pty' : 'node-pty'} rebuild failed (${context}). `
23
+ + 'See the npx/node-gyp output above for the cause. Check npm/cache errors before changing build tools; '
24
+ + 'on macOS, compiler/linker errors may require matching Xcode Command Line Tools and SDK versions.',
25
+ result.error ? { cause: result.error } : undefined);
26
+ }
27
+ }
28
+
9
29
  function patchSource(source) {
10
30
  if (hash(source) !== upstreamHash) throw new Error('Unrecognized node-pty source; review the macOS FD patch before upgrading');
11
31
  const start = source.indexOf('static void\npty_posix_spawn(char** argv', source.indexOf('pty_getproc(int fd)'));
@@ -49,15 +69,10 @@ function ensureNodePty(ptyRoot = path.dirname(require.resolve('node-pty/package.
49
69
  fs.rmSync(path.join(ptyRoot, 'prebuilds', `darwin-${process.arch}`), { recursive: true, force: true });
50
70
  fs.rmSync(path.join(ptyRoot, 'build/Debug'), { recursive: true, force: true });
51
71
  console.log('Rebuilding node-pty with the Termdock macOS FD cleanup fix...');
52
- const result = spawnSync('npx', ['--yes', 'node-gyp', 'rebuild'], {
53
- cwd: ptyRoot, stdio: 'inherit', timeout: 180_000,
54
- });
55
- if (result.error || result.status !== 0) {
56
- throw new Error('Patched node-pty rebuild failed; install Xcode Command Line Tools and retry. ' + (result.error?.message || ''));
57
- }
72
+ rebuildNodePty(ptyRoot, { patched: true });
58
73
  fs.chmodSync(helperPath, fs.statSync(helperPath).mode | 0o111);
59
74
  fs.writeFileSync(markerPath, JSON.stringify({ source: sourceHash, binary: hash(fs.readFileSync(binaryPath)) }));
60
75
  checked.add(ptyRoot);
61
76
  }
62
- module.exports = { ensureNodePty, patchSource };
77
+ module.exports = { ensureNodePty, patchSource, rebuildNodePty };
63
78
  if (require.main === module) ensureNodePty(process.argv[2]);
@@ -13,9 +13,10 @@ import { createRequire } from 'module';
13
13
  import fs from 'fs';
14
14
  import os from 'os';
15
15
  import path from 'path';
16
+ import { fileURLToPath } from 'node:url';
16
17
 
17
18
  const require_ = createRequire(import.meta.url);
18
- const pkgRoot = new URL('..', import.meta.url).pathname;
19
+ const pkgRoot = fileURLToPath(new URL('..', import.meta.url));
19
20
 
20
21
  function run(cmd, opts = {}) {
21
22
  console.log(` $ ${cmd}`);
@@ -48,7 +49,7 @@ function which(bin) {
48
49
  // —— native modules: 实际 spawn 测试,不只是 require ——
49
50
  console.log('\n=== Rebuilding native modules ===');
50
51
 
51
- const { ensureNodePty } = require_('./ensure-node-pty.cjs');
52
+ const { ensureNodePty, rebuildNodePty } = require_('./ensure-node-pty.cjs');
52
53
  const PTY_PATH = require_.resolve('node-pty/package.json', { paths: [pkgRoot] }).replace('/package.json', '');
53
54
 
54
55
  ensureNodePty(PTY_PATH);
@@ -91,8 +92,8 @@ if (testPty()) {
91
92
  console.log(' node-pty OK');
92
93
  } else {
93
94
  console.log(' node-pty needs rebuild (prebuilt binary incompatible with this OS/Node version)...');
94
- runOk(`rm -rf ${PTY_PATH}/prebuilds/*`);
95
- run(`cd ${PTY_PATH} && npx --yes node-gyp rebuild`, { timeout: 120_000 });
95
+ fs.rmSync(path.join(PTY_PATH, 'prebuilds'), { recursive: true, force: true });
96
+ rebuildNodePty(PTY_PATH, { timeout: 120_000 });
96
97
  if (testPty()) {
97
98
  console.log(' ✓ node-pty rebuilt successfully');
98
99
  } else {