@saluzi/saluzi-edu 0.3.0 → 0.3.2

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 (161) hide show
  1. package/dist/cli.js +204 -195
  2. package/dist/guide/guide-data.json +17 -5
  3. package/dist/rcs-web/assets/{AdminPanel-DgLYaHiP.js → AdminPanel-Dw_WcoUm.js} +1 -1
  4. package/{packages/remote-control-server/web/dist/assets/ArtifactView-CY2q-o_P.js → dist/rcs-web/assets/ArtifactView-1QwTt1_U.js} +1 -1
  5. package/dist/rcs-web/assets/{ArtifactsGallery-CjZFQhYm.js → ArtifactsGallery-BaqQmrpp.js} +1 -1
  6. package/{packages/remote-control-server/web/dist/assets/Claim-CjEYu8Jg.js → dist/rcs-web/assets/Claim-DbnYUnUa.js} +1 -1
  7. package/dist/rcs-web/assets/{Dashboard-g2VnKR61.js → Dashboard-I2zDQu_C.js} +1 -1
  8. package/dist/rcs-web/assets/{Join-DiEh0bNQ.js → Join-BW_5GOxc.js} +1 -1
  9. package/dist/rcs-web/assets/Login-DfpBv0-E.js +1 -0
  10. package/dist/rcs-web/assets/{Register-CBNGPMR6.js → Register-G3MsHXWX.js} +1 -1
  11. package/dist/rcs-web/assets/{SessionDetail-BkGAqYDS.js → SessionDetail-C1D2E27B.js} +1 -1
  12. package/dist/rcs-web/assets/{SessionVisibilityBadge-DJB8gn6j.js → SessionVisibilityBadge-BKEoqr7V.js} +1 -1
  13. package/dist/rcs-web/assets/{Setup-BqifzvSG.js → Setup-Ba0gdFpo.js} +1 -1
  14. package/dist/rcs-web/assets/{ShareLanding-twz_oOTr.js → ShareLanding-CD0g9hBP.js} +1 -1
  15. package/dist/rcs-web/assets/{TeamCreate-BxQ0djGK.js → TeamCreate-B95jdnoW.js} +1 -1
  16. package/dist/rcs-web/assets/{TeamDetail-BY3nmWNo.js → TeamDetail-B1ez_Vlm.js} +1 -1
  17. package/dist/rcs-web/assets/{TeamList-D1uw5ZQj.js → TeamList-Cfbc_pbK.js} +1 -1
  18. package/dist/rcs-web/assets/{TeamSettings-DqUlB3Gr.js → TeamSettings-CM3C5h_w.js} +1 -1
  19. package/dist/rcs-web/assets/{UserSearchInput-HY3vDxN9.js → UserSearchInput-CXTnk0hA.js} +1 -1
  20. package/dist/rcs-web/assets/{UserSettings-Ca0UvlLs.js → UserSettings-Bnq6nvYc.js} +1 -1
  21. package/dist/rcs-web/assets/{arc-M4eZFMsF.js → arc-BSYwIwEf.js} +1 -1
  22. package/dist/rcs-web/assets/{architectureDiagram-3BPJPVTR-OJqqY_9Z.js → architectureDiagram-3BPJPVTR-D3RCYL_1.js} +1 -1
  23. package/{packages/remote-control-server/web/dist/assets/blockDiagram-GPEHLZMM-BiWsXFB4.js → dist/rcs-web/assets/blockDiagram-GPEHLZMM-CHzBQR1p.js} +1 -1
  24. package/{packages/remote-control-server/web/dist/assets/c4Diagram-AAUBKEIU-A47kYHom.js → dist/rcs-web/assets/c4Diagram-AAUBKEIU-BJcaDDLG.js} +1 -1
  25. package/dist/rcs-web/assets/channel-CbFNrUsk.js +1 -0
  26. package/dist/rcs-web/assets/{chunk-2J33WTMH-bR31bKjT.js → chunk-2J33WTMH-Bg0Hnyyq.js} +1 -1
  27. package/dist/rcs-web/assets/{chunk-4BX2VUAB-BfujiUUC.js → chunk-4BX2VUAB-DfNc0_mN.js} +1 -1
  28. package/dist/rcs-web/assets/{chunk-55IACEB6-CbFE9tWc.js → chunk-55IACEB6-lSLgeJjv.js} +1 -1
  29. package/dist/rcs-web/assets/{chunk-727SXJPM-B5uYRnS4.js → chunk-727SXJPM-CLJOi1hb.js} +1 -1
  30. package/dist/rcs-web/assets/{chunk-AQP2D5EJ-BpScXOxx.js → chunk-AQP2D5EJ-DTW4EE2i.js} +1 -1
  31. package/dist/rcs-web/assets/{chunk-FMBD7UC4-QOgv52FY.js → chunk-FMBD7UC4-B57Jsd13.js} +1 -1
  32. package/dist/rcs-web/assets/{chunk-ND2GUHAM-Bsk0izyp.js → chunk-ND2GUHAM-B_msF9ch.js} +1 -1
  33. package/dist/rcs-web/assets/{chunk-QZHKN3VN-CqUHgfxZ.js → chunk-QZHKN3VN-BKdDyhR-.js} +1 -1
  34. package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-DjCl6Ad4.js +1 -0
  35. package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-DjCl6Ad4.js +1 -0
  36. package/dist/rcs-web/assets/{code-block-IT6T5CEO-BdhOgxxC.js → code-block-IT6T5CEO-By1Tu8pm.js} +1 -1
  37. package/dist/rcs-web/assets/{copy-BId_ACIH.js → copy-CIv8ifYN.js} +1 -1
  38. package/{packages/remote-control-server/web/dist/assets/cose-bilkent-S5V4N54A-CBemG5Rz.js → dist/rcs-web/assets/cose-bilkent-S5V4N54A--virsnmO.js} +1 -1
  39. package/dist/rcs-web/assets/{dagre-BM42HDAG-DFC7hnTe.js → dagre-BM42HDAG-DWHB77EO.js} +1 -1
  40. package/dist/rcs-web/assets/{diagram-2AECGRRQ--coK1eZ0.js → diagram-2AECGRRQ-Cngu5yzm.js} +1 -1
  41. package/dist/rcs-web/assets/{diagram-5GNKFQAL-DFv2rFe2.js → diagram-5GNKFQAL-KVNmlovi.js} +1 -1
  42. package/dist/rcs-web/assets/{diagram-KO2AKTUF-RJHPBcaH.js → diagram-KO2AKTUF-B7VOvyr-.js} +1 -1
  43. package/dist/rcs-web/assets/{diagram-LMA3HP47-C9WP4Nfe.js → diagram-LMA3HP47-BhGlWLSy.js} +1 -1
  44. package/dist/rcs-web/assets/{diagram-OG6HWLK6-BhsW9xiu.js → diagram-OG6HWLK6-B0nF0JCP.js} +1 -1
  45. package/{packages/remote-control-server/web/dist/assets/dialog-DfUuWIZS.js → dist/rcs-web/assets/dialog-D__YHb1u.js} +1 -1
  46. package/dist/rcs-web/assets/{erDiagram-TEJ5UH35-B5L7aiZD.js → erDiagram-TEJ5UH35-CEl50M4S.js} +1 -1
  47. package/dist/rcs-web/assets/{flowDiagram-I6XJVG4X-ABhMkIfD.js → flowDiagram-I6XJVG4X-fWBjdCNK.js} +1 -1
  48. package/{packages/remote-control-server/web/dist/assets/ganttDiagram-6RSMTGT7-DlOhmTa2.js → dist/rcs-web/assets/ganttDiagram-6RSMTGT7-BAL8_-XH.js} +1 -1
  49. package/{packages/remote-control-server/web/dist/assets/gitGraphDiagram-PVQCEYII-Bce8oSuR.js → dist/rcs-web/assets/gitGraphDiagram-PVQCEYII-BM_6XPU4.js} +1 -1
  50. package/dist/rcs-web/assets/{infoDiagram-5YYISTIA-Dkb2brY2.js → infoDiagram-5YYISTIA-DtwjUdP-.js} +1 -1
  51. package/dist/rcs-web/assets/{ishikawaDiagram-YF4QCWOH-ChFn0SpW.js → ishikawaDiagram-YF4QCWOH-BwxFByT9.js} +1 -1
  52. package/dist/rcs-web/assets/{journeyDiagram-JHISSGLW-WgDIwjKo.js → journeyDiagram-JHISSGLW-DeWYaHqa.js} +1 -1
  53. package/dist/rcs-web/assets/{kanban-definition-UN3LZRKU-CsOBZQC_.js → kanban-definition-UN3LZRKU-DMLiWipt.js} +1 -1
  54. package/dist/rcs-web/assets/{linear-D8M0DKLB.js → linear-DigNGInH.js} +1 -1
  55. package/dist/rcs-web/assets/{main-bilGpQlS.js → main-5C_gChTh.js} +18 -18
  56. package/{packages/remote-control-server/web/dist/assets/mermaid-VLURNSYL-B3Kglw26.js → dist/rcs-web/assets/mermaid-VLURNSYL-DiBP7v4h.js} +4 -4
  57. package/dist/rcs-web/assets/{mermaid.core-DCyqolwk.js → mermaid.core-CQwjc9NW.js} +5 -5
  58. package/{packages/remote-control-server/web/dist/assets/mindmap-definition-RKZ34NQL-N5OXbLbx.js → dist/rcs-web/assets/mindmap-definition-RKZ34NQL-CasTiX1-.js} +1 -1
  59. package/dist/rcs-web/assets/{pieDiagram-4H26LBE5-Bwldm4aG.js → pieDiagram-4H26LBE5-D94TX46C.js} +1 -1
  60. package/dist/rcs-web/assets/{quadrantDiagram-W4KKPZXB-ktiotrS5.js → quadrantDiagram-W4KKPZXB-wgKU_sO2.js} +1 -1
  61. package/dist/rcs-web/assets/{requirementDiagram-4Y6WPE33-D3G8oEBo.js → requirementDiagram-4Y6WPE33-DYKKTIT3.js} +1 -1
  62. package/{packages/remote-control-server/web/dist/assets/sankeyDiagram-5OEKKPKP-CKzAXLVh.js → dist/rcs-web/assets/sankeyDiagram-5OEKKPKP-BCovzmUn.js} +1 -1
  63. package/dist/rcs-web/assets/{sequenceDiagram-3UESZ5HK-BJk1-iXO.js → sequenceDiagram-3UESZ5HK-BLtYwGaQ.js} +1 -1
  64. package/dist/rcs-web/assets/{stateDiagram-AJRCARHV-DTJbbn1C.js → stateDiagram-AJRCARHV-jMZaPO--.js} +1 -1
  65. package/dist/rcs-web/assets/{stateDiagram-v2-BHNVJYJU-DTZV1yyE.js → stateDiagram-v2-BHNVJYJU-CoUWNtqD.js} +1 -1
  66. package/{packages/remote-control-server/web/dist/assets/timeline-definition-PNZ67QCA-DvSe-Rzm.js → dist/rcs-web/assets/timeline-definition-PNZ67QCA-CbqngX3Z.js} +1 -1
  67. package/{packages/remote-control-server/web/dist/assets/vennDiagram-CIIHVFJN-D4sxw7d3.js → dist/rcs-web/assets/vennDiagram-CIIHVFJN-F9m0_HxT.js} +1 -1
  68. package/{packages/remote-control-server/web/dist/assets/wardleyDiagram-YWT4CUSO-DaHUQFiA.js → dist/rcs-web/assets/wardleyDiagram-YWT4CUSO-d_Uua5Ta.js} +1 -1
  69. package/{packages/remote-control-server/web/dist/assets/xychartDiagram-2RQKCTM6-BS0clo8i.js → dist/rcs-web/assets/xychartDiagram-2RQKCTM6-BDwGBZT6.js} +1 -1
  70. package/dist/rcs-web/index.html +1 -1
  71. package/package.json +1 -1
  72. package/packages/remote-control-server/src/__tests__/helpers/db.ts +6 -0
  73. package/packages/remote-control-server/src/__tests__/helpers/mock-config.ts +2 -0
  74. package/packages/remote-control-server/src/__tests__/otp-route.test.ts +130 -0
  75. package/packages/remote-control-server/src/__tests__/single-user.test.ts +333 -0
  76. package/packages/remote-control-server/src/__tests__/web-login.test.ts +84 -0
  77. package/packages/remote-control-server/src/config.ts +55 -19
  78. package/packages/remote-control-server/src/index.ts +41 -0
  79. package/packages/remote-control-server/src/nodeServer.ts +143 -15
  80. package/packages/remote-control-server/src/registerRoutes.ts +37 -0
  81. package/packages/remote-control-server/src/routes/v1/environments.ts +11 -0
  82. package/packages/remote-control-server/src/routes/web/auth-routes.ts +21 -3
  83. package/packages/remote-control-server/src/services/disconnect-monitor.ts +2 -2
  84. package/packages/remote-control-server/src/services/single-user.ts +123 -0
  85. package/packages/remote-control-server/src/services/web-login.ts +96 -0
  86. package/packages/remote-control-server/web/dist/assets/{AdminPanel-DgLYaHiP.js → AdminPanel-Dw_WcoUm.js} +1 -1
  87. package/{dist/rcs-web/assets/ArtifactView-CY2q-o_P.js → packages/remote-control-server/web/dist/assets/ArtifactView-1QwTt1_U.js} +1 -1
  88. package/packages/remote-control-server/web/dist/assets/{ArtifactsGallery-CjZFQhYm.js → ArtifactsGallery-BaqQmrpp.js} +1 -1
  89. package/{dist/rcs-web/assets/Claim-CjEYu8Jg.js → packages/remote-control-server/web/dist/assets/Claim-DbnYUnUa.js} +1 -1
  90. package/packages/remote-control-server/web/dist/assets/{Dashboard-g2VnKR61.js → Dashboard-I2zDQu_C.js} +1 -1
  91. package/packages/remote-control-server/web/dist/assets/{Join-DiEh0bNQ.js → Join-BW_5GOxc.js} +1 -1
  92. package/packages/remote-control-server/web/dist/assets/Login-DfpBv0-E.js +1 -0
  93. package/packages/remote-control-server/web/dist/assets/{Register-CBNGPMR6.js → Register-G3MsHXWX.js} +1 -1
  94. package/packages/remote-control-server/web/dist/assets/{SessionDetail-BkGAqYDS.js → SessionDetail-C1D2E27B.js} +1 -1
  95. package/packages/remote-control-server/web/dist/assets/{SessionVisibilityBadge-DJB8gn6j.js → SessionVisibilityBadge-BKEoqr7V.js} +1 -1
  96. package/packages/remote-control-server/web/dist/assets/{Setup-BqifzvSG.js → Setup-Ba0gdFpo.js} +1 -1
  97. package/packages/remote-control-server/web/dist/assets/{ShareLanding-twz_oOTr.js → ShareLanding-CD0g9hBP.js} +1 -1
  98. package/packages/remote-control-server/web/dist/assets/{TeamCreate-BxQ0djGK.js → TeamCreate-B95jdnoW.js} +1 -1
  99. package/packages/remote-control-server/web/dist/assets/{TeamDetail-BY3nmWNo.js → TeamDetail-B1ez_Vlm.js} +1 -1
  100. package/packages/remote-control-server/web/dist/assets/{TeamList-D1uw5ZQj.js → TeamList-Cfbc_pbK.js} +1 -1
  101. package/packages/remote-control-server/web/dist/assets/{TeamSettings-DqUlB3Gr.js → TeamSettings-CM3C5h_w.js} +1 -1
  102. package/packages/remote-control-server/web/dist/assets/{UserSearchInput-HY3vDxN9.js → UserSearchInput-CXTnk0hA.js} +1 -1
  103. package/packages/remote-control-server/web/dist/assets/{UserSettings-Ca0UvlLs.js → UserSettings-Bnq6nvYc.js} +1 -1
  104. package/packages/remote-control-server/web/dist/assets/{arc-M4eZFMsF.js → arc-BSYwIwEf.js} +1 -1
  105. package/packages/remote-control-server/web/dist/assets/{architectureDiagram-3BPJPVTR-OJqqY_9Z.js → architectureDiagram-3BPJPVTR-D3RCYL_1.js} +1 -1
  106. package/{dist/rcs-web/assets/blockDiagram-GPEHLZMM-BiWsXFB4.js → packages/remote-control-server/web/dist/assets/blockDiagram-GPEHLZMM-CHzBQR1p.js} +1 -1
  107. package/{dist/rcs-web/assets/c4Diagram-AAUBKEIU-A47kYHom.js → packages/remote-control-server/web/dist/assets/c4Diagram-AAUBKEIU-BJcaDDLG.js} +1 -1
  108. package/packages/remote-control-server/web/dist/assets/channel-CbFNrUsk.js +1 -0
  109. package/packages/remote-control-server/web/dist/assets/{chunk-2J33WTMH-bR31bKjT.js → chunk-2J33WTMH-Bg0Hnyyq.js} +1 -1
  110. package/packages/remote-control-server/web/dist/assets/{chunk-4BX2VUAB-BfujiUUC.js → chunk-4BX2VUAB-DfNc0_mN.js} +1 -1
  111. package/packages/remote-control-server/web/dist/assets/{chunk-55IACEB6-CbFE9tWc.js → chunk-55IACEB6-lSLgeJjv.js} +1 -1
  112. package/packages/remote-control-server/web/dist/assets/{chunk-727SXJPM-B5uYRnS4.js → chunk-727SXJPM-CLJOi1hb.js} +1 -1
  113. package/packages/remote-control-server/web/dist/assets/{chunk-AQP2D5EJ-BpScXOxx.js → chunk-AQP2D5EJ-DTW4EE2i.js} +1 -1
  114. package/packages/remote-control-server/web/dist/assets/{chunk-FMBD7UC4-QOgv52FY.js → chunk-FMBD7UC4-B57Jsd13.js} +1 -1
  115. package/packages/remote-control-server/web/dist/assets/{chunk-ND2GUHAM-Bsk0izyp.js → chunk-ND2GUHAM-B_msF9ch.js} +1 -1
  116. package/packages/remote-control-server/web/dist/assets/{chunk-QZHKN3VN-CqUHgfxZ.js → chunk-QZHKN3VN-BKdDyhR-.js} +1 -1
  117. package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-DjCl6Ad4.js +1 -0
  118. package/packages/remote-control-server/web/dist/assets/classDiagram-v2-Q7XG4LA2-DjCl6Ad4.js +1 -0
  119. package/packages/remote-control-server/web/dist/assets/{code-block-IT6T5CEO-BdhOgxxC.js → code-block-IT6T5CEO-By1Tu8pm.js} +1 -1
  120. package/packages/remote-control-server/web/dist/assets/{copy-BId_ACIH.js → copy-CIv8ifYN.js} +1 -1
  121. package/{dist/rcs-web/assets/cose-bilkent-S5V4N54A-CBemG5Rz.js → packages/remote-control-server/web/dist/assets/cose-bilkent-S5V4N54A--virsnmO.js} +1 -1
  122. package/packages/remote-control-server/web/dist/assets/{dagre-BM42HDAG-DFC7hnTe.js → dagre-BM42HDAG-DWHB77EO.js} +1 -1
  123. package/packages/remote-control-server/web/dist/assets/{diagram-2AECGRRQ--coK1eZ0.js → diagram-2AECGRRQ-Cngu5yzm.js} +1 -1
  124. package/packages/remote-control-server/web/dist/assets/{diagram-5GNKFQAL-DFv2rFe2.js → diagram-5GNKFQAL-KVNmlovi.js} +1 -1
  125. package/packages/remote-control-server/web/dist/assets/{diagram-KO2AKTUF-RJHPBcaH.js → diagram-KO2AKTUF-B7VOvyr-.js} +1 -1
  126. package/packages/remote-control-server/web/dist/assets/{diagram-LMA3HP47-C9WP4Nfe.js → diagram-LMA3HP47-BhGlWLSy.js} +1 -1
  127. package/packages/remote-control-server/web/dist/assets/{diagram-OG6HWLK6-BhsW9xiu.js → diagram-OG6HWLK6-B0nF0JCP.js} +1 -1
  128. package/{dist/rcs-web/assets/dialog-DfUuWIZS.js → packages/remote-control-server/web/dist/assets/dialog-D__YHb1u.js} +1 -1
  129. package/packages/remote-control-server/web/dist/assets/{erDiagram-TEJ5UH35-B5L7aiZD.js → erDiagram-TEJ5UH35-CEl50M4S.js} +1 -1
  130. package/packages/remote-control-server/web/dist/assets/{flowDiagram-I6XJVG4X-ABhMkIfD.js → flowDiagram-I6XJVG4X-fWBjdCNK.js} +1 -1
  131. package/{dist/rcs-web/assets/ganttDiagram-6RSMTGT7-DlOhmTa2.js → packages/remote-control-server/web/dist/assets/ganttDiagram-6RSMTGT7-BAL8_-XH.js} +1 -1
  132. package/{dist/rcs-web/assets/gitGraphDiagram-PVQCEYII-Bce8oSuR.js → packages/remote-control-server/web/dist/assets/gitGraphDiagram-PVQCEYII-BM_6XPU4.js} +1 -1
  133. package/packages/remote-control-server/web/dist/assets/{infoDiagram-5YYISTIA-Dkb2brY2.js → infoDiagram-5YYISTIA-DtwjUdP-.js} +1 -1
  134. package/packages/remote-control-server/web/dist/assets/{ishikawaDiagram-YF4QCWOH-ChFn0SpW.js → ishikawaDiagram-YF4QCWOH-BwxFByT9.js} +1 -1
  135. package/packages/remote-control-server/web/dist/assets/{journeyDiagram-JHISSGLW-WgDIwjKo.js → journeyDiagram-JHISSGLW-DeWYaHqa.js} +1 -1
  136. package/packages/remote-control-server/web/dist/assets/{kanban-definition-UN3LZRKU-CsOBZQC_.js → kanban-definition-UN3LZRKU-DMLiWipt.js} +1 -1
  137. package/packages/remote-control-server/web/dist/assets/{linear-D8M0DKLB.js → linear-DigNGInH.js} +1 -1
  138. package/packages/remote-control-server/web/dist/assets/{main-bilGpQlS.js → main-5C_gChTh.js} +18 -18
  139. package/{dist/rcs-web/assets/mermaid-VLURNSYL-B3Kglw26.js → packages/remote-control-server/web/dist/assets/mermaid-VLURNSYL-DiBP7v4h.js} +4 -4
  140. package/packages/remote-control-server/web/dist/assets/{mermaid.core-DCyqolwk.js → mermaid.core-CQwjc9NW.js} +5 -5
  141. package/{dist/rcs-web/assets/mindmap-definition-RKZ34NQL-N5OXbLbx.js → packages/remote-control-server/web/dist/assets/mindmap-definition-RKZ34NQL-CasTiX1-.js} +1 -1
  142. package/packages/remote-control-server/web/dist/assets/{pieDiagram-4H26LBE5-Bwldm4aG.js → pieDiagram-4H26LBE5-D94TX46C.js} +1 -1
  143. package/packages/remote-control-server/web/dist/assets/{quadrantDiagram-W4KKPZXB-ktiotrS5.js → quadrantDiagram-W4KKPZXB-wgKU_sO2.js} +1 -1
  144. package/packages/remote-control-server/web/dist/assets/{requirementDiagram-4Y6WPE33-D3G8oEBo.js → requirementDiagram-4Y6WPE33-DYKKTIT3.js} +1 -1
  145. package/{dist/rcs-web/assets/sankeyDiagram-5OEKKPKP-CKzAXLVh.js → packages/remote-control-server/web/dist/assets/sankeyDiagram-5OEKKPKP-BCovzmUn.js} +1 -1
  146. package/packages/remote-control-server/web/dist/assets/{sequenceDiagram-3UESZ5HK-BJk1-iXO.js → sequenceDiagram-3UESZ5HK-BLtYwGaQ.js} +1 -1
  147. package/packages/remote-control-server/web/dist/assets/{stateDiagram-AJRCARHV-DTJbbn1C.js → stateDiagram-AJRCARHV-jMZaPO--.js} +1 -1
  148. package/packages/remote-control-server/web/dist/assets/{stateDiagram-v2-BHNVJYJU-DTZV1yyE.js → stateDiagram-v2-BHNVJYJU-CoUWNtqD.js} +1 -1
  149. package/{dist/rcs-web/assets/timeline-definition-PNZ67QCA-DvSe-Rzm.js → packages/remote-control-server/web/dist/assets/timeline-definition-PNZ67QCA-CbqngX3Z.js} +1 -1
  150. package/{dist/rcs-web/assets/vennDiagram-CIIHVFJN-D4sxw7d3.js → packages/remote-control-server/web/dist/assets/vennDiagram-CIIHVFJN-F9m0_HxT.js} +1 -1
  151. package/{dist/rcs-web/assets/wardleyDiagram-YWT4CUSO-DaHUQFiA.js → packages/remote-control-server/web/dist/assets/wardleyDiagram-YWT4CUSO-d_Uua5Ta.js} +1 -1
  152. package/{dist/rcs-web/assets/xychartDiagram-2RQKCTM6-BS0clo8i.js → packages/remote-control-server/web/dist/assets/xychartDiagram-2RQKCTM6-BDwGBZT6.js} +1 -1
  153. package/packages/remote-control-server/web/dist/index.html +1 -1
  154. package/dist/rcs-web/assets/Login-CvYL4i61.js +0 -1
  155. package/dist/rcs-web/assets/channel-CpK1-PDN.js +0 -1
  156. package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-BIsjdqJz.js +0 -1
  157. package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-BIsjdqJz.js +0 -1
  158. package/packages/remote-control-server/web/dist/assets/Login-CvYL4i61.js +0 -1
  159. package/packages/remote-control-server/web/dist/assets/channel-CpK1-PDN.js +0 -1
  160. package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-BIsjdqJz.js +0 -1
  161. package/packages/remote-control-server/web/dist/assets/classDiagram-v2-Q7XG4LA2-BIsjdqJz.js +0 -1
@@ -2448,8 +2448,8 @@
2448
2448
  "commands": [
2449
2449
  {
2450
2450
  "name": "remote-control-server",
2451
- "description": "Start a self-hosted Remote Control Server with Web UI (default API key: sk-slz)",
2452
- "descriptionZh": "启动自托管远程控制服务器(含 Web UI)",
2451
+ "description": "Start a self-hosted Remote Control Server with Web UI (default API key: sk-slz). Use ",
2452
+ "descriptionZh": "启动自托管远程控制服务器(含 Web UI);`/rcs one` 单用户模式(admin/admin123)",
2453
2453
  "aliases": [
2454
2454
  "rcs"
2455
2455
  ],
@@ -4187,8 +4187,8 @@
4187
4187
  },
4188
4188
  "remote-control-server": {
4189
4189
  "name": "remote-control-server",
4190
- "description": "Start a self-hosted Remote Control Server with Web UI (default API key: sk-slz)",
4191
- "descriptionZh": "启动自托管远程控制服务器(含 Web UI)",
4190
+ "description": "Start a self-hosted Remote Control Server with Web UI (default API key: sk-slz). Use ",
4191
+ "descriptionZh": "启动自托管远程控制服务器(含 Web UI);`/rcs one` 单用户模式(admin/admin123)",
4192
4192
  "aliases": [
4193
4193
  "rcs"
4194
4194
  ],
@@ -5920,12 +5920,24 @@
5920
5920
  "defaultValue": "0.0.0.0",
5921
5921
  "description": "RCS 监听地址"
5922
5922
  },
5923
+ {
5924
+ "name": "RCS_ONE_WORKER_DIR",
5925
+ "category": "other"
5926
+ },
5927
+ {
5928
+ "name": "RCS_ONE_WORKER_NAME",
5929
+ "category": "other"
5930
+ },
5923
5931
  {
5924
5932
  "name": "RCS_PORT",
5925
5933
  "category": "runtime",
5926
5934
  "defaultValue": "3000",
5927
5935
  "description": "RCS HTTP 端口"
5928
5936
  },
5937
+ {
5938
+ "name": "RCS_SINGLE_USER",
5939
+ "category": "other"
5940
+ },
5929
5941
  {
5930
5942
  "name": "RENDER",
5931
5943
  "category": "other"
@@ -7412,7 +7424,7 @@
7412
7424
  "可见域"
7413
7425
  ]
7414
7426
  },
7415
- "content": "\n## Remote Control Server (RCS)\n\nRCS 是 Saluzi 的自托管远程控制服务器,提供 Web UI 和会话管理。启动后,团队成员通过浏览器访问 Web UI,登录后即可创建会话、查看 worker 状态、与 agent 交互。\n\n## 启动 RCS\n\n```bash\n# 零配置启动(API Key 默认 sk-slz,与 worker 端默认 token 一致)\n# 需要自定义时再设置(管理员密码,也是 worker 连接 token):\n# export RCS_API_KEYS=sk-your-key\n\n# 启动(在 Saluzi CLI 中运行)\n> /rcs\n```\n\n也可通过 CLI 子命令直接启动:\n\n```bash\nslz rcs\n```\n\n默认端口 3000,Web UI 在 `http://localhost:3000/code/`。\n\n### Docker 部署(推荐用于常驻服务)\n\n不想在终端里常驻跑 `/rcs`,可以用 Docker 把 RCS 部署为随开机自启的常驻服务:\n\n```bash\n# 构建镜像(项目根目录执行)\ndocker build -t rcs:latest -f packages/remote-control-server/Dockerfile .\n\n# 启动容器\ndocker run -d \\\n --name rcs \\\n -p 3000:3000 \\\n -e RCS_API_KEYS=sk-your-key \\\n -e RCS_BASE_URL=https://rcs.example.com \\\n -v rcs-data:/app/data \\\n --restart unless-stopped \\\n rcs:latest\n```\n\n- `-v rcs-data:/app/data`:数据持久化卷(SQLite 数据库),重启容器不丢数据\n- `RCS_BASE_URL`:外部访问地址,反代 + HTTPS 部署时必须设置,且与客户端实际访问地址一致\n- Docker Compose 写法、健康检查(`curl /health`)与反代注意事项见仓库内 `docs/features/remote-control-self-hosting.md`\n\n## RCS Web UI 使用\n\nWeb UI 是团队成员日常使用的控制面板:登录后可创建会话、查看 worker、审批权限、管理团队与环境。下面按首次部署到日常使用的顺序介绍。\n\n### 管理员初始化(首次访问)\n\n第一次打开 Web UI 时,系统没有任何用户。第一个登录的账号会成为系统管理员(role=admin),流程如下:\n\n1. 浏览器打开 `http://localhost:3000/code/`,自动跳转到 Setup 页面\n2. 填写表单:\n - **API Key**:必须与 RCS 启动时设置的 `RCS_API_KEYS` 中的某个 key 完全一致\n - **用户名**:登录用,后续不可改\n - **密码**:至少 8 位\n - **确认密码**\n3. 提交后第一个用户即成为 admin,进入管理面板\n\n后续访问的用户分两种:\n\n- **自注册**:如果 `RCS_ALLOW_REGISTRATION` 未设为 `false`(默认开放),新访问者可在登录页注册账户(用户名 + 密码)。密码以 argon2id 加密存储,登录有速率限制(5 次失败后锁定 5 分钟)。\n- **邀请制**:将 `RCS_ALLOW_REGISTRATION=false` 后,只有管理员预先创建的账户或通过团队邀请链接加入的用户能登录。\n\n管理员 API Key 拥有系统级权限,可直接访问所有 API(不通过 Web UI 登录流程)。\n\n登录后浏览器会保存 session cookie(`rcs_access`),后续请求自动认证。\n\n### 团队与角色\n\nRCS 用「团队」组织成员、环境和会话。每个登录用户都有一个「个人空间」(无需创建),可被加入一个或多个团队。\n\n**系统级角色**(`users.role`):\n\n| 角色 | 能力 |\n|------|------|\n| `admin` | 看到所有会话(含无主孤儿)、管理所有团队、转移任意环境;通常由 Setup 流程产生 |\n| 普通用户 | 仅看到自己拥有的、所属团队可见的、显式共享给自己的会话 |\n| `guest` | 不能创建团队;通常对应被降级的账户 |\n\n**团队级角色**(`team_members.role`):\n\n| 角色 | 团队内能力 |\n|------|-----------|\n| `owner` | 修改团队信息、删除团队、加/减成员、改成员角色、创建/撤销邀请、转移或解绑环境 |\n| `admin` | 加成员、创建/撤销邀请,但不能改 owner/admin 的角色,也不能删团队 |\n| `member` | 只能自退团队,看不到团队级管理按钮 |\n\n团队至少要保留一个 owner — 系统禁止降级或移除最后一个 owner。系统 admin 在任何团队中都视为 owner。\n\n**邀请加入**:团队 owner/admin 可在「团队详情 → 邀请」页面创建邀请链接,链接形如 `/join/<inv_xxx>`,可设置:\n\n- 角色:新成员加入后的角色(仅 `admin` 或 `member`,不能邀请为 owner)\n- 过期时间(默认 24 小时)\n- 最大使用次数(默认 1)\n\n也可以「添加已有用户」:通过用户名或用户 ID 搜索已注册账户,直接加入团队。\n\n### 环境管理\n\n「环境」(environment)是 worker 向 RCS 注册后产生的实体,代表一台正在提供 agent 服务的工作机。每个环境有:\n\n- 拥有者(owner_user_id,可能为空 → 需要认领)\n- 关联团队(可选,关联后团队内成员可见该环境及其会话)\n- worker 类型(slz CLI / ACP agent)、容量、心跳\n\n**环境的归属**:\n\n- 启动 worker 时通过 `--user-id` / `--team-id` 指定 → 直接归属到该用户或团队\n- 未指定且使用共享 API Key → 生成 `claim_token`,进入待认领状态(见下文 claim 机制)\n\n**环境与团队的关联**:\n\n- 在「团队详情 → 环境」页面可把个人环境链接到团队,或把团队环境解绑回个人\n- 环境可在团队之间转移(需要源团队和目标团队的 owner/admin 权限)\n- 转移环境时,该环境下的所有会话归属随之转移到目标团队\n\n### Claim 机制(环境认领)\n\n当 worker 使用共享 API Key 启动、且未指定 `--user-id` / `--team-id` 时,RCS 不会把环境直接归属给任何人,而是生成一个 `claim_token`(形如 `clm_xxxxxxxx`)并打印认领 URL:\n\n```\n/code/claim/clm_xxxxxxxx\n```\n\n**认领流程**:\n\n1. worker 启动后在终端看到认领 URL\n2. 把这个 URL 发给任意已登录用户\n3. 该用户在浏览器打开 URL → 自动调用 `/environments/claim` 接口\n4. 该环境的 `owner_user_id` 写入此用户,`claim_token` 清空\n5. 该环境下已经创建的会话也会一并 backfill 到该用户名下(否则会成为无主孤儿会话)\n\n`claim_token` 有过期时间(`claim_expires_at`),过期后无法认领。已被认领的环境再次访问会返回 409。\n\n这个机制让团队成员用共享 API Key 启动 worker 后,再由具体的人认领,避免环境长期处于无主状态。\n\n### 会话可见域\n\n每个会话有 `visibility` 字段,控制谁能看到它:\n\n| 可见域 | 谁能看到 |\n|--------|---------|\n| `private` | 仅会话的 user owner |\n| `team` | 会话所属团队的所有成员 |\n| `public` | 所有登录用户 |\n\n实际的可见规则综合考虑了 ownership、visibility 和显式共享:\n\n1. 系统 admin 能看到所有会话(含无主孤儿会话)\n2. 用户作为 user owner 拥有的会话\n3. 用户所属团队作为 team owner 拥有、且 visibility 为 `team` 或 `public` 的会话\n4. 通过 `session_shares` 显式共享给该用户的会话(未过期)\n5. 通过 `session_shares` 显式共享给该用户所属团队的会话(未过期)\n6. visibility=`public` 的会话\n7. 无主孤儿会话:仅 admin 可见\n\n**会话转移**:会话 owner(或团队 admin)可把会话从个人空间转到团队(visibility 自动变 `team`),或从团队转回个人(visibility 自动变 `private`)。转移时需要目标是该团队的 owner/admin。\n\n**会话分享**:会话 owner 可生成分享链接,授予指定用户或团队「只读」或「读写」权限,可设置过期时间。被分享者会在自己的会话列表里看到该会话。\n\n### 权限审批\n\nRCS Web UI 在 agent 请求工具调用时弹出审批面板。权限模式(permissionMode)有 6 种,决定 agent 是否需要等待人工确认:\n\n| 模式 | 行为 |\n|------|------|\n| `default` | 每次工具调用都请求确认 |\n| `auto` | agent 自动判断是否需要确认 |\n| `acceptEdits` | 自动接受文件编辑,其他工具仍需确认 |\n| `plan` | 规划模式,仅制定计划不执行 |\n| `dontAsk` | 不询问,直接执行 |\n| `bypassPermissions` | 绕过所有权限检查(仅 sandbox 环境可用,非 root) |\n\n权限模式可在创建会话时指定,也可在会话进行中切换。fallback 顺序:客户端传值 > acp-link 启动时的 `ACP_PERMISSION_MODE` 环境变量。\n\n**三种审批面板**:\n\n- **工具调用审批**:显示工具名、参数和描述,提供 Approve / Reject 按钮\n- **多问题面板**(AskUserQuestion):agent 一次提多个问题,用户在标签页中切换回答,每题可选预设选项或填写「Other」自定义文本\n- **计划审批**:显示 plan 内容,提供「Yes, auto-accept edits」「Yes, manually approve edits」「No, keep planning」三个选项,选 No 时可附反馈让 agent 重新规划\n\n### Worker 状态\n\nWeb UI 显示所有已连接的 worker(包括 slz CLI worker 和 acp-link agent):\n\n- **在线状态**:worker 当前是否可接受会话\n- **最大并发**:worker 配置的 `--capacity`\n- **最后活动时间**:最近一次心跳\n\n### Artifacts 托管与团队画廊\n\nRCS 内置 Artifacts 存储服务。CLI 会话中用 `artifact` 工具发布的 HTML/Markdown 页面(进度面板、报告、交互式看板)会上传到 RCS 并归属到当前会话:\n\n- **会话详情页**:内嵌该会话上传的全部 artifact,可复制分享链接\n- **团队画廊** `/code/artifacts`:浏览所有你有权限查看的 artifact,可基于内置模板(PR 审查板、事故时间线、数据看板、发布清单)直接新建,也可删除\n- **可见性跟随会话**:会话对谁可见,其 artifact 就对谁可见;画廊新建的无会话 artifact 仅创建者与所属团队可见\n- **访问模型**:内容链接形如 `{BASE_URL}/v1/artifacts/{id}/content`,默认「URL 即密钥」(id 为不可猜测的随机串);设 `RCS_ARTIFACTS_PUBLIC_ACCESS=false` 可改为读取也需登录凭证\n\nCLI 侧完整用法(Markdown 自动转换、hash 覆盖更新、TTL、环境变量)见「Saluzi 特色 → Artifacts」章节([Artifacts](./artifacts))。\n\n## RCS 服务器配置\n\n| 环境变量 | 默认 | 说明 |\n|---------|------|------|\n| `RCS_PORT` | 3000 | HTTP 端口 |\n| `RCS_HOST` | 0.0.0.0 | 监听地址 |\n| `RCS_API_KEYS` | `sk-slz` | 逗号分隔的 API Key(管理员权限,也是 worker 连接 token)。默认值与 worker 端默认 token 一致,同机部署零配置;公网部署务必换强密钥 |\n| `RCS_ALLOW_REGISTRATION` | true | 是否允许开放注册(设为 false 改为邀请制) |\n| `RCS_BASE_URL` | — | 外部访问 URL(反代时设置) |\n| `RCS_DB_PATH` | — | SQLite 数据库路径(默认内存,生产环境建议持久化) |\n| `RCS_WEB_CORS_ORIGINS` | — | Web UI CORS 允许的源(逗号分隔) |\n| `RCS_JWT_EXPIRES_IN` | 3600 | JWT 有效期(秒) |\n| `RCS_DISCONNECT_TIMEOUT` | 300 | 断开连接超时(秒) |\n| `RCS_WS_CLIENT_INACTIVITY_TIMEOUT` | 300 | WebSocket 客户端无活动超时(秒) |\n| `RCS_ARTIFACTS_PUBLIC_ACCESS` | true | artifact 内容读取是否公开(URL 即密钥);设为 `false` 需登录凭证 |\n\n## Worker 接入\n\nWorker 是连接到 RCS 的 Saluzi CLI 实例,执行来自 Web UI 或其他客户端的会话。\n\n### 前置:设置环境变量\n\n**同机零配置**:RCS 与 worker 在同一台机器上时无需设置任何变量 —— `SALUZI_BRIDGE_BASE_URL` 默认 `http://localhost:3000`,`SALUZI_BRIDGE_OAUTH_TOKEN` 默认 `sk-slz`(与 RCS 默认 API Key 一致),直接 `slz rc` 即可绑定。\n\nRCS 在其他机器(`rcs-host`)上时,设置以下两个环境变量:\n\n```bash\nexport SALUZI_BRIDGE_BASE_URL=http://rcs-host:3000\nexport SALUZI_BRIDGE_OAUTH_TOKEN=sk-your-key\n```\n\n- `SALUZI_BRIDGE_BASE_URL`:RCS 服务器地址\n- `SALUZI_BRIDGE_OAUTH_TOKEN`:必须与 RCS 启动时设置的 `RCS_API_KEYS` 中的某个 key 一致\n\n可选环境变量(用于归属和团队关联):\n\n| 环境变量 | 说明 |\n|---------|------|\n| `SALUZI_BRIDGE_USERNAME` | 归属用户名(发送为 `X-Username` 头,RCS 自动认领 env 到该用户) |\n| `SALUZI_BRIDGE_USER_ID` | 归属用户 ID(绕过自动认领,直接绑定到该用户) |\n| `SALUZI_BRIDGE_TEAM_ID` | 关联团队 ID(env 注册到指定团队) |\n| `SALUZI_ENVIRONMENT_KIND` | 设为 `bridge` 标记会话来源为 remote-control |\n| `SALUZI_USE_CCR_V2` | 启用 CCR v2 传输协议 |\n| `SALUZI_BRIDGE_ALLOW_INSECURE_HTTP` | 设为 `1` 允许非 localhost 的 HTTP 连接(自托管内网场景,见下文) |\n| `SALUZI_BRIDGE_AUTO_CONNECT` | 设为 `1` 启用启动时自动连接 RCS(默认关闭;未设置时需在 CLI 内手动运行 `/rc` 或使用 `slz rc` 启动) |\n| `SALUZI_BRIDGE_SESSION_TIMEOUT` | 会话超时秒数,超时后 worker 强制结束该会话;默认 0 = 不限制会话时长 |\n\n**关于 HTTP 连接**:默认情况下,`SALUZI_BRIDGE_BASE_URL` 如果是 `http://` 且不是 `localhost`/`127.0.0.1`,worker 会拒绝启动——这是为了防止 credentials 明文传输。如果远程 RCS 部署在可信内网(例如 TLS 由上游反代终止、或网络已加密),可设置 `SALUZI_BRIDGE_ALLOW_INSECURE_HTTP=1` 放开此限制。生产环境建议优先用 HTTPS 或 SSH 隧道转发到 localhost。\n\n如果不设置 `SALUZI_BRIDGE_USERNAME`/`SALUZI_BRIDGE_USER_ID`/`SALUZI_BRIDGE_TEAM_ID`,且 token 是共享的管理员 API Key,RCS 会生成 `claim_token` 并打印认领 URL,worker 终端会显示该 URL 供用户认领(详见上文「Claim 机制」)。\n\n### 启动方式\n\n设置好环境变量后,推荐直接运行:\n\n```bash\nslz rc\n```\n\n`slz rc` 是最简的启动方式,默认配置即可作为 worker 连接到 RCS。它是 `slz remote-control` 的简写,也接受 `slz remote`、`slz sync`、`slz bridge` 作为别名。\n\n其他可选方式:\n\n```bash\n# 交互式会话 + worker(既可本地用,也接受远程请求)\nslz --remote-control\n\n# 普通会话自动连接(需额外设置 SALUZI_BRIDGE_AUTO_CONNECT=1,否则普通会话不自动连接)\nSALUZI_BRIDGE_AUTO_CONNECT=1 slz\n```\n\n### 高级参数\n\n需要调整 worker 行为时,`slz rc` 支持以下参数:\n\n| 参数 | 说明 | 示例 |\n|------|------|------|\n| `--spawn <mode>` | Spawn 模式:`same-dir`、`worktree`、`session` | `--spawn=worktree` |\n| `--capacity <N>` | 最大并发会话数(仅 worktree/session 模式) | `--capacity=5` |\n| `--create-session-in-dir` | 启动时在当前目录预创建会话(默认开启) | `--no-create-session-in-dir` 禁用 |\n| `--session-id <id>` | 恢复指定会话 | `--session-id=abc123` |\n| `--continue` | 恢复最近会话 | — |\n| `--name <name>` | 会话名称(也用于 RCS 显示) | `--name=\"我的会话\"` |\n| `--username <name>` | 归属用户名(对应 `SALUZI_BRIDGE_USERNAME`) | `--username=alice` |\n| `--user-id <id>` | 归属用户 ID(对应 `SALUZI_BRIDGE_USER_ID`) | `--user-id=u-123` |\n| `--team-id <id>` | 关联团队 ID(对应 `SALUZI_BRIDGE_TEAM_ID`) | `--team-id=team-abc` |\n| `--session-timeout <sec>` | 会话超时秒数,超时后强制结束会话;0 = 不超时(对应 `SALUZI_BRIDGE_SESSION_TIMEOUT`) | `--session-timeout=3600` |\n\n**会话超时(默认关闭)**:worker 默认不限制会话时长。会话由用户在 Web UI 中自主管理、随时可删除,自动清理只会让长时间运行的任务意外中断——所以默认不设超时。需要为 worker 设上限时(例如防止闲置会话占用容量),设置 `--session-timeout <秒>` 或 `SALUZI_BRIDGE_SESSION_TIMEOUT`,会话运行超过该秒数后会被强制结束;设为 `0` 可显式禁用。\n\n### Spawn 模式\n\n| 模式 | 说明 | 适用场景 |\n|------|------|---------|\n| `same-dir`(默认) | 所有会话在同一工作目录创建 | 单项目快速响应 |\n| `worktree` | 每个会话在独立 git worktree 中创建 | 多项目隔离,避免文件冲突 |\n| `session` | 单会话模式(容量固定为 1) | 简单场景,不需要并发 |\n\n## 会话接入(Attach)\n\n默认情况下,`/remote-control` 会为当前终端**新建**一个远程会话。Attach 模式改变这一行为:不新建会话,而是把一个**已经存在**的 RCS 会话接入当前终端,在本地继续这段对话,Web UI 上同步可见。\n\n适合场景:会话是在 Web UI 上创建的、或由其他终端发起,想换到自己的终端里继续;团队协作中接手队友的会话;或者把多台机器上的工作收拢到一个终端。\n\n### 三种接入方式\n\n| 方式 | 命令 | 行为 |\n|------|------|------|\n| 指定会话 | `/rc --attach <会话ID>` | 直接接入指定会话 |\n| 交互式选择 | `/rc --attach` | 打开会话选择器:模糊搜索列表(标题 — 状态 (会话ID)),回车接入,Esc 取消 |\n| 等待接入 | `/rc --wait`(或 `/rc --attach --wait`) | 注册后待命,等待 Web UI 侧把会话接到这台终端 |\n\n选择器里只会列出**你有权限管理**的会话;已结束、正被占用的会话和 ACP agent 的会话不会出现。\n\n**等待接入**时,终端会显示提示并持续待命。此时在 RCS Web UI 中把会话绑定到这个 worker(例如新建会话时在环境中选择该 worker),接入立即完成;若该环境还没有归属,终端会同时给出认领 URL,先认领才能接入。\n\n### 接入后发生什么\n\n- 该会话的既有对话历史会合并进本地终端(本地已有内容时保留在后面,并有提示行说明合并了多少条)\n- 之后终端与 Web UI 实时共享同一个会话:任意一端发送消息、发起审批,另一端都同步可见\n- 历史拉取失败时接入会中止并报错——不会出现「半接入」状态\n\n### 启动时自动接入(环境变量)\n\n除在会话内执行 `/rc` 命令外,也可以在启动 CLI 时通过环境变量直接进入接入模式:\n\n| 环境变量 | 说明 |\n|---------|------|\n| `SALUZI_BRIDGE_SESSION_ID` | 启动时直接接入指定会话(等效 `/rc --attach <会话ID>`) |\n| `SALUZI_BRIDGE_SESSION_MODE` | 设为 `attach`:启动后进入等待接入状态 |\n| `SALUZI_BRIDGE_ATTACH_TIMEOUT_MS` | 等待接入的超时时间(毫秒,默认 24 小时) |\n\n```bash\n# 启动即接入指定会话\nexport SALUZI_BRIDGE_SESSION_ID=sess-abc123\nslz\n\n# 或启动后等待 Web UI 分配会话\nexport SALUZI_BRIDGE_SESSION_MODE=attach\nslz\n```\n\n### 已连接时再次执行 /rc\n\n已处于远程控制连接状态时,再次执行 `/rc`(不带参数)会弹出连接管理对话框,包含三个选项:\n\n- **Disconnect this session** — 断开当前远程控制连接\n- **Show QR code** — 显示/隐藏会话 URL 二维码(手机扫码直接打开)\n- **Continue** — 保持连接,关闭对话框继续使用\n\n### 已连接时切换绑定\n\n再次执行 `/rc --attach …`、`/rc --wait`(或带 `--team-id` 等归属参数)会弹出确认框:确认后断开当前远程会话,按新的目标重新绑定;取消则保持现状。\n\n## Worker 与 RCS 的关系\n\n```\n┌─────────────────┐\n│ RCS Server │ ← 运行 slz rcs\n│ (Web UI + API) │\n└────────┬────────┘\n │ Bridge 协议\n │\n ┌────┴────┐\n │ │\n┌───▼──┐ ┌──▼───┐\n│Worker│ │Worker│ ← slz rc / slz --remote-control / slz\n│ 1 │ │ 2 │\n└──────┘ └──────┘\n```\n\n- **RCS**:中央服务器,管理会话、用户、权限\n- **Worker**:通过 bridge 协议连接,从 RCS 获取任务,汇报状态\n- **Web UI**:通过浏览器访问 RCS,创建/查看会话\n\n## ACP 协议\n\nACP(Agent Control Protocol)让**外部 agent**(非 slz CLI,如 Claude Code、其他 ACP 兼容 agent)接入 RCS 的会话系统。slz CLI 自身使用 bridge 协议,不走 ACP。\n\n`acp-link` 是 ACP 桥接工具,随 `@saluzi/saluzi-edu` 一起安装,无需单独安装。\n\n### 连接 slz 到 RCS\n\n如果要让 slz CLI 作为 ACP agent 接入 RCS(而非 bridge worker),使用 `acp-link` 桥接:\n\n#### 1. 设置环境变量\n\n**同机零配置**:`ACP_RCS_URL` 默认 `http://localhost:3000`,`ACP_RCS_TOKEN` 默认 `sk-slz`(与 RCS 默认 API Key 一致),RCS 在本机时直接跳到下一步。\n\nRCS 在其他机器(`rcs-host`)上时:\n\n```bash\nexport ACP_RCS_URL=http://rcs-host:3000\nexport ACP_RCS_TOKEN=sk-your-key\n```\n\n- `ACP_RCS_URL`:RCS 服务器地址\n- `ACP_RCS_TOKEN`:必须与 RCS 的 `RCS_API_KEYS` 中的某个 key 一致\n\n可选环境变量:\n\n| 环境变量 | 说明 |\n|---------|------|\n| `ACP_RCS_GROUP` | Channel group ID(字母、数字、下划线、连字符) |\n| `ACP_RCS_USERNAME` | 归属用户名(自动认领 env 到该用户) |\n| `ACP_RCS_USER_ID` | 归属用户 ID(绕过自动认领) |\n| `ACP_RCS_TEAM_ID` | 关联团队 ID |\n| `ACP_AUTH_TOKEN` | 本地 WS 认证 token(不设则自动生成) |\n| `ACP_PERMISSION_MODE` | 默认权限模式 |\n\n#### 2. 启动 acp-link\n\n```bash\nacp-link slz -- --acp\n```\n\n`acp-link` 会启动 slz 作为子进程,通过 ACP 协议代理它与 RCS 之间的通信。slz 会出现在 RCS Web UI 的 agent 列表中,可接受会话请求。\n\n`--` 之后是传递给 slz 的参数(`--acp` 让 slz 进入 ACP 兼容模式)。\n\n### 连接 Claude Code 到 RCS\n\n`acp-link` 支持任何遵循 ACP 协议的 agent。Claude Code 通过专用的 ACP 适配包 `@agentclientprotocol/claude-agent-acp` 接入,接入命令是 `acp-link claude-agent-acp`(**不是** `acp-link claude`,因为 Claude Code 本身不直接说 ACP 协议,需要先装适配包)。\n\n#### 1. 安装 claude-agent-acp\n\nClaude Code 的 ACP 适配包需要单独安装:\n\n```bash\nnpm install -g @agentclientprotocol/claude-agent-acp\n```\n\n安装后会注册 `claude-agent-acp` 命令。\n\n#### 2. 设置环境变量\n\n```bash\nexport ACP_RCS_URL=http://rcs-host:3000\nexport ACP_RCS_TOKEN=sk-your-key\n```\n\n#### 3. 启动 acp-link 桥接\n\n```bash\nacp-link claude-agent-acp\n```\n\n`acp-link` 的第一个参数是 agent 的可执行命令名(这里是 `claude-agent-acp`)。`claude-agent-acp` 本身不需要额外参数,因此不需要 `--`。\n\n连接成功后,Claude Code 会作为 ACP agent 出现在 RCS Web UI 中,与 slz agent 并列,团队成员可在 Web UI 中选择它创建会话。\n\n其他 ACP 兼容 agent 的接入方式类似:安装对应的 ACP 适配包,然后用 `acp-link <命令名>` 启动。可在 npm 官网搜索 `@agentclientprotocol/*` 查找已适配的 agent。\n\n## 团队协作场景\n\n### 共享会话\n\n在 RCS Web UI 中创建会话,分享链接给队友(需登录才能查看),他们可查看或加入对话。也可通过 `session_shares` 显式授予指定用户或团队「只读」/「读写」权限,并设置过期时间。\n\n### 多 Worker 协作\n\n团队多个成员各自启动 worker,连接到同一 RCS:\n\n```bash\n# 成员 A:默认配置\nslz rc\n\n# 成员 B:worktree 隔离,5 并发\nslz rc --spawn=worktree --capacity=5\n```\n\nWeb UI 显示所有 worker 状态,会话与权限集中管理。\n\n### 外部 Agent 接入\n\n用 ACP 让非 slz 的 agent 接入 RCS。Claude Code 通过 `claude-agent-acp` 适配包接入:\n\n```bash\n# 先装适配包(仅一次)\nnpm install -g @agentclientprotocol/claude-agent-acp\n\n# 设置 RCS 连接(RCS 在本机时可跳过 —— 默认 http://localhost:3000 + sk-slz)\nexport ACP_RCS_URL=http://rcs-host:3000\nexport ACP_RCS_TOKEN=sk-your-key\n\n# 启动桥接\nacp-link claude-agent-acp\n```\n\n接入后所有 agent 在 Web UI 中统一管理,团队成员可选择任意 agent 创建会话。\n\n## 安全建议\n\n- RCS 默认监听 0.0.0.0,生产环境建议用反代 + HTTPS\n- 用强 API Key,定期轮换\n- 生产环境关闭 `RCS_ALLOW_REGISTRATION` 改为邀请制\n- 使用 `RCS_WEB_CORS_ORIGINS` 限制 Web UI 访问来源\n- 设置 `RCS_DB_PATH` 持久化 SQLite 数据库\n- 限制 worker 的权限(`/permissions` 配置)\n- `bypassPermissions` 模式仅在 sandbox 环境中启用,避免在主机直接放行所有工具调用\n\n## 故障排查\n\n| 问题 | 排查 |\n|------|------|\n| Worker 无法连接 | 同机部署默认零配置(`http://localhost:3000` + `sk-slz`);跨机器时检查 `SALUZI_BRIDGE_BASE_URL` 和 `SALUZI_BRIDGE_OAUTH_TOKEN`,确认 token 与 RCS 的 `RCS_API_KEYS` 匹配 |\n| `Only HTTPS or localhost HTTP is allowed` | 远程 RCS 用 HTTP 被拒。优先用 HTTPS;或 SSH 隧道转发到 localhost;可信内网可设 `SALUZI_BRIDGE_ALLOW_INSECURE_HTTP=1` |\n| Web UI 登录失败 | 检查用户名密码;5 次失败后锁定 5 分钟 |\n| Web UI 401 | 确认使用 `RCS_API_KEYS` 中的 key 或有效的 session token |\n| 看不到某个会话 | 检查会话 visibility(private/team/public);确认是否在所属团队的成员列表里;admin 可看所有 |\n| `/rc --attach` 列表为空 | 只列出你有权限管理、且未结束/未被占用的会话;确认目标会话的可见域与你的归属,或让会话 owner 共享 |\n| 接入报「环境无主」 | 该环境还没被认领,先在终端提示的 `/code/claim/clm_xxx` URL 完成认领,再重新接入 |\n| 等待接入一直没有会话 | 在 Web UI 把会话绑定到该 worker;超过超时(默认 24 小时)会放弃,可用 `SALUZI_BRIDGE_ATTACH_TIMEOUT_MS` 调整 |\n| 接入后历史没出现 | 接入会拉取会话历史,失败即中止;确认网络可达 RCS 后重试 `/rc --attach` |\n| 环境显示「待认领」 | worker 没指定 `--user-id`/`--team-id`,找到终端里的 `/code/claim/clm_xxx` URL,已登录用户打开即可认领 |\n| acp-link 无法连接 RCS | 同机部署默认零配置(`http://localhost:3000` + `sk-slz`);跨机器时检查 `ACP_RCS_URL` 和 `ACP_RCS_TOKEN` |\n| Agent 不出现在 Web UI | 确认 acp-link 已启动且 `ACP_RCS_TOKEN` 与 `RCS_API_KEYS` 匹配 |\n| 邀请链接失效 | 邀请 token 可能过期或达到 max_uses 上限;让团队 owner/admin 重新创建 |\n| 会话连接意外断开 | 调整 `RCS_DISCONNECT_TIMEOUT` 和 `RCS_WS_CLIENT_INACTIVITY_TIMEOUT`;若是设置了会话时长上限,检查 `SALUZI_BRIDGE_SESSION_TIMEOUT` |\n"
7427
+ "content": "\n## Remote Control Server (RCS)\n\nRCS 是 Saluzi 的自托管远程控制服务器,提供 Web UI 和会话管理。启动后,团队成员通过浏览器访问 Web UI,登录后即可创建会话、查看 worker 状态、与 agent 交互。\n\n## 启动 RCS\n\n```bash\n# 零配置启动(API Key 默认 sk-slz,与 worker 端默认 token 一致)\n# 需要自定义时再设置(管理员密码,也是 worker 连接 token):\n# export RCS_API_KEYS=sk-your-key\n\n# 启动(在 Saluzi CLI 中运行)\n> /rcs\n```\n\n也可通过 CLI 子命令直接启动:\n\n```bash\nslz rcs\n```\n\n默认端口 3000,Web UI 在 `http://localhost:3000/code/`。\n\n### 单用户模式(`slz rcs one`)\n\n本地部署只想管理自己机器上的 worker、不需要多用户鉴权时,用单用户模式:\n\n```bash\nslz rcs one # 或 /rcs one\n```\n\n- **首次部署自动初始化**:自动创建唯一的管理员账号 `admin` / `admin123`,无需走 Setup 流程(登录页会提示默认账号)\n- **任意 worker 直接归属**:所有绑定该服务器的 worker 自动归属该管理员,不用声明 `SALUZI_BRIDGE_USER_ID`,也不会进入 claim 认领流程\n- **只有这一个账号**:自注册与邀请加入均被禁用\n- **默认只监听 `127.0.0.1:3000`**:不对局域网/公网暴露(可用 `RCS_HOST` 显式覆盖)\n\nworker 端零配置(同机默认 `http://localhost:3000` + `sk-slz`),登录 Web UI 后建议尽快在「个人设置」中修改默认密码。默认密码为公开约定值,仅适用于本机回环部署。\n\n### Docker 部署(推荐用于常驻服务)\n\n不想在终端里常驻跑 `/rcs`,可以用 Docker 把 RCS 部署为随开机自启的常驻服务:\n\n```bash\n# 构建镜像(项目根目录执行)\ndocker build -t rcs:latest -f packages/remote-control-server/Dockerfile .\n\n# 启动容器\ndocker run -d \\\n --name rcs \\\n -p 3000:3000 \\\n -e RCS_API_KEYS=sk-your-key \\\n -e RCS_BASE_URL=https://rcs.example.com \\\n -v rcs-data:/app/data \\\n --restart unless-stopped \\\n rcs:latest\n```\n\n- `-v rcs-data:/app/data`:数据持久化卷(SQLite 数据库),重启容器不丢数据\n- `RCS_BASE_URL`:外部访问地址,反代 + HTTPS 部署时必须设置,且与客户端实际访问地址一致\n- Docker Compose 写法、健康检查(`curl /health`)与反代注意事项见仓库内 `docs/features/remote-control-self-hosting.md`\n\n## RCS Web UI 使用\n\nWeb UI 是团队成员日常使用的控制面板:登录后可创建会话、查看 worker、审批权限、管理团队与环境。下面按首次部署到日常使用的顺序介绍。\n\n### 管理员初始化(首次访问)\n\n第一次打开 Web UI 时,系统没有任何用户。第一个登录的账号会成为系统管理员(role=admin),流程如下:\n\n1. 浏览器打开 `http://localhost:3000/code/`,自动跳转到 Setup 页面\n2. 填写表单:\n - **API Key**:必须与 RCS 启动时设置的 `RCS_API_KEYS` 中的某个 key 完全一致\n - **用户名**:登录用,后续不可改\n - **密码**:至少 8 位\n - **确认密码**\n3. 提交后第一个用户即成为 admin,进入管理面板\n\n后续访问的用户分两种:\n\n- **自注册**:如果 `RCS_ALLOW_REGISTRATION` 未设为 `false`(默认开放),新访问者可在登录页注册账户(用户名 + 密码)。密码以 argon2id 加密存储,登录有速率限制(5 次失败后锁定 5 分钟)。\n- **邀请制**:将 `RCS_ALLOW_REGISTRATION=false` 后,只有管理员预先创建的账户或通过团队邀请链接加入的用户能登录。\n\n管理员 API Key 拥有系统级权限,可直接访问所有 API(不通过 Web UI 登录流程)。\n\n登录后浏览器会保存 session cookie(`rcs_access`),后续请求自动认证。\n\n### 团队与角色\n\nRCS 用「团队」组织成员、环境和会话。每个登录用户都有一个「个人空间」(无需创建),可被加入一个或多个团队。\n\n**系统级角色**(`users.role`):\n\n| 角色 | 能力 |\n|------|------|\n| `admin` | 看到所有会话(含无主孤儿)、管理所有团队、转移任意环境;通常由 Setup 流程产生 |\n| 普通用户 | 仅看到自己拥有的、所属团队可见的、显式共享给自己的会话 |\n| `guest` | 不能创建团队;通常对应被降级的账户 |\n\n**团队级角色**(`team_members.role`):\n\n| 角色 | 团队内能力 |\n|------|-----------|\n| `owner` | 修改团队信息、删除团队、加/减成员、改成员角色、创建/撤销邀请、转移或解绑环境 |\n| `admin` | 加成员、创建/撤销邀请,但不能改 owner/admin 的角色,也不能删团队 |\n| `member` | 只能自退团队,看不到团队级管理按钮 |\n\n团队至少要保留一个 owner — 系统禁止降级或移除最后一个 owner。系统 admin 在任何团队中都视为 owner。\n\n**邀请加入**:团队 owner/admin 可在「团队详情 → 邀请」页面创建邀请链接,链接形如 `/join/<inv_xxx>`,可设置:\n\n- 角色:新成员加入后的角色(仅 `admin` 或 `member`,不能邀请为 owner)\n- 过期时间(默认 24 小时)\n- 最大使用次数(默认 1)\n\n也可以「添加已有用户」:通过用户名或用户 ID 搜索已注册账户,直接加入团队。\n\n### 环境管理\n\n「环境」(environment)是 worker 向 RCS 注册后产生的实体,代表一台正在提供 agent 服务的工作机。每个环境有:\n\n- 拥有者(owner_user_id,可能为空 → 需要认领)\n- 关联团队(可选,关联后团队内成员可见该环境及其会话)\n- worker 类型(slz CLI / ACP agent)、容量、心跳\n\n**环境的归属**:\n\n- 启动 worker 时通过 `--user-id` / `--team-id` 指定 → 直接归属到该用户或团队\n- 未指定且使用共享 API Key → 生成 `claim_token`,进入待认领状态(见下文 claim 机制)\n\n**环境与团队的关联**:\n\n- 在「团队详情 → 环境」页面可把个人环境链接到团队,或把团队环境解绑回个人\n- 环境可在团队之间转移(需要源团队和目标团队的 owner/admin 权限)\n- 转移环境时,该环境下的所有会话归属随之转移到目标团队\n\n### Claim 机制(环境认领)\n\n当 worker 使用共享 API Key 启动、且未指定 `--user-id` / `--team-id` 时,RCS 不会把环境直接归属给任何人,而是生成一个 `claim_token`(形如 `clm_xxxxxxxx`)并打印认领 URL:\n\n```\n/code/claim/clm_xxxxxxxx\n```\n\n**认领流程**:\n\n1. worker 启动后在终端看到认领 URL\n2. 把这个 URL 发给任意已登录用户\n3. 该用户在浏览器打开 URL → 自动调用 `/environments/claim` 接口\n4. 该环境的 `owner_user_id` 写入此用户,`claim_token` 清空\n5. 该环境下已经创建的会话也会一并 backfill 到该用户名下(否则会成为无主孤儿会话)\n\n`claim_token` 有过期时间(`claim_expires_at`),过期后无法认领。已被认领的环境再次访问会返回 409。\n\n这个机制让团队成员用共享 API Key 启动 worker 后,再由具体的人认领,避免环境长期处于无主状态。\n\n### 会话可见域\n\n每个会话有 `visibility` 字段,控制谁能看到它:\n\n| 可见域 | 谁能看到 |\n|--------|---------|\n| `private` | 仅会话的 user owner |\n| `team` | 会话所属团队的所有成员 |\n| `public` | 所有登录用户 |\n\n实际的可见规则综合考虑了 ownership、visibility 和显式共享:\n\n1. 系统 admin 能看到所有会话(含无主孤儿会话)\n2. 用户作为 user owner 拥有的会话\n3. 用户所属团队作为 team owner 拥有、且 visibility 为 `team` 或 `public` 的会话\n4. 通过 `session_shares` 显式共享给该用户的会话(未过期)\n5. 通过 `session_shares` 显式共享给该用户所属团队的会话(未过期)\n6. visibility=`public` 的会话\n7. 无主孤儿会话:仅 admin 可见\n\n**会话转移**:会话 owner(或团队 admin)可把会话从个人空间转到团队(visibility 自动变 `team`),或从团队转回个人(visibility 自动变 `private`)。转移时需要目标是该团队的 owner/admin。\n\n**会话分享**:会话 owner 可生成分享链接,授予指定用户或团队「只读」或「读写」权限,可设置过期时间。被分享者会在自己的会话列表里看到该会话。\n\n### 权限审批\n\nRCS Web UI 在 agent 请求工具调用时弹出审批面板。权限模式(permissionMode)有 6 种,决定 agent 是否需要等待人工确认:\n\n| 模式 | 行为 |\n|------|------|\n| `default` | 每次工具调用都请求确认 |\n| `auto` | agent 自动判断是否需要确认 |\n| `acceptEdits` | 自动接受文件编辑,其他工具仍需确认 |\n| `plan` | 规划模式,仅制定计划不执行 |\n| `dontAsk` | 不询问,直接执行 |\n| `bypassPermissions` | 绕过所有权限检查(仅 sandbox 环境可用,非 root) |\n\n权限模式可在创建会话时指定,也可在会话进行中切换。fallback 顺序:客户端传值 > acp-link 启动时的 `ACP_PERMISSION_MODE` 环境变量。\n\n**三种审批面板**:\n\n- **工具调用审批**:显示工具名、参数和描述,提供 Approve / Reject 按钮\n- **多问题面板**(AskUserQuestion):agent 一次提多个问题,用户在标签页中切换回答,每题可选预设选项或填写「Other」自定义文本\n- **计划审批**:显示 plan 内容,提供「Yes, auto-accept edits」「Yes, manually approve edits」「No, keep planning」三个选项,选 No 时可附反馈让 agent 重新规划\n\n### Worker 状态\n\nWeb UI 显示所有已连接的 worker(包括 slz CLI worker 和 acp-link agent):\n\n- **在线状态**:worker 当前是否可接受会话\n- **最大并发**:worker 配置的 `--capacity`\n- **最后活动时间**:最近一次心跳\n\n### Artifacts 托管与团队画廊\n\nRCS 内置 Artifacts 存储服务。CLI 会话中用 `artifact` 工具发布的 HTML/Markdown 页面(进度面板、报告、交互式看板)会上传到 RCS 并归属到当前会话:\n\n- **会话详情页**:内嵌该会话上传的全部 artifact,可复制分享链接\n- **团队画廊** `/code/artifacts`:浏览所有你有权限查看的 artifact,可基于内置模板(PR 审查板、事故时间线、数据看板、发布清单)直接新建,也可删除\n- **可见性跟随会话**:会话对谁可见,其 artifact 就对谁可见;画廊新建的无会话 artifact 仅创建者与所属团队可见\n- **访问模型**:内容链接形如 `{BASE_URL}/v1/artifacts/{id}/content`,默认「URL 即密钥」(id 为不可猜测的随机串);设 `RCS_ARTIFACTS_PUBLIC_ACCESS=false` 可改为读取也需登录凭证\n\nCLI 侧完整用法(Markdown 自动转换、hash 覆盖更新、TTL、环境变量)见「Saluzi 特色 → Artifacts」章节([Artifacts](./artifacts))。\n\n## RCS 服务器配置\n\n| 环境变量 | 默认 | 说明 |\n|---------|------|------|\n| `RCS_PORT` | 3000 | HTTP 端口 |\n| `RCS_HOST` | 0.0.0.0 | 监听地址 |\n| `RCS_API_KEYS` | `sk-slz` | 逗号分隔的 API Key(管理员权限,也是 worker 连接 token)。默认值与 worker 端默认 token 一致,同机部署零配置;公网部署务必换强密钥 |\n| `RCS_ALLOW_REGISTRATION` | true | 是否允许开放注册(设为 false 改为邀请制) |\n| `RCS_BASE_URL` | — | 外部访问 URL(反代时设置) |\n| `RCS_DB_PATH` | — | SQLite 数据库路径(默认内存,生产环境建议持久化) |\n| `RCS_WEB_CORS_ORIGINS` | — | Web UI CORS 允许的源(逗号分隔) |\n| `RCS_JWT_EXPIRES_IN` | 3600 | JWT 有效期(秒) |\n| `RCS_DISCONNECT_TIMEOUT` | 300 | 断开连接超时(秒) |\n| `RCS_WS_CLIENT_INACTIVITY_TIMEOUT` | 300 | WebSocket 客户端无活动超时(秒) |\n| `RCS_ARTIFACTS_PUBLIC_ACCESS` | true | artifact 内容读取是否公开(URL 即密钥);设为 `false` 需登录凭证 |\n\n## Worker 接入\n\nWorker 是连接到 RCS 的 Saluzi CLI 实例,执行来自 Web UI 或其他客户端的会话。\n\n### 前置:设置环境变量\n\n**同机零配置**:RCS 与 worker 在同一台机器上时无需设置任何变量 —— `SALUZI_BRIDGE_BASE_URL` 默认 `http://localhost:3000`,`SALUZI_BRIDGE_OAUTH_TOKEN` 默认 `sk-slz`(与 RCS 默认 API Key 一致),直接 `slz rc` 即可绑定。\n\nRCS 在其他机器(`rcs-host`)上时,设置以下两个环境变量:\n\n```bash\nexport SALUZI_BRIDGE_BASE_URL=http://rcs-host:3000\nexport SALUZI_BRIDGE_OAUTH_TOKEN=sk-your-key\n```\n\n- `SALUZI_BRIDGE_BASE_URL`:RCS 服务器地址\n- `SALUZI_BRIDGE_OAUTH_TOKEN`:必须与 RCS 启动时设置的 `RCS_API_KEYS` 中的某个 key 一致\n\n可选环境变量(用于归属和团队关联):\n\n| 环境变量 | 说明 |\n|---------|------|\n| `SALUZI_BRIDGE_USERNAME` | 归属用户名(发送为 `X-Username` 头,RCS 自动认领 env 到该用户) |\n| `SALUZI_BRIDGE_USER_ID` | 归属用户 ID(绕过自动认领,直接绑定到该用户) |\n| `SALUZI_BRIDGE_TEAM_ID` | 关联团队 ID(env 注册到指定团队) |\n| `SALUZI_ENVIRONMENT_KIND` | 设为 `bridge` 标记会话来源为 remote-control |\n| `SALUZI_USE_CCR_V2` | 启用 CCR v2 传输协议 |\n| `SALUZI_BRIDGE_ALLOW_INSECURE_HTTP` | 设为 `1` 允许非 localhost 的 HTTP 连接(自托管内网场景,见下文) |\n| `SALUZI_BRIDGE_AUTO_CONNECT` | 设为 `1` 启用启动时自动连接 RCS(默认关闭;未设置时需在 CLI 内手动运行 `/rc` 或使用 `slz rc` 启动) |\n| `SALUZI_BRIDGE_SESSION_TIMEOUT` | 会话超时秒数,超时后 worker 强制结束该会话;默认 0 = 不限制会话时长 |\n\n**关于 HTTP 连接**:默认情况下,`SALUZI_BRIDGE_BASE_URL` 如果是 `http://` 且不是 `localhost`/`127.0.0.1`,worker 会拒绝启动——这是为了防止 credentials 明文传输。如果远程 RCS 部署在可信内网(例如 TLS 由上游反代终止、或网络已加密),可设置 `SALUZI_BRIDGE_ALLOW_INSECURE_HTTP=1` 放开此限制。生产环境建议优先用 HTTPS 或 SSH 隧道转发到 localhost。\n\n如果不设置 `SALUZI_BRIDGE_USERNAME`/`SALUZI_BRIDGE_USER_ID`/`SALUZI_BRIDGE_TEAM_ID`,且 token 是共享的管理员 API Key,RCS 会生成 `claim_token` 并打印认领 URL,worker 终端会显示该 URL 供用户认领(详见上文「Claim 机制」)。\n\n### 启动方式\n\n设置好环境变量后,推荐直接运行:\n\n```bash\nslz rc\n```\n\n`slz rc` 是最简的启动方式,默认配置即可作为 worker 连接到 RCS。它是 `slz remote-control` 的简写,也接受 `slz remote`、`slz sync`、`slz bridge` 作为别名。\n\n其他可选方式:\n\n```bash\n# 交互式会话 + worker(既可本地用,也接受远程请求)\nslz --remote-control\n\n# 普通会话自动连接(需额外设置 SALUZI_BRIDGE_AUTO_CONNECT=1,否则普通会话不自动连接)\nSALUZI_BRIDGE_AUTO_CONNECT=1 slz\n```\n\n### 高级参数\n\n需要调整 worker 行为时,`slz rc` 支持以下参数:\n\n| 参数 | 说明 | 示例 |\n|------|------|------|\n| `--spawn <mode>` | Spawn 模式:`same-dir`、`worktree`、`session` | `--spawn=worktree` |\n| `--capacity <N>` | 最大并发会话数(仅 worktree/session 模式) | `--capacity=5` |\n| `--create-session-in-dir` | 启动时在当前目录预创建会话(默认开启) | `--no-create-session-in-dir` 禁用 |\n| `--session-id <id>` | 恢复指定会话 | `--session-id=abc123` |\n| `--continue` | 恢复最近会话 | — |\n| `--name <name>` | 会话名称(也用于 RCS 显示) | `--name=\"我的会话\"` |\n| `--username <name>` | 归属用户名(对应 `SALUZI_BRIDGE_USERNAME`) | `--username=alice` |\n| `--user-id <id>` | 归属用户 ID(对应 `SALUZI_BRIDGE_USER_ID`) | `--user-id=u-123` |\n| `--team-id <id>` | 关联团队 ID(对应 `SALUZI_BRIDGE_TEAM_ID`) | `--team-id=team-abc` |\n| `--session-timeout <sec>` | 会话超时秒数,超时后强制结束会话;0 = 不超时(对应 `SALUZI_BRIDGE_SESSION_TIMEOUT`) | `--session-timeout=3600` |\n\n**会话超时(默认关闭)**:worker 默认不限制会话时长。会话由用户在 Web UI 中自主管理、随时可删除,自动清理只会让长时间运行的任务意外中断——所以默认不设超时。需要为 worker 设上限时(例如防止闲置会话占用容量),设置 `--session-timeout <秒>` 或 `SALUZI_BRIDGE_SESSION_TIMEOUT`,会话运行超过该秒数后会被强制结束;设为 `0` 可显式禁用。\n\n### Spawn 模式\n\n| 模式 | 说明 | 适用场景 |\n|------|------|---------|\n| `same-dir`(默认) | 所有会话在同一工作目录创建 | 单项目快速响应 |\n| `worktree` | 每个会话在独立 git worktree 中创建 | 多项目隔离,避免文件冲突 |\n| `session` | 单会话模式(容量固定为 1) | 简单场景,不需要并发 |\n\n## 会话接入(Attach)\n\n默认情况下,`/remote-control` 会为当前终端**新建**一个远程会话。Attach 模式改变这一行为:不新建会话,而是把一个**已经存在**的 RCS 会话接入当前终端,在本地继续这段对话,Web UI 上同步可见。\n\n适合场景:会话是在 Web UI 上创建的、或由其他终端发起,想换到自己的终端里继续;团队协作中接手队友的会话;或者把多台机器上的工作收拢到一个终端。\n\n### 三种接入方式\n\n| 方式 | 命令 | 行为 |\n|------|------|------|\n| 指定会话 | `/rc --attach <会话ID>` | 直接接入指定会话 |\n| 交互式选择 | `/rc --attach` | 打开会话选择器:模糊搜索列表(标题 — 状态 (会话ID)),回车接入,Esc 取消 |\n| 等待接入 | `/rc --wait`(或 `/rc --attach --wait`) | 注册后待命,等待 Web UI 侧把会话接到这台终端 |\n\n选择器里只会列出**你有权限管理**的会话;已结束、正被占用的会话和 ACP agent 的会话不会出现。\n\n**等待接入**时,终端会显示提示并持续待命。此时在 RCS Web UI 中把会话绑定到这个 worker(例如新建会话时在环境中选择该 worker),接入立即完成;若该环境还没有归属,终端会同时给出认领 URL,先认领才能接入。\n\n### 接入后发生什么\n\n- 该会话的既有对话历史会合并进本地终端(本地已有内容时保留在后面,并有提示行说明合并了多少条)\n- 之后终端与 Web UI 实时共享同一个会话:任意一端发送消息、发起审批,另一端都同步可见\n- 历史拉取失败时接入会中止并报错——不会出现「半接入」状态\n\n### 启动时自动接入(环境变量)\n\n除在会话内执行 `/rc` 命令外,也可以在启动 CLI 时通过环境变量直接进入接入模式:\n\n| 环境变量 | 说明 |\n|---------|------|\n| `SALUZI_BRIDGE_SESSION_ID` | 启动时直接接入指定会话(等效 `/rc --attach <会话ID>`) |\n| `SALUZI_BRIDGE_SESSION_MODE` | 设为 `attach`:启动后进入等待接入状态 |\n| `SALUZI_BRIDGE_ATTACH_TIMEOUT_MS` | 等待接入的超时时间(毫秒,默认 24 小时) |\n\n```bash\n# 启动即接入指定会话\nexport SALUZI_BRIDGE_SESSION_ID=sess-abc123\nslz\n\n# 或启动后等待 Web UI 分配会话\nexport SALUZI_BRIDGE_SESSION_MODE=attach\nslz\n```\n\n### 已连接时再次执行 /rc\n\n已处于远程控制连接状态时,再次执行 `/rc`(不带参数)会弹出连接管理对话框,包含三个选项:\n\n- **Disconnect this session** — 断开当前远程控制连接\n- **Show QR code** — 显示/隐藏会话 URL 二维码(手机扫码直接打开)\n- **Continue** — 保持连接,关闭对话框继续使用\n\n### 已连接时切换绑定\n\n再次执行 `/rc --attach …`、`/rc --wait`(或带 `--team-id` 等归属参数)会弹出确认框:确认后断开当前远程会话,按新的目标重新绑定;取消则保持现状。\n\n## Worker 与 RCS 的关系\n\n```\n┌─────────────────┐\n│ RCS Server │ ← 运行 slz rcs\n│ (Web UI + API) │\n└────────┬────────┘\n │ Bridge 协议\n │\n ┌────┴────┐\n │ │\n┌───▼──┐ ┌──▼───┐\n│Worker│ │Worker│ ← slz rc / slz --remote-control / slz\n│ 1 │ │ 2 │\n└──────┘ └──────┘\n```\n\n- **RCS**:中央服务器,管理会话、用户、权限\n- **Worker**:通过 bridge 协议连接,从 RCS 获取任务,汇报状态\n- **Web UI**:通过浏览器访问 RCS,创建/查看会话\n\n## ACP 协议\n\nACP(Agent Control Protocol)让**外部 agent**(非 slz CLI,如 Claude Code、其他 ACP 兼容 agent)接入 RCS 的会话系统。slz CLI 自身使用 bridge 协议,不走 ACP。\n\n`acp-link` 是 ACP 桥接工具,随 `@saluzi/saluzi-edu` 一起安装,无需单独安装。\n\n### 连接 slz 到 RCS\n\n如果要让 slz CLI 作为 ACP agent 接入 RCS(而非 bridge worker),使用 `acp-link` 桥接:\n\n#### 1. 设置环境变量\n\n**同机零配置**:`ACP_RCS_URL` 默认 `http://localhost:3000`,`ACP_RCS_TOKEN` 默认 `sk-slz`(与 RCS 默认 API Key 一致),RCS 在本机时直接跳到下一步。\n\nRCS 在其他机器(`rcs-host`)上时:\n\n```bash\nexport ACP_RCS_URL=http://rcs-host:3000\nexport ACP_RCS_TOKEN=sk-your-key\n```\n\n- `ACP_RCS_URL`:RCS 服务器地址\n- `ACP_RCS_TOKEN`:必须与 RCS 的 `RCS_API_KEYS` 中的某个 key 一致\n\n可选环境变量:\n\n| 环境变量 | 说明 |\n|---------|------|\n| `ACP_RCS_GROUP` | Channel group ID(字母、数字、下划线、连字符) |\n| `ACP_RCS_USERNAME` | 归属用户名(自动认领 env 到该用户) |\n| `ACP_RCS_USER_ID` | 归属用户 ID(绕过自动认领) |\n| `ACP_RCS_TEAM_ID` | 关联团队 ID |\n| `ACP_AUTH_TOKEN` | 本地 WS 认证 token(不设则自动生成) |\n| `ACP_PERMISSION_MODE` | 默认权限模式 |\n\n#### 2. 启动 acp-link\n\n```bash\nacp-link slz -- --acp\n```\n\n`acp-link` 会启动 slz 作为子进程,通过 ACP 协议代理它与 RCS 之间的通信。slz 会出现在 RCS Web UI 的 agent 列表中,可接受会话请求。\n\n`--` 之后是传递给 slz 的参数(`--acp` 让 slz 进入 ACP 兼容模式)。\n\n### 连接 Claude Code 到 RCS\n\n`acp-link` 支持任何遵循 ACP 协议的 agent。Claude Code 通过专用的 ACP 适配包 `@agentclientprotocol/claude-agent-acp` 接入,接入命令是 `acp-link claude-agent-acp`(**不是** `acp-link claude`,因为 Claude Code 本身不直接说 ACP 协议,需要先装适配包)。\n\n#### 1. 安装 claude-agent-acp\n\nClaude Code 的 ACP 适配包需要单独安装:\n\n```bash\nnpm install -g @agentclientprotocol/claude-agent-acp\n```\n\n安装后会注册 `claude-agent-acp` 命令。\n\n#### 2. 设置环境变量\n\n```bash\nexport ACP_RCS_URL=http://rcs-host:3000\nexport ACP_RCS_TOKEN=sk-your-key\n```\n\n#### 3. 启动 acp-link 桥接\n\n```bash\nacp-link claude-agent-acp\n```\n\n`acp-link` 的第一个参数是 agent 的可执行命令名(这里是 `claude-agent-acp`)。`claude-agent-acp` 本身不需要额外参数,因此不需要 `--`。\n\n连接成功后,Claude Code 会作为 ACP agent 出现在 RCS Web UI 中,与 slz agent 并列,团队成员可在 Web UI 中选择它创建会话。\n\n其他 ACP 兼容 agent 的接入方式类似:安装对应的 ACP 适配包,然后用 `acp-link <命令名>` 启动。可在 npm 官网搜索 `@agentclientprotocol/*` 查找已适配的 agent。\n\n## 团队协作场景\n\n### 共享会话\n\n在 RCS Web UI 中创建会话,分享链接给队友(需登录才能查看),他们可查看或加入对话。也可通过 `session_shares` 显式授予指定用户或团队「只读」/「读写」权限,并设置过期时间。\n\n### 多 Worker 协作\n\n团队多个成员各自启动 worker,连接到同一 RCS:\n\n```bash\n# 成员 A:默认配置\nslz rc\n\n# 成员 B:worktree 隔离,5 并发\nslz rc --spawn=worktree --capacity=5\n```\n\nWeb UI 显示所有 worker 状态,会话与权限集中管理。\n\n### 外部 Agent 接入\n\n用 ACP 让非 slz 的 agent 接入 RCS。Claude Code 通过 `claude-agent-acp` 适配包接入:\n\n```bash\n# 先装适配包(仅一次)\nnpm install -g @agentclientprotocol/claude-agent-acp\n\n# 设置 RCS 连接(RCS 在本机时可跳过 —— 默认 http://localhost:3000 + sk-slz)\nexport ACP_RCS_URL=http://rcs-host:3000\nexport ACP_RCS_TOKEN=sk-your-key\n\n# 启动桥接\nacp-link claude-agent-acp\n```\n\n接入后所有 agent 在 Web UI 中统一管理,团队成员可选择任意 agent 创建会话。\n\n## 安全建议\n\n- RCS 默认监听 0.0.0.0,生产环境建议用反代 + HTTPS\n- 用强 API Key,定期轮换\n- 生产环境关闭 `RCS_ALLOW_REGISTRATION` 改为邀请制\n- 使用 `RCS_WEB_CORS_ORIGINS` 限制 Web UI 访问来源\n- 设置 `RCS_DB_PATH` 持久化 SQLite 数据库\n- 限制 worker 的权限(`/permissions` 配置)\n- `bypassPermissions` 模式仅在 sandbox 环境中启用,避免在主机直接放行所有工具调用\n\n## 故障排查\n\n| 问题 | 排查 |\n|------|------|\n| Worker 无法连接 | 同机部署默认零配置(`http://localhost:3000` + `sk-slz`);跨机器时检查 `SALUZI_BRIDGE_BASE_URL` 和 `SALUZI_BRIDGE_OAUTH_TOKEN`,确认 token 与 RCS 的 `RCS_API_KEYS` 匹配 |\n| `Only HTTPS or localhost HTTP is allowed` | 远程 RCS 用 HTTP 被拒。优先用 HTTPS;或 SSH 隧道转发到 localhost;可信内网可设 `SALUZI_BRIDGE_ALLOW_INSECURE_HTTP=1` |\n| Web UI 登录失败 | 检查用户名密码;5 次失败后锁定 5 分钟 |\n| Web UI 401 | 确认使用 `RCS_API_KEYS` 中的 key 或有效的 session token |\n| 看不到某个会话 | 检查会话 visibility(private/team/public);确认是否在所属团队的成员列表里;admin 可看所有 |\n| `/rc --attach` 列表为空 | 只列出你有权限管理、且未结束/未被占用的会话;确认目标会话的可见域与你的归属,或让会话 owner 共享 |\n| 接入报「环境无主」 | 该环境还没被认领,先在终端提示的 `/code/claim/clm_xxx` URL 完成认领,再重新接入 |\n| 等待接入一直没有会话 | 在 Web UI 把会话绑定到该 worker;超过超时(默认 24 小时)会放弃,可用 `SALUZI_BRIDGE_ATTACH_TIMEOUT_MS` 调整 |\n| 接入后历史没出现 | 接入会拉取会话历史,失败即中止;确认网络可达 RCS 后重试 `/rc --attach` |\n| 环境显示「待认领」 | worker 没指定 `--user-id`/`--team-id`,找到终端里的 `/code/claim/clm_xxx` URL,已登录用户打开即可认领 |\n| acp-link 无法连接 RCS | 同机部署默认零配置(`http://localhost:3000` + `sk-slz`);跨机器时检查 `ACP_RCS_URL` 和 `ACP_RCS_TOKEN` |\n| Agent 不出现在 Web UI | 确认 acp-link 已启动且 `ACP_RCS_TOKEN` 与 `RCS_API_KEYS` 匹配 |\n| 邀请链接失效 | 邀请 token 可能过期或达到 max_uses 上限;让团队 owner/admin 重新创建 |\n| 会话连接意外断开 | 调整 `RCS_DISCONNECT_TIMEOUT` 和 `RCS_WS_CLIENT_INACTIVITY_TIMEOUT`;若是设置了会话时长上限,检查 `SALUZI_BRIDGE_SESSION_TIMEOUT` |\n"
7416
7428
  },
7417
7429
  "docs/guide/conversation-basics": {
7418
7430
  "frontmatter": {
@@ -1 +1 @@
1
- import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{at as c,au as o,Q as m,ao as s,ag as l,x as u}from"./main-bilGpQlS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function j(){c();const[a,i]=d.useState([]),{myTeams:r,isLoading:x}=o(),n=d.useCallback(async()=>{try{const t=await m();i(t||[])}catch(t){console.error("Admin: failed to load sessions",t)}},[]);return d.useEffect(()=>{n()},[n]),e.jsx("div",{className:"flex-1 overflow-y-auto",children:e.jsxs("div",{className:"mx-auto max-w-5xl px-4 py-8",children:[e.jsx("h1",{className:"mb-6 font-display text-2xl font-semibold text-text-primary",children:s("admin.title")}),e.jsxs("section",{className:"mb-10",children:[e.jsxs("h2",{className:"mb-4 font-display text-lg font-semibold text-text-primary",children:[s("admin.teams")," (",r.length,")"]}),x?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("common.loading")}):r.length===0?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("admin.noTeams")}):e.jsx("div",{className:"space-y-2",children:r.map(t=>e.jsxs("a",{href:`/teams/${t.slug}`,className:"flex items-center justify-between rounded-xl border border-border bg-surface-1 px-4 py-3 no-underline transition-colors hover:border-border-light hover:bg-surface-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"font-medium text-text-primary",children:t.name}),e.jsx("span",{className:"ml-2 text-xs text-text-muted",children:t.slug})]}),e.jsx("span",{className:"text-xs text-text-muted",children:l(new Date(t.created_at).getTime()/1e3)})]},t.id))})]}),e.jsxs("section",{children:[e.jsxs("h2",{className:"mb-4 font-display text-lg font-semibold text-text-primary",children:[s("admin.sessions")," (",a.length,")"]}),a.length===0?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("admin.noSessions")}):e.jsx("div",{className:"space-y-2",children:a.map(t=>e.jsxs("a",{href:`/code/${t.id}`,className:"flex items-center justify-between rounded-xl border border-border bg-surface-1 px-4 py-3 no-underline transition-colors hover:border-border-light hover:bg-surface-2",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"truncate font-medium text-text-primary",children:t.title||t.id}),e.jsx("span",{className:"rounded-full bg-surface-2 px-2 py-0.5 text-xs text-text-muted",children:t.source||"unknown"})]}),e.jsx("div",{className:"truncate text-xs text-text-muted",children:t.id})]}),e.jsxs("div",{className:"ml-4 flex items-center gap-3",children:[e.jsx(u,{status:t.status}),e.jsx("span",{className:"text-xs text-text-muted",children:l(t.updated_at||t.created_at)})]})]},t.id))})]})]})})}export{j as AdminPanel};
1
+ import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{at as c,au as o,Q as m,ao as s,ag as l,x as u}from"./main-5C_gChTh.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function j(){c();const[a,i]=d.useState([]),{myTeams:r,isLoading:x}=o(),n=d.useCallback(async()=>{try{const t=await m();i(t||[])}catch(t){console.error("Admin: failed to load sessions",t)}},[]);return d.useEffect(()=>{n()},[n]),e.jsx("div",{className:"flex-1 overflow-y-auto",children:e.jsxs("div",{className:"mx-auto max-w-5xl px-4 py-8",children:[e.jsx("h1",{className:"mb-6 font-display text-2xl font-semibold text-text-primary",children:s("admin.title")}),e.jsxs("section",{className:"mb-10",children:[e.jsxs("h2",{className:"mb-4 font-display text-lg font-semibold text-text-primary",children:[s("admin.teams")," (",r.length,")"]}),x?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("common.loading")}):r.length===0?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("admin.noTeams")}):e.jsx("div",{className:"space-y-2",children:r.map(t=>e.jsxs("a",{href:`/teams/${t.slug}`,className:"flex items-center justify-between rounded-xl border border-border bg-surface-1 px-4 py-3 no-underline transition-colors hover:border-border-light hover:bg-surface-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"font-medium text-text-primary",children:t.name}),e.jsx("span",{className:"ml-2 text-xs text-text-muted",children:t.slug})]}),e.jsx("span",{className:"text-xs text-text-muted",children:l(new Date(t.created_at).getTime()/1e3)})]},t.id))})]}),e.jsxs("section",{children:[e.jsxs("h2",{className:"mb-4 font-display text-lg font-semibold text-text-primary",children:[s("admin.sessions")," (",a.length,")"]}),a.length===0?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("admin.noSessions")}):e.jsx("div",{className:"space-y-2",children:a.map(t=>e.jsxs("a",{href:`/code/${t.id}`,className:"flex items-center justify-between rounded-xl border border-border bg-surface-1 px-4 py-3 no-underline transition-colors hover:border-border-light hover:bg-surface-2",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"truncate font-medium text-text-primary",children:t.title||t.id}),e.jsx("span",{className:"rounded-full bg-surface-2 px-2 py-0.5 text-xs text-text-muted",children:t.source||"unknown"})]}),e.jsx("div",{className:"truncate text-xs text-text-muted",children:t.id})]}),e.jsxs("div",{className:"ml-4 flex items-center gap-3",children:[e.jsx(u,{status:t.status}),e.jsx("span",{className:"text-xs text-text-muted",children:l(t.updated_at||t.created_at)})]})]},t.id))})]})]})})}export{j as AdminPanel};
@@ -1,4 +1,4 @@
1
- import{e as a,j as t}from"./vendor-DE_-CLIE.js";import{ad as q,at as A,V as j,ao as r,K as M,ac as U,P as F,z as O}from"./main-bilGpQlS.js";import{S as R,E as K,C as G}from"./ArtifactsGallery-CjZFQhYm.js";import{C as P}from"./copy-BId_ACIH.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";import"./dialog-DfUuWIZS.js";/**
1
+ import{e as a,j as t}from"./vendor-DE_-CLIE.js";import{ad as q,at as A,V as j,ao as r,K as M,ac as U,P as F,z as O}from"./main-5C_gChTh.js";import{S as R,E as K,C as G}from"./ArtifactsGallery-BaqQmrpp.js";import{C as P}from"./copy-CIv8ifYN.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";import"./dialog-D__YHb1u.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- var ht=Object.defineProperty;var ut=(t,e,r)=>e in t?ht(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var S=(t,e,r)=>ut(t,typeof e!="symbol"?e+"":e,r);import{e as k,j as o}from"./vendor-DE_-CLIE.js";import{ad as Re,ah as ft,at as Ve,au as mt,W as xt,ao as f,K as gt,ac as bt,F as kt,g as yt,P as wt,z as vt,p as He,V as St,a0 as Rt,al as Tt,$ as $t,a6 as jt,a7 as Et,H as Nt,b as Ct}from"./main-bilGpQlS.js";import{D as It,a as At,c as Lt,d as zt,b as _t}from"./dialog-DfUuWIZS.js";import{C as Dt}from"./copy-BId_ACIH.js";/**
1
+ var ht=Object.defineProperty;var ut=(t,e,r)=>e in t?ht(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var S=(t,e,r)=>ut(t,typeof e!="symbol"?e+"":e,r);import{e as k,j as o}from"./vendor-DE_-CLIE.js";import{ad as Re,ah as ft,at as Ve,au as mt,W as xt,ao as f,K as gt,ac as bt,F as kt,g as yt,P as wt,z as vt,p as He,V as St,a0 as Rt,al as Tt,$ as $t,a6 as jt,a7 as Et,H as Nt,b as Ct}from"./main-5C_gChTh.js";import{D as It,a as At,c as Lt,d as zt,b as _t}from"./dialog-D__YHb1u.js";import{C as Dt}from"./copy-CIv8ifYN.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{E as u,Q as f}from"./main-bilGpQlS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";const v=2e3,N=3e4;function E(){const c=window.location.pathname.split("/"),i=c[c.length-1]||"",[s,n]=r.useState("idle"),[m,l]=r.useState(null),[a,d]=r.useState(null);return r.useEffect(()=>{if(!i||!i.startsWith("clm_")){l("Invalid claim token"),n("error");return}n("claiming"),u(i).then(t=>{d(t.environment_id),n("waiting")}).catch(t=>{l(t instanceof Error?t.message:"Claim failed"),n("error")})},[i]),r.useEffect(()=>{if(s!=="waiting"||!a)return;let t=!1;const x=Date.now(),o=setInterval(()=>{if(Date.now()-x>N){clearInterval(o),t||n("timeout");return}f().then(h=>{t||(h||[]).some(p=>p.environment_id===a)&&(clearInterval(o),window.location.href="/code/")}).catch(()=>{})},v);return()=>{t=!0,clearInterval(o)}},[s,a]),s==="claiming"?e.jsx("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:e.jsx("p",{className:"text-sm text-text-muted",children:"Claiming environment..."})}):s==="error"?e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsx("p",{className:"text-sm text-destructive",children:m}),e.jsx("a",{href:"/code",className:"mt-4 inline-block text-accent hover:underline",children:"Back to dashboard"})]}):s==="waiting"||s==="timeout"?e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsxs("header",{className:"mb-10",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold tracking-tight text-text-primary",children:"Environment claimed"}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:"You are now the owner of this environment."})]}),e.jsxs("div",{className:"space-y-4",children:[a&&e.jsx("p",{className:"font-mono text-xs text-text-muted",children:a}),s==="waiting"?e.jsxs("p",{className:"text-sm text-text-muted",children:["Waiting for the worker to create a session",e.jsx("span",{className:"animate-pulse",children:"…"})]}):e.jsx("p",{className:"text-sm text-text-muted",children:"The worker has not created a session yet — it may be offline or stopped. The session will appear on the dashboard once the worker connects."}),e.jsx("a",{href:"/code",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90 transition-colors",children:"Go to dashboard"})]})]}):e.jsx("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:e.jsx("p",{className:"text-sm text-text-muted",children:"Claiming environment..."})})}export{E as Claim};
1
+ import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{E as u,Q as f}from"./main-5C_gChTh.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";const v=2e3,N=3e4;function E(){const c=window.location.pathname.split("/"),i=c[c.length-1]||"",[s,n]=r.useState("idle"),[m,l]=r.useState(null),[a,d]=r.useState(null);return r.useEffect(()=>{if(!i||!i.startsWith("clm_")){l("Invalid claim token"),n("error");return}n("claiming"),u(i).then(t=>{d(t.environment_id),n("waiting")}).catch(t=>{l(t instanceof Error?t.message:"Claim failed"),n("error")})},[i]),r.useEffect(()=>{if(s!=="waiting"||!a)return;let t=!1;const x=Date.now(),o=setInterval(()=>{if(Date.now()-x>N){clearInterval(o),t||n("timeout");return}f().then(h=>{t||(h||[]).some(p=>p.environment_id===a)&&(clearInterval(o),window.location.href="/code/")}).catch(()=>{})},v);return()=>{t=!0,clearInterval(o)}},[s,a]),s==="claiming"?e.jsx("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:e.jsx("p",{className:"text-sm text-text-muted",children:"Claiming environment..."})}):s==="error"?e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsx("p",{className:"text-sm text-destructive",children:m}),e.jsx("a",{href:"/code",className:"mt-4 inline-block text-accent hover:underline",children:"Back to dashboard"})]}):s==="waiting"||s==="timeout"?e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsxs("header",{className:"mb-10",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold tracking-tight text-text-primary",children:"Environment claimed"}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:"You are now the owner of this environment."})]}),e.jsxs("div",{className:"space-y-4",children:[a&&e.jsx("p",{className:"font-mono text-xs text-text-muted",children:a}),s==="waiting"?e.jsxs("p",{className:"text-sm text-text-muted",children:["Waiting for the worker to create a session",e.jsx("span",{className:"animate-pulse",children:"…"})]}):e.jsx("p",{className:"text-sm text-text-muted",children:"The worker has not created a session yet — it may be offline or stopped. The session will appear on the dashboard once the worker connects."}),e.jsx("a",{href:"/code",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90 transition-colors",children:"Go to dashboard"})]})]}):e.jsx("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:e.jsx("p",{className:"text-sm text-text-muted",children:"Claiming environment..."})})}export{E as Claim};
@@ -1,4 +1,4 @@
1
- import{j as e,e as l}from"./vendor-DE_-CLIE.js";import{ad as O,ab as _,au as E,as as T,x as F,at as L,ao as a,ag as A,q as $,s as W,e as H,r as V,d as P,aj as q,I as Q,Q as R,Y as U,N as Y}from"./main-bilGpQlS.js";import{g as D}from"./workerType-Bd-zteMi.js";import{S as Z}from"./SessionVisibilityBadge-DJB8gn6j.js";import{D as z,a as G,c as J,d as K,b as X}from"./dialog-DfUuWIZS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";/**
1
+ import{j as e,e as l}from"./vendor-DE_-CLIE.js";import{ad as O,ab as _,au as E,as as T,x as F,at as L,ao as a,ag as A,q as $,s as W,e as H,r as V,d as P,aj as q,I as Q,Q as R,Y as U,N as Y}from"./main-5C_gChTh.js";import{g as D}from"./workerType-Bd-zteMi.js";import{S as Z}from"./SessionVisibilityBadge-BKEoqr7V.js";import{D as z,a as G,c as J,d as K,b as X}from"./dialog-D__YHb1u.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{as as v,ao as t}from"./main-bilGpQlS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function E({onSuccess:b,onInvalidInvite:l}){const{join:h}=v(),[u,f]=r.useState(""),[d,j]=r.useState(""),[o,w]=r.useState(""),[c,g]=r.useState(""),[m,n]=r.useState(""),[x,p]=r.useState(!1);r.useEffect(()=>{const a=new URLSearchParams(window.location.search).get("invite");a?f(a):l()},[l]);const y=async s=>{if(s.preventDefault(),n(""),o.length<8){n(t("auth.setup.passwordTooShort"));return}if(o!==c){n(t("auth.setup.passwordMismatch"));return}p(!0);try{await h(u,d,o),b()}catch(a){const i=a instanceof Error?a.message:"Join failed";if(i.includes("Invalid invitation")||i.includes("expired")||i.includes("already used")){l();return}n(i)}finally{p(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.join.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.join.welcome")}),e.jsx("p",{className:"mt-1 text-sm text-text-muted",children:t("auth.join.description")})]}),e.jsxs("form",{onSubmit:y,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.username")}),e.jsx("input",{type:"text",value:d,onChange:s=>j(s.target.value),required:!0,autoComplete:"username",autoFocus:!0,className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.password")}),e.jsx("input",{type:"password",value:o,onChange:s=>w(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.confirmPassword")}),e.jsx("input",{type:"password",value:c,onChange:s=>g(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),m&&e.jsx("p",{className:"text-sm text-status-error",children:m}),e.jsx("button",{type:"submit",disabled:x||!u,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:x?t("common.loading"):t("auth.join.submit")})]})]})})}export{E as Join};
1
+ import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{as as v,ao as t}from"./main-5C_gChTh.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function E({onSuccess:b,onInvalidInvite:l}){const{join:h}=v(),[u,f]=r.useState(""),[d,j]=r.useState(""),[o,w]=r.useState(""),[c,g]=r.useState(""),[m,n]=r.useState(""),[x,p]=r.useState(!1);r.useEffect(()=>{const a=new URLSearchParams(window.location.search).get("invite");a?f(a):l()},[l]);const y=async s=>{if(s.preventDefault(),n(""),o.length<8){n(t("auth.setup.passwordTooShort"));return}if(o!==c){n(t("auth.setup.passwordMismatch"));return}p(!0);try{await h(u,d,o),b()}catch(a){const i=a instanceof Error?a.message:"Join failed";if(i.includes("Invalid invitation")||i.includes("expired")||i.includes("already used")){l();return}n(i)}finally{p(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.join.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.join.welcome")}),e.jsx("p",{className:"mt-1 text-sm text-text-muted",children:t("auth.join.description")})]}),e.jsxs("form",{onSubmit:y,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.username")}),e.jsx("input",{type:"text",value:d,onChange:s=>j(s.target.value),required:!0,autoComplete:"username",autoFocus:!0,className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.password")}),e.jsx("input",{type:"password",value:o,onChange:s=>w(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.confirmPassword")}),e.jsx("input",{type:"password",value:c,onChange:s=>g(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),m&&e.jsx("p",{className:"text-sm text-status-error",children:m}),e.jsx("button",{type:"submit",disabled:x||!u,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:x?t("common.loading"):t("auth.join.submit")})]})]})})}export{E as Join};
@@ -0,0 +1 @@
1
+ import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{as as f,ao as t}from"./main-5C_gChTh.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function v({onSuccess:u,onNavigateRegister:c}){const{login:m,registrationAllowed:x,singleUserMode:p}=f(),[a,b]=r.useState(""),[o,h]=r.useState(""),[n,l]=r.useState(""),[i,d]=r.useState(!1),g=async s=>{s.preventDefault(),l(""),d(!0);try{await m(a,o),u()}catch{l(t("auth.login.failed"))}finally{d(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.login.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.login.description")})]}),e.jsxs("form",{onSubmit:g,className:"space-y-4",children:[p&&e.jsxs("div",{className:"rounded-lg border border-border bg-surface-2 px-3 py-2 text-xs text-text-secondary",children:[e.jsx("p",{children:t("auth.login.singleUserHint")}),e.jsx("p",{className:"mt-1 font-mono text-text-primary",children:"admin / admin123"}),e.jsx("p",{className:"mt-1 text-text-muted",children:t("auth.login.singleUserHintFooter")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.login.username")}),e.jsx("input",{type:"text",value:a,onChange:s=>b(s.target.value),required:!0,autoComplete:"username",autoFocus:!0,className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.login.password")}),e.jsx("input",{type:"password",value:o,onChange:s=>h(s.target.value),required:!0,autoComplete:"current-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),n&&e.jsx("p",{className:"text-sm text-status-error",children:n}),e.jsx("button",{type:"submit",disabled:i,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:i?t("common.loading"):t("auth.login.submit")})]}),x&&e.jsx("button",{type:"button",onClick:c,className:"w-full text-center text-sm text-text-muted hover:text-text-primary transition-colors",children:t("auth.login.register")})]})})}export{v as Login};
@@ -1 +1 @@
1
- import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{as as y,ao as t}from"./main-bilGpQlS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function S({onSuccess:m,onBack:x}){const{register:p}=y(),[n,b]=r.useState(""),[a,h]=r.useState(""),[l,f]=r.useState(""),[i,o]=r.useState(""),[u,d]=r.useState(!1),g=async s=>{if(s.preventDefault(),o(""),a.length<8){o(t("auth.setup.passwordTooShort"));return}if(a!==l){o(t("auth.setup.passwordMismatch"));return}d(!0);try{await p(n,a),m()}catch(c){o(c instanceof Error?c.message:t("auth.register.failed"))}finally{d(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.register.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.register.description")})]}),e.jsxs("form",{onSubmit:g,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.login.username")}),e.jsx("input",{type:"text",value:n,onChange:s=>b(s.target.value),required:!0,autoComplete:"username",autoFocus:!0,className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.login.password")}),e.jsx("input",{type:"password",value:a,onChange:s=>h(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.confirmPassword")}),e.jsx("input",{type:"password",value:l,onChange:s=>f(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),i&&e.jsx("p",{className:"text-sm text-status-error",children:i}),e.jsx("button",{type:"submit",disabled:u,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:u?t("common.loading"):t("auth.register.submit")})]}),e.jsx("button",{type:"button",onClick:x,className:"w-full text-center text-sm text-text-muted hover:text-text-primary transition-colors",children:t("auth.register.backToLogin")})]})})}export{S as Register};
1
+ import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{as as y,ao as t}from"./main-5C_gChTh.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function S({onSuccess:m,onBack:x}){const{register:p}=y(),[n,b]=r.useState(""),[a,h]=r.useState(""),[l,f]=r.useState(""),[i,o]=r.useState(""),[u,d]=r.useState(!1),g=async s=>{if(s.preventDefault(),o(""),a.length<8){o(t("auth.setup.passwordTooShort"));return}if(a!==l){o(t("auth.setup.passwordMismatch"));return}d(!0);try{await p(n,a),m()}catch(c){o(c instanceof Error?c.message:t("auth.register.failed"))}finally{d(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.register.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.register.description")})]}),e.jsxs("form",{onSubmit:g,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.login.username")}),e.jsx("input",{type:"text",value:n,onChange:s=>b(s.target.value),required:!0,autoComplete:"username",autoFocus:!0,className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.login.password")}),e.jsx("input",{type:"password",value:a,onChange:s=>h(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.confirmPassword")}),e.jsx("input",{type:"password",value:l,onChange:s=>f(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),i&&e.jsx("p",{className:"text-sm text-status-error",children:i}),e.jsx("button",{type:"submit",disabled:u,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:u?t("common.loading"):t("auth.register.submit")})]}),e.jsx("button",{type:"button",onClick:x,className:"w-full text-center text-sm text-text-muted hover:text-text-primary transition-colors",children:t("auth.register.backToLogin")})]})})}export{S as Register};
@@ -1,4 +1,4 @@
1
- var bt=Object.defineProperty;var jt=(s,t,r)=>t in s?bt(s,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):s[t]=r;var E=(s,t,r)=>jt(s,typeof t!="symbol"?t+"":t,r);import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{ad as D,_ as kt,ak as Ie,am as wt,al as we,a7 as Nt,ah as je,a6 as L,a1 as vt,x as We,g as Pe,ag as Qe,L as Ge,z as _t,w as St,af as P,ab as J,d as Ke,ap as qe,a2 as Ct,J as Et,a5 as Mt,at as Ye,ao as w,A as Tt,ai as Rt,G as At,aq as $t,ae as It,b as Pt,N as qt,a3 as Dt,y as Je,P as Ut,F as Ft,c as Ot,C as Lt,R as De,Z as Bt,D as Ht,a as zt,q as Xe,s as Ze,v as Vt,f as et,e as tt,r as st,M as Wt}from"./main-bilGpQlS.js";import{g as Qt}from"./workerType-Bd-zteMi.js";import{D as nt,a as rt,c as at,d as ot,b as Gt}from"./dialog-DfUuWIZS.js";import{E as Kt,A as Yt}from"./ArtifactsGallery-CjZFQhYm.js";import{S as Jt}from"./SessionVisibilityBadge-DJB8gn6j.js";import{U as Xt}from"./UserSearchInput-HY3vDxN9.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";import"./copy-BId_ACIH.js";/**
1
+ var bt=Object.defineProperty;var jt=(s,t,r)=>t in s?bt(s,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):s[t]=r;var E=(s,t,r)=>jt(s,typeof t!="symbol"?t+"":t,r);import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{ad as D,_ as kt,ak as Ie,am as wt,al as we,a7 as Nt,ah as je,a6 as L,a1 as vt,x as We,g as Pe,ag as Qe,L as Ge,z as _t,w as St,af as P,ab as J,d as Ke,ap as qe,a2 as Ct,J as Et,a5 as Mt,at as Ye,ao as w,A as Tt,ai as Rt,G as At,aq as $t,ae as It,b as Pt,N as qt,a3 as Dt,y as Je,P as Ut,F as Ft,c as Ot,C as Lt,R as De,Z as Bt,D as Ht,a as zt,q as Xe,s as Ze,v as Vt,f as et,e as tt,r as st,M as Wt}from"./main-5C_gChTh.js";import{g as Qt}from"./workerType-Bd-zteMi.js";import{D as nt,a as rt,c as at,d as ot,b as Gt}from"./dialog-D__YHb1u.js";import{E as Kt,A as Yt}from"./ArtifactsGallery-BaqQmrpp.js";import{S as Jt}from"./SessionVisibilityBadge-BKEoqr7V.js";import{U as Xt}from"./UserSearchInput-CXTnk0hA.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";import"./copy-CIv8ifYN.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{j as e}from"./vendor-DE_-CLIE.js";import{ad as c,U as n,ab as i}from"./main-bilGpQlS.js";/**
1
+ import{j as e}from"./vendor-DE_-CLIE.js";import{ad as c,U as n,ab as i}from"./main-5C_gChTh.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{as as v,ao as t}from"./main-bilGpQlS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function q({onSuccess:p,onAlreadyDone:b}){const{setup:f}=v(),[n,h]=r.useState(""),[l,y]=r.useState(""),[a,g]=r.useState(""),[d,w]=r.useState(""),[i,o]=r.useState(""),[c,m]=r.useState(!1),j=async s=>{if(s.preventDefault(),o(""),a.length<8){o(t("auth.setup.passwordTooShort"));return}if(a!==d){o(t("auth.setup.passwordMismatch"));return}m(!0);try{await f(n,l,a),p()}catch(x){const u=x instanceof Error?x.message:"Setup failed";if(u.includes("already")||u.includes("409")){b();return}o(u)}finally{m(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.setup.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.setup.description")})]}),e.jsxs("form",{onSubmit:j,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.apiKey")}),e.jsx("input",{type:"password",value:n,onChange:s=>h(s.target.value),required:!0,autoComplete:"off",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.username")}),e.jsx("input",{type:"text",value:l,onChange:s=>y(s.target.value),required:!0,autoComplete:"username",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.password")}),e.jsx("input",{type:"password",value:a,onChange:s=>g(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.confirmPassword")}),e.jsx("input",{type:"password",value:d,onChange:s=>w(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),i&&e.jsx("p",{className:"text-sm text-status-error",children:i}),e.jsx("button",{type:"submit",disabled:c,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:c?t("common.loading"):t("auth.setup.submit")})]})]})})}export{q as Setup};
1
+ import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{as as v,ao as t}from"./main-5C_gChTh.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function q({onSuccess:p,onAlreadyDone:b}){const{setup:f}=v(),[n,h]=r.useState(""),[l,y]=r.useState(""),[a,g]=r.useState(""),[d,w]=r.useState(""),[i,o]=r.useState(""),[c,m]=r.useState(!1),j=async s=>{if(s.preventDefault(),o(""),a.length<8){o(t("auth.setup.passwordTooShort"));return}if(a!==d){o(t("auth.setup.passwordMismatch"));return}m(!0);try{await f(n,l,a),p()}catch(x){const u=x instanceof Error?x.message:"Setup failed";if(u.includes("already")||u.includes("409")){b();return}o(u)}finally{m(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.setup.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.setup.description")})]}),e.jsxs("form",{onSubmit:j,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.apiKey")}),e.jsx("input",{type:"password",value:n,onChange:s=>h(s.target.value),required:!0,autoComplete:"off",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.username")}),e.jsx("input",{type:"text",value:l,onChange:s=>y(s.target.value),required:!0,autoComplete:"username",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.password")}),e.jsx("input",{type:"password",value:a,onChange:s=>g(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.confirmPassword")}),e.jsx("input",{type:"password",value:d,onChange:s=>w(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),i&&e.jsx("p",{className:"text-sm text-status-error",children:i}),e.jsx("button",{type:"submit",disabled:c,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:c?t("common.loading"):t("auth.setup.submit")})]})]})})}export{q as Setup};
@@ -1 +1 @@
1
- import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{a4 as m,b as h}from"./main-bilGpQlS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function j(){const[t,r]=d.useState("loading"),[i,a]=d.useState(""),l=(typeof window<"u"?window.location.pathname:"").match(/\/code\/s\/([^/?]+)/),o=l?l[1]:null;return d.useEffect(()=>{if(!o){r("invalid"),a("Share link is invalid — no token found.");return}if(!o.startsWith("shr_")){r("invalid"),a("Invalid share token format.");return}let n=!1;async function c(){try{const s=await m(o);if(n)return;window.location.href=`/code/${s.id}`}catch(s){if(n)return;s instanceof h?s.status===401&&s.message.toLowerCase().includes("expired")?(r("expired"),a("This share has expired.")):s.status===404?s.message.toLowerCase().includes("session")?(r("not_found"),a("Session not found.")):(r("invalid"),a("Share not found or has been revoked.")):s.status===403?(r("invalid"),a("You do not have permission to access this share.")):(r("error"),a(s.message||"Failed to resolve share.")):(r("error"),a(s instanceof Error?s.message:"Failed to resolve share."))}}return c(),()=>{n=!0}},[o]),d.useEffect(()=>{if(t!=="loading"&&t!=="error"){const n=setTimeout(()=>{window.location.href="/code"},3e3);return()=>clearTimeout(n)}},[t]),t==="loading"?e.jsx("div",{className:"flex h-screen items-center justify-center bg-surface-0 text-text-muted",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"animate-spin h-8 w-8 border-2 border-brand border-t-transparent rounded-full mx-auto mb-3"}),e.jsx("p",{children:"Resolving share link..."})]})}):e.jsx("div",{className:"flex h-screen items-center justify-center bg-surface-0 text-text-primary",children:e.jsxs("div",{className:"text-center max-w-md px-4",children:[t==="expired"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Share Expired"}),e.jsx("p",{className:"text-text-muted mb-4",children:i||"This share has expired."})]}),t==="invalid"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Invalid Share"}),e.jsx("p",{className:"text-text-muted mb-4",children:i||"This share link is invalid or has been revoked."})]}),t==="not_found"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Not Found"}),e.jsx("p",{className:"text-text-muted mb-4",children:i||"The session could not be found."})]}),t==="error"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Error"}),e.jsx("p",{className:"text-status-error mb-4",children:i})]}),e.jsx("a",{href:"/code",className:"text-brand hover:underline",children:"← Back to Dashboard"})]})})}export{j as ShareLanding};
1
+ import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{a4 as m,b as h}from"./main-5C_gChTh.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function j(){const[t,r]=d.useState("loading"),[i,a]=d.useState(""),l=(typeof window<"u"?window.location.pathname:"").match(/\/code\/s\/([^/?]+)/),o=l?l[1]:null;return d.useEffect(()=>{if(!o){r("invalid"),a("Share link is invalid — no token found.");return}if(!o.startsWith("shr_")){r("invalid"),a("Invalid share token format.");return}let n=!1;async function c(){try{const s=await m(o);if(n)return;window.location.href=`/code/${s.id}`}catch(s){if(n)return;s instanceof h?s.status===401&&s.message.toLowerCase().includes("expired")?(r("expired"),a("This share has expired.")):s.status===404?s.message.toLowerCase().includes("session")?(r("not_found"),a("Session not found.")):(r("invalid"),a("Share not found or has been revoked.")):s.status===403?(r("invalid"),a("You do not have permission to access this share.")):(r("error"),a(s.message||"Failed to resolve share.")):(r("error"),a(s instanceof Error?s.message:"Failed to resolve share."))}}return c(),()=>{n=!0}},[o]),d.useEffect(()=>{if(t!=="loading"&&t!=="error"){const n=setTimeout(()=>{window.location.href="/code"},3e3);return()=>clearTimeout(n)}},[t]),t==="loading"?e.jsx("div",{className:"flex h-screen items-center justify-center bg-surface-0 text-text-muted",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"animate-spin h-8 w-8 border-2 border-brand border-t-transparent rounded-full mx-auto mb-3"}),e.jsx("p",{children:"Resolving share link..."})]})}):e.jsx("div",{className:"flex h-screen items-center justify-center bg-surface-0 text-text-primary",children:e.jsxs("div",{className:"text-center max-w-md px-4",children:[t==="expired"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Share Expired"}),e.jsx("p",{className:"text-text-muted mb-4",children:i||"This share has expired."})]}),t==="invalid"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Invalid Share"}),e.jsx("p",{className:"text-text-muted mb-4",children:i||"This share link is invalid or has been revoked."})]}),t==="not_found"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Not Found"}),e.jsx("p",{className:"text-text-muted mb-4",children:i||"The session could not be found."})]}),t==="error"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Error"}),e.jsx("p",{className:"text-status-error mb-4",children:i})]}),e.jsx("a",{href:"/code",className:"text-brand hover:underline",children:"← Back to Dashboard"})]})})}export{j as ShareLanding};
@@ -1 +1 @@
1
- import{e as a,j as e}from"./vendor-DE_-CLIE.js";import{at as f,au as y,ao as r}from"./main-bilGpQlS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function S(){f();const{createTeam:u}=y(),[o,p]=a.useState(""),[s,c]=a.useState(""),[i,b]=a.useState(""),[m,l]=a.useState(null),[d,x]=a.useState(!1),h=t=>{p(t),s||c(t.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-"))},g=async t=>{t.preventDefault(),l(null),x(!0);try{const n=await u({name:o,slug:s,description:i||void 0});window.location.href=`/teams/${n.slug}`}catch(n){l(n instanceof Error?n.message:"Failed to create team")}finally{x(!1)}};return e.jsx("div",{className:"px-6 py-12 sm:px-10 sm:py-16",children:e.jsxs("div",{children:[e.jsx("h1",{className:"mb-10 font-display text-2xl font-semibold tracking-tight text-text-primary",children:r("team.create.title")}),e.jsxs("form",{onSubmit:g,className:"max-w-md space-y-8",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"name",className:"block text-sm font-medium text-text-primary mb-2",children:r("team.create.name")}),e.jsx("input",{id:"name",type:"text",required:!0,value:o,onChange:t=>h(t.target.value),className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",placeholder:"Engineering"}),e.jsx("p",{className:"mt-1.5 text-xs text-text-muted",children:r("team.create.nameHint")})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"slug",className:"block text-sm font-medium text-text-primary mb-2",children:r("team.create.slug")}),e.jsx("input",{id:"slug",type:"text",required:!0,value:s,onChange:t=>c(t.target.value),pattern:"^[a-z0-9-]{3,32}$",className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",placeholder:"engineering"}),e.jsx("p",{className:"mt-1.5 text-xs text-text-muted",children:r("team.create.slugHint")})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"description",className:"block text-sm font-medium text-text-primary mb-2",children:r("team.create.description")}),e.jsx("textarea",{id:"description",value:i,onChange:t=>b(t.target.value),className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",rows:3})]}),m&&e.jsx("p",{className:"text-sm text-destructive",children:m}),e.jsxs("div",{className:"flex gap-3 pt-2",children:[e.jsx("button",{type:"button",onClick:()=>window.history.back(),className:"rounded-md border border-border px-4 py-2 text-sm text-text-primary hover:bg-surface-2 transition-colors",children:r("common.cancel")}),e.jsx("button",{type:"submit",disabled:d||!o||!s,className:"rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90 disabled:opacity-50 transition-colors",children:d?r("common.creating"):r("team.create.submit")})]})]})]})})}export{S as TeamCreate};
1
+ import{e as a,j as e}from"./vendor-DE_-CLIE.js";import{at as f,au as y,ao as r}from"./main-5C_gChTh.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function S(){f();const{createTeam:u}=y(),[o,p]=a.useState(""),[s,c]=a.useState(""),[i,b]=a.useState(""),[m,l]=a.useState(null),[d,x]=a.useState(!1),h=t=>{p(t),s||c(t.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-"))},g=async t=>{t.preventDefault(),l(null),x(!0);try{const n=await u({name:o,slug:s,description:i||void 0});window.location.href=`/teams/${n.slug}`}catch(n){l(n instanceof Error?n.message:"Failed to create team")}finally{x(!1)}};return e.jsx("div",{className:"px-6 py-12 sm:px-10 sm:py-16",children:e.jsxs("div",{children:[e.jsx("h1",{className:"mb-10 font-display text-2xl font-semibold tracking-tight text-text-primary",children:r("team.create.title")}),e.jsxs("form",{onSubmit:g,className:"max-w-md space-y-8",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"name",className:"block text-sm font-medium text-text-primary mb-2",children:r("team.create.name")}),e.jsx("input",{id:"name",type:"text",required:!0,value:o,onChange:t=>h(t.target.value),className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",placeholder:"Engineering"}),e.jsx("p",{className:"mt-1.5 text-xs text-text-muted",children:r("team.create.nameHint")})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"slug",className:"block text-sm font-medium text-text-primary mb-2",children:r("team.create.slug")}),e.jsx("input",{id:"slug",type:"text",required:!0,value:s,onChange:t=>c(t.target.value),pattern:"^[a-z0-9-]{3,32}$",className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",placeholder:"engineering"}),e.jsx("p",{className:"mt-1.5 text-xs text-text-muted",children:r("team.create.slugHint")})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"description",className:"block text-sm font-medium text-text-primary mb-2",children:r("team.create.description")}),e.jsx("textarea",{id:"description",value:i,onChange:t=>b(t.target.value),className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",rows:3})]}),m&&e.jsx("p",{className:"text-sm text-destructive",children:m}),e.jsxs("div",{className:"flex gap-3 pt-2",children:[e.jsx("button",{type:"button",onClick:()=>window.history.back(),className:"rounded-md border border-border px-4 py-2 text-sm text-text-primary hover:bg-surface-2 transition-colors",children:r("common.cancel")}),e.jsx("button",{type:"submit",disabled:d||!o||!s,className:"rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90 disabled:opacity-50 transition-colors",children:d?r("common.creating"):r("team.create.submit")})]})]})]})})}export{S as TeamCreate};
@@ -1,4 +1,4 @@
1
- import{e as n,j as e}from"./vendor-DE_-CLIE.js";import{ad as H,B as T,at as P,ao as i,d as B,X as z,x as G,Y as I,a9 as W,a8 as Y,as as q,S as X,ab as J,j as K,o as Q,P as V,k as Z,m as ee,l as M,n as te,z as se}from"./main-bilGpQlS.js";import{U as ae}from"./UserSearchInput-HY3vDxN9.js";import{C as D}from"./copy-BId_ACIH.js";import{g as ne}from"./workerType-Bd-zteMi.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";/**
1
+ import{e as n,j as e}from"./vendor-DE_-CLIE.js";import{ad as H,B as T,at as P,ao as i,d as B,X as z,x as G,Y as I,a9 as W,a8 as Y,as as q,S as X,ab as J,j as K,o as Q,P as V,k as Z,m as ee,l as M,n as te,z as se}from"./main-5C_gChTh.js";import{U as ae}from"./UserSearchInput-CXTnk0hA.js";import{C as D}from"./copy-CIv8ifYN.js";import{g as ne}from"./workerType-Bd-zteMi.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{j as e}from"./vendor-DE_-CLIE.js";import{au as l,p as a}from"./main-bilGpQlS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function c(){const{myTeams:t,isLoading:i}=l();return i?e.jsx("div",{className:"px-6 py-20 sm:px-10",children:e.jsxs("div",{className:"max-w-4xl",children:[e.jsx("div",{className:"h-8 w-32 animate-pulse rounded bg-surface-2"}),e.jsx("div",{className:"mt-12 space-y-10",children:[0,1,2].map(s=>e.jsxs("div",{className:"space-y-3",children:[e.jsx("div",{className:"h-6 w-48 animate-pulse rounded bg-surface-2"}),e.jsx("div",{className:"h-4 w-32 animate-pulse rounded bg-surface-2"})]},s))})]})}):e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsxs("header",{className:"mb-16",children:[e.jsx("h1",{className:"font-display text-3xl font-semibold tracking-tight text-text-primary sm:text-4xl",children:"Teams"}),e.jsx("p",{className:"mt-3 text-sm text-text-muted",children:t.length===0?"Create your first team to start collaborating.":`${t.length} ${t.length===1?"team":"teams"}`})]}),t.length===0?e.jsx("div",{className:"py-8",children:e.jsxs("a",{href:"/teams/new",className:"inline-flex items-center gap-2 rounded-md bg-accent px-5 py-2.5 text-sm font-medium text-white transition-all hover:bg-accent/90 active:translate-y-px",children:[e.jsx(a,{className:"h-4 w-4"}),"Create team"]})}):e.jsx("ul",{className:"space-y-10",children:t.map(s=>e.jsx("li",{children:e.jsxs("a",{href:`/teams/${s.slug}`,className:"group block",children:[e.jsxs("div",{className:"flex items-baseline gap-4",children:[e.jsx("h2",{className:"font-display text-xl font-medium tracking-tight text-text-primary transition-colors group-hover:text-accent",children:s.name}),e.jsxs("span",{className:"font-mono text-xs text-text-muted",children:["/",s.slug]})]}),s.description?e.jsx("p",{className:"mt-2 max-w-2xl text-sm leading-relaxed text-text-muted",children:s.description}):e.jsx("p",{className:"mt-2 text-sm italic text-text-muted/60",children:"No description"})]})},s.id))}),t.length>0&&e.jsx("div",{className:"mt-16",children:e.jsxs("a",{href:"/teams/new",className:"inline-flex items-center gap-2 rounded-md border border-border px-4 py-2 text-sm font-medium text-text-primary transition-all hover:bg-surface-2 active:translate-y-px",children:[e.jsx(a,{className:"h-4 w-4"}),"New team"]})})]})}export{c as TeamList};
1
+ import{j as e}from"./vendor-DE_-CLIE.js";import{au as l,p as a}from"./main-5C_gChTh.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function c(){const{myTeams:t,isLoading:i}=l();return i?e.jsx("div",{className:"px-6 py-20 sm:px-10",children:e.jsxs("div",{className:"max-w-4xl",children:[e.jsx("div",{className:"h-8 w-32 animate-pulse rounded bg-surface-2"}),e.jsx("div",{className:"mt-12 space-y-10",children:[0,1,2].map(s=>e.jsxs("div",{className:"space-y-3",children:[e.jsx("div",{className:"h-6 w-48 animate-pulse rounded bg-surface-2"}),e.jsx("div",{className:"h-4 w-32 animate-pulse rounded bg-surface-2"})]},s))})]})}):e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsxs("header",{className:"mb-16",children:[e.jsx("h1",{className:"font-display text-3xl font-semibold tracking-tight text-text-primary sm:text-4xl",children:"Teams"}),e.jsx("p",{className:"mt-3 text-sm text-text-muted",children:t.length===0?"Create your first team to start collaborating.":`${t.length} ${t.length===1?"team":"teams"}`})]}),t.length===0?e.jsx("div",{className:"py-8",children:e.jsxs("a",{href:"/teams/new",className:"inline-flex items-center gap-2 rounded-md bg-accent px-5 py-2.5 text-sm font-medium text-white transition-all hover:bg-accent/90 active:translate-y-px",children:[e.jsx(a,{className:"h-4 w-4"}),"Create team"]})}):e.jsx("ul",{className:"space-y-10",children:t.map(s=>e.jsx("li",{children:e.jsxs("a",{href:`/teams/${s.slug}`,className:"group block",children:[e.jsxs("div",{className:"flex items-baseline gap-4",children:[e.jsx("h2",{className:"font-display text-xl font-medium tracking-tight text-text-primary transition-colors group-hover:text-accent",children:s.name}),e.jsxs("span",{className:"font-mono text-xs text-text-muted",children:["/",s.slug]})]}),s.description?e.jsx("p",{className:"mt-2 max-w-2xl text-sm leading-relaxed text-text-muted",children:s.description}):e.jsx("p",{className:"mt-2 text-sm italic text-text-muted/60",children:"No description"})]})},s.id))}),t.length>0&&e.jsx("div",{className:"mt-16",children:e.jsxs("a",{href:"/teams/new",className:"inline-flex items-center gap-2 rounded-md border border-border px-4 py-2 text-sm font-medium text-text-primary transition-all hover:bg-surface-2 active:translate-y-px",children:[e.jsx(a,{className:"h-4 w-4"}),"New team"]})})]})}export{c as TeamList};
@@ -1 +1 @@
1
- import{e as n,j as e}from"./vendor-DE_-CLIE.js";import{B as c}from"./main-bilGpQlS.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";async function j(s){try{const r=s.startsWith("team_")?`/web/teams/${s}`:`/web/teams/by-slug/${s}`;return await c("GET",r)}catch{return null}}async function w(s,r){await c("PATCH",`/web/teams/${s}`,r)}async function N(s){await c("DELETE",`/web/teams/${s}`)}function k(){const s=window.location.pathname.split("/"),r=s[s.length-2]||"",[a,h]=n.useState(null),[b,y]=n.useState(!0),[i,m]=n.useState(""),[l,d]=n.useState(""),[u,o]=n.useState(null),[x,p]=n.useState(!1);n.useEffect(()=>{r&&j(r).then(t=>{t&&(h(t),m(t.name),d(t.description||"")),y(!1)})},[r]);const g=async t=>{if(t.preventDefault(),!!a){o(null),p(!0);try{await w(a.id,{name:i,description:l}),window.location.href=`/teams/${a.slug}`}catch(f){o(f instanceof Error?f.message:"Failed to update")}finally{p(!1)}}},v=async()=>{if(a&&window.confirm("Delete this team? Environments must be transferred first."))try{await N(a.id),window.location.href="/teams"}catch(t){o(t instanceof Error?t.message:"Failed to delete")}};return b?e.jsx("div",{className:"flex items-center justify-center py-12 text-text-muted",children:"Loading..."}):a?e.jsx("div",{className:"px-6 py-12 sm:px-10 sm:py-16",children:e.jsxs("div",{children:[e.jsxs("header",{className:"mb-12",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold tracking-tight text-text-primary",children:a.name}),e.jsxs("p",{className:"mt-1 font-mono text-xs text-text-muted",children:["/",a.slug]})]}),e.jsxs("form",{onSubmit:g,className:"mb-16 max-w-md space-y-8",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"name",className:"block text-sm font-medium text-text-primary mb-2",children:"Team Name"}),e.jsx("input",{id:"name",type:"text",required:!0,value:i,onChange:t=>m(t.target.value),className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"description",className:"block text-sm font-medium text-text-primary mb-2",children:"Description"}),e.jsx("textarea",{id:"description",value:l,onChange:t=>d(t.target.value),className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",rows:3})]}),u&&e.jsx("p",{className:"text-sm text-destructive",children:u}),e.jsxs("div",{className:"flex gap-3 pt-2",children:[e.jsx("button",{type:"button",onClick:()=>window.history.back(),className:"rounded-md border border-border px-4 py-2 text-sm text-text-primary hover:bg-surface-2 transition-colors",children:"Cancel"}),e.jsx("button",{type:"submit",disabled:x||!i,className:"rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90 disabled:opacity-50 transition-colors",children:x?"Saving...":"Save Changes"})]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"mb-3 text-sm font-medium text-destructive",children:"Delete team"}),e.jsx("p",{className:"mb-4 text-sm text-text-muted",children:"Deleting a team requires all environments to be transferred first."}),e.jsx("button",{type:"button",onClick:v,className:"rounded-md border border-destructive/60 px-4 py-2 text-sm font-medium text-destructive hover:bg-destructive/10 transition-colors",children:"Delete Team"})]})]})}):e.jsxs("div",{className:"mx-auto max-w-lg px-4 py-8",children:[e.jsx("p",{className:"text-text-muted",children:"Team not found."}),e.jsx("a",{href:"/teams",className:"text-accent hover:underline",children:"Back to teams"})]})}export{k as TeamSettings};
1
+ import{e as n,j as e}from"./vendor-DE_-CLIE.js";import{B as c}from"./main-5C_gChTh.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";async function j(s){try{const r=s.startsWith("team_")?`/web/teams/${s}`:`/web/teams/by-slug/${s}`;return await c("GET",r)}catch{return null}}async function w(s,r){await c("PATCH",`/web/teams/${s}`,r)}async function N(s){await c("DELETE",`/web/teams/${s}`)}function k(){const s=window.location.pathname.split("/"),r=s[s.length-2]||"",[a,h]=n.useState(null),[b,y]=n.useState(!0),[i,m]=n.useState(""),[l,d]=n.useState(""),[u,o]=n.useState(null),[x,p]=n.useState(!1);n.useEffect(()=>{r&&j(r).then(t=>{t&&(h(t),m(t.name),d(t.description||"")),y(!1)})},[r]);const g=async t=>{if(t.preventDefault(),!!a){o(null),p(!0);try{await w(a.id,{name:i,description:l}),window.location.href=`/teams/${a.slug}`}catch(f){o(f instanceof Error?f.message:"Failed to update")}finally{p(!1)}}},v=async()=>{if(a&&window.confirm("Delete this team? Environments must be transferred first."))try{await N(a.id),window.location.href="/teams"}catch(t){o(t instanceof Error?t.message:"Failed to delete")}};return b?e.jsx("div",{className:"flex items-center justify-center py-12 text-text-muted",children:"Loading..."}):a?e.jsx("div",{className:"px-6 py-12 sm:px-10 sm:py-16",children:e.jsxs("div",{children:[e.jsxs("header",{className:"mb-12",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold tracking-tight text-text-primary",children:a.name}),e.jsxs("p",{className:"mt-1 font-mono text-xs text-text-muted",children:["/",a.slug]})]}),e.jsxs("form",{onSubmit:g,className:"mb-16 max-w-md space-y-8",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"name",className:"block text-sm font-medium text-text-primary mb-2",children:"Team Name"}),e.jsx("input",{id:"name",type:"text",required:!0,value:i,onChange:t=>m(t.target.value),className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"description",className:"block text-sm font-medium text-text-primary mb-2",children:"Description"}),e.jsx("textarea",{id:"description",value:l,onChange:t=>d(t.target.value),className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",rows:3})]}),u&&e.jsx("p",{className:"text-sm text-destructive",children:u}),e.jsxs("div",{className:"flex gap-3 pt-2",children:[e.jsx("button",{type:"button",onClick:()=>window.history.back(),className:"rounded-md border border-border px-4 py-2 text-sm text-text-primary hover:bg-surface-2 transition-colors",children:"Cancel"}),e.jsx("button",{type:"submit",disabled:x||!i,className:"rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90 disabled:opacity-50 transition-colors",children:x?"Saving...":"Save Changes"})]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"mb-3 text-sm font-medium text-destructive",children:"Delete team"}),e.jsx("p",{className:"mb-4 text-sm text-text-muted",children:"Deleting a team requires all environments to be transferred first."}),e.jsx("button",{type:"button",onClick:v,className:"rounded-md border border-destructive/60 px-4 py-2 text-sm font-medium text-destructive hover:bg-destructive/10 transition-colors",children:"Delete Team"})]})]})}):e.jsxs("div",{className:"mx-auto max-w-lg px-4 py-8",children:[e.jsx("p",{className:"text-text-muted",children:"Team not found."}),e.jsx("a",{href:"/teams",className:"text-accent hover:underline",children:"Back to teams"})]})}export{k as TeamSettings};
@@ -1 +1 @@
1
- import{e as a,j as t}from"./vendor-DE_-CLIE.js";import{at as v,ao as o,B as S}from"./main-bilGpQlS.js";function C({onSelect:l,excludeUserIds:x=[],placeholder:u,actionLabel:m,actionDisabled:h=!1,className:p}){v();const[n,c]=a.useState(""),[b,s]=a.useState([]),[i,d]=a.useState(!1),f=async e=>{if(c(e),e.trim().length<2){s([]);return}d(!0);try{const N=await S("GET",`/web/users/search?q=${encodeURIComponent(e.trim())}`);s(N)}catch{s([])}finally{d(!1)}},y=e=>{l(e),c(""),s([])},r=b.filter(e=>!x.includes(e.id)),g=m??o("invitation.add"),j=u??o("invitation.searchUser");return t.jsxs("div",{className:p,children:[t.jsx("input",{type:"text",value:n,onChange:e=>f(e.target.value),placeholder:j,className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"}),i&&t.jsx("p",{className:"mt-1 text-xs text-text-muted",children:"Searching..."}),r.length>0&&t.jsx("ul",{className:"mt-2 divide-y divide-border rounded border border-border bg-surface-1",children:r.map(e=>t.jsxs("li",{className:"flex items-center justify-between px-3 py-2 text-sm",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsx("div",{className:"text-text-primary",children:e.username}),t.jsx("div",{className:"truncate font-mono text-xs text-text-muted",children:e.id})]}),t.jsx("button",{type:"button",onClick:()=>y(e.id),disabled:h,className:"rounded bg-accent px-2 py-1 text-xs text-white hover:bg-accent/90 disabled:opacity-50",children:g})]},e.id))}),n.trim().length>=2&&r.length===0&&!i&&t.jsx("p",{className:"mt-1 text-xs text-text-muted",children:"No users found."})]})}export{C as U};
1
+ import{e as a,j as t}from"./vendor-DE_-CLIE.js";import{at as v,ao as o,B as S}from"./main-5C_gChTh.js";function C({onSelect:l,excludeUserIds:x=[],placeholder:u,actionLabel:m,actionDisabled:h=!1,className:p}){v();const[n,c]=a.useState(""),[b,s]=a.useState([]),[i,d]=a.useState(!1),f=async e=>{if(c(e),e.trim().length<2){s([]);return}d(!0);try{const N=await S("GET",`/web/users/search?q=${encodeURIComponent(e.trim())}`);s(N)}catch{s([])}finally{d(!1)}},y=e=>{l(e),c(""),s([])},r=b.filter(e=>!x.includes(e.id)),g=m??o("invitation.add"),j=u??o("invitation.searchUser");return t.jsxs("div",{className:p,children:[t.jsx("input",{type:"text",value:n,onChange:e=>f(e.target.value),placeholder:j,className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"}),i&&t.jsx("p",{className:"mt-1 text-xs text-text-muted",children:"Searching..."}),r.length>0&&t.jsx("ul",{className:"mt-2 divide-y divide-border rounded border border-border bg-surface-1",children:r.map(e=>t.jsxs("li",{className:"flex items-center justify-between px-3 py-2 text-sm",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsx("div",{className:"text-text-primary",children:e.username}),t.jsx("div",{className:"truncate font-mono text-xs text-text-muted",children:e.id})]}),t.jsx("button",{type:"button",onClick:()=>y(e.id),disabled:h,className:"rounded bg-accent px-2 py-1 text-xs text-white hover:bg-accent/90 disabled:opacity-50",children:g})]},e.id))}),n.trim().length>=2&&r.length===0&&!i&&t.jsx("p",{className:"mt-1 text-xs text-text-muted",children:"No users found."})]})}export{C as U};
@@ -1 +1 @@
1
- import{e as o,j as e}from"./vendor-DE_-CLIE.js";import{as as C,at as P,ao as t,an as S}from"./main-bilGpQlS.js";import{C as k}from"./copy-BId_ACIH.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function L(){const{user:n,logout:f}=C(),w=P(),[l,u]=o.useState(""),[c,m]=o.useState(""),[x,p]=o.useState(""),[h,b]=o.useState(""),[g,a]=o.useState(""),[y,d]=o.useState(!1);if(!n)return null;const j=async()=>{const s=n.userId;try{if(navigator.clipboard&&window.isSecureContext){await navigator.clipboard.writeText(s),d(!0),setTimeout(()=>d(!1),2e3);return}}catch{}const r=document.createElement("textarea");r.value=s,r.style.position="fixed",r.style.opacity="0",document.body.appendChild(r),r.select();try{document.execCommand("copy"),d(!0),setTimeout(()=>d(!1),2e3)}catch{}document.body.removeChild(r)},N=async s=>{if(s.preventDefault(),a(""),b(""),c.length<8){a(t("auth.setup.passwordTooShort"));return}if(c!==x){a(t("auth.setup.passwordMismatch"));return}try{const r=await fetch("/web/auth/change-password",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json","X-Requested-With":"XMLHttpRequest"},body:JSON.stringify({currentPassword:l,newPassword:c})});if(!r.ok){const i=await r.json();throw new Error(i.error||t("user.settings.changeFailed"))}b(t("user.settings.passwordChanged")),u(""),m(""),p("")}catch(r){const i=r instanceof Error?r.message:t("user.settings.changeFailed");a(i)}},v=async()=>{try{if(!(await fetch("/web/auth/logout-all",{method:"POST",credentials:"include",headers:{"X-Requested-With":"XMLHttpRequest"}})).ok){a(t("common.error"));return}await f()}catch{a(t("common.error"))}};return e.jsx("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:e.jsxs("div",{children:[e.jsxs("header",{className:"mb-16",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold tracking-tight text-text-primary",children:n.username}),e.jsxs("div",{className:"mt-3 flex items-center gap-2",children:[e.jsx("code",{className:"font-mono text-xs text-text-muted",children:n.userId}),e.jsx("button",{type:"button",onClick:j,className:"text-text-muted transition-colors hover:text-text-primary","aria-label":"Copy user ID",children:e.jsx(k,{className:"h-3.5 w-3.5"})}),y&&e.jsx("span",{className:"text-xs text-status-active",children:t("share.copied")}),e.jsx("span",{className:"text-text-muted/40",children:"·"}),e.jsx("span",{className:"text-xs text-text-muted",children:n.role})]})]}),e.jsxs("section",{className:"mb-16",children:[e.jsx("h2",{className:"mb-5 text-sm font-medium text-text-primary",children:t("user.settings.language")}),e.jsxs("select",{value:w,onChange:s=>S(s.target.value),className:"rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",children:[e.jsx("option",{value:"zh",children:"中文"}),e.jsx("option",{value:"en",children:"English"})]})]}),e.jsxs("section",{className:"mb-16",children:[e.jsx("h2",{className:"mb-5 text-sm font-medium text-text-primary",children:t("user.settings.changePassword")}),e.jsxs("form",{onSubmit:N,className:"max-w-md space-y-6",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-2 block text-sm font-medium text-text-primary",children:t("user.settings.currentPassword")}),e.jsx("input",{type:"password",value:l,onChange:s=>u(s.target.value),required:!0,autoComplete:"current-password",className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-accent focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-2 block text-sm font-medium text-text-primary",children:t("user.settings.newPassword")}),e.jsx("input",{type:"password",value:c,onChange:s=>m(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-accent focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-2 block text-sm font-medium text-text-primary",children:t("user.settings.confirmNewPassword")}),e.jsx("input",{type:"password",value:x,onChange:s=>p(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-accent focus:outline-none"})]}),g&&e.jsx("p",{className:"text-sm text-status-error",children:g}),h&&e.jsx("p",{className:"text-sm text-status-active",children:h}),e.jsx("div",{className:"pt-2",children:e.jsx("button",{type:"submit",className:"rounded-md bg-accent px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-accent/90",children:t("user.settings.submit")})})]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"mb-5 text-sm font-medium text-destructive",children:t("user.settings.logoutAll")}),e.jsx("p",{className:"mb-4 text-sm text-text-muted",children:"Revoke sessions on all devices."}),e.jsx("button",{onClick:v,className:"rounded-md border border-status-error/30 px-4 py-2 text-sm font-medium text-status-error transition-colors hover:bg-status-error/10",children:t("user.settings.logoutAll")})]})]})})}export{L as UserSettings};
1
+ import{e as o,j as e}from"./vendor-DE_-CLIE.js";import{as as C,at as P,ao as t,an as S}from"./main-5C_gChTh.js";import{C as k}from"./copy-CIv8ifYN.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function L(){const{user:n,logout:f}=C(),w=P(),[l,u]=o.useState(""),[c,m]=o.useState(""),[x,p]=o.useState(""),[h,b]=o.useState(""),[g,a]=o.useState(""),[y,d]=o.useState(!1);if(!n)return null;const j=async()=>{const s=n.userId;try{if(navigator.clipboard&&window.isSecureContext){await navigator.clipboard.writeText(s),d(!0),setTimeout(()=>d(!1),2e3);return}}catch{}const r=document.createElement("textarea");r.value=s,r.style.position="fixed",r.style.opacity="0",document.body.appendChild(r),r.select();try{document.execCommand("copy"),d(!0),setTimeout(()=>d(!1),2e3)}catch{}document.body.removeChild(r)},N=async s=>{if(s.preventDefault(),a(""),b(""),c.length<8){a(t("auth.setup.passwordTooShort"));return}if(c!==x){a(t("auth.setup.passwordMismatch"));return}try{const r=await fetch("/web/auth/change-password",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json","X-Requested-With":"XMLHttpRequest"},body:JSON.stringify({currentPassword:l,newPassword:c})});if(!r.ok){const i=await r.json();throw new Error(i.error||t("user.settings.changeFailed"))}b(t("user.settings.passwordChanged")),u(""),m(""),p("")}catch(r){const i=r instanceof Error?r.message:t("user.settings.changeFailed");a(i)}},v=async()=>{try{if(!(await fetch("/web/auth/logout-all",{method:"POST",credentials:"include",headers:{"X-Requested-With":"XMLHttpRequest"}})).ok){a(t("common.error"));return}await f()}catch{a(t("common.error"))}};return e.jsx("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:e.jsxs("div",{children:[e.jsxs("header",{className:"mb-16",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold tracking-tight text-text-primary",children:n.username}),e.jsxs("div",{className:"mt-3 flex items-center gap-2",children:[e.jsx("code",{className:"font-mono text-xs text-text-muted",children:n.userId}),e.jsx("button",{type:"button",onClick:j,className:"text-text-muted transition-colors hover:text-text-primary","aria-label":"Copy user ID",children:e.jsx(k,{className:"h-3.5 w-3.5"})}),y&&e.jsx("span",{className:"text-xs text-status-active",children:t("share.copied")}),e.jsx("span",{className:"text-text-muted/40",children:"·"}),e.jsx("span",{className:"text-xs text-text-muted",children:n.role})]})]}),e.jsxs("section",{className:"mb-16",children:[e.jsx("h2",{className:"mb-5 text-sm font-medium text-text-primary",children:t("user.settings.language")}),e.jsxs("select",{value:w,onChange:s=>S(s.target.value),className:"rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",children:[e.jsx("option",{value:"zh",children:"中文"}),e.jsx("option",{value:"en",children:"English"})]})]}),e.jsxs("section",{className:"mb-16",children:[e.jsx("h2",{className:"mb-5 text-sm font-medium text-text-primary",children:t("user.settings.changePassword")}),e.jsxs("form",{onSubmit:N,className:"max-w-md space-y-6",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-2 block text-sm font-medium text-text-primary",children:t("user.settings.currentPassword")}),e.jsx("input",{type:"password",value:l,onChange:s=>u(s.target.value),required:!0,autoComplete:"current-password",className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-accent focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-2 block text-sm font-medium text-text-primary",children:t("user.settings.newPassword")}),e.jsx("input",{type:"password",value:c,onChange:s=>m(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-accent focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-2 block text-sm font-medium text-text-primary",children:t("user.settings.confirmNewPassword")}),e.jsx("input",{type:"password",value:x,onChange:s=>p(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-accent focus:outline-none"})]}),g&&e.jsx("p",{className:"text-sm text-status-error",children:g}),h&&e.jsx("p",{className:"text-sm text-status-active",children:h}),e.jsx("div",{className:"pt-2",children:e.jsx("button",{type:"submit",className:"rounded-md bg-accent px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-accent/90",children:t("user.settings.submit")})})]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"mb-5 text-sm font-medium text-destructive",children:t("user.settings.logoutAll")}),e.jsx("p",{className:"mb-4 text-sm text-text-muted",children:"Revoke sessions on all devices."}),e.jsx("button",{onClick:v,className:"rounded-md border border-status-error/30 px-4 py-2 text-sm font-medium text-status-error transition-colors hover:bg-status-error/10",children:t("user.settings.logoutAll")})]})]})})}export{L as UserSettings};
@@ -1 +1 @@
1
- import{bl as ln,aO as an,H as z,b8 as w,F as G,ah as un,W as y,bd as tn,b9 as J,aI as _,c as rn,m as o,aG as on,j as sn,d as fn}from"./mermaid.core-DCyqolwk.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,j,I,v,A,H,a){var q=j-l,i=I-h,n=H-v,d=a-A,u=d*q-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*q,h+u*i]}function U(l,h,j,I,v,A,H){var a=l-j,q=h-I,i=(H?A:-A)/J(a*a+q*q),n=i*q,d=-i*a,u=l+n,s=h+d,f=j+n,c=I+d,S=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,D=(g<0?-1:1)*J(on(0,T*T*R-P*P)),E=(P*g-m*D)/R,F=(-P*m-g*D)/R,b=(P*g+m*D)/R,p=(-P*m+g*D)/R,x=E-S,e=F-t,r=b-S,W=p-t;return x*x+e*e>r*r+W*W&&(E=b,F=p),{cx:E,cy:F,x01:-n,y01:-d,x11:E*(v/T-1),y11:F*(v/T-1)}}function hn(){var l=cn,h=yn,j=G(0),I=null,v=gn,A=dn,H=mn,a=null,q=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,S=rn(c-f),t=c>f;if(a||(a=n=q()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(S>tn-y)a.moveTo(s*z(f),s*w(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*z(c),u*w(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=S,D=S,E=H.apply(this,arguments)/2,F=E>y&&(I?+I.apply(this,arguments):J(u*u+s*s)),b=_(rn(s-u)/2,+j.apply(this,arguments)),p=b,x=b,e,r;if(F>y){var W=sn(F/u*w(E)),K=sn(F/s*w(E));(P-=W*2)>y?(W*=t?1:-1,R+=W,T-=W):(P=0,R=T=(f+c)/2),(D-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(D=0,m=g=(f+c)/2)}var B=s*z(m),C=s*w(m),L=u*z(T),M=u*w(T);if(b>y){var N=s*z(g),Q=s*w(g),V=u*z(R),X=u*w(R),O;if(S<an)if(O=pn(B,C,V,X,N,Q,L,M)){var Y=B-O[0],Z=C-O[1],$=N-O[0],k=Q-O[1],nn=1/w(fn((Y*$+Z*k)/(J(Y*Y+Z*Z)*J($*$+k*k)))/2),en=J(O[0]*O[0]+O[1]*O[1]);p=_(b,(u-en)/(nn-1)),x=_(b,(s-en)/(nn+1))}else p=x=0}D>y?x>y?(e=U(V,X,B,C,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<b?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(B,C),a.arc(0,0,s,m,g,!t)):a.moveTo(B,C),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(B,C,V,X,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<b?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[z(d)*n,w(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:G(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:G(+n),i):h},i.cornerRadius=function(n){return arguments.length?(j=typeof n=="function"?n:G(+n),i):j},i.padRadius=function(n){return arguments.length?(I=n==null?null:typeof n=="function"?n:G(+n),i):I},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:G(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:G(+n),i):A},i.padAngle=function(n){return arguments.length?(H=typeof n=="function"?n:G(+n),i):H},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
1
+ import{bl as ln,aO as an,H as z,b8 as w,F as G,ah as un,W as y,bd as tn,b9 as J,aI as _,c as rn,m as o,aG as on,j as sn,d as fn}from"./mermaid.core-CQwjc9NW.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,j,I,v,A,H,a){var q=j-l,i=I-h,n=H-v,d=a-A,u=d*q-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*q,h+u*i]}function U(l,h,j,I,v,A,H){var a=l-j,q=h-I,i=(H?A:-A)/J(a*a+q*q),n=i*q,d=-i*a,u=l+n,s=h+d,f=j+n,c=I+d,S=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,D=(g<0?-1:1)*J(on(0,T*T*R-P*P)),E=(P*g-m*D)/R,F=(-P*m-g*D)/R,b=(P*g+m*D)/R,p=(-P*m+g*D)/R,x=E-S,e=F-t,r=b-S,W=p-t;return x*x+e*e>r*r+W*W&&(E=b,F=p),{cx:E,cy:F,x01:-n,y01:-d,x11:E*(v/T-1),y11:F*(v/T-1)}}function hn(){var l=cn,h=yn,j=G(0),I=null,v=gn,A=dn,H=mn,a=null,q=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,S=rn(c-f),t=c>f;if(a||(a=n=q()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(S>tn-y)a.moveTo(s*z(f),s*w(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*z(c),u*w(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=S,D=S,E=H.apply(this,arguments)/2,F=E>y&&(I?+I.apply(this,arguments):J(u*u+s*s)),b=_(rn(s-u)/2,+j.apply(this,arguments)),p=b,x=b,e,r;if(F>y){var W=sn(F/u*w(E)),K=sn(F/s*w(E));(P-=W*2)>y?(W*=t?1:-1,R+=W,T-=W):(P=0,R=T=(f+c)/2),(D-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(D=0,m=g=(f+c)/2)}var B=s*z(m),C=s*w(m),L=u*z(T),M=u*w(T);if(b>y){var N=s*z(g),Q=s*w(g),V=u*z(R),X=u*w(R),O;if(S<an)if(O=pn(B,C,V,X,N,Q,L,M)){var Y=B-O[0],Z=C-O[1],$=N-O[0],k=Q-O[1],nn=1/w(fn((Y*$+Z*k)/(J(Y*Y+Z*Z)*J($*$+k*k)))/2),en=J(O[0]*O[0]+O[1]*O[1]);p=_(b,(u-en)/(nn-1)),x=_(b,(s-en)/(nn+1))}else p=x=0}D>y?x>y?(e=U(V,X,B,C,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<b?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(B,C),a.arc(0,0,s,m,g,!t)):a.moveTo(B,C),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(B,C,V,X,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<b?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[z(d)*n,w(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:G(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:G(+n),i):h},i.cornerRadius=function(n){return arguments.length?(j=typeof n=="function"?n:G(+n),i):j},i.padRadius=function(n){return arguments.length?(I=n==null?null:typeof n=="function"?n:G(+n),i):I},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:G(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:G(+n),i):A},i.padAngle=function(n){return arguments.length?(H=typeof n=="function"?n:G(+n),i):H},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};