@saluzi/saluzi-edu 0.2.61 → 0.2.63

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 (147) hide show
  1. package/dist/cli.js +204 -116
  2. package/dist/parade/web/menu.html +71 -23
  3. package/dist/rcs-web/assets/{AdminPanel-Xlza8Stt.js → AdminPanel-CqP_94xa.js} +1 -1
  4. package/{packages/remote-control-server/web/dist/assets/Claim-BMWwu213.js → dist/rcs-web/assets/Claim-BvfARQ6Q.js} +1 -1
  5. package/{packages/remote-control-server/web/dist/assets/Dashboard-D5awDzM3.js → dist/rcs-web/assets/Dashboard-BDGi4XpN.js} +1 -1
  6. package/{packages/remote-control-server/web/dist/assets/Join-ok37ggfZ.js → dist/rcs-web/assets/Join-PPDYBhsJ.js} +1 -1
  7. package/dist/rcs-web/assets/{Login-5qo97rq-.js → Login-JprQIEpr.js} +1 -1
  8. package/dist/rcs-web/assets/{Register-D_UOG8ar.js → Register-cuGuAE83.js} +1 -1
  9. package/dist/rcs-web/assets/{SessionDetail-BbHrR4Qu.js → SessionDetail-D-xhkyLo.js} +5 -5
  10. package/dist/rcs-web/assets/{SessionVisibilityBadge-Dy4FwTzo.js → SessionVisibilityBadge-91WyR9K6.js} +1 -1
  11. package/dist/rcs-web/assets/{Setup-GnPeNyH9.js → Setup-Buwa9Y3M.js} +1 -1
  12. package/dist/rcs-web/assets/{ShareLanding-CUjQydLL.js → ShareLanding-DhwgJb6V.js} +1 -1
  13. package/dist/rcs-web/assets/{TeamCreate-Ck2fEoUW.js → TeamCreate-CaoinTSG.js} +1 -1
  14. package/dist/rcs-web/assets/{TeamDetail-De6EPND0.js → TeamDetail-D5ahen24.js} +1 -1
  15. package/dist/rcs-web/assets/{TeamList-C-0LJRxd.js → TeamList-qCuKKSH3.js} +1 -1
  16. package/dist/rcs-web/assets/{TeamSettings-BszOrXVW.js → TeamSettings-BaIwImrp.js} +1 -1
  17. package/dist/rcs-web/assets/{UserSearchInput-CyQWtLL-.js → UserSearchInput-BxcYR_HU.js} +1 -1
  18. package/dist/rcs-web/assets/{UserSettings-DgyYp-1y.js → UserSettings-zfGfcuWs.js} +1 -1
  19. package/dist/rcs-web/assets/{arc-BaOPt7k-.js → arc-DwAbF6eM.js} +1 -1
  20. package/dist/rcs-web/assets/{architectureDiagram-3BPJPVTR-SvIakXbT.js → architectureDiagram-3BPJPVTR-uMOwOwiN.js} +1 -1
  21. package/{packages/remote-control-server/web/dist/assets/blockDiagram-GPEHLZMM-CiDp9J7i.js → dist/rcs-web/assets/blockDiagram-GPEHLZMM-B5BqFTkP.js} +1 -1
  22. package/dist/rcs-web/assets/{c4Diagram-AAUBKEIU-D9wzA9ur.js → c4Diagram-AAUBKEIU-D6eienz2.js} +1 -1
  23. package/dist/rcs-web/assets/channel-CCfqpGSl.js +1 -0
  24. package/dist/rcs-web/assets/{chunk-2J33WTMH-qfYueRAP.js → chunk-2J33WTMH-DqVxv8yW.js} +1 -1
  25. package/dist/rcs-web/assets/{chunk-4BX2VUAB-D1V_UCiK.js → chunk-4BX2VUAB-X5o4x8om.js} +1 -1
  26. package/dist/rcs-web/assets/{chunk-55IACEB6-C67QiGmo.js → chunk-55IACEB6-D7G25_Y5.js} +1 -1
  27. package/{packages/remote-control-server/web/dist/assets/chunk-727SXJPM-D2Wln4TT.js → dist/rcs-web/assets/chunk-727SXJPM-CoXI1FIy.js} +1 -1
  28. package/dist/rcs-web/assets/{chunk-AQP2D5EJ-03h8hZhw.js → chunk-AQP2D5EJ-C73Crhqe.js} +1 -1
  29. package/dist/rcs-web/assets/{chunk-FMBD7UC4-7zas8pDp.js → chunk-FMBD7UC4-DVzxIsSE.js} +1 -1
  30. package/dist/rcs-web/assets/{chunk-ND2GUHAM-PUXucyY6.js → chunk-ND2GUHAM-C6_oEhLf.js} +1 -1
  31. package/dist/rcs-web/assets/{chunk-QZHKN3VN-M3U5l4yW.js → chunk-QZHKN3VN-COvH7k5r.js} +1 -1
  32. package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-DzNdVs3v.js +1 -0
  33. package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-DzNdVs3v.js +1 -0
  34. package/dist/rcs-web/assets/{code-block-IT6T5CEO-BgUazuuS.js → code-block-IT6T5CEO-CE-2f_-K.js} +1 -1
  35. package/dist/rcs-web/assets/{copy-DjaSB1Rw.js → copy-9pzb1Po6.js} +1 -1
  36. package/dist/rcs-web/assets/{cose-bilkent-S5V4N54A-zPupX74N.js → cose-bilkent-S5V4N54A-B9sMDFRe.js} +1 -1
  37. package/dist/rcs-web/assets/{dagre-BM42HDAG-B_EJ050J.js → dagre-BM42HDAG-DB1jXylM.js} +1 -1
  38. package/dist/rcs-web/assets/{diagram-2AECGRRQ-dnnxPH7w.js → diagram-2AECGRRQ-MNuqSRmg.js} +1 -1
  39. package/dist/rcs-web/assets/{diagram-5GNKFQAL-CLEOqCLZ.js → diagram-5GNKFQAL-BZwhvaEY.js} +1 -1
  40. package/dist/rcs-web/assets/{diagram-KO2AKTUF-DKBGpiRW.js → diagram-KO2AKTUF-3Wp2PnI2.js} +1 -1
  41. package/dist/rcs-web/assets/{diagram-LMA3HP47-BAilhXiA.js → diagram-LMA3HP47-CTcV1SBj.js} +1 -1
  42. package/dist/rcs-web/assets/{diagram-OG6HWLK6-C3CdmOxC.js → diagram-OG6HWLK6-DzXhSQDC.js} +1 -1
  43. package/dist/rcs-web/assets/{erDiagram-TEJ5UH35-D1yv-3Jv.js → erDiagram-TEJ5UH35-CwSihkB8.js} +1 -1
  44. package/dist/rcs-web/assets/{flowDiagram-I6XJVG4X-DpW11XWj.js → flowDiagram-I6XJVG4X-BSuXctT4.js} +1 -1
  45. package/{packages/remote-control-server/web/dist/assets/ganttDiagram-6RSMTGT7-CWr8suZm.js → dist/rcs-web/assets/ganttDiagram-6RSMTGT7-B87oxjmY.js} +1 -1
  46. package/dist/rcs-web/assets/{gitGraphDiagram-PVQCEYII-BspxLSNV.js → gitGraphDiagram-PVQCEYII-BRrwOi3C.js} +1 -1
  47. package/dist/rcs-web/assets/{infoDiagram-5YYISTIA-Bow20s-Q.js → infoDiagram-5YYISTIA-B-8QXS0n.js} +1 -1
  48. package/dist/rcs-web/assets/{ishikawaDiagram-YF4QCWOH-BESvGYGI.js → ishikawaDiagram-YF4QCWOH-Bau9MU6C.js} +1 -1
  49. package/dist/rcs-web/assets/{journeyDiagram-JHISSGLW-DZ6gzC7H.js → journeyDiagram-JHISSGLW-D_tAp--R.js} +1 -1
  50. package/dist/rcs-web/assets/{kanban-definition-UN3LZRKU-DIQo2GiM.js → kanban-definition-UN3LZRKU---UIvjMZ.js} +1 -1
  51. package/dist/rcs-web/assets/{linear-CdXALiZ8.js → linear-CIDLjd5h.js} +1 -1
  52. package/dist/rcs-web/assets/{main-CwLwGVDc.js → main-N3GYCdLF.js} +3 -3
  53. package/dist/rcs-web/assets/{mermaid-VLURNSYL-C0ZKM74W.js → mermaid-VLURNSYL-Cu5A5sMk.js} +4 -4
  54. package/dist/rcs-web/assets/{mermaid.core-eEtoQhrQ.js → mermaid.core-CEJOtCGw.js} +5 -5
  55. package/dist/rcs-web/assets/{mindmap-definition-RKZ34NQL-CcW3H_cH.js → mindmap-definition-RKZ34NQL-ldyccyCP.js} +1 -1
  56. package/dist/rcs-web/assets/{pieDiagram-4H26LBE5-DpXUpJMl.js → pieDiagram-4H26LBE5-CmghofeF.js} +1 -1
  57. package/{packages/remote-control-server/web/dist/assets/quadrantDiagram-W4KKPZXB-DOwMRzzP.js → dist/rcs-web/assets/quadrantDiagram-W4KKPZXB-B-2N2UHr.js} +1 -1
  58. package/dist/rcs-web/assets/{requirementDiagram-4Y6WPE33-CBi_6NcW.js → requirementDiagram-4Y6WPE33-39jlO9Y8.js} +1 -1
  59. package/{packages/remote-control-server/web/dist/assets/sankeyDiagram-5OEKKPKP-CKbAoTHm.js → dist/rcs-web/assets/sankeyDiagram-5OEKKPKP-DdY7KNFB.js} +1 -1
  60. package/dist/rcs-web/assets/{sequenceDiagram-3UESZ5HK-a3rYCe-w.js → sequenceDiagram-3UESZ5HK-D2k5rX6x.js} +1 -1
  61. package/dist/rcs-web/assets/{stateDiagram-AJRCARHV-B6R_Dt84.js → stateDiagram-AJRCARHV-CP9N457o.js} +1 -1
  62. package/dist/rcs-web/assets/{stateDiagram-v2-BHNVJYJU-Cq935fvz.js → stateDiagram-v2-BHNVJYJU-CPhZYlL0.js} +1 -1
  63. package/{packages/remote-control-server/web/dist/assets/timeline-definition-PNZ67QCA-8DXPKq1k.js → dist/rcs-web/assets/timeline-definition-PNZ67QCA-DSEPBO8O.js} +1 -1
  64. package/dist/rcs-web/assets/{vennDiagram-CIIHVFJN-BfDEkku5.js → vennDiagram-CIIHVFJN-CkNMwCJ3.js} +1 -1
  65. package/dist/rcs-web/assets/{wardleyDiagram-YWT4CUSO-Dvp2XZVf.js → wardleyDiagram-YWT4CUSO-Cxd-F60s.js} +1 -1
  66. package/{packages/remote-control-server/web/dist/assets/xychartDiagram-2RQKCTM6-DiPjQLUx.js → dist/rcs-web/assets/xychartDiagram-2RQKCTM6-BLL105NN.js} +1 -1
  67. package/dist/rcs-web/index.html +1 -1
  68. package/package.json +1 -1
  69. package/packages/remote-control-server/src/__tests__/models-state-snapshot.test.ts +216 -0
  70. package/packages/remote-control-server/src/__tests__/turn-end-status.test.ts +217 -1
  71. package/packages/remote-control-server/src/routes/v2/worker-events.ts +12 -1
  72. package/packages/remote-control-server/src/routes/web/control.ts +11 -2
  73. package/packages/remote-control-server/src/routes/web/sessions.ts +33 -0
  74. package/packages/remote-control-server/src/services/transport.ts +12 -0
  75. package/packages/remote-control-server/src/transport/event-bus.ts +25 -0
  76. package/packages/remote-control-server/src/transport/ws-handler.ts +14 -1
  77. package/packages/remote-control-server/web/dist/assets/{AdminPanel-Xlza8Stt.js → AdminPanel-CqP_94xa.js} +1 -1
  78. package/{dist/rcs-web/assets/Claim-BMWwu213.js → packages/remote-control-server/web/dist/assets/Claim-BvfARQ6Q.js} +1 -1
  79. package/{dist/rcs-web/assets/Dashboard-D5awDzM3.js → packages/remote-control-server/web/dist/assets/Dashboard-BDGi4XpN.js} +1 -1
  80. package/{dist/rcs-web/assets/Join-ok37ggfZ.js → packages/remote-control-server/web/dist/assets/Join-PPDYBhsJ.js} +1 -1
  81. package/packages/remote-control-server/web/dist/assets/{Login-5qo97rq-.js → Login-JprQIEpr.js} +1 -1
  82. package/packages/remote-control-server/web/dist/assets/{Register-D_UOG8ar.js → Register-cuGuAE83.js} +1 -1
  83. package/packages/remote-control-server/web/dist/assets/{SessionDetail-BbHrR4Qu.js → SessionDetail-D-xhkyLo.js} +5 -5
  84. package/packages/remote-control-server/web/dist/assets/{SessionVisibilityBadge-Dy4FwTzo.js → SessionVisibilityBadge-91WyR9K6.js} +1 -1
  85. package/packages/remote-control-server/web/dist/assets/{Setup-GnPeNyH9.js → Setup-Buwa9Y3M.js} +1 -1
  86. package/packages/remote-control-server/web/dist/assets/{ShareLanding-CUjQydLL.js → ShareLanding-DhwgJb6V.js} +1 -1
  87. package/packages/remote-control-server/web/dist/assets/{TeamCreate-Ck2fEoUW.js → TeamCreate-CaoinTSG.js} +1 -1
  88. package/packages/remote-control-server/web/dist/assets/{TeamDetail-De6EPND0.js → TeamDetail-D5ahen24.js} +1 -1
  89. package/packages/remote-control-server/web/dist/assets/{TeamList-C-0LJRxd.js → TeamList-qCuKKSH3.js} +1 -1
  90. package/packages/remote-control-server/web/dist/assets/{TeamSettings-BszOrXVW.js → TeamSettings-BaIwImrp.js} +1 -1
  91. package/packages/remote-control-server/web/dist/assets/{UserSearchInput-CyQWtLL-.js → UserSearchInput-BxcYR_HU.js} +1 -1
  92. package/packages/remote-control-server/web/dist/assets/{UserSettings-DgyYp-1y.js → UserSettings-zfGfcuWs.js} +1 -1
  93. package/packages/remote-control-server/web/dist/assets/{arc-BaOPt7k-.js → arc-DwAbF6eM.js} +1 -1
  94. package/packages/remote-control-server/web/dist/assets/{architectureDiagram-3BPJPVTR-SvIakXbT.js → architectureDiagram-3BPJPVTR-uMOwOwiN.js} +1 -1
  95. package/{dist/rcs-web/assets/blockDiagram-GPEHLZMM-CiDp9J7i.js → packages/remote-control-server/web/dist/assets/blockDiagram-GPEHLZMM-B5BqFTkP.js} +1 -1
  96. package/packages/remote-control-server/web/dist/assets/{c4Diagram-AAUBKEIU-D9wzA9ur.js → c4Diagram-AAUBKEIU-D6eienz2.js} +1 -1
  97. package/packages/remote-control-server/web/dist/assets/channel-CCfqpGSl.js +1 -0
  98. package/packages/remote-control-server/web/dist/assets/{chunk-2J33WTMH-qfYueRAP.js → chunk-2J33WTMH-DqVxv8yW.js} +1 -1
  99. package/packages/remote-control-server/web/dist/assets/{chunk-4BX2VUAB-D1V_UCiK.js → chunk-4BX2VUAB-X5o4x8om.js} +1 -1
  100. package/packages/remote-control-server/web/dist/assets/{chunk-55IACEB6-C67QiGmo.js → chunk-55IACEB6-D7G25_Y5.js} +1 -1
  101. package/{dist/rcs-web/assets/chunk-727SXJPM-D2Wln4TT.js → packages/remote-control-server/web/dist/assets/chunk-727SXJPM-CoXI1FIy.js} +1 -1
  102. package/packages/remote-control-server/web/dist/assets/{chunk-AQP2D5EJ-03h8hZhw.js → chunk-AQP2D5EJ-C73Crhqe.js} +1 -1
  103. package/packages/remote-control-server/web/dist/assets/{chunk-FMBD7UC4-7zas8pDp.js → chunk-FMBD7UC4-DVzxIsSE.js} +1 -1
  104. package/packages/remote-control-server/web/dist/assets/{chunk-ND2GUHAM-PUXucyY6.js → chunk-ND2GUHAM-C6_oEhLf.js} +1 -1
  105. package/packages/remote-control-server/web/dist/assets/{chunk-QZHKN3VN-M3U5l4yW.js → chunk-QZHKN3VN-COvH7k5r.js} +1 -1
  106. package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-DzNdVs3v.js +1 -0
  107. package/packages/remote-control-server/web/dist/assets/classDiagram-v2-Q7XG4LA2-DzNdVs3v.js +1 -0
  108. package/packages/remote-control-server/web/dist/assets/{code-block-IT6T5CEO-BgUazuuS.js → code-block-IT6T5CEO-CE-2f_-K.js} +1 -1
  109. package/packages/remote-control-server/web/dist/assets/{copy-DjaSB1Rw.js → copy-9pzb1Po6.js} +1 -1
  110. package/packages/remote-control-server/web/dist/assets/{cose-bilkent-S5V4N54A-zPupX74N.js → cose-bilkent-S5V4N54A-B9sMDFRe.js} +1 -1
  111. package/packages/remote-control-server/web/dist/assets/{dagre-BM42HDAG-B_EJ050J.js → dagre-BM42HDAG-DB1jXylM.js} +1 -1
  112. package/packages/remote-control-server/web/dist/assets/{diagram-2AECGRRQ-dnnxPH7w.js → diagram-2AECGRRQ-MNuqSRmg.js} +1 -1
  113. package/packages/remote-control-server/web/dist/assets/{diagram-5GNKFQAL-CLEOqCLZ.js → diagram-5GNKFQAL-BZwhvaEY.js} +1 -1
  114. package/packages/remote-control-server/web/dist/assets/{diagram-KO2AKTUF-DKBGpiRW.js → diagram-KO2AKTUF-3Wp2PnI2.js} +1 -1
  115. package/packages/remote-control-server/web/dist/assets/{diagram-LMA3HP47-BAilhXiA.js → diagram-LMA3HP47-CTcV1SBj.js} +1 -1
  116. package/packages/remote-control-server/web/dist/assets/{diagram-OG6HWLK6-C3CdmOxC.js → diagram-OG6HWLK6-DzXhSQDC.js} +1 -1
  117. package/packages/remote-control-server/web/dist/assets/{erDiagram-TEJ5UH35-D1yv-3Jv.js → erDiagram-TEJ5UH35-CwSihkB8.js} +1 -1
  118. package/packages/remote-control-server/web/dist/assets/{flowDiagram-I6XJVG4X-DpW11XWj.js → flowDiagram-I6XJVG4X-BSuXctT4.js} +1 -1
  119. package/{dist/rcs-web/assets/ganttDiagram-6RSMTGT7-CWr8suZm.js → packages/remote-control-server/web/dist/assets/ganttDiagram-6RSMTGT7-B87oxjmY.js} +1 -1
  120. package/packages/remote-control-server/web/dist/assets/{gitGraphDiagram-PVQCEYII-BspxLSNV.js → gitGraphDiagram-PVQCEYII-BRrwOi3C.js} +1 -1
  121. package/packages/remote-control-server/web/dist/assets/{infoDiagram-5YYISTIA-Bow20s-Q.js → infoDiagram-5YYISTIA-B-8QXS0n.js} +1 -1
  122. package/packages/remote-control-server/web/dist/assets/{ishikawaDiagram-YF4QCWOH-BESvGYGI.js → ishikawaDiagram-YF4QCWOH-Bau9MU6C.js} +1 -1
  123. package/packages/remote-control-server/web/dist/assets/{journeyDiagram-JHISSGLW-DZ6gzC7H.js → journeyDiagram-JHISSGLW-D_tAp--R.js} +1 -1
  124. package/packages/remote-control-server/web/dist/assets/{kanban-definition-UN3LZRKU-DIQo2GiM.js → kanban-definition-UN3LZRKU---UIvjMZ.js} +1 -1
  125. package/packages/remote-control-server/web/dist/assets/{linear-CdXALiZ8.js → linear-CIDLjd5h.js} +1 -1
  126. package/packages/remote-control-server/web/dist/assets/{main-CwLwGVDc.js → main-N3GYCdLF.js} +3 -3
  127. package/packages/remote-control-server/web/dist/assets/{mermaid-VLURNSYL-C0ZKM74W.js → mermaid-VLURNSYL-Cu5A5sMk.js} +4 -4
  128. package/packages/remote-control-server/web/dist/assets/{mermaid.core-eEtoQhrQ.js → mermaid.core-CEJOtCGw.js} +5 -5
  129. package/packages/remote-control-server/web/dist/assets/{mindmap-definition-RKZ34NQL-CcW3H_cH.js → mindmap-definition-RKZ34NQL-ldyccyCP.js} +1 -1
  130. package/packages/remote-control-server/web/dist/assets/{pieDiagram-4H26LBE5-DpXUpJMl.js → pieDiagram-4H26LBE5-CmghofeF.js} +1 -1
  131. package/{dist/rcs-web/assets/quadrantDiagram-W4KKPZXB-DOwMRzzP.js → packages/remote-control-server/web/dist/assets/quadrantDiagram-W4KKPZXB-B-2N2UHr.js} +1 -1
  132. package/packages/remote-control-server/web/dist/assets/{requirementDiagram-4Y6WPE33-CBi_6NcW.js → requirementDiagram-4Y6WPE33-39jlO9Y8.js} +1 -1
  133. package/{dist/rcs-web/assets/sankeyDiagram-5OEKKPKP-CKbAoTHm.js → packages/remote-control-server/web/dist/assets/sankeyDiagram-5OEKKPKP-DdY7KNFB.js} +1 -1
  134. package/packages/remote-control-server/web/dist/assets/{sequenceDiagram-3UESZ5HK-a3rYCe-w.js → sequenceDiagram-3UESZ5HK-D2k5rX6x.js} +1 -1
  135. package/packages/remote-control-server/web/dist/assets/{stateDiagram-AJRCARHV-B6R_Dt84.js → stateDiagram-AJRCARHV-CP9N457o.js} +1 -1
  136. package/packages/remote-control-server/web/dist/assets/{stateDiagram-v2-BHNVJYJU-Cq935fvz.js → stateDiagram-v2-BHNVJYJU-CPhZYlL0.js} +1 -1
  137. package/{dist/rcs-web/assets/timeline-definition-PNZ67QCA-8DXPKq1k.js → packages/remote-control-server/web/dist/assets/timeline-definition-PNZ67QCA-DSEPBO8O.js} +1 -1
  138. package/packages/remote-control-server/web/dist/assets/{vennDiagram-CIIHVFJN-BfDEkku5.js → vennDiagram-CIIHVFJN-CkNMwCJ3.js} +1 -1
  139. package/packages/remote-control-server/web/dist/assets/{wardleyDiagram-YWT4CUSO-Dvp2XZVf.js → wardleyDiagram-YWT4CUSO-Cxd-F60s.js} +1 -1
  140. package/{dist/rcs-web/assets/xychartDiagram-2RQKCTM6-DiPjQLUx.js → packages/remote-control-server/web/dist/assets/xychartDiagram-2RQKCTM6-BLL105NN.js} +1 -1
  141. package/packages/remote-control-server/web/dist/index.html +1 -1
  142. package/dist/rcs-web/assets/channel-CirgRB_G.js +0 -1
  143. package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-Cq12UEz9.js +0 -1
  144. package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-Cq12UEz9.js +0 -1
  145. package/packages/remote-control-server/web/dist/assets/channel-CirgRB_G.js +0 -1
  146. package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-Cq12UEz9.js +0 -1
  147. package/packages/remote-control-server/web/dist/assets/classDiagram-v2-Q7XG4LA2-Cq12UEz9.js +0 -1
@@ -7,6 +7,12 @@
7
7
  * - v1 session-ingress (HybridTransport POST → ingestBridgeMessage)
8
8
  * - v2 CCR worker events (POST /v1/code/sessions/:id/worker/events)
9
9
  * Both must end the turn with a derived session_status event, status=idle.
10
+ *
11
+ * Also covers the inversion variant: the worker's bridge write paths are not
12
+ * strictly ordered, so the turn-end result can arrive BEFORE the final
13
+ * mirrored assistant message. A late assistant must NOT flip the session
14
+ * back to running (turn-signal guard, EventBus.turnActive) — that re-engaged
15
+ * the web UI input and left every subsequent message stuck in the queue.
10
16
  */
11
17
  import { describe, test, expect, beforeEach, mock } from 'bun:test'
12
18
  import { mockConfigModule } from './helpers/mock-config'
@@ -131,7 +137,23 @@ describe('turn end emits session_status idle (stuck-running regression)', () =>
131
137
  expect(getSession(sessionId)?.status).toBe('idle')
132
138
  })
133
139
 
134
- test('v2 worker events: assistant → result derives running → idle', async () => {
140
+ test('v2 worker events: user → assistant → result derives running → idle', async () => {
141
+ // User message from the web UI starts the turn (turn-signal)
142
+ const res0 = await app.request(`/web/sessions/${sessionId}/events`, {
143
+ method: 'POST',
144
+ headers: {
145
+ Authorization: auth('user-1'),
146
+ 'Content-Type': 'application/json',
147
+ },
148
+ body: JSON.stringify({
149
+ type: 'user',
150
+ uuid: 'v2-web-user-1',
151
+ content: 'hello',
152
+ message: { content: 'hello' },
153
+ }),
154
+ })
155
+ expect(res0.status).toBe(200)
156
+
135
157
  // Assistant event marks the turn running
136
158
  const res1 = await app.request(
137
159
  `/v1/code/sessions/${sessionId}/worker/events`,
@@ -179,6 +201,200 @@ describe('turn end emits session_status idle (stuck-running regression)', () =>
179
201
  expect(statuses[statuses.length - 1]).toBe('idle')
180
202
  })
181
203
 
204
+ test('v1 session-ingress: REPL-initiated turn (mirrored user) derives running', async () => {
205
+ // A turn typed in the terminal REPL reaches the server via the
206
+ // transcript mirror: [user, assistant] in one writeBatch POST. The
207
+ // mirrored user message must arm the turn signal so the assistant
208
+ // event derives running.
209
+ const res = await app.request(
210
+ `/v2/session_ingress/session/${sessionId}/events`,
211
+ {
212
+ method: 'POST',
213
+ headers: { ...AUTH_HEADERS, 'Content-Type': 'application/json' },
214
+ body: JSON.stringify({
215
+ events: [
216
+ {
217
+ type: 'user',
218
+ uuid: 'repl-user-1',
219
+ message: { role: 'user', content: 'typed in terminal' },
220
+ },
221
+ {
222
+ type: 'assistant',
223
+ uuid: 'repl-asst-1',
224
+ message: {
225
+ role: 'assistant',
226
+ content: [{ type: 'text', text: 'terminal reply' }],
227
+ },
228
+ },
229
+ ],
230
+ }),
231
+ },
232
+ )
233
+ expect(res.status).toBe(200)
234
+ expect(getSession(sessionId)?.status).toBe('running')
235
+ })
236
+
237
+ test('v1 session-ingress: late assistant after result does not resurrect running', async () => {
238
+ // Inversion regression: the REPL bridge POSTs the synthetic turn-end
239
+ // result BEFORE the final mirrored assistant message (transcript-mirror
240
+ // render race). The late assistant must not flip the session back to
241
+ // running — that left the web UI input engaged and queued every new
242
+ // message indefinitely.
243
+ await app.request(`/web/sessions/${sessionId}/events`, {
244
+ method: 'POST',
245
+ headers: {
246
+ Authorization: auth('user-1'),
247
+ 'Content-Type': 'application/json',
248
+ },
249
+ body: JSON.stringify({
250
+ type: 'user',
251
+ uuid: 'inv-user-1',
252
+ content: 'hi',
253
+ message: { content: 'hi' },
254
+ }),
255
+ })
256
+
257
+ // Worker delivers result first, then the final assistant message
258
+ const res = await app.request(
259
+ `/v2/session_ingress/session/${sessionId}/events`,
260
+ {
261
+ method: 'POST',
262
+ headers: { ...AUTH_HEADERS, 'Content-Type': 'application/json' },
263
+ body: JSON.stringify({
264
+ events: [
265
+ {
266
+ type: 'result_success',
267
+ subtype: 'success',
268
+ uuid: 'inv-result-1',
269
+ result: '',
270
+ total_cost_usd: 0,
271
+ usage: {},
272
+ },
273
+ ],
274
+ }),
275
+ },
276
+ )
277
+ expect(res.status).toBe(200)
278
+ expect(getSession(sessionId)?.status).toBe('idle')
279
+
280
+ const lateRes = await app.request(
281
+ `/v2/session_ingress/session/${sessionId}/events`,
282
+ {
283
+ method: 'POST',
284
+ headers: { ...AUTH_HEADERS, 'Content-Type': 'application/json' },
285
+ body: JSON.stringify({
286
+ events: [
287
+ {
288
+ type: 'assistant',
289
+ uuid: 'inv-asst-1',
290
+ message: {
291
+ role: 'assistant',
292
+ content: [{ type: 'text', text: 'Hello again!' }],
293
+ },
294
+ },
295
+ ],
296
+ }),
297
+ },
298
+ )
299
+ expect(lateRes.status).toBe(200)
300
+ expect(getSession(sessionId)?.status).toBe('idle')
301
+
302
+ const statuses = statusEvents(getEventBus(sessionId).getEventsSince(0))
303
+ expect(statuses[statuses.length - 1]).toBe('idle')
304
+ })
305
+
306
+ test('v2 worker events: late assistant after result does not resurrect running', async () => {
307
+ await app.request(`/web/sessions/${sessionId}/events`, {
308
+ method: 'POST',
309
+ headers: {
310
+ Authorization: auth('user-1'),
311
+ 'Content-Type': 'application/json',
312
+ },
313
+ body: JSON.stringify({
314
+ type: 'user',
315
+ uuid: 'inv2-user-1',
316
+ content: 'hi',
317
+ message: { content: 'hi' },
318
+ }),
319
+ })
320
+
321
+ await app.request(`/v1/code/sessions/${sessionId}/worker/events`, {
322
+ method: 'POST',
323
+ headers: { ...AUTH_HEADERS, 'Content-Type': 'application/json' },
324
+ body: JSON.stringify([
325
+ {
326
+ type: 'result_success',
327
+ subtype: 'success',
328
+ uuid: 'inv2-result-1',
329
+ result: '',
330
+ },
331
+ ]),
332
+ })
333
+ expect(getSession(sessionId)?.status).toBe('idle')
334
+
335
+ await app.request(`/v1/code/sessions/${sessionId}/worker/events`, {
336
+ method: 'POST',
337
+ headers: { ...AUTH_HEADERS, 'Content-Type': 'application/json' },
338
+ body: JSON.stringify([
339
+ {
340
+ type: 'assistant',
341
+ uuid: 'inv2-asst-1',
342
+ message: {
343
+ role: 'assistant',
344
+ content: [{ type: 'text', text: 'late mirror' }],
345
+ },
346
+ },
347
+ ]),
348
+ })
349
+ expect(getSession(sessionId)?.status).toBe('idle')
350
+
351
+ const statuses = statusEvents(getEventBus(sessionId).getEventsSince(0))
352
+ expect(statuses[statuses.length - 1]).toBe('idle')
353
+ })
354
+
355
+ test('interrupt ends the turn: late assistant does not resurrect running', async () => {
356
+ await app.request(`/web/sessions/${sessionId}/events`, {
357
+ method: 'POST',
358
+ headers: {
359
+ Authorization: auth('user-1'),
360
+ 'Content-Type': 'application/json',
361
+ },
362
+ body: JSON.stringify({
363
+ type: 'user',
364
+ uuid: 'intr-user-1',
365
+ content: 'work',
366
+ message: { content: 'work' },
367
+ }),
368
+ })
369
+ expect(getSession(sessionId)?.status).toBe('running')
370
+
371
+ await app.request(`/web/sessions/${sessionId}/interrupt`, {
372
+ method: 'POST',
373
+ headers: { Authorization: auth('user-1') },
374
+ })
375
+ expect(getSession(sessionId)?.status).toBe('idle')
376
+
377
+ // A mirrored assistant message that was still in flight when the user
378
+ // hit Stop arrives after the interrupt — must not re-engage running.
379
+ await app.request(`/v2/session_ingress/session/${sessionId}/events`, {
380
+ method: 'POST',
381
+ headers: { ...AUTH_HEADERS, 'Content-Type': 'application/json' },
382
+ body: JSON.stringify({
383
+ events: [
384
+ {
385
+ type: 'assistant',
386
+ uuid: 'intr-asst-1',
387
+ message: {
388
+ role: 'assistant',
389
+ content: [{ type: 'text', text: 'partial reply' }],
390
+ },
391
+ },
392
+ ],
393
+ }),
394
+ })
395
+ expect(getSession(sessionId)?.status).toBe('idle')
396
+ })
397
+
182
398
  test('v2 worker events: control_request derives requires_action', async () => {
183
399
  const res = await app.request(
184
400
  `/v1/code/sessions/${sessionId}/worker/events`,
@@ -77,12 +77,23 @@ app.post(
77
77
  // state uploads leaves the session stuck on 'running', so the web UI
78
78
  // input never leaves the running state and every new message lands
79
79
  // in the queue instead of being sent.
80
+ //
81
+ // Turn-signal accounting (EventBus.turnActive): the worker's write
82
+ // paths are not strictly ordered — the turn-end result can reach the
83
+ // server BEFORE the final assistant message. A late assistant must
84
+ // not flip the session back to running after the turn ended.
85
+ const bus = getEventBus(sessionId)
86
+ if (eventType === 'user') {
87
+ bus.turnActive = true
88
+ } else if (eventType === 'result' || eventType === 'result_success') {
89
+ bus.turnActive = false
90
+ }
80
91
  const targetStatus =
81
92
  eventType === 'result' || eventType === 'result_success'
82
93
  ? 'idle'
83
94
  : eventType === 'control_request'
84
95
  ? 'requires_action'
85
- : eventType === 'assistant'
96
+ : eventType === 'assistant' && bus.turnActive
86
97
  ? 'running'
87
98
  : null
88
99
  if (targetStatus) {
@@ -75,8 +75,14 @@ app.post('/sessions/:id/events', sessionAuth, async c => {
75
75
  // (ws-handler.ts ingestBridgeMessage) marks it idle again. Skip when the
76
76
  // session is already running so repeated user messages don't spam
77
77
  // session_status events.
78
- if (eventType === 'user' && getSession(sessionId)?.status !== 'running') {
79
- updateSessionStatus(sessionId, 'running')
78
+ if (eventType === 'user') {
79
+ // Turn-signal (EventBus.turnActive): a user message starts a turn —
80
+ // later assistant events of this turn may derive `running` (see
81
+ // ws-handler.ts).
82
+ getEventBus(sessionId).turnActive = true
83
+ if (getSession(sessionId)?.status !== 'running') {
84
+ updateSessionStatus(sessionId, 'running')
85
+ }
80
86
  }
81
87
  log(
82
88
  `[RC-DEBUG] web -> server: published outbound event id=${event.id} type=${event.type} direction=${event.direction} subscribers=${getEventBus(sessionId).subscriberCount()}`,
@@ -134,6 +140,9 @@ app.post('/sessions/:id/interrupt', sessionAuth, async c => {
134
140
  { action: 'interrupt' },
135
141
  'outbound',
136
142
  )
143
+ // Interrupt ends the turn — a late mirrored assistant message must not
144
+ // flip the session back to running (EventBus.turnActive, see ws-handler.ts).
145
+ getEventBus(sessionId).turnActive = false
137
146
  updateSessionStatus(sessionId, 'idle')
138
147
  return c.json({ status: 'ok' }, 200)
139
148
  })
@@ -34,6 +34,7 @@ import {
34
34
  import { createWorkItem, stopWork } from '../../services/work-dispatch'
35
35
  import { createSSEStream } from '../../transport/sse-writer'
36
36
  import { getEventBus } from '../../transport/event-bus'
37
+ import { publishSessionEvent } from '../../services/transport'
37
38
 
38
39
  const app = new Hono()
39
40
 
@@ -286,6 +287,26 @@ app.get('/sessions/:id/history', sessionAuth, async c => {
286
287
  const events = [...byId.values()].sort(
287
288
  (a, b) => a.createdAt - b.createdAt || a.seqNum - b.seqNum,
288
289
  )
290
+ // models_state fallback: the worker reports the model list once per bridge
291
+ // connect, so the event log can legitimately lack it (/clear before the
292
+ // re-seed existed, event-window eviction, pre-persistence servers). The
293
+ // bus keeps the latest snapshot out-of-band — merge it here so the web UI
294
+ // can restore the model selector on every re-entry.
295
+ if (!events.some(e => e.type === 'models_state')) {
296
+ const snapshot = getEventBus(sessionId).modelsStateSnapshot
297
+ if (snapshot) {
298
+ const lastCreated = events[events.length - 1]?.createdAt ?? Date.now()
299
+ events.push({
300
+ id: `models_state_snapshot_${sessionId}`,
301
+ sessionId,
302
+ seqNum: 0,
303
+ type: 'models_state',
304
+ payload: { models_state: snapshot },
305
+ direction: 'inbound',
306
+ createdAt: lastCreated + 1,
307
+ })
308
+ }
309
+ }
289
310
  return c.json({ events }, 200)
290
311
  })
291
312
 
@@ -344,6 +365,18 @@ app.post('/sessions/:id/clear', sessionAuth, async c => {
344
365
  },
345
366
  { transient: true },
346
367
  )
368
+ // Re-seed models_state from the bus snapshot. The worker only reports
369
+ // models_state once per bridge connect, so a plain history wipe would make
370
+ // the model selector permanently gray after re-entering the session (and
371
+ // /model would report "未提供模型选择能力") until the worker reconnects.
372
+ if (bus.modelsStateSnapshot) {
373
+ publishSessionEvent(
374
+ sessionId,
375
+ 'models_state',
376
+ { type: 'models_state', models_state: bus.modelsStateSnapshot },
377
+ 'inbound',
378
+ )
379
+ }
347
380
  log(`[RCS] Cleared conversation history for session ${sessionId}`)
348
381
  return c.json({ status: 'ok' }, 200)
349
382
  })
@@ -169,6 +169,18 @@ export function publishSessionEvent(
169
169
  const bus = getEventBus(sessionId)
170
170
  const eventId = randomUUID()
171
171
 
172
+ // models_state is a one-shot snapshot from the worker (sent on bridge
173
+ // connect, never re-sent during the worker's lifetime). Keep the latest
174
+ // payload on the bus so /clear re-seeding and /history fallback can
175
+ // restore the web UI's model selector even after the event log lost the
176
+ // original entry.
177
+ if (type === 'models_state' && payload && typeof payload === 'object') {
178
+ const state = (payload as Record<string, unknown>).models_state
179
+ if (state && typeof state === 'object') {
180
+ bus.modelsStateSnapshot = state as Record<string, unknown>
181
+ }
182
+ }
183
+
172
184
  const normalized = normalizePayload(type, payload)
173
185
  const transient = TRANSIENT_EVENT_TYPES.has(type)
174
186
 
@@ -30,6 +30,31 @@ export class EventBus {
30
30
  MAX_SEEN_UUIDS_PER_BUS,
31
31
  )
32
32
  private seenUuidWriteIdx = 0
33
+ /**
34
+ * Latest models_state payload for the session, kept OUT of the retained
35
+ * event window. The worker reports models_state only once per bridge
36
+ * connect, while the event log is mutable (/clear wipes it, the bounded
37
+ * window evicts old entries) — without this snapshot any log loss makes
38
+ * the web UI's model selector permanently gray until the worker
39
+ * reconnects. Lives on the bus so it is dropped when the session is
40
+ * deleted (removeEventBus) and survives clearHistory().
41
+ */
42
+ modelsStateSnapshot: Record<string, unknown> | null = null
43
+ /**
44
+ * Turn-signal for status derivation (ws-handler.ts / worker-events.ts /
45
+ * control.ts): `true` while a turn is in progress (set by user events),
46
+ * `false` once it ends (result / result_success / interrupt).
47
+ *
48
+ * The REPL bridge's write paths are not strictly ordered — the synthetic
49
+ * turn-end result can be POSTed BEFORE the final mirrored assistant
50
+ * message (transcript-mirror render race, flush-gate bypass). Deriving
51
+ * `running` from such a late assistant flips the session back to running
52
+ * AFTER the turn ended, so the web UI input stays engaged and every new
53
+ * message lands in the queue instead of being sent. `false` by default:
54
+ * an assistant arriving with no user signal in flight belongs to an
55
+ * already-ended turn.
56
+ */
57
+ turnActive = false
33
58
 
34
59
  subscribe(callback: Subscriber): () => void {
35
60
  this.subscribers.add(callback)
@@ -342,13 +342,26 @@ export function ingestBridgeMessage(
342
342
  // assistant → running (LLM streaming). Skip when the session isn't in the
343
343
  // store (test fixtures) or status is already the target so streaming
344
344
  // assistant chunks don't spam session_status events.
345
+ //
346
+ // Turn-signal accounting (EventBus.turnActive): the REPL bridge can POST
347
+ // the synthetic turn-end result BEFORE the final mirrored assistant
348
+ // message (transcript-mirror render race in useReplBridge / flush-gate
349
+ // bypass in replBridge.writeMessages). A late assistant must not flip
350
+ // the session back to running after the turn ended — the web UI input
351
+ // would re-engage and every new message would land in the queue.
352
+ const bus = getEventBus(sessionId)
353
+ if (eventType === 'user') {
354
+ bus.turnActive = true
355
+ } else if (eventType === 'result' || eventType === 'result_success') {
356
+ bus.turnActive = false
357
+ }
345
358
  const session = getSession(sessionId)
346
359
  const targetStatus =
347
360
  eventType === 'result' || eventType === 'result_success'
348
361
  ? 'idle'
349
362
  : eventType === 'control_request'
350
363
  ? 'requires_action'
351
- : eventType === 'assistant'
364
+ : eventType === 'assistant' && bus.turnActive
352
365
  ? 'running'
353
366
  : null
354
367
  if (session && targetStatus && session.status !== targetStatus) {
@@ -1 +1 @@
1
- import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{ak as c,al as o,J as m,af as s,a8 as l,x as u}from"./main-CwLwGVDc.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{ak as c,al as o,J as m,af as s,a8 as l,x as u}from"./main-N3GYCdLF.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 +1 @@
1
- import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{E as u,J as f}from"./main-CwLwGVDc.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,J as f}from"./main-N3GYCdLF.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 o}from"./vendor-DE_-CLIE.js";import{a5 as O,a4 as _,al as E,aj as T,x as F,ak as L,af as a,a8 as A,q as $,s as W,e as H,r as V,d as P,ab as q,G,J,K,I as R}from"./main-CwLwGVDc.js";import{g as D}from"./workerType-Bd-zteMi.js";import{S as U,D as Z,a as z,c as Q,d as X,b as Y}from"./SessionVisibilityBadge-Dy4FwTzo.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";/**
1
+ import{j as e,e as o}from"./vendor-DE_-CLIE.js";import{a5 as O,a4 as _,al as E,aj as T,x as F,ak as L,af as a,a8 as A,q as $,s as W,e as H,r as V,d as P,ab as q,G,J,K,I as R}from"./main-N3GYCdLF.js";import{g as D}from"./workerType-Bd-zteMi.js";import{S as U,D as Z,a as z,c as Q,d as X,b as Y}from"./SessionVisibilityBadge-91WyR9K6.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{aj as v,af as t}from"./main-CwLwGVDc.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function E({onSuccess:b,onInvalidInvite:l}){const{join:f}=v(),[u,h]=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?h(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 f(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{aj as v,af as t}from"./main-N3GYCdLF.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function E({onSuccess:b,onInvalidInvite:l}){const{join:f}=v(),[u,h]=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?h(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 f(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 +1 @@
1
- import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{aj as f,af as t}from"./main-CwLwGVDc.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function N({onSuccess:d,onNavigateRegister:c}){const{login:m,registrationAllowed:x}=f(),[a,p]=r.useState(""),[o,b]=r.useState(""),[l,n]=r.useState(""),[i,u]=r.useState(!1),h=async s=>{s.preventDefault(),n(""),u(!0);try{await m(a,o),d()}catch{n(t("auth.login.failed"))}finally{u(!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:h,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:a,onChange:s=>p(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=>b(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"})]}),l&&e.jsx("p",{className:"text-sm text-status-error",children:l}),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{N as Login};
1
+ import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{aj as f,af as t}from"./main-N3GYCdLF.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function N({onSuccess:d,onNavigateRegister:c}){const{login:m,registrationAllowed:x}=f(),[a,p]=r.useState(""),[o,b]=r.useState(""),[l,n]=r.useState(""),[i,u]=r.useState(!1),h=async s=>{s.preventDefault(),n(""),u(!0);try{await m(a,o),d()}catch{n(t("auth.login.failed"))}finally{u(!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:h,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:a,onChange:s=>p(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=>b(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"})]}),l&&e.jsx("p",{className:"text-sm text-status-error",children:l}),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{N as Login};
@@ -1 +1 @@
1
- import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{aj as y,af as t}from"./main-CwLwGVDc.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{aj as y,af as t}from"./main-N3GYCdLF.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};