lookatstudy-mobile 0.30.0 → 0.31.0

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 (151) hide show
  1. package/package.json +1 -1
  2. package/server.cjs +1439 -559
  3. package/web/assets/{CanvasStage-CCg0mR3C.js → CanvasStage-Cyt4NB7v.js} +1 -1
  4. package/web/assets/{CommandPalette-R5Ao1bZa.js → CommandPalette-maHlqYwL.js} +1 -1
  5. package/web/assets/CompanionBotLab-BjbCeiRW.js +8 -0
  6. package/web/assets/{CourseSearchPanel-ZiNMRYeo.js → CourseSearchPanel-wyjGWBGr.js} +1 -1
  7. package/web/assets/{ExamView-DiBjtPlN.js → ExamView-BoGgfcwj.js} +1 -1
  8. package/web/assets/{ReviewPanel-BS8bsZT9.js → ReviewPanel-BxY2T_Ut.js} +1 -1
  9. package/web/assets/SettingsView-CdxkxEkP.js +10 -0
  10. package/web/assets/{VoicePanel-BPABzLLX.js → VoicePanel-BzRCM6vH.js} +1 -1
  11. package/web/assets/{abnfDiagram-N423BO3Z-D3qEZ3wx.js → abnfDiagram-N423BO3Z-iXwATPSN.js} +1 -1
  12. package/web/assets/{abnfDiagram-VCTEODGH-ODA7YWAP-BBQ0ZYnF.js → abnfDiagram-VCTEODGH-ODA7YWAP-C1yAT6qh.js} +1 -1
  13. package/web/assets/alien-body-DXq5WJRs.png +0 -0
  14. package/web/assets/alien-happy-Ci3JfpxD.png +0 -0
  15. package/web/assets/alien-head-CS10QxqG.png +0 -0
  16. package/web/assets/alien-idle-D2VKjYsl.png +0 -0
  17. package/web/assets/alien-keyL-C_tZriGQ.png +0 -0
  18. package/web/assets/alien-thinking-gWKA2xDz.png +0 -0
  19. package/web/assets/api-web-BCzlfr07.js +1 -0
  20. package/web/assets/{architectureDiagram-5GKGNRK7-C4PU3XN7-BcPfzHrO.js → architectureDiagram-5GKGNRK7-C4PU3XN7-NvY1Ic-5.js} +1 -1
  21. package/web/assets/{architectureDiagram-T3A2C74G-BetPhhJ_.js → architectureDiagram-T3A2C74G-DwrvQJhj.js} +1 -1
  22. package/web/assets/{arrow-right-BW9yawWu.js → arrow-right-33rr0pBZ.js} +1 -1
  23. package/web/assets/{blockDiagram-NRAW4CY4-UMJ6PMQQ-DZDS1Qrk.js → blockDiagram-NRAW4CY4-UMJ6PMQQ-DsNh9SAm.js} +1 -1
  24. package/web/assets/{blockDiagram-VBNYF7ZC-CwbzWh4u.js → blockDiagram-VBNYF7ZC-BX4qMKoE.js} +1 -1
  25. package/web/assets/{c4Diagram-5PPSVZJV-CuoQiYnK.js → c4Diagram-5PPSVZJV-wjiwvuPV.js} +1 -1
  26. package/web/assets/{c4Diagram-UCG6FXSJ-75X3U2P3-MNKifmBN.js → c4Diagram-UCG6FXSJ-75X3U2P3-Df4YtSzV.js} +1 -1
  27. package/web/assets/channel-D9baWZnV.js +1 -0
  28. package/web/assets/{chunk-2GRJ4B5K-MGdPJJSz.js → chunk-2GRJ4B5K-BqUg5toN.js} +1 -1
  29. package/web/assets/{chunk-2Q5K7J3B-C7xrI1z5.js → chunk-2Q5K7J3B-D2YxB7H3.js} +1 -1
  30. package/web/assets/{chunk-5RXB4S5H-q7_wbM5v.js → chunk-5RXB4S5H-zfO8batT.js} +1 -1
  31. package/web/assets/{chunk-5VM5RSS4-DGzhNwYE.js → chunk-5VM5RSS4-CdfFIz--.js} +1 -1
  32. package/web/assets/{chunk-6Q2QTUOP-Bnx3pMW2.js → chunk-6Q2QTUOP-c0FQ_SfU.js} +1 -1
  33. package/web/assets/{chunk-7XDTSPCN-BpaSrByV.js → chunk-7XDTSPCN-BBCpJUAH.js} +1 -1
  34. package/web/assets/{chunk-CTNIYPP6-D_psz8OE.js → chunk-CTNIYPP6-DW2rJhu_.js} +1 -1
  35. package/web/assets/{chunk-CXNFBKHE-B3NrBrh5.js → chunk-CXNFBKHE-renpw2QE.js} +1 -1
  36. package/web/assets/{chunk-GF5L2VYU-DH4Xjup-.js → chunk-GF5L2VYU-DiF8ZWcT.js} +1 -1
  37. package/web/assets/{chunk-ISA7TJRJ-BWhRpuJG.js → chunk-ISA7TJRJ-DhN-xjNX.js} +1 -1
  38. package/web/assets/{chunk-JWPE2WC7-Q9MkO98l.js → chunk-JWPE2WC7-smESCI0k.js} +1 -1
  39. package/web/assets/{chunk-KBJHAD2P-BnDJz0cn.js → chunk-KBJHAD2P-CLazgX1V.js} +1 -1
  40. package/web/assets/{chunk-LV3HUYFY-BFhZlxBi.js → chunk-LV3HUYFY-DTGGOw_N.js} +1 -1
  41. package/web/assets/{chunk-M3IUQBOH-CAPsa3nq.js → chunk-M3IUQBOH-Cp2xYH3K.js} +1 -1
  42. package/web/assets/{chunk-NDIOYS4C-DKs52SAc.js → chunk-NDIOYS4C-B_iYUPk5.js} +1 -1
  43. package/web/assets/{chunk-RE4WF27V-BzaQ0kW3.js → chunk-RE4WF27V-DFrNGxeZ.js} +1 -1
  44. package/web/assets/{chunk-RYQCIY6F-DB7ZT0W5.js → chunk-RYQCIY6F-CXmfoCP1.js} +1 -1
  45. package/web/assets/{chunk-VII2H2IX-efS7Zm4t.js → chunk-VII2H2IX-CTIhHlIp.js} +1 -1
  46. package/web/assets/{chunk-X5GNSKZ3-DYokAkhB.js → chunk-X5GNSKZ3-BnL2P09p.js} +1 -1
  47. package/web/assets/{chunk-XCWWM2C3-1jGJbVyZ.js → chunk-XCWWM2C3-B3diWYxV.js} +1 -1
  48. package/web/assets/{chunk-XXDRQBXY-BawDkI_V.js → chunk-XXDRQBXY-Cm9DsbCI.js} +1 -1
  49. package/web/assets/classDiagram-DTDB5LWJ-LWRDKZ5K-CiuZ0TyW.js +1 -0
  50. package/web/assets/classDiagram-JCYQIIEL-DJMqLmfy.js +1 -0
  51. package/web/assets/classDiagram-v2-JRS7N3AN-2BZHGRP2-CiuZ0TyW.js +1 -0
  52. package/web/assets/classDiagram-v2-OCEON4UE-DJMqLmfy.js +1 -0
  53. package/web/assets/{core-a88hYP2v.js → core-CnhTLa0G.js} +1 -1
  54. package/web/assets/{cose-bilkent-JH36ORCC-Jl-SkPuF.js → cose-bilkent-JH36ORCC-B1ZJcbUV.js} +1 -1
  55. package/web/assets/{cose-bilkent-JH36ORCC-OB24KH3T-CrbHDK16.js → cose-bilkent-JH36ORCC-OB24KH3T-BJpRu0cc.js} +1 -1
  56. package/web/assets/{cynefin-OW5HDTMX-GVF3BKWE-B-NBQ_17.js → cynefin-OW5HDTMX-GVF3BKWE-CLl32jOg.js} +1 -1
  57. package/web/assets/{cynefin-VYW2F7L2-BjNU-j_h.js → cynefin-VYW2F7L2-BFZHy-wK.js} +1 -1
  58. package/web/assets/{cynefinDiagram-5FMLGOSQ-H3WIRU3N-C9I0D50W.js → cynefinDiagram-5FMLGOSQ-H3WIRU3N-BpmHF9Wo.js} +1 -1
  59. package/web/assets/{cynefinDiagram-MW4NZA55-B7Vbl8wF.js → cynefinDiagram-MW4NZA55-BECq_tlH.js} +1 -1
  60. package/web/assets/{dagre-3AP2YEHR-DCERTXHT-BDRZvdKj.js → dagre-3AP2YEHR-DCERTXHT-DIUrMTsj.js} +1 -1
  61. package/web/assets/{dagre-VZM6K2ZE-DBJln4b_.js → dagre-VZM6K2ZE-D-oITinM.js} +1 -1
  62. package/web/assets/{diagram-7IWD3JNH-Dn2grKMm.js → diagram-7IWD3JNH-07yeFgf1.js} +1 -1
  63. package/web/assets/{diagram-B4RE2ZJO-C7Vyc_yD.js → diagram-B4RE2ZJO-dNtQBNGN.js} +1 -1
  64. package/web/assets/{diagram-LBJQPF4R-CmaGFdAR.js → diagram-LBJQPF4R-BoiQEUHl.js} +1 -1
  65. package/web/assets/{diagram-Q27KOJAE-C-p9KRf2.js → diagram-Q27KOJAE-Bi0oJVBH.js} +1 -1
  66. package/web/assets/{diagram-S7CK7UJ4-MULGZGEL-Uwc94dO5.js → diagram-S7CK7UJ4-MULGZGEL-Bpt08-bP.js} +1 -1
  67. package/web/assets/{diagram-UB23O5K3-BeBC1pLd.js → diagram-UB23O5K3-FLVFr6Cc.js} +1 -1
  68. package/web/assets/{diagram-UQ7AKVKN-YQBY353J-DpKpMQdr.js → diagram-UQ7AKVKN-YQBY353J-DORAQMoA.js} +1 -1
  69. package/web/assets/{diagram-VSXAHHWV-WLNH2ELY-BvnZVqDy.js → diagram-VSXAHHWV-WLNH2ELY-Ce82dDi6.js} +1 -1
  70. package/web/assets/{diagram-VX7I27RA-XW6YQV5G-CRLosetY.js → diagram-VX7I27RA-XW6YQV5G-D-fdo9DM.js} +1 -1
  71. package/web/assets/{diagram-Z3DM3KII-HG7RF65D-CDhznfkR.js → diagram-Z3DM3KII-HG7RF65D-ZqMt25Js.js} +1 -1
  72. package/web/assets/{ebnfDiagram-BXEA7PRR-ClYHHpf3.js → ebnfDiagram-BXEA7PRR-R3UwRAR7.js} +1 -1
  73. package/web/assets/{ebnfDiagram-PWID7BFC-OKY4VHYD-SCAzhJFX.js → ebnfDiagram-PWID7BFC-OKY4VHYD-DDVM1P1I.js} +1 -1
  74. package/web/assets/{elk.bundled-COEZiBRU.js → elk.bundled-Dv5OJ-BO.js} +1 -1
  75. package/web/assets/{erDiagram-JOGREHBK-CQtxmkXJ.js → erDiagram-JOGREHBK-Dr_g_g8q.js} +1 -1
  76. package/web/assets/{erDiagram-SSCWMZ5O-PIPKOIK7-Cic-rvYb.js → erDiagram-SSCWMZ5O-PIPKOIK7-CxTLMFn2.js} +1 -1
  77. package/web/assets/{flowDiagram-A5DVABFB-2Z4AVO5R-Buf1q55B.js → flowDiagram-A5DVABFB-2Z4AVO5R-DRUX3zZ5.js} +1 -1
  78. package/web/assets/{flowDiagram-UKHOOZJN-DTNxUKXJ.js → flowDiagram-UKHOOZJN-BEX6wJhw.js} +1 -1
  79. package/web/assets/{ganttDiagram-EL5Y4UJY-JZNG7GOG-4j9UxRRI.js → ganttDiagram-EL5Y4UJY-JZNG7GOG-DjG0obYU.js} +1 -1
  80. package/web/assets/{ganttDiagram-PKOTCBZU-Cch79h3b.js → ganttDiagram-PKOTCBZU-D-5FV0PV.js} +1 -1
  81. package/web/assets/{gitGraphDiagram-DS77QQ5N-CE7GRTAT.js → gitGraphDiagram-DS77QQ5N-DF-LawNi.js} +1 -1
  82. package/web/assets/{gitGraphDiagram-WWUBYQGX-DMWMLL3G-DEY2TMGz.js → gitGraphDiagram-WWUBYQGX-DMWMLL3G-D70uly9x.js} +1 -1
  83. package/web/assets/{index-auPs2wIW.js → index-CApU5KjU.js} +1 -1
  84. package/web/assets/index-CvvLDKMx.css +1 -0
  85. package/web/assets/index-DZN4z5wF.js +53 -0
  86. package/web/assets/{index-Cq6cgm2q.js → index-DawWPxKA.js} +4 -4
  87. package/web/assets/{index-Cid4nWeb.js → index-X3hjUtR3.js} +2 -2
  88. package/web/assets/{infoDiagram-6WML65LV-CLqRvjN1.js → infoDiagram-6WML65LV-w8kz4hEa.js} +1 -1
  89. package/web/assets/{infoDiagram-RXCK75RN-HANS5KVC-B-gCpjUC.js → infoDiagram-RXCK75RN-HANS5KVC-C1PHC-YD.js} +1 -1
  90. package/web/assets/{ishikawaDiagram-5VMMS53U-7GCIT7WU-Bsci7xnu.js → ishikawaDiagram-5VMMS53U-7GCIT7WU-BrPFk2Ox.js} +1 -1
  91. package/web/assets/{ishikawaDiagram-WSZJBQD7-Br8hddHM.js → ishikawaDiagram-WSZJBQD7-C34Z0ADb.js} +1 -1
  92. package/web/assets/{journeyDiagram-EYS64GPL-OAPELBT7-C3S3QJ0n.js → journeyDiagram-EYS64GPL-OAPELBT7-CVn7FA19.js} +1 -1
  93. package/web/assets/{journeyDiagram-NVQOT4AX-q7oxzffp.js → journeyDiagram-NVQOT4AX-B6wtGi4C.js} +1 -1
  94. package/web/assets/{kanban-definition-27J2QSJJ-Dx7aMk7V.js → kanban-definition-27J2QSJJ-Cauno8t4.js} +1 -1
  95. package/web/assets/{kanban-definition-3QL26DDD-I7RKWQQY-DNpRVVuU.js → kanban-definition-3QL26DDD-I7RKWQQY-DSkHnZWn.js} +1 -1
  96. package/web/assets/{katex-N6JRN4PM-DUn2v_Up.js → katex-N6JRN4PM-7jQy_F2_.js} +1 -1
  97. package/web/assets/{main-BbOwLoeH.js → main-CmJlqSDk.js} +130 -106
  98. package/web/assets/{mermaid-layout-elk.core-hmulpQUA.js → mermaid-layout-elk.core-h_IjwDpP.js} +2 -2
  99. package/web/assets/{mermaid.core-DUsXuPYV.js → mermaid.core-n1vgOa_E.js} +4 -4
  100. package/web/assets/{mindmap-definition-FAOFIHXS-HsDwfUOG.js → mindmap-definition-FAOFIHXS-oc1QsLGD.js} +1 -1
  101. package/web/assets/{mindmap-definition-FBJOCRG2-KIYZG64Y-DMlLaIf9.js → mindmap-definition-FBJOCRG2-KIYZG64Y-De94GIvB.js} +1 -1
  102. package/web/assets/{pegDiagram-VL7TDLO6-B_CQxksA.js → pegDiagram-VL7TDLO6-C9eNGZDr.js} +1 -1
  103. package/web/assets/{pegDiagram-XKGWAZYB-OIP57N6J-CwSsFCw4.js → pegDiagram-XKGWAZYB-OIP57N6J-C2k8WABX.js} +1 -1
  104. package/web/assets/{pet-BqoPCJEd.js → pet-D6jEJc1f.js} +1 -1
  105. package/web/assets/{pieDiagram-7S7Q4E2Y-Dz7YO9kD.js → pieDiagram-7S7Q4E2Y-lAjmXNe_.js} +1 -1
  106. package/web/assets/{pieDiagram-E7YTZNPT-2UOTW327-DcGAFS18.js → pieDiagram-E7YTZNPT-2UOTW327-h1VN7kXL.js} +1 -1
  107. package/web/assets/{quadrantDiagram-AXDQQJYC-SN3ASJJK-CoF5reED.js → quadrantDiagram-AXDQQJYC-SN3ASJJK-CVllGfdW.js} +1 -1
  108. package/web/assets/{quadrantDiagram-CIZ2JOQS-C6bWSZMA.js → quadrantDiagram-CIZ2JOQS-B0NfwoFD.js} +1 -1
  109. package/web/assets/{railroadDiagram-AXF67PYL-_W8MikWh.js → railroadDiagram-AXF67PYL-BiLISELA.js} +1 -1
  110. package/web/assets/{railroadDiagram-O6MQD6OU-34742W6X-Lt-SXGEJ.js → railroadDiagram-O6MQD6OU-34742W6X-CqYqMw2v.js} +1 -1
  111. package/web/assets/{render-O7CIS3YK-DiJ-EmQM.js → render-O7CIS3YK-C1DYXW0Z.js} +7 -7
  112. package/web/assets/{requirementDiagram-EFPCY7ZU-NGAFFSMB-BludraKW.js → requirementDiagram-EFPCY7ZU-NGAFFSMB-6i5RYobc.js} +1 -1
  113. package/web/assets/{requirementDiagram-LRYGKXZP-SrMwv2X8.js → requirementDiagram-LRYGKXZP-BMUGWzen.js} +1 -1
  114. package/web/assets/{rotate-ccw-D1vRxSpM.js → rotate-ccw-DhViz0iw.js} +1 -1
  115. package/web/assets/{sankeyDiagram-P5KCCOFB-3D3M4XPB-BlzAtbTK.js → sankeyDiagram-P5KCCOFB-3D3M4XPB-EtCUQUn1.js} +1 -1
  116. package/web/assets/{sankeyDiagram-W5VNT64P-DdLeFYgz.js → sankeyDiagram-W5VNT64P-C_r4P5MM.js} +1 -1
  117. package/web/assets/{sequenceDiagram-SI44F4Z6-BcQQ0nzP.js → sequenceDiagram-SI44F4Z6-pG01U8Cr.js} +1 -1
  118. package/web/assets/{sequenceDiagram-WJ2MYXX4-Q2IOPB4R-CEylu1jV.js → sequenceDiagram-WJ2MYXX4-Q2IOPB4R-sL3lWU4l.js} +1 -1
  119. package/web/assets/{sizeCapture-X5ZJPWSS-PSGVOMYM-DvxYnTjx.js → sizeCapture-X5ZJPWSS-PSGVOMYM-VHssc8WH.js} +1 -1
  120. package/web/assets/{sizeCapture-X5ZJPWSS-DMJpw6x4.js → sizeCapture-X5ZJPWSS-TfK3b41W.js} +1 -1
  121. package/web/assets/{stateDiagram-HBIQ2CUA-4M2S6MAN-p_Muo_9t.js → stateDiagram-HBIQ2CUA-4M2S6MAN-DY0svUZL.js} +1 -1
  122. package/web/assets/{stateDiagram-OKZ733FA-B0IjuFEV.js → stateDiagram-OKZ733FA-CHPWqFKU.js} +1 -1
  123. package/web/assets/stateDiagram-v2-4QOOHH4V-LBBLA2WV-B2GuWRPu.js +1 -0
  124. package/web/assets/stateDiagram-v2-UEYNNEHI-mdLp8HQQ.js +1 -0
  125. package/web/assets/{swimlanes-SLNWSIFB-BODuryXb.js → swimlanes-SLNWSIFB-BoK2wZ7r.js} +2 -2
  126. package/web/assets/{swimlanes-XN3QIQJK-N6N2CCQ6-CTQ-daQG.js → swimlanes-XN3QIQJK-N6N2CCQ6-tXCXpXUD.js} +1 -1
  127. package/web/assets/swimlanesDiagram-ULZ7WXOC-CI3RFQDZ.js +8 -0
  128. package/web/assets/swimlanesDiagram-VK2B7HYN-E6N4H5SY-DLkFvd5d.js +8 -0
  129. package/web/assets/{timeline-definition-24CTP7MA-KN7RSRVM-O8Yphry8.js → timeline-definition-24CTP7MA-KN7RSRVM-uhQqtZRP.js} +1 -1
  130. package/web/assets/{timeline-definition-Z64GVDOM-CXw6-4p3.js → timeline-definition-Z64GVDOM-BID9BJj_.js} +1 -1
  131. package/web/assets/{vennDiagram-4TSXK5OY-AKJ7LXAN-B4C2KaX_.js → vennDiagram-4TSXK5OY-AKJ7LXAN-MJEMZHM_.js} +1 -1
  132. package/web/assets/{vennDiagram-T6HMQDX7-Cscv288S.js → vennDiagram-T6HMQDX7-noYkNxPf.js} +1 -1
  133. package/web/assets/{wardleyDiagram-T6FBY63Y-C6LZlU6j.js → wardleyDiagram-T6FBY63Y-CnUMOnEG.js} +1 -1
  134. package/web/assets/{wardleyDiagram-VM6X3IG4-3B6A3BN5-DC6vVvzB.js → wardleyDiagram-VM6X3IG4-3B6A3BN5-D_oZuxaD.js} +1 -1
  135. package/web/assets/{xychartDiagram-ELKLHX3M-DZ07gv7H.js → xychartDiagram-ELKLHX3M-Ck_2zrW5.js} +1 -1
  136. package/web/assets/{xychartDiagram-S5SC5T6Z-OBDNV6WG-Bj6wGGRd.js → xychartDiagram-S5SC5T6Z-OBDNV6WG-Cd6y2GuD.js} +1 -1
  137. package/web/index.html +3 -3
  138. package/web/pet.html +3 -3
  139. package/web/assets/SettingsView-DtRypHxS.js +0 -7
  140. package/web/assets/api-web-BUHi8j_m.js +0 -1
  141. package/web/assets/channel-C4o9Ykyf.js +0 -1
  142. package/web/assets/classDiagram-DTDB5LWJ-LWRDKZ5K-DqD8T9BT.js +0 -1
  143. package/web/assets/classDiagram-JCYQIIEL-BHZwOJ3M.js +0 -1
  144. package/web/assets/classDiagram-v2-JRS7N3AN-2BZHGRP2-DqD8T9BT.js +0 -1
  145. package/web/assets/classDiagram-v2-OCEON4UE-BHZwOJ3M.js +0 -1
  146. package/web/assets/index-BlYQ3CxE.css +0 -1
  147. package/web/assets/index-DjO1zEnx.js +0 -53
  148. package/web/assets/stateDiagram-v2-4QOOHH4V-LBBLA2WV-D1Y1O6zn.js +0 -1
  149. package/web/assets/stateDiagram-v2-UEYNNEHI-SKGW5UQZ.js +0 -1
  150. package/web/assets/swimlanesDiagram-ULZ7WXOC-C0vv9__D.js +0 -8
  151. package/web/assets/swimlanesDiagram-VK2B7HYN-E6N4H5SY-DGgs8WcV.js +0 -8
@@ -1,4 +1,4 @@
1
- import{r,j as h}from"./index-DjO1zEnx.js";import{c as T,u as L,P as D}from"./main-BbOwLoeH.js";/**
1
+ import{r,j as h}from"./index-DZN4z5wF.js";import{c as T,u as L,P as D}from"./main-CmJlqSDk.js";/**
2
2
  * @license lucide-react v0.468.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{r as s,j as t}from"./index-DjO1zEnx.js";import{c as y,u as v,b as k,L as j,F as N,M as w,G as C,T as M,d as _}from"./main-BbOwLoeH.js";/**
1
+ import{r as s,j as t}from"./index-DZN4z5wF.js";import{c as y,u as v,b as k,L as j,F as N,M as w,G as C,T as M,d as _}from"./main-CmJlqSDk.js";/**
2
2
  * @license lucide-react v0.468.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -0,0 +1,8 @@
1
+ import{u as G,r as v,j as c,o as ie,n as ce,c as le}from"./index-DZN4z5wF.js";function A(e,t){return{code:e,message:t}}function me(e,t={}){const n=t.minSide??256,u=t.maxSide??4096,i=t.marginRatio??.02,o=t.alphaThreshold??128,r=t.minBlobAreaRatio??.05,h=t.maxSamples??1e6,l=[],g=(s,p=0,w=0)=>({ok:!1,issues:s.map(([T,C])=>A(T,C)),opaqueRatio:p,blobCount:w}),{width:a,height:m,rgba:b}=e;if(!Number.isFinite(a)||!Number.isFinite(m)||a<=0||m<=0||!Number.isInteger(a)||!Number.isInteger(m))return g([["BAD_DIMENSIONS",`非法尺寸 ${a}x${m}`]]);if(Math.min(a,m)<n&&l.push(A("TOO_SMALL",`短边 ${Math.min(a,m)}px < ${n}px`)),Math.max(a,m)>u&&l.push(A("TOO_LARGE",`长边 ${Math.max(a,m)}px > ${u}px(导入时自动缩放)`)),!b||b.length!==a*m*4)return l.push(A("BAD_PIXEL_BUFFER",`rgba 长度 ${(b==null?void 0:b.length)??0} ≠ ${a}*${m}*4`)),{ok:!1,issues:l,opaqueRatio:0,blobCount:0};const x=Math.max(1,Math.ceil(Math.sqrt(a*m/h))),d=Math.floor((a-1)/x)+1,f=Math.floor((m-1)/x)+1,y=new Uint8Array(d*f);let L=0,M=0,N=255,S=d,R=-1,k=f,Y=-1;for(let s=0;s<f;s++){const p=s*x;for(let w=0;w<d;w++){const T=w*x,C=b[(p*a+T)*4+3];M++,C<N&&(N=C),C>=o&&(y[s*d+w]=1,L++,w<S&&(S=w),w>R&&(R=w),s<k&&(k=s),s>Y&&(Y=s))}}const J=M>0?L/M:0;if(L===0)return l.push(A("ALL_TRANSPARENT","整图无不透明像素(空图/坏抠图)")),{ok:l.length===0,issues:l,opaqueRatio:J,blobCount:0};if(N===255&&l.push(A("NO_ALPHA","未检出任何透明像素——需要透明底 PNG(可一键抠图/豆包抠图)")),S===0||k===0||R===d-1||Y===f-1){const s=a*i,p=m*i;(S*x<s||k*x<p||R*x+x-1>a-1-s||Y*x+x-1>m-1-p)&&l.push(A("EDGE_TOUCH","主体贴边——四周留 5~10% 空白,给跳跃/挤压变换留余地"))}const _=new Uint8Array(d*f),B=[],$=[];for(let s=0;s<y.length;s++){if(!y[s]||_[s])continue;let p=0,w=d,T=-1,C=f,O=-1;for($.push(s),_[s]=1;$.length>0;){const E=$.pop();p++;const P=E%d,X=(E-P)/d;P<w&&(w=P),P>T&&(T=P),X<C&&(C=X),X>O&&(O=X);const D=I=>{y[I]&&!_[I]&&(_[I]=1,$.push(I))};P>0&&D(E-1),P<d-1&&D(E+1),X>0&&D(E-d),X<f-1&&D(E+d)}B.push({area:p,minX:w,maxX:T,minY:C,maxY:O})}const se=B.length>0?Math.max(...B.map(s=>s.area)):0,Z=B.filter(s=>s.area>=se*r),re=(s,p)=>s.minX>=p.minX&&s.maxX<=p.maxX&&s.minY>=p.minY&&s.maxY<=p.maxY,oe=(s,p)=>{const w=Math.min(s.maxX,p.maxX)-Math.max(s.minX,p.minX),T=Math.min(s.maxY,p.maxY)-Math.max(s.minY,p.minY);if(w<=0||T<=0)return 0;const C=w*T,O=(s.maxX-s.minX+1)*(s.maxY-s.minY+1),E=(p.maxX-p.minX+1)*(p.maxY-p.minY+1);return C/Math.min(O,E)},F=Z.filter(s=>!Z.some(p=>p!==s&&p.area>=s.area&&(re(s,p)||oe(s,p)>=.4))).length;return F>=2&&l.push(A("MULTI_BLOB",`检出 ${F} 个独立主体——请裁剪到单角色`)),{ok:l.length===0,issues:l,opaqueRatio:J,blobCount:F}}function de(e){return typeof e.poseHoldMs=="number"?e.poseHoldMs:1200}const ue=""+new URL("alien-idle-D2VKjYsl.png",import.meta.url).href,fe=""+new URL("alien-happy-Ci3JfpxD.png",import.meta.url).href,he=""+new URL("alien-thinking-gWKA2xDz.png",import.meta.url).href,pe=""+new URL("alien-keyL-C_tZriGQ.png",import.meta.url).href,xe=""+new URL("alien-keyL-C_tZriGQ.png",import.meta.url).href,z=""+new URL("alien-head-CS10QxqG.png",import.meta.url).href,be=""+new URL("alien-body-DXq5WJRs.png",import.meta.url).href,j={head:{x:.3,y:.05,w:.4,h:.2726},body:{x:.3,y:.3226,w:.4,h:.2841}},ee={x:.5,y:.3226},ye={formatVersion:1,id:"lab-alien",name:"Lab 小宇航员(Kenney)",author:"Kenney",license:"CC0-1.0 (Kenney Platformer Characters)",tier:"bongo",states:{idle:"idle.png",keyL:"keyl.png",keyR:"keyr.png",happy:"happy.png",thinking:"thinking.png"},poseHoldMs:1100};async function ge(){const e={idle:ue,keyL:pe,keyR:xe,happy:fe,thinking:he},t=await we(z),n=document.createElement("canvas");n.width=512,n.height=512;const u=n.getContext("2d");u.drawImage(t,0,0);const i=u.getImageData(0,0,512,512),o=me({width:512,height:512,rgba:i.data});return{srcs:e,parts:{head:z,body:be},selfSpec:o}}function we(e){return new Promise((t,n)=>{const u=new Image;u.onload=()=>t(u),u.onerror=()=>n(new Error(`image load failed: ${e}`)),u.src=e})}function te(e,t,n){const{x:u,y:i,w:o,h:r,t:h,deform:l}=n,g=n.cols??6,a=n.rows??8,m=n.src??{x:0,y:0,w:t.width,h:t.height},b=[];for(let d=0;d<=a;d++)for(let f=0;f<=g;f++){const y=f/g,L=d/a,M=l(y,L,h);b.push([u+y*o+M.dx,i+L*r+M.dy])}const x=(d,f)=>b[f*(g+1)+d];for(let d=0;d<a;d++)for(let f=0;f<g;f++){const y=x(f,d),L=x(f+1,d),M=x(f,d+1),N=x(f+1,d+1),S=m.x+f/g*m.w,R=m.y+d/a*m.h,k=m.x+(f+1)/g*m.w,Y=m.y+(d+1)/a*m.h;ne(e,t,[S,R],[k,R],[S,Y],y,L,M),ne(e,t,[k,R],[k,Y],[S,Y],L,N,M)}}function ne(e,t,n,u,i,o,r,h){const l=(u[0]-n[0])*(i[1]-n[1])-(i[0]-n[0])*(u[1]-n[1]);if(Math.abs(l)<1e-8)return;const g=((r[0]-o[0])*(i[1]-n[1])-(h[0]-o[0])*(u[1]-n[1]))/l,a=((h[0]-o[0])*(u[0]-n[0])-(r[0]-o[0])*(i[0]-n[0]))/l,m=((r[1]-o[1])*(i[1]-n[1])-(h[1]-o[1])*(u[1]-n[1]))/l,b=((h[1]-o[1])*(u[0]-n[0])-(r[1]-o[1])*(i[0]-n[0]))/l,x=o[0]-g*n[0]-a*n[1],d=o[1]-m*n[0]-b*n[1];e.save(),e.beginPath(),e.moveTo(o[0],o[1]),e.lineTo(r[0],r[1]),e.lineTo(h[0],h[1]),e.closePath(),e.clip(),e.transform(g,m,a,b,x,d),e.drawImage(t,0,0),e.restore()}function K(e){const t=v.useRef(e);t.current=e,v.useEffect(()=>{const n={side:1},u=r=>{if(r.repeat)return;const h=ce(r.code,n.side);n.side=n.side===1?-1:1,t.current(h===1?"keyR":"keyL")},i=r=>t.current(r.detail?"thinking":"idle"),o=ie(r=>t.current(r.kind==="wrong"?"wrong":"happy"));return window.addEventListener("keydown",u,{passive:!0}),window.addEventListener("companion-streaming",i),()=>{window.removeEventListener("keydown",u),window.removeEventListener("companion-streaming",i),o()}},[])}function H(){const[e,t]=v.useState("idle"),n=v.useRef(null),u=v.useCallback((i,o=0)=>{n.current!==null&&window.clearTimeout(n.current),n.current=null,t(i);const r=o>0?o:0;r>0&&i!=="idle"&&(n.current=window.setTimeout(()=>t("idle"),r))},[]);return v.useEffect(()=>()=>{n.current!==null&&window.clearTimeout(n.current)},[]),{pose:e,setTimed:u}}function Q(e,t){t||!e||typeof e.animate!="function"||e.animate([{transform:"translateY(0)"},{transform:"translateY(-12%)"},{transform:"translateY(2%)"},{transform:"translateY(0)"}],{duration:380,easing:"cubic-bezier(0.2, 1.4, 0.4, 1)"})}function V(e,t){t||!e||typeof e.animate!="function"||e.animate([{transform:"rotate(0deg)"},{transform:"rotate(-6deg)"},{transform:"rotate(6deg)"},{transform:"rotate(0deg)"}],{duration:280})}function q(e,t){t||!e||typeof e.animate!="function"||e.animate([{transform:"translateY(0px) scale(1, 1)"},{transform:"translateY(2.5px) scale(1.045, 0.93)",offset:.42},{transform:"translateY(0px) scale(1, 1)"}],{duration:185,easing:"ease-out",composite:"add"})}const W=`
2
+ .cbot { position: relative; display: inline-block; line-height: 0;
3
+ animation: cbot-breath 3.4s ease-in-out infinite; transform-origin: 50% 62%; }
4
+ .cbot img, .cbot canvas { display: block; user-select: none; }
5
+ .cbot-lite img { position: absolute; pointer-events: none; }
6
+ @keyframes cbot-breath { 0%, 100% { transform: scale(1, 1); } 50% { transform: scale(1.012, 1.03); } }
7
+ @media (prefers-reduced-motion: reduce) { .cbot { animation: none; } }
8
+ `;function ke({pack:e,size:t=128,label:n,poseOverride:u=null}){const i=G(),{pose:o,setTimed:r}=H(),h=v.useRef(null);K(a=>{a==="keyL"||a==="keyR"?(r(a,180),q(h.current,i)):a==="happy"?(r("happy",de(e.manifest)),Q(h.current,i)):a==="thinking"?r("thinking",0):a==="idle"?r("idle",0):V(h.current,i)});const l=u??o,g=e.srcs[l]??e.srcs.idle??"";return c.jsxs("div",{className:"cbot","data-companion-bot":e.manifest.tier,"data-bot-state":l,style:{width:t,height:t},children:[c.jsx("img",{ref:h,src:g,alt:n??e.manifest.name,width:t,height:t,draggable:!1}),c.jsx("style",{children:W})]})}const ae={left:0,top:0,width:"100%",height:"100%"};function je({parts:e,size:t=160,label:n,poseOverride:u=null}){const i=G(),{pose:o,setTimed:r}=H(),h=v.useRef(null),l=v.useRef(null);K(a=>{var b,x;const m=d=>{i||!l.current||typeof l.current.animate!="function"||l.current.animate([{transform:"rotate(0deg)"},{transform:`rotate(${d*10}deg)`,offset:.38},{transform:"rotate(0deg)"}],{duration:185,easing:"cubic-bezier(0.2, 1.5, 0.4, 1)",composite:"add"})};a==="keyL"?(r("keyL",185),m(-1),q(h.current,i)):a==="keyR"?(r("keyR",185),m(1),q(h.current,i)):a==="happy"?(r("happy",1100),Q(h.current,i)):a==="thinking"?(r("thinking",0),!i&&((b=l.current)!=null&&b.animate)&&l.current.animate([{transform:"rotate(0deg)"},{transform:"rotate(9deg)"}],{duration:260,fill:"forwards"})):a==="idle"?(r("idle",0),!i&&((x=l.current)!=null&&x.animate)&&l.current.animate([{transform:"rotate(9deg)"},{transform:"rotate(0deg)"}],{duration:180,fill:"forwards"})):V(h.current,i)});const g=u??o;return c.jsxs("div",{className:"cbot cbot-lite",ref:h,"data-companion-bot":"pd-lite","data-bot-state":g,style:{width:t,height:t},children:[c.jsx("img",{src:e.body,alt:"",draggable:!1,style:ae}),c.jsx("img",{src:e.head,alt:n??"pd-lite",draggable:!1,ref:l,style:{...ae,transformOrigin:`${ee.x*100}% ${ee.y*100}%`}}),c.jsx("style",{children:W})]})}function ve({parts:e,size:t=160,label:n,poseOverride:u=null}){const i=G(),{pose:o,setTimed:r}=H(),h=v.useRef(null),l=v.useRef(0),g=u??o;return K(a=>{a==="keyL"||a==="keyR"?(l.current=1,r(a,185),q(h.current,i)):a==="happy"?(l.current=1.6,r("happy",1100),Q(h.current,i)):a==="thinking"?r("thinking",0):a==="idle"?r("idle",0):V(h.current,i)}),v.useEffect(()=>{const a=h.current;if(!a)return;const m=a.getContext("2d");if(!m)return;const b=Math.min(2,window.devicePixelRatio||1);a.width=t*b,a.height=t*b;const x=[e.head,e.body].map(f=>{const y=new Image;return y.src=f,y});let d=!1;return Promise.all(x.map(f=>new Promise(y=>{if(f.complete)return y();f.onload=()=>y(),f.onerror=()=>y()}))).then(()=>{if(d)return;const f=performance.now(),y=L=>{if(d)return;l.current*=.92;const M=L-f,N=l.current;m.clearRect(0,0,a.width,a.height),m.save(),m.scale(b,b),te(m,x[1],{x:j.body.x*t,y:j.body.y*t,w:j.body.w*t,h:j.body.h*t,src:{x:j.body.x*512,y:j.body.y*512,w:j.body.w*512,h:j.body.h*512},cols:6,rows:6,t:M,deform:(S,R,k)=>({dx:Math.sin(k/640)*1.1+Math.sin(k/700)*2.2*Math.abs(S-.5)*2*(1+N*.5),dy:N*2.5})}),te(m,x[0],{x:j.head.x*t,y:j.head.y*t,w:j.head.w*t,h:j.head.h*t,src:{x:j.head.x*512,y:j.head.y*512,w:j.head.w*512,h:j.head.h*512},cols:7,rows:7,t:M,deform:(S,R,k)=>({dx:Math.sin(k/820)*1.4*(1+N*2)+Math.sin(k/500)*1.8*R*(1+N*2),dy:Math.sin(k/640)*1.8*(1-R)+Math.sin(k/460)*1.4*N*(1-R)+N*2})}),m.restore(),requestAnimationFrame(y)};requestAnimationFrame(y)}),()=>{d=!0}},[e,t,i]),c.jsxs("div",{className:"cbot","data-companion-bot":"pd-mesh","data-bot-state":g,style:{width:t,height:t},children:[c.jsx("canvas",{ref:h,style:{width:t,height:t},"aria-label":n??"pd-mesh"}),c.jsx("style",{children:W})]})}const Re=[{pose:null,label:"待机"},{pose:"happy",label:"开心"},{pose:"thinking",label:"思考"}],U=[{key:"sticker",title:"贴纸级 / Bongo 档",note:"整图帧替换 + 呼吸/squash/jump——M0 引擎,零切层"},{key:"pd-lite",title:"PD-Lite 纸偶",note:"四层切分 + 肩点旋转——刚体变换 + 次级运动,无网格"},{key:"pd-mesh",title:"PD-Mesh 网格",note:"同四层 + Canvas2D 网格变形——Live2D-lite,实验性"}];function Le(){const[e,t]=v.useState(null),[n,u]=v.useState(null);v.useEffect(()=>{let o=!0;return ge().then(r=>{o&&t(r)}),()=>{o=!1}},[]);const i=()=>{location.hash=""};return e?c.jsx("div",{"data-companion-bot-lab":"",className:"fixed inset-0 z-[70] flex items-center justify-center bg-black/45",onPointerDown:o=>{o.target===o.currentTarget&&i()},children:c.jsxs("div",{className:"bg-surface-0 text-ink max-h-[92vh] w-[min(920px,94vw)] overflow-auto rounded-2xl p-6 shadow-pop",children:[c.jsxs("div",{className:"mb-4 flex items-start justify-between gap-4",children:[c.jsxs("div",{children:[c.jsx("h2",{className:"text-title font-bold",children:"CompanionBot Lab · M0 spike"}),c.jsx("p",{className:"text-label text-ink/60",children:"外部角色包三档对照——同一套伴学 bus 信号驱动。键击/庆祝事件对三栏同时生效。"})]}),c.jsx("button",{type:"button",className:"btn-3d-neutral text-label px-3 py-2",onClick:i,children:"关闭"})]}),c.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-2",children:[Re.map(({pose:o,label:r})=>c.jsx("button",{type:"button",className:`text-label px-3 py-2 ${(o??null)===n?"btn-3d-brand":"btn-3d-neutral"}`,onClick:()=>u(o),children:r},r)),c.jsx("button",{type:"button",className:"btn-3d-brand text-label px-3 py-2","data-testid":"bot-lab-celebrate",onClick:()=>le("correct"),children:"庆祝总线(celebrate correct)"}),c.jsx("textarea",{className:"text-label h-10 w-44 resize-none rounded-xl border border-ink/15 bg-surface-2 px-3 py-2",placeholder:"在此打字→拍臂","aria-label":"typing test input"})]}),c.jsxs("div",{className:"grid grid-cols-1 gap-4 sm:grid-cols-3",children:[c.jsxs("div",{className:"rounded-xl bg-surface-2 p-4 text-center",children:[c.jsx("div",{className:"flex h-[200px] items-center justify-center",children:c.jsx(ke,{pack:{manifest:ye,srcs:e.srcs},size:148,poseOverride:n})}),c.jsx("h3",{className:"text-label mt-2 font-bold",children:U[0].title}),c.jsx("p",{className:"text-caption mt-1 text-ink/60",children:U[0].note})]}),c.jsxs("div",{className:"rounded-xl bg-surface-2 p-4 text-center",children:[c.jsx("div",{className:"flex h-[200px] items-center justify-center",children:c.jsx(je,{parts:e.parts,size:156,poseOverride:n})}),c.jsx("h3",{className:"text-label mt-2 font-bold",children:U[1].title}),c.jsx("p",{className:"text-caption mt-1 text-ink/60",children:U[1].note})]}),c.jsxs("div",{className:"rounded-xl bg-surface-2 p-4 text-center",children:[c.jsx("div",{className:"flex h-[200px] items-center justify-center",children:c.jsx(ve,{parts:e.parts,size:156,poseOverride:n})}),c.jsx("h3",{className:"text-label mt-2 font-bold",children:U[2].title}),c.jsx("p",{className:"text-caption mt-1 text-ink/60",children:U[2].note})]})]}),c.jsx("p",{className:`text-caption mt-4 ${e.selfSpec.ok?"text-brand":"text-warning"}`,children:e.selfSpec.ok?"✓ 样例 body 件通过 PNG 三行规格检测(透明底/单主体/别贴边)——analyzePngSpec 活演示":`✗ 样例未过规格:${e.selfSpec.issues.map(o=>o.code).join(", ")}`})]})}):c.jsx("div",{"data-companion-bot-lab":"",className:"fixed inset-0 z-[70] bg-black/45"})}export{Le as CompanionBotLab};
@@ -1,4 +1,4 @@
1
- import{r as u,j as t}from"./index-DjO1zEnx.js";import{c as C,U as I,u as y,a as L,d as S,X as N,B as M,T as E,C as R}from"./main-BbOwLoeH.js";/**
1
+ import{r as u,j as t}from"./index-DZN4z5wF.js";import{c as C,U as I,u as y,a as L,d as S,X as N,B as M,T as E,C as R}from"./main-CmJlqSDk.js";/**
2
2
  * @license lucide-react v0.468.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{r as o,h as U,j as e,c as ie}from"./index-DjO1zEnx.js";import{c as te,u as ce,a as j,g as de,T as z,h as Y,L as V,i as oe,X as xe}from"./main-BbOwLoeH.js";import{R as G}from"./rotate-ccw-D1vRxSpM.js";import{A as q}from"./arrow-right-BW9yawWu.js";/**
1
+ import{r as o,h as U,j as e,c as ie}from"./index-DZN4z5wF.js";import{c as te,u as ce,a as j,g as de,T as z,h as Y,L as V,i as oe,X as xe}from"./main-CmJlqSDk.js";import{R as G}from"./rotate-ccw-DhViz0iw.js";import{A as q}from"./arrow-right-33rr0pBZ.js";/**
2
2
  * @license lucide-react v0.468.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{r as a,j as e,c as S}from"./index-DjO1zEnx.js";import{u as j,a as N,S as M}from"./main-BbOwLoeH.js";function A({tree:c,onReviewNode:d,progressMap:o}){const s=j(),[l,f]=a.useState([]),[b,h]=a.useState(!0),[n,x]=a.useState(null);a.useEffect(()=>{N.getAllSrsItems().then(t=>f(t)).catch(()=>f([])).finally(()=>h(!1))},[]);const p=a.useMemo(()=>new Map(c.map(t=>[t.id,t])),[c]),g=a.useMemo(()=>new Set(l.filter(t=>t.overdue).map(t=>t.nodeId)),[l]),i=a.useMemo(()=>{const t=c.filter(u=>{var y;const m=(y=o[u.id])==null?void 0:y.status;return u.type==="lesson"&&(m==="in_progress"||m==="mastered")}),r=new Map;for(const u of t){const m=u.parentId??"(root)";r.has(m)||r.set(m,[]),r.get(m).push(u)}return r},[c,o]),w=a.useMemo(()=>Array.from(i.values()).flat().filter(t=>g.has(t.id)).length,[i,g]),v=a.useMemo(()=>Array.from(i.values()).flat(),[i]);if(a.useEffect(()=>{if(i.size>0&&(!n||!i.has(n))){const t=i.keys().next().value;t&&x(t)}},[i,n]),b)return e.jsxs("div",{className:"text-center py-12 text-body text-ink-muted flex items-center justify-center gap-2",children:[e.jsx("span",{className:"typing-dot w-1.5 h-1.5 bg-brand rounded-full inline-block"}),s("review.loading")]});if(v.length===0)return e.jsxs("div",{className:"text-center py-16","data-testid":"review-empty",children:[e.jsx("div",{className:"text-4xl mb-3 opacity-30",children:"📖"}),e.jsx("div",{className:"text-body text-ink-muted",children:s("review.empty.title")}),e.jsx("div",{className:"text-label text-ink-faint mt-1",children:s("review.empty.desc")})]});const k=t=>{var r;return((r=p.get(t))==null?void 0:r.title)??t};return e.jsxs("div",{className:"p-5 max-w-2xl mx-auto","data-testid":"review-panel",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsx("h2",{className:"text-title font-extrabold text-ink-strong",children:s("review.title")}),w>0&&e.jsxs("span",{className:"text-label font-bold text-review","data-testid":"review-due-count",children:[w," ",s("review.due.count")]})]}),e.jsxs("button",{onClick:()=>{const t=v[Math.floor(Math.random()*v.length)];t&&d(t.id)},"data-testid":"review-interleave",className:"btn-3d-neutral w-full py-2.5 text-body mb-5 flex items-center justify-center gap-1.5",children:[e.jsx(M,{className:"w-4 h-4"}),s("review.interleave")]}),e.jsx("div",{className:"text-label font-bold text-ink-muted mb-2",children:s("review.selectSection")}),e.jsx("div",{className:"flex flex-wrap gap-1.5 mb-4",children:Array.from(i.entries()).map(([t,r])=>e.jsxs("button",{onClick:()=>x(t),className:`px-2.5 py-1 rounded-full text-label font-bold transition-colors ${n===t?"bg-brand/15 text-brand ring-1 ring-brand/30":"bg-surface-3 text-ink-muted hover:text-ink-strong"}`,children:[k(t),e.jsxs("span",{className:"ml-1 opacity-60",children:["(",r.length,")"]})]},t))}),n&&i.has(n)&&e.jsx("div",{className:"space-y-1.5","data-testid":"review-lesson-list",children:i.get(n).map(t=>{const r=g.has(t.id);return e.jsxs("div",{className:`flex items-center justify-between gap-2 p-2.5 rounded-lg transition-colors ${r?"bg-review/8 ring-1 ring-review/20":"bg-surface-3 hover:bg-surface-3/80"}`,children:[e.jsxs("div",{className:"flex items-center gap-1.5 truncate flex-1",children:[r&&e.jsx("span",{className:"shrink-0 w-1.5 h-1.5 rounded-full bg-review"}),e.jsx("span",{className:"text-body text-ink-strong truncate",children:t.title})]}),e.jsx("button",{onClick:()=>d(t.id),"data-testid":`review-lesson-${t.id.slice(0,8)}`,className:"shrink-0 px-3 py-1 rounded-lg bg-brand/15 text-brand text-label font-bold hover:bg-brand/25 transition-colors",children:s("review.reviewLesson")})]},t.id)})})]})}function E({nodeId:c,onRated:d}){const o=a.useRef(null),s=j(),[l,f]=a.useState(!1),[b,h]=a.useState(!1),n=async x=>{if(!(l||b)){f(!0);try{await N.recordReview(c,x),h(!0),d==null||d(),S(x>=4?"correct":"wrong",{origin:x>=4&&o.current?(()=>{const p=o.current.getBoundingClientRect();return{x:p.right-48,y:p.top+24}})():void 0})}catch{}finally{f(!1)}}};return b?e.jsx("div",{className:"text-center text-body text-brand py-2","data-testid":"self-rated",children:s("review.selfrated")}):e.jsxs("div",{ref:o,className:"border-t border-[var(--border-faint)] pt-3 mt-3","data-testid":"self-rating",children:[e.jsx("div",{className:"text-caption font-bold text-ink-muted uppercase tracking-wider mb-2 text-center",children:s("review.selfrate.title")}),e.jsxs("div",{className:"grid grid-cols-3 gap-2",children:[e.jsxs("button",{onClick:()=>n(1),disabled:l,"data-testid":"rate-again",className:"py-2 rounded-lg border border-warning/40 text-warning hover:bg-warning/10 transition-colors disabled:opacity-40 flex flex-col items-center gap-0.5",children:[e.jsx("span",{className:"text-body font-bold",children:s("review.selfrate.again")}),e.jsx("span",{className:"text-caption opacity-70",children:s("review.selfrate.again.hint")})]}),e.jsxs("button",{onClick:()=>n(4),disabled:l,"data-testid":"rate-remembered",className:"py-2 rounded-lg border border-accent/40 text-accent hover:bg-accent/10 transition-colors disabled:opacity-40 flex flex-col items-center gap-0.5",children:[e.jsx("span",{className:"text-body font-bold",children:s("review.selfrate.remembered")}),e.jsx("span",{className:"text-caption opacity-70",children:s("review.selfrate.remembered.hint")})]}),e.jsxs("button",{onClick:()=>n(5),disabled:l,"data-testid":"rate-mastered",className:"py-2 rounded-lg border border-brand/40 text-brand hover:bg-brand/10 transition-colors disabled:opacity-40 flex flex-col items-center gap-0.5",children:[e.jsx("span",{className:"text-body font-bold",children:s("review.selfrate.mastered")}),e.jsx("span",{className:"text-caption opacity-70",children:s("review.selfrate.mastered.hint")})]})]})]})}export{A as ReviewPanel,E as SelfRatingCard};
1
+ import{r as a,j as e,c as S}from"./index-DZN4z5wF.js";import{u as j,a as N,S as M}from"./main-CmJlqSDk.js";function A({tree:c,onReviewNode:d,progressMap:o}){const s=j(),[l,f]=a.useState([]),[b,h]=a.useState(!0),[n,x]=a.useState(null);a.useEffect(()=>{N.getAllSrsItems().then(t=>f(t)).catch(()=>f([])).finally(()=>h(!1))},[]);const p=a.useMemo(()=>new Map(c.map(t=>[t.id,t])),[c]),g=a.useMemo(()=>new Set(l.filter(t=>t.overdue).map(t=>t.nodeId)),[l]),i=a.useMemo(()=>{const t=c.filter(u=>{var y;const m=(y=o[u.id])==null?void 0:y.status;return u.type==="lesson"&&(m==="in_progress"||m==="mastered")}),r=new Map;for(const u of t){const m=u.parentId??"(root)";r.has(m)||r.set(m,[]),r.get(m).push(u)}return r},[c,o]),w=a.useMemo(()=>Array.from(i.values()).flat().filter(t=>g.has(t.id)).length,[i,g]),v=a.useMemo(()=>Array.from(i.values()).flat(),[i]);if(a.useEffect(()=>{if(i.size>0&&(!n||!i.has(n))){const t=i.keys().next().value;t&&x(t)}},[i,n]),b)return e.jsxs("div",{className:"text-center py-12 text-body text-ink-muted flex items-center justify-center gap-2",children:[e.jsx("span",{className:"typing-dot w-1.5 h-1.5 bg-brand rounded-full inline-block"}),s("review.loading")]});if(v.length===0)return e.jsxs("div",{className:"text-center py-16","data-testid":"review-empty",children:[e.jsx("div",{className:"text-4xl mb-3 opacity-30",children:"📖"}),e.jsx("div",{className:"text-body text-ink-muted",children:s("review.empty.title")}),e.jsx("div",{className:"text-label text-ink-faint mt-1",children:s("review.empty.desc")})]});const k=t=>{var r;return((r=p.get(t))==null?void 0:r.title)??t};return e.jsxs("div",{className:"p-5 max-w-2xl mx-auto","data-testid":"review-panel",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsx("h2",{className:"text-title font-extrabold text-ink-strong",children:s("review.title")}),w>0&&e.jsxs("span",{className:"text-label font-bold text-review","data-testid":"review-due-count",children:[w," ",s("review.due.count")]})]}),e.jsxs("button",{onClick:()=>{const t=v[Math.floor(Math.random()*v.length)];t&&d(t.id)},"data-testid":"review-interleave",className:"btn-3d-neutral w-full py-2.5 text-body mb-5 flex items-center justify-center gap-1.5",children:[e.jsx(M,{className:"w-4 h-4"}),s("review.interleave")]}),e.jsx("div",{className:"text-label font-bold text-ink-muted mb-2",children:s("review.selectSection")}),e.jsx("div",{className:"flex flex-wrap gap-1.5 mb-4",children:Array.from(i.entries()).map(([t,r])=>e.jsxs("button",{onClick:()=>x(t),className:`px-2.5 py-1 rounded-full text-label font-bold transition-colors ${n===t?"bg-brand/15 text-brand ring-1 ring-brand/30":"bg-surface-3 text-ink-muted hover:text-ink-strong"}`,children:[k(t),e.jsxs("span",{className:"ml-1 opacity-60",children:["(",r.length,")"]})]},t))}),n&&i.has(n)&&e.jsx("div",{className:"space-y-1.5","data-testid":"review-lesson-list",children:i.get(n).map(t=>{const r=g.has(t.id);return e.jsxs("div",{className:`flex items-center justify-between gap-2 p-2.5 rounded-lg transition-colors ${r?"bg-review/8 ring-1 ring-review/20":"bg-surface-3 hover:bg-surface-3/80"}`,children:[e.jsxs("div",{className:"flex items-center gap-1.5 truncate flex-1",children:[r&&e.jsx("span",{className:"shrink-0 w-1.5 h-1.5 rounded-full bg-review"}),e.jsx("span",{className:"text-body text-ink-strong truncate",children:t.title})]}),e.jsx("button",{onClick:()=>d(t.id),"data-testid":`review-lesson-${t.id.slice(0,8)}`,className:"shrink-0 px-3 py-1 rounded-lg bg-brand/15 text-brand text-label font-bold hover:bg-brand/25 transition-colors",children:s("review.reviewLesson")})]},t.id)})})]})}function E({nodeId:c,onRated:d}){const o=a.useRef(null),s=j(),[l,f]=a.useState(!1),[b,h]=a.useState(!1),n=async x=>{if(!(l||b)){f(!0);try{await N.recordReview(c,x),h(!0),d==null||d(),S(x>=4?"correct":"wrong",{origin:x>=4&&o.current?(()=>{const p=o.current.getBoundingClientRect();return{x:p.right-48,y:p.top+24}})():void 0})}catch{}finally{f(!1)}}};return b?e.jsx("div",{className:"text-center text-body text-brand py-2","data-testid":"self-rated",children:s("review.selfrated")}):e.jsxs("div",{ref:o,className:"border-t border-[var(--border-faint)] pt-3 mt-3","data-testid":"self-rating",children:[e.jsx("div",{className:"text-caption font-bold text-ink-muted uppercase tracking-wider mb-2 text-center",children:s("review.selfrate.title")}),e.jsxs("div",{className:"grid grid-cols-3 gap-2",children:[e.jsxs("button",{onClick:()=>n(1),disabled:l,"data-testid":"rate-again",className:"py-2 rounded-lg border border-warning/40 text-warning hover:bg-warning/10 transition-colors disabled:opacity-40 flex flex-col items-center gap-0.5",children:[e.jsx("span",{className:"text-body font-bold",children:s("review.selfrate.again")}),e.jsx("span",{className:"text-caption opacity-70",children:s("review.selfrate.again.hint")})]}),e.jsxs("button",{onClick:()=>n(4),disabled:l,"data-testid":"rate-remembered",className:"py-2 rounded-lg border border-accent/40 text-accent hover:bg-accent/10 transition-colors disabled:opacity-40 flex flex-col items-center gap-0.5",children:[e.jsx("span",{className:"text-body font-bold",children:s("review.selfrate.remembered")}),e.jsx("span",{className:"text-caption opacity-70",children:s("review.selfrate.remembered.hint")})]}),e.jsxs("button",{onClick:()=>n(5),disabled:l,"data-testid":"rate-mastered",className:"py-2 rounded-lg border border-brand/40 text-brand hover:bg-brand/10 transition-colors disabled:opacity-40 flex flex-col items-center gap-0.5",children:[e.jsx("span",{className:"text-body font-bold",children:s("review.selfrate.mastered")}),e.jsx("span",{className:"text-caption opacity-70",children:s("review.selfrate.mastered.hint")})]})]})]})}export{A as ReviewPanel,E as SelfRatingCard};
@@ -0,0 +1,10 @@
1
+ import{r as i,j as e,V as We,k as Ee,l as $e,s as nt,m as it,C as lt,M as ot}from"./index-DZN4z5wF.js";import{c as rt,u as te,b as ct,r as dt,X as Ve,f as mt,k as ie,n as he,a as l,W as ze,P as Ue,p as Fe,s as ut,i as xt,g as De,q as ht,t as pt,v as gt}from"./main-CmJlqSDk.js";/**
2
+ * @license lucide-react v0.468.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const ft=rt("RotateCw",[["path",{d:"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",key:"1p45f6"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}]]),bt={vision:"companion.custom.routeVision",geometric:"companion.custom.routeGeometric",l1:"companion.custom.routeL1"};function vt(t){let m="";for(let h=0;h<t.length;h+=32768)m+=String.fromCharCode(...t.subarray(h,h+32768));return btoa(m)}async function jt(t){try{return await navigator.clipboard.writeText(t),!0}catch{}const m=document.createElement("textarea");m.value=t,m.style.position="fixed",m.style.opacity="0",document.body.appendChild(m),m.focus(),m.select();let o=!1;try{o=document.execCommand("copy")}catch{o=!1}return m.remove(),o}function wt({onClose:t,onSaved:m}){const o=te(),[h,u]=i.useState(!1),[c,r]=i.useState(!1),[g,x]=i.useState(0),[p,C]=i.useState(null),[f,y]=i.useState(null),[_,D]=i.useState(""),[k,P]=i.useState(""),[S,M]=i.useState("ember"),R=i.useRef(null),L=i.useRef(null);ct(L,!0),i.useEffect(()=>{if(!c)return;x(0);const d=Date.now(),j=window.setInterval(()=>x(Math.floor((Date.now()-d)/1e3)),500);return()=>window.clearInterval(j)},[c]);const F=async()=>{const d=await jt(o("companion.wizard.prompt"));u(d),d?setTimeout(()=>u(!1),2400):y(o("companion.wizard.copyFail"))},V=async d=>{if(d){r(!0),y(null),C(null),D(d.name.replace(/\.png$/i,""));try{const j=vt(new Uint8Array(await d.arrayBuffer())),v=await window.api.companionPackCutFromImage({pngBase64:j});C(v),v.visionError?y(`${o("companion.custom.visionFallback")} · ${v.visionError}`):y(`${o("companion.custom.cutDone")} · ${o(bt[v.route]??"companion.custom.routeL1")}`)}catch(j){y(`${o("companion.custom.fail")}: ${String(j)}`)}finally{r(!1)}}},$=async()=>{if(p){r(!0);try{await window.api.companionPackApplyPack({name:k.trim()||_||"My Bot",manifest:{...p.manifest,vehicle:S},parts:p.parts.map(d=>({name:d.name,pngBase64:d.pngBase64}))}),await $e(),await window.api.setSetting("companion_form","custom"),window.dispatchEvent(new Event("companion-config-changed")),m()}catch(d){y(`${o("companion.custom.fail")}: ${String(d)}`)}finally{r(!1)}}};return dt.createPortal(e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/70 p-4","data-noswipe":"",role:"dialog","aria-modal":"true","aria-label":o("companion.wizard.title"),onClick:t,children:e.jsxs("div",{ref:L,onClick:d=>d.stopPropagation(),className:"w-full max-w-xl max-h-[86vh] overflow-y-auto rounded-2xl bg-surface-1 shadow-pop p-4","data-testid":"companion-wizard",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("h3",{className:"text-body font-bold text-ink-strong",children:o("companion.wizard.title")}),e.jsx("button",{onClick:t,"aria-label":o("action.close"),className:"text-ink-muted hover:text-ink-strong w-8 h-8 flex items-center justify-center rounded-lg hover:bg-surface-2",children:e.jsx(Ve,{className:"w-4 h-4"})})]}),e.jsxs("div",{className:"rounded-xl border border-[var(--border-faint)] p-3 mb-2",children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-1",children:o("companion.wizard.s1")}),e.jsx("p",{className:"text-caption text-ink-muted leading-relaxed",children:o("companion.wizard.s1body")})]}),e.jsxs("div",{className:"rounded-xl border border-[var(--border-faint)] p-3 mb-2",children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-1",children:o("companion.wizard.s2")}),e.jsx("p",{className:"text-caption text-ink-muted leading-relaxed mb-2",children:o("companion.wizard.s2body")}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 mb-2",children:[e.jsx("a",{href:"https://www.doubao.com/chat/",target:"_blank",rel:"noreferrer",className:"rounded-lg border border-[var(--border-faint)] px-3 py-1.5 text-label hover:bg-surface-2",children:o("companion.wizard.s2doubao")}),e.jsx("a",{href:"https://jimeng.jianying.com/",target:"_blank",rel:"noreferrer",className:"rounded-lg border border-[var(--border-faint)] px-3 py-1.5 text-label hover:bg-surface-2",children:o("companion.wizard.s2jimeng")}),e.jsx("a",{href:"https://chatgpt.com/",target:"_blank",rel:"noreferrer",className:"rounded-lg border border-[var(--border-faint)] px-3 py-1.5 text-label hover:bg-surface-2",children:o("companion.wizard.s2chatgpt")}),e.jsx("button",{type:"button",onClick:()=>void F(),"data-testid":"companion-wizard-copy",className:"rounded-lg bg-accent px-3 py-1.5 text-label text-white hover:opacity-90",children:o(h?"companion.wizard.copied":"companion.wizard.copy")})]}),e.jsx("textarea",{readOnly:!0,value:o("companion.wizard.prompt"),rows:6,className:"w-full rounded-lg bg-surface-2 border border-[var(--border-faint)] p-2 text-caption text-ink-muted font-mono resize-y select-all",onFocus:d=>d.currentTarget.select()})]}),e.jsxs("div",{className:"rounded-xl border border-[var(--border-faint)] p-3",children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-1",children:o("companion.wizard.s3")}),e.jsxs("div",{className:"mb-2",children:[e.jsx("div",{className:"text-caption text-ink-muted mb-1",children:o("companion.wizard.vehicle")}),e.jsx("div",{className:"flex flex-wrap gap-1.5",role:"radiogroup","aria-label":o("companion.wizard.vehicle"),children:We.map(d=>{const j=S===d;return e.jsxs("button",{type:"button",role:"radio","aria-checked":j,"data-testid":`companion-wizard-veh-${d}`,onClick:()=>M(d),className:`flex items-center gap-1.5 rounded-lg border px-2.5 py-1 text-label motion-safe:transition-colors
7
+ ${j?"border-[var(--accent)] bg-surface-2 text-ink-strong font-medium":"border-[var(--border-faint)] hover:bg-surface-2 text-ink-muted"}`,children:[e.jsx("span",{"aria-hidden":"true",className:"w-3 h-3 rounded-full border border-black/20",style:{background:Ee[d].dot}}),o(`companion.form.${d}.name`)]},d)})})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 mb-2",children:[e.jsx("input",{ref:R,type:"file",accept:"image/png",className:"hidden","data-testid":"companion-custom-file",onChange:d=>{var j;return void V((j=d.target.files)==null?void 0:j[0])}}),e.jsx("button",{type:"button",disabled:c,onClick:()=>{var d;return(d=R.current)==null?void 0:d.click()},"data-testid":"companion-wizard-pick",className:"rounded-lg border border-[var(--border-faint)] px-3 py-1.5 text-label hover:bg-surface-2 disabled:opacity-50",children:o("companion.wizard.pick")}),c&&e.jsxs("span",{className:"flex items-center gap-1.5 text-label text-ink-muted","data-testid":"companion-custom-busy",children:[e.jsx(mt,{size:14,className:"animate-spin"}),o(p?"companion.custom.applying":"companion.custom.locating"),e.jsxs("span",{className:"tabular-nums",children:[g,"s"]})]}),f&&e.jsx("span",{className:"text-caption text-ink-muted","data-testid":"companion-custom-msg",children:f})]}),p&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2","data-testid":"companion-custom-preview",children:[p.parts.map(d=>e.jsx("img",{src:`data:image/png;base64,${d.pngBase64}`,alt:d.name,title:d.name,className:"h-14 w-14 object-contain rounded-lg bg-surface-2"},d.name)),e.jsx("input",{value:k,onChange:d=>P(d.target.value),placeholder:o("companion.wizard.namePh"),"data-testid":"companion-wizard-name",className:"rounded-lg border border-[var(--border-faint)] bg-surface-0 px-2.5 py-1.5 text-label text-ink-strong placeholder:text-ink-muted w-36"}),e.jsx("button",{type:"button",disabled:c,onClick:()=>void $(),"data-testid":"companion-custom-apply",className:"rounded-lg bg-brand px-3 py-1.5 text-label text-white hover:opacity-90 disabled:opacity-50",children:o("companion.wizard.save")})]})]})]})}),document.body)}const xe="bg-ink/[0.04] text-ink-strong text-label rounded-lg border border-transparent focus:border-accent focus:bg-ink/[0.06] transition-colors placeholder:text-ink-faint";function ye({kind:t,showProtocol:m=!0,testPrefix:o="custom",titleKey:h="settings.custom.form_title",modelPhKey:u="settings.custom.model_ph",testOverride:c,onSaved:r,onCancel:g}){const x=te(),[p,C]=i.useState(""),[f,y]=i.useState("openai-compatible"),[_,D]=i.useState(""),[k,P]=i.useState(""),[S,M]=i.useState(""),[R,L]=i.useState(!1),[F,V]=i.useState(!1),[$,d]=i.useState(null),j=async()=>{if(!(!_.trim()||!S.trim()||F)){V(!0),d(null);try{const a=c?await c({baseUrl:_.trim(),apiKey:k.trim(),model:S.trim()}):await l.testCustomProvider({label:p||x("settings.custom.test_label"),protocol:f,baseUrl:_.trim(),apiKey:k.trim()||void 0,defaultModel:S.trim()});d({ok:a.ok,detail:a.detail})}catch(a){d({ok:!1,detail:a instanceof Error?a.message:String(a)})}finally{V(!1)}}},v=async()=>{if(!(!p.trim()||!_.trim()||!S.trim()))try{const a=await l.createCustomProvider({label:p.trim(),kind:t,protocol:m?f:"openai-compatible",baseUrl:_.trim(),apiKey:k.trim()||void 0,defaultModel:S.trim(),vision:t==="llm"?R:void 0});r(a)}catch{}};return e.jsxs("div",{className:"space-y-2.5","data-testid":`${o}-provider-form`,children:[e.jsx("div",{className:"text-label font-bold text-ink-strong",children:x(h)}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{type:"text",value:p,onChange:a=>C(a.target.value),placeholder:x("settings.custom.label_ph"),"data-testid":`${o}-label`,className:`${xe} flex-1 px-2.5 py-1.5`}),m&&e.jsxs("select",{value:f,onChange:a=>y(a.target.value),"data-testid":`${o}-protocol`,className:`${xe} px-2 py-1.5`,children:[e.jsx("option",{value:"openai-compatible",children:x("settings.proto.openai")}),e.jsx("option",{value:"anthropic",children:"Anthropic"}),e.jsx("option",{value:"google",children:"Google"})]})]}),e.jsx("input",{type:"text",value:_,onChange:a=>D(a.target.value),placeholder:x("settings.custom.baseurl_ph"),"data-testid":`${o}-baseurl`,className:`${xe} w-full px-2.5 py-1.5 font-mono`}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{type:"text",value:S,onChange:a=>M(a.target.value),placeholder:x(u),"data-testid":`${o}-model`,className:`${xe} flex-1 px-2.5 py-1.5 font-mono`}),e.jsx("input",{type:"password",value:k,onChange:a=>P(a.target.value),placeholder:x("settings.custom.apikey_ph"),"data-testid":`${o}-apikey`,className:`${xe} flex-1 px-2.5 py-1.5`})]}),t==="llm"&&e.jsxs("label",{className:"inline-flex items-center gap-2 text-label cursor-pointer select-none","data-testid":`${o}-vision`,children:[e.jsx("input",{type:"checkbox",checked:R,onChange:a=>L(a.target.checked),className:"w-4 h-4 rounded accent-brand"}),e.jsx("span",{className:"text-ink-strong",children:x("settings.custom.vision")}),e.jsx("span",{className:"text-ink-faint",children:x("settings.custom.visionHint")})]}),$&&e.jsxs("div",{className:`text-label rounded p-2 inline-flex items-start gap-1.5 ${$.ok?"bg-brand/10 text-brand":"bg-warning/10 text-warning"}`,children:[$.ok?e.jsx(ie,{className:"w-4 h-4 mt-px shrink-0","aria-hidden":"true"}):e.jsx(he,{className:"w-4 h-4 mt-px shrink-0","aria-hidden":"true"}),e.jsx("span",{className:"break-words",children:$.detail})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{onClick:()=>void j(),disabled:!_.trim()||!S.trim()||F,"data-testid":`${o}-test`,className:"btn-3d-neutral px-3 py-1.5 text-label disabled:opacity-40",children:x(F?"settings.testing":"settings.test")}),e.jsx("button",{onClick:()=>void v(),disabled:!p.trim()||!_.trim()||!S.trim(),"data-testid":`${o}-save`,className:"btn-3d-brand px-3 py-1.5 text-label disabled:opacity-40",children:x("settings.custom.save")}),g&&e.jsx("button",{onClick:g,className:"text-label text-ink-muted hover:text-ink-strong px-3 py-1.5 transition-colors",children:x("action.cancel")})]})]})}const Ie="lookatstudy-theme",Ke="auto",Oe="(prefers-color-scheme: dark)";function Ce(){return typeof window>"u"||window.matchMedia(Oe).matches?"dark":"light"}function kt(){if(typeof localStorage>"u")return Ke;const t=localStorage.getItem(Ie);return t==="auto"||t==="light"||t==="dark"?t:Ke}function _e(t){const m=document.documentElement;m.classList.remove("dark","light"),m.classList.add(t),window.dispatchEvent(new CustomEvent("theme-changed",{detail:{resolved:t}}))}function Nt(){const[t,m]=i.useState(()=>kt()),[o,h]=i.useState(()=>t==="auto"?Ce():t),u=i.useCallback(c=>{m(c),localStorage.setItem(Ie,c);const r=c==="auto"?Ce():c;h(r),_e(r)},[]);return i.useEffect(()=>{if(t!=="auto")return;const c=window.matchMedia(Oe),r=g=>{const x=g.matches?"dark":"light";h(x),_e(x)};return c.addEventListener("change",r),()=>c.removeEventListener("change",r)},[t]),i.useEffect(()=>{const c=t==="auto"?Ce():t;h(c),_e(c)},[t]),{mode:t,resolved:o,setMode:u}}const yt="0.31.0",St={version:yt};function Ne(){window.dispatchEvent(new Event(gt))}const X="bg-surface-1 text-ink text-body rounded-lg border border-[var(--border)] focus:border-brand focus:outline-none transition-colors placeholder:text-ink-faint",G="bg-surface-3 text-ink-muted hover:bg-surface-3 hover:bg-surface-3 hover:text-ink-strong",H="bg-brand text-white shadow-sm";function N(t){return t?"px-4 py-3.5 border-t border-[var(--border-faint)]":"px-4 py-3.5"}function Rt(){const t=te(),[m,o]=i.useState([]),[h,u]=i.useState([]),[c,r]=i.useState("glm"),[g,x]=i.useState(""),[p,C]=i.useState(""),[f,y]=i.useState(null),[_,D]=i.useState(!1),[k,P]=i.useState(null),[S,M]=i.useState(!1),[R,L]=i.useState(!1),[F,V]=i.useState([]),[$,d]=i.useState(!1),[j,v]=i.useState(null),[a,E]=i.useState(null),[T,O]=i.useState(""),[pe,de]=i.useState(!1),se=Nt(),oe=async n=>{if(K)try{await l.updateCustomProvider(K.id,{vision:n}),await B()}catch{}},re=async()=>{d(!0),v(null);try{const n=await l.discoverModels();n.ok&&n.models?V(n.models):v(n.error||t("settings.discover_failed"))}catch(n){v(n instanceof Error?n.message:String(n))}finally{d(!1)}},B=i.useCallback(async()=>{try{const[n,w,W,Q]=await Promise.all([l.getProviderPresets(),l.listCustomProviders(),l.getSetting("active_provider"),l.getSetting("active_model")]);o(n),u(w);const U=W??"glm";if(r(U),U.startsWith("custom-")){const z=w.find(A=>A.id===U);y(z!=null&&z.hasApiKey?t("settings.key.configured"):null)}else{const z=n.find(A=>A.id===U);if(z){const A=await l.getSetting(z.apiKeySetting);y(A?`${A.slice(0,4)}…${A.slice(-4)}`:null)}}if(U.startsWith("custom-")){const z=w.find(A=>A.id===U);x(Q??(z==null?void 0:z.defaultModel)??"")}else{const z=n.find(A=>A.id===U);x(Q??(z==null?void 0:z.defaultModel)??"")}}catch(n){console.error("[SettingsView] load() failed:",n)}},[t]);i.useEffect(()=>{B()},[B]);const me=async n=>{r(n),P(null),C("");const w=m.find(W=>W.id===n);if(w){const W=await l.getSetting(w.apiKeySetting);y(W?`${W.slice(0,4)}…${W.slice(-4)}`:null),x(g||w.defaultModel)}},ge=async()=>{M(!1);try{if(await l.setSetting("active_provider",c),await l.setSetting("active_model",g),p.trim()){const n=m.find(w=>w.id===c);n&&(await l.setSetting(n.apiKeySetting,p.trim()),y(`${p.trim().slice(0,4)}…${p.trim().slice(-4)}`),C(""))}M(!0),setTimeout(()=>M(!1),2e3),window.dispatchEvent(new Event("llm-config-changed"))}catch{}},q=async()=>{D(!0),P(null);try{const n=await l.testLlmConnection();P(n)}catch(n){P({ok:!1,detail:n instanceof Error?n.message:String(n),errorKind:"unknown"})}finally{D(!1)}},fe=async n=>{await l.setSetting("active_provider",n.id),await l.setSetting("active_model",n.defaultModel),r(n.id),x(n.defaultModel),L(!1),await B(),window.dispatchEvent(new Event("llm-config-changed"))},ae=async n=>{try{await l.deleteCustomProvider(n),c===n&&(await l.setSetting("active_provider","glm"),r("glm")),await B()}catch{}},K=c.startsWith("custom-")?h.find(n=>n.id===c):null;i.useEffect(()=>{if(!K)return;const n=K.models.find(w=>w.id===g);O(n!=null&&n.contextWindow?String(n.contextWindow):"")},[K,g]);const be=async()=>{var U,z;if(!K)return;const n=T.trim().replace(/[,\s_]/g,""),w=/^(\d+)([km]?)$/i.exec(n);if(n!==""&&!w)return;const W=((U=w==null?void 0:w[2])==null?void 0:U.toLowerCase())==="k"?1e3:((z=w==null?void 0:w[2])==null?void 0:z.toLowerCase())==="m"?1e6:1,Q=n===""||!w?null:Math.max(1,Math.round(parseInt(w[1],10)*W));de(!0);try{const A=K.models.map(Y=>Y.id===g?{...Y,contextWindow:Q}:Y);await l.updateCustomProvider(K.id,{models:A}),await B(),window.dispatchEvent(new Event("llm-config-changed"))}catch{}finally{de(!1)}},Z=c.startsWith("custom-")?null:m.find(n=>n.id===c);return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"px-5 pt-5 space-y-6",children:[e.jsxs("section",{children:[e.jsx("h3",{className:"text-label font-bold text-ink-muted mb-2 px-1",children:t("settings.group.ai")}),e.jsxs("div",{className:"surface-card overflow-hidden",children:[e.jsxs("div",{className:N(!1),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-2",children:t("settings.row.provider")}),e.jsxs("div",{className:"flex flex-wrap gap-1.5","data-testid":"provider-grid",children:[m.map(n=>e.jsx("button",{onClick:()=>me(n.id),"data-testid":`provider-card-${n.id}`,"aria-pressed":c===n.id,className:`px-3 py-1.5 rounded-lg text-label font-medium whitespace-nowrap transition-colors ${c===n.id?H:G}`,children:n.label},n.id)),h.filter(n=>n.kind==="llm").map(n=>e.jsxs("button",{onClick:()=>me(n.id),"data-testid":`provider-card-${n.id}`,"aria-pressed":c===n.id,className:`px-3 py-1.5 rounded-lg text-label font-medium whitespace-nowrap transition-colors inline-flex items-center gap-1 ${c===n.id?H:G}`,children:[e.jsx(ze,{className:"w-3.5 h-3.5","aria-hidden":"true"}),n.label]},n.id)),e.jsxs("button",{onClick:()=>L(n=>!n),"data-testid":"add-custom-provider",className:"px-3 py-1.5 rounded-lg text-label whitespace-nowrap inline-flex items-center gap-1 border border-dashed border-[var(--border)] text-ink-muted hover:border-ink-muted hover:text-ink-strong transition-colors",children:[e.jsx(Ue,{className:"w-3.5 h-3.5","aria-hidden":"true"}),t("settings.add_custom")]})]})]}),R&&e.jsx("div",{className:"px-4 py-3.5 bg-surface-1 border-t border-[var(--border-faint)]",children:e.jsx(ye,{kind:"llm",testPrefix:"custom",onSaved:n=>void fe(n),onCancel:()=>L(!1)})}),h.length>0&&c.startsWith("custom-")&&e.jsx("div",{className:N(!0),children:e.jsx("button",{onClick:n=>{const w=n.currentTarget.getBoundingClientRect(),W=h.find(Q=>Q.id===c);W&&E({id:W.id,label:W.label,rect:w})},className:"text-label text-warning hover:underline",children:t("settings.delete_custom")})}),Z&&e.jsxs(e.Fragment,{children:[Z.baseUrl&&e.jsxs("div",{className:N(!0),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-1.5",children:"Base URL"}),e.jsx("code",{className:"text-label text-ink-faint font-mono break-all",children:Z.baseUrl})]}),e.jsxs("div",{className:N(!0),children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-label font-medium text-ink-strong shrink-0 w-14",children:t("settings.model")}),e.jsxs("div",{className:"flex-1 flex items-center gap-2",children:[e.jsxs("select",{value:g,onChange:n=>x(n.target.value),"data-testid":"model-select",className:`${X} flex-1 px-2.5 py-1.5`,children:[Z.models.map(n=>e.jsx("option",{value:n.id,children:n.id},n.id)),c==="openrouter"&&F.map(n=>e.jsx("option",{value:n.id,children:n.id},n.id))]}),c==="openrouter"&&e.jsxs("button",{onClick:re,disabled:$,"data-testid":"discover-models-btn",className:"text-label text-accent hover:underline disabled:opacity-40 whitespace-nowrap inline-flex items-center gap-1",children:[e.jsx(ft,{className:`w-3.5 h-3.5 ${$?"animate-spin":""}`,"aria-hidden":"true"}),t($?"settings.discovering":"settings.refresh")]})]})]}),j&&e.jsx("div",{className:"text-label text-warning mt-1.5 ml-[68px]",children:j})]}),e.jsx("div",{className:N(!0),children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-label font-medium text-ink-strong shrink-0 w-14",children:t("settings.apikey")}),e.jsxs("div",{className:"flex-1 flex items-center gap-2",children:[f&&e.jsxs("span",{className:"text-label text-brand shrink-0 inline-flex items-center gap-1",children:[e.jsx(ie,{className:"w-3.5 h-3.5","aria-hidden":"true"}),f]}),e.jsx("input",{type:"password",value:p,onChange:n=>C(n.target.value),placeholder:t(f?"settings.key.overwrite_ph":"settings.key.paste_ph"),"data-testid":"settings-key-input",className:`${X} flex-1 px-2.5 py-1.5`}),e.jsx("a",{href:Z.keyUrl,target:"_blank",rel:"noopener noreferrer",className:"text-label text-brand hover:underline whitespace-nowrap",children:t("settings.key.get")})]})]})}),e.jsx("div",{className:N(!0),children:e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-1 min-w-0",children:[e.jsx("button",{onClick:q,disabled:_,"data-testid":"test-connection-btn",className:"btn-3d-neutral px-3 py-1.5 text-label disabled:opacity-40",children:t(_?"settings.testing":"settings.test")}),k&&e.jsxs("span",{className:`text-label inline-flex items-center gap-1 min-w-0 break-words ${k.ok?"text-brand":"text-warning"}`,children:[k.ok?e.jsx(ie,{className:"w-4 h-4 shrink-0","aria-hidden":"true"}):e.jsx(he,{className:"w-4 h-4 shrink-0","aria-hidden":"true"}),k.detail]})]})})]}),K&&!Z&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:N(!0),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-1.5",children:"Base URL"}),e.jsx("code",{className:"text-label text-ink-faint font-mono break-all",children:K.baseUrl})]}),e.jsx("div",{className:N(!0),children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-label font-medium text-ink-strong shrink-0 w-14",children:t("settings.model")}),K.models.length>1?e.jsx("select",{value:g,onChange:n=>x(n.target.value),"data-testid":"model-select-custom",className:`${X} flex-1 px-2.5 py-1.5`,children:K.models.map(n=>e.jsx("option",{value:n.id,children:n.id},n.id))}):e.jsx("input",{type:"text",value:g,onChange:n=>x(n.target.value),placeholder:t("settings.custom.model_ph"),"data-testid":"model-input-custom",className:`${X} flex-1 px-2.5 py-1.5 font-mono`})]})}),e.jsxs("div",{className:N(!0),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-1.5",children:t("settings.custom.windowLabel")}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"text",inputMode:"numeric",value:T,onChange:n=>O(n.target.value),placeholder:t("settings.custom.windowPh"),"data-testid":"context-window-input",className:`${X} flex-1 px-2.5 py-1.5 font-mono tabular-nums`}),e.jsx("button",{onClick:be,disabled:pe,"data-testid":"context-window-save",className:"btn-3d-neutral px-3 py-1.5 text-label shrink-0 disabled:opacity-40",children:t("settings.custom.save")})]}),e.jsx("div",{className:"text-caption text-ink-faint mt-1",children:t("settings.custom.windowHint")})]}),e.jsx("div",{className:N(!0),children:e.jsxs("label",{className:"inline-flex items-center gap-2 text-label cursor-pointer select-none","data-testid":"custom-vision-toggle",children:[e.jsx("input",{type:"checkbox",checked:K.vision,onChange:n=>void oe(n.target.checked),className:"w-4 h-4 rounded accent-brand"}),e.jsx("span",{className:"text-ink-strong",children:t("settings.custom.vision")}),e.jsx("span",{className:"text-ink-faint",children:t("settings.custom.visionHint")})]})}),e.jsx("div",{className:N(!0),children:e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-1 min-w-0",children:[e.jsx("button",{onClick:q,disabled:_,"data-testid":"test-connection-btn",className:"btn-3d-neutral px-3 py-1.5 text-label disabled:opacity-40",children:t(_?"settings.testing":"settings.test")}),k&&e.jsxs("span",{className:`text-label inline-flex items-center gap-1 min-w-0 break-words ${k.ok?"text-brand":"text-warning"}`,children:[k.ok?e.jsx(ie,{className:"w-4 h-4 shrink-0","aria-hidden":"true"}):e.jsx(he,{className:"w-4 h-4 shrink-0","aria-hidden":"true"}),k.detail]})]})})]})]})]}),e.jsxs("section",{children:[e.jsx("h3",{className:"text-label font-bold text-ink-muted mb-2 px-1",children:t("settings.group.vision")}),e.jsx("div",{className:"surface-card overflow-hidden",children:e.jsx(_t,{activeProvider:c,activeModel:g,presets:m,customProviders:h})})]}),e.jsxs("section",{children:[e.jsx("h3",{className:"text-label font-bold text-ink-muted mb-2 px-1",children:t("settings.group.speech")}),e.jsx("div",{className:"surface-card overflow-hidden",children:e.jsx(Pt,{})})]}),e.jsxs("section",{children:[e.jsx("h3",{className:"text-label font-bold text-ink-muted mb-2 px-1",children:t("settings.group.memory")}),e.jsx("div",{className:"surface-card overflow-hidden",children:e.jsx(Et,{})})]}),e.jsxs("section",{children:[e.jsx("h3",{className:"text-label font-bold text-ink-muted mb-2 px-1",children:t("settings.group.companion")}),e.jsx("div",{className:"surface-card overflow-hidden",children:e.jsx($t,{})})]}),e.jsxs("section",{children:[e.jsx("h3",{className:"text-label font-bold text-ink-muted mb-2 px-1",children:t("settings.group.appearance")}),e.jsxs("div",{className:"surface-card overflow-hidden",children:[e.jsxs("div",{className:N(!1),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-2",children:t("settings.row.theme")}),e.jsx("div",{className:"flex gap-2",children:[{mode:"auto",label:t("settings.theme.auto")},{mode:"light",label:t("settings.theme.light")},{mode:"dark",label:t("settings.theme.dark")}].map(({mode:n,label:w})=>e.jsx("button",{onClick:()=>se.setMode(n),"data-testid":`theme-${n}`,"aria-pressed":se.mode===n,className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${se.mode===n?H:G}`,children:w},n))}),e.jsx("p",{className:"text-label text-ink-muted mt-2",children:se.mode==="auto"?t("settings.theme.following",{mode:t(`settings.theme.${se.resolved}`)}):null})]}),e.jsxs("div",{className:N(!0),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-2",children:t("settings.row.interface_lang")}),e.jsx("div",{className:"flex gap-2",children:["zh-CN","en"].map(n=>e.jsx("button",{onClick:()=>ut(n),"data-testid":`lang-${n}`,"aria-pressed":Fe()===n,className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${Fe()===n?H:G}`,children:n==="zh-CN"?"中文":"English"},n))})]}),e.jsxs("div",{className:N(!0),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-2",children:t("settings.row.import_lang")}),e.jsx(Ct,{})]})]})]}),e.jsxs("section",{children:[e.jsx("h3",{className:"text-label font-bold text-ink-muted mb-2 px-1",children:t("settings.group.data")}),e.jsx("div",{className:"surface-card overflow-hidden",children:e.jsx(Mt,{})})]}),e.jsxs("section",{children:[e.jsx("h3",{className:"text-label font-bold text-ink-muted mb-2 px-1",children:t("settings.group.about")}),e.jsx("div",{className:"surface-card overflow-hidden",children:e.jsxs("div",{className:N(!1),children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-3",children:[e.jsx("div",{className:"text-label font-medium text-ink-strong",children:t("settings.row.version")}),e.jsxs("a",{href:"https://github.com/Kaiji-Z/LookatStudy/releases",target:"_blank",rel:"noopener noreferrer",className:"text-label font-mono text-brand hover:underline","data-testid":"settings-version",children:["v",St.version]})]}),e.jsx("p",{className:"text-label text-ink-muted mt-2",children:t("settings.version.hint")})]})})]})]}),e.jsxs("div",{className:"sticky bottom-0 px-5 py-3 bg-surface-0 border-t border-[var(--border)] flex items-center justify-between gap-3",children:[e.jsx("span",{className:"text-label text-ink-muted",children:t("settings.footer.hint")}),e.jsxs("button",{onClick:ge,"data-testid":"settings-save",className:"btn-3d-brand px-5 py-2 text-body inline-flex items-center gap-1.5",children:[S&&e.jsx(xt,{className:"w-4 h-4","aria-hidden":"true"}),t(S?"settings.saved_text":"settings.footer.save")]})]}),a&&e.jsx(De,{anchorRect:a.rect,message:t("settings.delete_custom_confirm",{name:a.label}),danger:!0,confirmLabel:t("action.delete"),testid:"custom-provider-delete-confirm",onConfirm:()=>{ae(a.id),E(null)},onCancel:()=>E(null)})]})}function Ct(){const[t,m]=i.useState("en"),[o,h]=i.useState(!1);i.useEffect(()=>{l.getSetting("pref_lang").then(r=>{r&&m(r),h(!0)})},[]);const u=async r=>{m(r),await l.setSetting("pref_lang",r)},c=[{code:"en",label:"English"},{code:"zh-CN",label:"简体中文"},{code:"zh-TW",label:"繁體中文"}];return o?e.jsx("div",{className:"flex gap-2","data-testid":"pref-lang-options",children:c.map(r=>e.jsx("button",{onClick:()=>u(r.code),"data-testid":`pref-lang-${r.code}`,"aria-pressed":t===r.code,className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${t===r.code?H:G}`,children:r.label},r.code))}):null}function _t({activeProvider:t,activeModel:m,presets:o,customProviders:h}){const u=te(),[c,r]=i.useState(!1),[g,x]=i.useState(!1),[p,C]=i.useState(""),[f,y]=i.useState(!1),[_,D]=i.useState(!1),[k,P]=i.useState(null),[S,M]=i.useState(!1);i.useEffect(()=>{Promise.all([l.getSetting("flag_multimodal_import"),l.getSetting("vision_provider_override"),l.getSetting("vision_model_override"),l.getSetting("flag_math_vision")]).then(([a,E,T])=>{r(a==="true"),C(E??""),M(T==="true"),x(!0)})},[]);const R=async()=>{const a=!c;r(a),await l.setSetting("flag_multimodal_import",String(a))},L=async()=>{const a=!S;M(a),await l.setSetting("flag_math_vision",String(a))},F=async a=>{await l.setSetting("vision_provider_override",a.id),await l.setSetting("vision_model_override",a.defaultModel),C(a.id),y(!1)},V=async()=>{await l.setSetting("vision_provider_override",""),await l.setSetting("vision_model_override",""),C(""),y(!1)},$=async()=>{if(!_){D(!0),P(null);try{const a=await l.testLlmConnection({vision:!0});P({ok:a.ok,detail:a.detail})}catch(a){P({ok:!1,detail:a instanceof Error?a.message:String(a)})}finally{D(!1)}}},d=h.filter(a=>a.kind==="vision"),j=p.startsWith("custom-")?h.find(a=>a.id===p):null,v=p&&!p.startsWith("custom-")?o.find(a=>a.id===p):null;return g?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"px-4 py-3.5 flex items-center gap-3",children:[e.jsx(le,{checked:c,onChange:R,label:u("settings.multimodal.toggle"),testid:"multimodal-toggle"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-body font-medium text-ink-strong",children:u("settings.multimodal.toggle")}),e.jsx("div",{className:"text-label text-ink-muted",children:u("settings.multimodal.toggle.desc")})]})]}),e.jsxs("div",{className:"px-4 py-3.5 border-t border-[var(--border-faint)] space-y-3",children:[e.jsxs("div",{className:"text-label text-ink-muted bg-ink/5 rounded-lg p-3",children:[e.jsx("div",{className:"font-medium mb-1",children:u("settings.multimodal.current_model",{model:m||u("settings.multimodal.not_selected")})}),e.jsx("div",{children:t.startsWith("custom-")?u("settings.multimodal.hint_custom"):u("settings.multimodal.hint_preset")})]}),e.jsxs("div",{className:"bg-ink/5 rounded-lg p-3",children:[e.jsx("div",{className:"text-label font-medium text-ink-muted mb-2",children:u("settings.multimodal.override_title")}),e.jsx("div",{className:"text-caption text-ink-muted mb-2",children:u("settings.multimodal.override_bridge_hint")}),e.jsxs("div",{className:"space-y-3 mt-1",children:[j&&e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-label",children:[e.jsx(ze,{className:"w-3.5 h-3.5 text-ink-faint shrink-0","aria-hidden":"true"}),e.jsx("span",{className:"font-medium text-ink-strong",children:j.label}),e.jsx("code",{className:"text-ink-faint font-mono break-all",children:j.defaultModel}),e.jsx("span",{className:"text-ink-faint break-all min-w-0",children:j.baseUrl})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("button",{onClick:()=>void $(),disabled:_,"data-testid":"vision-override-test",className:"btn-3d-neutral px-4 py-1.5 text-label disabled:opacity-50",children:u(_?"settings.testing":"settings.multimodal.test_override")}),e.jsx("button",{onClick:()=>y(a=>!a),className:"text-label text-accent hover:underline",children:u("settings.multimodal.replace_custom")}),e.jsx("button",{onClick:()=>void V(),className:"text-label text-ink-muted hover:text-ink-strong",children:u("settings.multimodal.stop_override")}),k&&e.jsxs("span",{className:`text-label inline-flex items-center gap-1 ${k.ok?"text-brand":"text-warning"}`,children:[k.ok?e.jsx(ie,{className:"w-4 h-4","aria-hidden":"true"}):e.jsx(he,{className:"w-4 h-4","aria-hidden":"true"}),k.detail]})]})]}),v&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-label",children:[e.jsx("span",{className:"text-ink-muted",children:u("settings.multimodal.legacy_preset",{label:v.label})}),e.jsx("button",{onClick:()=>void V(),className:"text-label text-ink-muted hover:text-ink-strong underline",children:u("settings.multimodal.stop_override")})]}),!j&&!v&&e.jsxs(e.Fragment,{children:[d.map(a=>e.jsxs("button",{onClick:()=>void F(a),className:"w-full text-left px-3 py-2 rounded-lg bg-surface-1 hover:bg-surface-3 transition-colors","data-testid":`vision-pick-${a.id}`,children:[e.jsx("span",{className:"text-label font-medium text-ink-strong",children:a.label}),e.jsx("span",{className:"text-label text-ink-faint font-mono break-all ml-2",children:a.defaultModel})]},a.id)),(f||d.length===0)&&e.jsx(ye,{kind:"vision",testPrefix:"vision-custom",titleKey:"settings.custom.form_title_vision",modelPhKey:"settings.custom.model_ph_vision",onSaved:a=>void F(a),onCancel:()=>y(!1)}),d.length>0&&e.jsx("button",{onClick:()=>y(a=>!a),className:"text-label text-accent hover:underline",children:u(f?"action.cancel":"settings.custom.new")})]})]})]}),e.jsxs("div",{className:"bg-ink/5 rounded-lg p-3 flex items-center gap-3",children:[e.jsx(le,{checked:S,onChange:L,label:u("settings.mathvision.toggle"),testid:"math-vision-toggle"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-label font-medium text-ink-strong",children:u("settings.mathvision.toggle")}),e.jsx("div",{className:"text-caption text-ink-muted",children:u("settings.mathvision.desc")})]})]})]})]}):null}function Et(){const t=te(),[m,o]=i.useState(!1),[h,u]=i.useState(!1);i.useEffect(()=>{l.getSetting("flag_memory_system").then(r=>{o(r==="true"),u(!0)})},[]);const c=async()=>{const r=!m;o(r),await l.setSetting("flag_memory_system",String(r))};return h?e.jsxs("div",{className:"px-4 py-3.5 flex items-center gap-3",children:[e.jsx(le,{checked:m,onChange:c,label:t("settings.memory.toggle"),testid:"memory-toggle"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-body font-medium text-ink-strong",children:t("settings.memory.toggle")}),e.jsx("div",{className:"text-label text-ink-muted",children:t("settings.memory.toggle.desc")})]})]}):null}function $t(){const t=te(),[m,o]=i.useState(!0),[h,u]=i.useState(!1),c=i.useSyncExternalStore(nt,it),[r,g]=i.useState(!0),[x,p]=i.useState(!1),C=typeof window<"u"&&!!window.__lookatstudyWeb;i.useEffect(()=>{l.getSetting("companion_enabled").then(a=>{o(a!=="false"&&a!=="0"),u(!0)}),l.getSetting("companion_sfx").then(a=>{g(a!=="false"&&a!=="0")}),l.getSetting("companion_pet_mode").then(a=>{p(a==="1")})},[]);const f=async()=>{const a=!m;o(a),await l.setSetting("companion_enabled",String(a)),window.dispatchEvent(new Event("companion-config-changed"))},y=async()=>{const a=!r;g(a),await l.setSetting("companion_sfx",String(a)),window.dispatchEvent(new Event("companion-config-changed"))},_=async()=>{const a=!x;p(a),await l.setSetting("companion_pet_mode",a?"1":"0"),window.dispatchEvent(new Event("companion-config-changed"))},D=async a=>{a!==c.form&&(await l.setSetting("companion_form",a),window.dispatchEvent(new Event("companion-config-changed")))},[k,P]=i.useState([]),[S,M]=i.useState(!1),[R,L]=i.useState(null),[F,V]=i.useState(null),$=i.useCallback(async()=>{try{P((await window.api.companionPackList()).packs)}catch{}},[]);i.useEffect(()=>{$();const a=()=>void $();return window.addEventListener("companion-config-changed",a),()=>window.removeEventListener("companion-config-changed",a)},[$]);const d=async a=>{await window.api.companionPackActivate({id:a}),c.form!=="custom"&&await l.setSetting("companion_form","custom"),await $e(),window.dispatchEvent(new Event("companion-config-changed"))},j=async a=>{(await window.api.companionPackDelete({id:a})).formReset&&window.dispatchEvent(new Event("companion-config-changed")),L(null),V(null),$()},v=async(a,E)=>{var T;await window.api.companionPackSetVehicle({id:a,vehicle:E}),await $(),(T=k.find(O=>O.id===a))!=null&&T.active&&(await $e(),window.dispatchEvent(new Event("companion-config-changed")))};return h?e.jsxs("div",{className:"px-4 py-3.5 flex flex-col gap-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(le,{checked:m,onChange:f,label:t("settings.companion.toggle"),testid:"companion-toggle"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-body font-medium text-ink-strong",children:t("settings.companion.toggle")}),e.jsx("div",{className:"text-label text-ink-muted",children:t("settings.companion.toggle.desc")})]})]}),m&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(le,{checked:r,onChange:y,label:t("settings.companion.sfx"),testid:"companion-sfx-toggle"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-body font-medium text-ink-strong",children:t("settings.companion.sfx")}),e.jsx("div",{className:"text-label text-ink-muted",children:t("settings.companion.sfx.desc")})]})]}),!C&&e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(le,{checked:x,onChange:_,label:t("settings.companion.pet"),testid:"companion-pet-toggle"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-body font-medium text-ink-strong",children:t("settings.companion.pet")}),e.jsx("div",{className:"text-label text-ink-muted",children:t("settings.companion.pet.desc")})]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-label text-ink-muted mb-2",children:t("settings.companion.form")}),e.jsxs("div",{className:"flex flex-wrap gap-2",role:"radiogroup","aria-label":t("settings.companion.form"),children:[lt.filter(a=>a!=="custom").map(a=>{const E=c.form===a;return e.jsxs("button",{type:"button",role:"radio","aria-checked":E,"data-testid":`companion-form-${a}`,onClick:()=>{D(a)},className:`flex flex-col items-center gap-0.5 rounded-xl p-1.5 border motion-safe:transition-colors
8
+ ${E?"border-[var(--accent)] bg-surface-2 shadow-card":"border-[var(--border-faint)] hover:bg-surface-2"}`,title:t(`companion.form.${a}.desc`),children:[e.jsx(ot,{form:a,expression:"happy",pose:"float",size:64}),e.jsx("span",{className:`text-label ${E?"text-ink-strong font-medium":"text-ink-muted"}`,children:t(`companion.form.${a}.name`)})]},a)}),k.map(a=>{const E=c.form==="custom"&&a.active;return e.jsxs("span",{className:"relative inline-block",children:[e.jsxs("button",{type:"button",role:"radio","aria-checked":E,"data-testid":`companion-form-pack-${a.id}`,onClick:()=>{d(a.id)},title:a.name,className:`flex flex-col items-center gap-0.5 rounded-xl p-1.5 border motion-safe:transition-colors
9
+ ${E?"border-[var(--accent)] bg-surface-2 shadow-card":"border-[var(--border-faint)] hover:bg-surface-2"}`,children:[a.thumb?e.jsx("img",{src:a.thumb,alt:"",className:"h-14 w-14 object-contain"}):e.jsx("span",{className:"h-14 w-14 flex items-center justify-center",children:e.jsx("span",{className:"h-9 w-9 rounded-full bg-[#c8a06e]"})}),e.jsx("span",{className:`text-label max-w-20 truncate ${E?"text-ink-strong font-medium":"text-ink-muted"}`,children:a.name})]}),e.jsx("button",{type:"button","aria-label":t("companion.bots.veh"),"data-tooltip":t("companion.bots.veh"),"data-testid":`companion-pack-veh-${a.id}`,onClick:T=>{T.stopPropagation(),V(O=>O===a.id?null:a.id)},className:"absolute -top-1.5 -left-1.5 w-5 h-5 rounded-full border border-black/25 shadow-card hover:scale-110 motion-safe:transition-transform",style:{background:Ee[a.vehicle??"silver"].dot}}),e.jsx("button",{type:"button","aria-label":t("companion.custom.delete"),"data-tooltip":t("companion.custom.delete"),onClick:T=>{T.stopPropagation(),L({id:a.id,rect:T.currentTarget.getBoundingClientRect()})},className:"absolute -top-1.5 -right-1.5 w-5 h-5 rounded-full bg-surface-1 border border-[var(--border-faint)] text-ink-muted hover:text-warning flex items-center justify-center",children:e.jsx(Ve,{className:"w-3 h-3"})})]},a.id)}),e.jsxs("button",{type:"button",role:"radio","aria-checked":!1,"data-testid":"companion-form-add","aria-label":t("companion.bots.add"),onClick:()=>M(!0),className:"flex flex-col items-center gap-0.5 rounded-xl p-1.5 border border-dashed border-[var(--border-faint)] hover:bg-surface-2",children:[e.jsx("span",{className:"h-14 w-14 flex items-center justify-center text-ink-muted",children:e.jsx(Ue,{className:"w-6 h-6"})}),e.jsx("span",{className:"text-label text-ink-muted",children:t("companion.bots.add")})]})]}),F&&e.jsxs("div",{className:"mt-2 rounded-xl border border-[var(--border-faint)] bg-surface-0 p-2.5","data-testid":"companion-veh-picker",children:[e.jsx("div",{className:"text-caption text-ink-muted mb-1.5",children:t("companion.wizard.vehicle")}),e.jsx("div",{className:"flex flex-wrap gap-1.5",role:"radiogroup","aria-label":t("companion.wizard.vehicle"),children:["silver",...We].map(a=>{var T;const E=(((T=k.find(O=>O.id===F))==null?void 0:T.vehicle)??"silver")===a;return e.jsxs("button",{type:"button",role:"radio","aria-checked":E,"data-testid":`companion-veh-pick-${a}`,onClick:()=>void v(F,a),className:`flex items-center gap-1.5 rounded-lg border px-2.5 py-1 text-label motion-safe:transition-colors
10
+ ${E?"border-[var(--accent)] bg-surface-2 text-ink-strong font-medium":"border-[var(--border-faint)] hover:bg-surface-2 text-ink-muted"}`,children:[e.jsx("span",{"aria-hidden":"true",className:"w-3 h-3 rounded-full border border-black/20",style:{background:Ee[a].dot}}),t(a==="silver"?"companion.veh.silver":`companion.form.${a}.name`)]},a)})})]}),R&&e.jsx(De,{anchorRect:R.rect,message:t("companion.bots.deleteConfirm"),danger:!0,testid:"companion-pack-delete-confirm",onConfirm:()=>void j(R.id),onCancel:()=>L(null)}),S&&e.jsx(wt,{onClose:()=>M(!1),onSaved:()=>{M(!1),$()}})]})]})]}):null}function le({checked:t,onChange:m,label:o,testid:h}){return e.jsx("button",{type:"button",role:"switch","aria-checked":t,"aria-label":o,onClick:m,"data-testid":h,className:`relative w-12 h-6 rounded-full transition-colors shrink-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/60 focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--surface-2)] ${t?"bg-brand":"bg-ink/20 hover:bg-ink/25"}`,children:e.jsx("span",{className:`absolute left-0.5 top-1/2 -translate-y-1/2 w-5 h-5 rounded-full bg-white shadow transition-transform ${t?"translate-x-6":""}`})})}const zt=[{id:"zh-CN-XiaoxiaoNeural",label:"zh-CN · 晓晓(女)"},{id:"zh-CN-XiaoyiNeural",label:"zh-CN · 晓伊(女)"},{id:"zh-CN-YunxiNeural",label:"zh-CN · 云希(男)"},{id:"zh-CN-YunyangNeural",label:"zh-CN · 云扬(男·新闻)"},{id:"zh-CN-liaoning-XiaobeiNeural",label:"zh-CN · 晓北(女·东北)"},{id:"zh-CN-shaanxi-XiaoniNeural",label:"zh-CN · 晓妮(女·陕西)"},{id:"en-US-AriaNeural",label:"en-US · Aria(女)"},{id:"en-US-GuyNeural",label:"en-US · Guy(男)"},{id:"en-US-JennyNeural",label:"en-US · Jenny(女)"}],Tt=[{sid:"45",label:"zf_xiaobei(女)"},{sid:"46",label:"zf_xiaoni(女)"},{sid:"47",label:"zf_xiaoxiao(女)"},{sid:"48",label:"zf_xiaoyi(女·默认)"},{sid:"49",label:"zm_yunjian(男)"},{sid:"50",label:"zm_yunxi(男)"},{sid:"51",label:"zm_yunxia(男)"},{sid:"52",label:"zm_yunyang(男)"}];function Pt(){const t=te(),[m,o]=i.useState([]),[h,u]=i.useState(null),[c,r]=i.useState(null),[g,x]=i.useState(null),[p,C]=i.useState(null),[f,y]=i.useState("edge"),[_,D]=i.useState("zh-CN-XiaoxiaoNeural"),[k,P]=i.useState("48"),[S,M]=i.useState("1.0"),[R,L]=i.useState(""),[F,V]=i.useState(""),[$,d]=i.useState([]),j=typeof window<"u"&&"speechSynthesis"in window,[v,a]=i.useState("local"),[E,T]=i.useState("asr-whisper-turbo"),[O,pe]=i.useState(!0),[de,se]=i.useState([]),[oe,re]=i.useState(!1),[B,me]=i.useState(!1),[ge,q]=i.useState(!1),[fe,ae]=i.useState(!1),[K,be]=i.useState(!1),[Z,n]=i.useState(null),[w,W]=i.useState(!1),[Q,U]=i.useState(null),[z,A]=i.useState(null),Y=i.useCallback(()=>{l.listCustomProviders().then(s=>se(s.filter(b=>b.kind==="tts"||b.kind==="asr"))).catch(()=>{})},[]);i.useEffect(()=>{Promise.all([l.getSetting("tts_engine"),l.getSetting("tts_voice_edge"),l.getSetting("tts_sid_local"),l.getSetting("tts_speed"),l.getSetting("tts_custom_voice"),l.getSetting("tts_system_voice"),l.getSetting("asr_engine"),l.getSetting("asr_local_model"),l.getSetting("asr_auto_stop")]).then(([s,b,I,J,ke,Ae,Re,Se,at])=>{s&&y(s),b&&D(b),I&&P(I),J&&M(J),ke&&L(ke),Ae&&V(Ae),Re&&a(Re),(Se==="asr-whisper-turbo"||Se==="asr-whisper-small")&&T(Se),pe(at!=="0")}),Y()},[Y]),i.useEffect(()=>{if(typeof window>"u"||!("speechSynthesis"in window))return;const s=()=>d(pt(window.speechSynthesis.getVoices()));return s(),window.speechSynthesis.addEventListener("voiceschanged",s),()=>window.speechSynthesis.removeEventListener("voiceschanged",s)},[]);const ue=i.useCallback(()=>{window.api.getSpeechModelStatus().then(s=>o(s)).catch(()=>{})},[]);i.useEffect(()=>(ue(),window.api.on("speech:modelProgress",b=>{x({id:b.id,pct:Math.floor(b.progress*100),label:b.currentFile?b.currentFile.split("/").pop()??"":""})})),[ue]);const Be=s=>{r(null),u(s),x({id:s,pct:0,label:""}),window.api.ensureSpeechModel(s).then(()=>{u(null),x(null),ue()}).catch(b=>{u(null),x(null),r(b instanceof Error?b.message:String(b)),ue()})},Ge=s=>{u(s),C(null),window.api.deleteSpeechModel(s).then(ue).catch(b=>r(b instanceof Error?b.message:String(b))).finally(()=>u(null))},He=s=>t(s==="tts-kokoro"?"settings.speech.model.tts":s==="asr-whisper-turbo"?"settings.speech.model.asr_turbo":"settings.speech.model.asr_small"),qe=s=>t(s==="asr-whisper-turbo"?"settings.speech.model.turbo_short":"settings.speech.model.small_short"),Xe=s=>s.startsWith("asr-whisper")?t("settings.speech.license_mit"):t("settings.speech.license"),Te=s=>t(s==="ready"?"settings.speech.state.ready":s==="error"?"settings.speech.state.error":"settings.speech.state.absent"),Pe=s=>{var b;return((b=m.find(I=>I.id===s))==null?void 0:b.state)??"absent"},ce=s=>{y(s),n(null),l.setSetting("tts_engine",s),Ne()},Ye=s=>{V(s),l.setSetting("tts_system_voice",s),Ne()},ve=s=>{a(s),U(null),l.setSetting("asr_engine",s)},je=de.filter(s=>s.kind==="tts"),we=de.filter(s=>s.kind==="asr"),ee=f.startsWith("custom-")?je.find(s=>s.id===f)??null:null,ne=v.startsWith("custom-")?we.find(s=>s.id===v)??null:null,Je=f==="azure",Ze=v==="groq",Qe=v==="azure",et=async()=>{if(!(!ee||K)){be(!0),n(null);try{n(await l.testCustomTts({providerId:ee.id}))}catch(s){n({ok:!1,detail:s instanceof Error?s.message:String(s)})}finally{be(!1)}}},tt=async()=>{if(!(!ne||w)){W(!0),U(null);try{U(await l.testCustomAsr({providerId:ne.id}))}catch(s){U({ok:!1,detail:s instanceof Error?s.message:String(s)})}finally{W(!1)}}},st=async(s,b)=>{A(null);try{await l.deleteCustomProvider(s),b==="tts"&&f===s&&ce("edge"),b==="asr"&&v===s&&ve("local"),Y()}catch{}},Me=s=>{const b=m.find(J=>J.id===s),I=(b==null?void 0:b.state)??"absent";return e.jsxs("div",{className:"flex items-center gap-3 flex-wrap",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("div",{className:"text-label font-medium text-ink-strong truncate",children:He(s)}),e.jsxs("div",{className:"text-caption text-ink-muted",children:[Te(I)," · ",Xe(s)]}),h===s&&(g==null?void 0:g.id)===s&&e.jsx("div",{className:"mt-1.5 h-1.5 rounded-full bg-ink/[0.08] overflow-hidden","data-testid":`speech-dl-bar-${s}`,children:e.jsx("div",{className:"h-full bg-brand transition-all",style:{width:`${g.pct}%`}})}),h===s&&(g==null?void 0:g.id)===s&&e.jsxs("div",{className:"text-caption text-ink-faint mt-0.5","data-testid":`speech-dl-pct-${s}`,children:[g.pct,"%",g.label?` · ${g.label}`:""]})]}),I==="ready"?p===s?e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"text-caption text-warning",children:t("settings.speech.confirm_del")}),e.jsx("button",{onClick:()=>Ge(s),className:"text-label text-warning hover:underline","data-testid":`speech-del-confirm-${s}`,children:t("settings.speech.delete")}),e.jsx("button",{onClick:()=>C(null),className:"text-label text-ink-muted hover:text-ink-strong",children:t("action.cancel")})]}):e.jsx("button",{onClick:()=>C(s),disabled:h===s,className:"text-label text-ink-muted hover:text-warning disabled:opacity-40","data-testid":`speech-del-${s}`,children:t("settings.speech.delete")}):e.jsx("button",{onClick:()=>Be(s),disabled:h!=null||I==="downloading",className:"btn-3d-brand px-3 py-1 text-label disabled:opacity-40","data-testid":`speech-dl-${s}`,children:t(h===s||I==="downloading"?"settings.speech.downloading":"settings.speech.download")})]},s)},Le=(s,b,I,J,ke)=>e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-label",children:[e.jsx(ze,{className:"w-3.5 h-3.5 text-ink-faint shrink-0","aria-hidden":"true"}),e.jsx("span",{className:"font-medium text-ink-strong",children:s.label}),e.jsx("code",{className:"text-ink-faint font-mono break-all",children:s.defaultModel}),e.jsx("span",{className:"text-ink-faint break-all min-w-0",children:s.baseUrl}),s.hasApiKey&&e.jsxs("span",{className:"text-brand shrink-0 inline-flex items-center gap-0.5",children:[e.jsx(ie,{className:"w-3.5 h-3.5","aria-hidden":"true"}),t("settings.speech.key_saved")]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("button",{onClick:()=>void ke(),disabled:I,className:"btn-3d-neutral px-3 py-1 text-label disabled:opacity-40","data-testid":`${b}-custom-test`,children:t(I?"settings.testing":"settings.test")}),z===s.id?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-caption text-warning",children:t("settings.speech.confirm_del_custom")}),e.jsx("button",{onClick:()=>void st(s.id,b),className:"text-label text-warning hover:underline","data-testid":`${b}-custom-del-confirm`,children:t("settings.speech.delete")}),e.jsx("button",{onClick:()=>A(null),className:"text-label text-ink-muted hover:text-ink-strong",children:t("action.cancel")})]}):e.jsx("button",{onClick:()=>A(s.id),className:"text-label text-ink-muted hover:text-warning","data-testid":`${b}-custom-del`,children:t("settings.speech.delete")}),J&&e.jsxs("span",{className:`text-label inline-flex items-center gap-1 ${J.ok?"text-brand":"text-warning"}`,children:[J.ok?e.jsx(ie,{className:"w-4 h-4","aria-hidden":"true"}):e.jsx(he,{className:"w-4 h-4","aria-hidden":"true"}),J.detail]})]})]});return e.jsxs("div",{"data-testid":"settings-speech",children:[e.jsxs("div",{className:N(!1),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-2",children:t("settings.speech.tts_title")}),e.jsxs("div",{className:"flex gap-2 flex-wrap",children:[e.jsx("button",{onClick:()=>{ce("edge"),re(!1),q(!1)},"data-testid":"tts-engine-edge","aria-pressed":f==="edge",className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${f==="edge"?H:G}`,children:t("settings.speech.engine.edge")}),e.jsxs("button",{onClick:()=>{ce("local"),re(!1),q(!1)},"data-testid":"tts-engine-local","aria-pressed":f==="local",className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${f==="local"?H:G}`,children:[t("settings.speech.engine.local"),Pe("tts-kokoro")!=="ready"?` · ${t("settings.speech.state.absent")}`:""]}),e.jsx("button",{onClick:()=>{ce("system"),re(!1),q(!1)},disabled:!j,"data-testid":"tts-engine-system","aria-pressed":f==="system",title:j?void 0:t("settings.speech.engine.system_unavailable"),className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${f==="system"?H:G} ${j?"":"opacity-40 cursor-not-allowed"}`,children:t("settings.speech.engine.system")}),e.jsx("button",{onClick:()=>{re(s=>!s),oe||q(!1)},"data-testid":"tts-engine-custom","aria-pressed":f.startsWith("custom-")||oe,className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${f.startsWith("custom-")||oe?H:G}`,children:t("settings.speech.engine.custom")}),Je&&e.jsxs("button",{disabled:!0,"data-testid":"tts-engine-azure",className:"px-4 py-2 rounded-xl text-body font-bold opacity-50 cursor-not-allowed",children:["Azure · ",t("settings.speech.legacy")]})]}),f==="edge"&&e.jsx("p",{className:"text-label text-ink-muted mt-2",children:t("settings.speech.engine.edge_note")})]}),f==="edge"&&e.jsxs("div",{className:N(!1),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-1.5",children:t("settings.speech.voice")}),e.jsx("select",{value:_,onChange:s=>{D(s.target.value),l.setSetting("tts_voice_edge",s.target.value)},"data-testid":"tts-voice-select",className:`${X} w-full min-w-0 px-2.5 py-1.5`,children:zt.map(s=>e.jsx("option",{value:s.id,children:s.label},s.id))})]}),f==="local"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:N(!1),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-1.5",children:t("settings.speech.voice")}),e.jsx("select",{value:k,onChange:s=>{P(s.target.value),l.setSetting("tts_sid_local",s.target.value)},"data-testid":"tts-sid-select",className:`${X} w-full min-w-0 px-2.5 py-1.5`,children:Tt.map(s=>e.jsx("option",{value:s.sid,children:s.label},s.sid))})]}),e.jsx("div",{className:N(!1),children:Me("tts-kokoro")})]}),f==="system"&&e.jsx(e.Fragment,{children:e.jsxs("div",{className:N(!1),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-1.5",children:t("settings.speech.voice")}),e.jsxs("select",{value:F,onChange:s=>Ye(s.target.value),"data-testid":"tts-system-voice-select",className:`${X} w-full min-w-0 px-2.5 py-1.5`,children:[e.jsx("option",{value:"",children:t("settings.speech.voice_auto")}),$.map(s=>e.jsx("option",{value:s.name,children:ht(s)},s.voiceURI))]}),e.jsx("p",{className:"text-label text-ink-muted mt-2",children:t("settings.speech.engine.system_note")})]})}),oe&&e.jsx("div",{className:N(!1),children:e.jsxs("div",{className:"space-y-3",children:[ee&&Le(ee,"tts",K,Z,et),ee&&e.jsxs("div",{children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-1.5",children:t("settings.speech.voice")}),e.jsx("input",{type:"text",value:R,onChange:s=>L(s.target.value),onBlur:()=>void l.setSetting("tts_custom_voice",R.trim()),placeholder:t("settings.speech.custom_voice_ph"),"data-testid":"tts-custom-voice",className:`${X} w-full min-w-0 px-2.5 py-1.5 font-mono`})]}),!ee&&je.map(s=>e.jsxs("button",{onClick:()=>ce(s.id),className:"w-full text-left px-3 py-2 rounded-lg bg-surface-1 hover:bg-surface-3 transition-colors","data-testid":`tts-pick-${s.id}`,children:[e.jsx("span",{className:"text-label font-medium text-ink-strong",children:s.label}),e.jsx("span",{className:"text-label text-ink-faint font-mono break-all ml-2",children:s.defaultModel})]},s.id)),(ge||!ee&&je.length===0)&&e.jsx(ye,{kind:"tts",showProtocol:!1,testPrefix:"tts-custom",titleKey:"settings.custom.form_title_tts",modelPhKey:"settings.custom.model_ph_tts",testOverride:s=>l.testCustomTts({baseUrl:s.baseUrl,apiKey:s.apiKey||void 0,model:s.model}),onSaved:s=>{ce(s.id),q(!1),Y()},onCancel:()=>q(!1)}),(ee||je.length>0)&&e.jsx("button",{onClick:()=>q(s=>!s),className:"text-label text-accent hover:underline",children:t(ge?"action.cancel":"settings.custom.new")})]})}),e.jsx("div",{className:N(!0),children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-label font-medium text-ink-strong shrink-0 w-14",children:t("settings.speech.speed")}),e.jsx("input",{type:"range",min:"0.5",max:"2",step:"0.05",value:S,onChange:s=>M(s.target.value),onPointerUp:()=>{l.setSetting("tts_speed",S),Ne()},onKeyUp:()=>{l.setSetting("tts_speed",S),Ne()},"data-testid":"tts-speed-range",className:"flex-1 min-w-0 accent-[var(--brand)]"}),e.jsxs("span",{className:"text-label text-ink-muted tabular-nums w-10 text-right","data-testid":"tts-speed-value",children:[Number(S).toFixed(2),"x"]})]})}),e.jsxs("div",{className:N(!0),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-2",children:t("settings.speech.asr_title")}),e.jsxs("div",{className:"flex gap-2 flex-wrap",children:[e.jsx("button",{onClick:()=>{ve("local"),me(!1),ae(!1)},"data-testid":"asr-engine-local","aria-pressed":v==="local",className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${v==="local"?H:G}`,children:t("settings.speech.asr_engine.local")}),e.jsx("button",{onClick:()=>{me(s=>!s),B||ae(!1)},"data-testid":"asr-engine-custom","aria-pressed":v.startsWith("custom-")||B,className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${v.startsWith("custom-")||B?H:G}`,children:t("settings.speech.engine.custom")}),Ze&&e.jsxs("button",{disabled:!0,"data-testid":"asr-engine-groq",className:"px-4 py-2 rounded-xl text-body font-bold opacity-50 cursor-not-allowed",children:["Groq · ",t("settings.speech.legacy")]}),Qe&&e.jsxs("button",{disabled:!0,"data-testid":"asr-engine-azure",className:"px-4 py-2 rounded-xl text-body font-bold opacity-50 cursor-not-allowed",children:["Azure · ",t("settings.speech.legacy")]})]}),v==="local"?e.jsx("p",{className:"text-label text-ink-muted mt-2",children:t("settings.speech.asr_engine.local_note")}):v.startsWith("custom-")&&e.jsx("p",{className:"text-label text-ink-muted mt-2",children:t("settings.speech.asr_engine.custom_note")})]}),v==="local"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:N(!1),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-1.5",children:t("settings.model")}),e.jsx("select",{value:E,onChange:s=>{T(s.target.value),l.setSetting("asr_local_model",s.target.value)},"data-testid":"asr-model-select",className:`${X} w-full min-w-0 px-2.5 py-1.5`,children:["asr-whisper-turbo","asr-whisper-small"].map(s=>e.jsxs("option",{value:s,children:[qe(s)," · ",Te(Pe(s))]},s))})]}),e.jsx("div",{className:N(!1),children:Me(E)})]}),B&&e.jsx("div",{className:N(!1),children:e.jsxs("div",{className:"space-y-3",children:[ne&&Le(ne,"asr",w,Q,tt),!ne&&we.map(s=>e.jsxs("button",{onClick:()=>ve(s.id),className:"w-full text-left px-3 py-2 rounded-lg bg-surface-1 hover:bg-surface-3 transition-colors","data-testid":`asr-pick-${s.id}`,children:[e.jsx("span",{className:"text-label font-medium text-ink-strong",children:s.label}),e.jsx("span",{className:"text-label text-ink-faint font-mono break-all ml-2",children:s.defaultModel})]},s.id)),(fe||!ne&&we.length===0)&&e.jsx(ye,{kind:"asr",showProtocol:!1,testPrefix:"asr-custom",titleKey:"settings.custom.form_title_asr",modelPhKey:"settings.custom.model_ph_asr",testOverride:s=>l.testCustomAsr({baseUrl:s.baseUrl,apiKey:s.apiKey||void 0,model:s.model}),onSaved:s=>{ve(s.id),ae(!1),Y()},onCancel:()=>ae(!1)}),(ne||we.length>0)&&e.jsx("button",{onClick:()=>ae(s=>!s),className:"text-label text-accent hover:underline",children:t(fe?"action.cancel":"settings.custom.new")})]})}),e.jsxs("div",{className:N(!0),children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(le,{checked:O,onChange:()=>{const s=!O;pe(s),l.setSetting("asr_auto_stop",s?"1":"0")},label:t("settings.speech.asr_auto_stop"),testid:"asr-auto-stop-toggle"}),e.jsx("div",{className:"text-body font-medium text-ink-strong",children:t("settings.speech.asr_auto_stop")})]}),e.jsx("p",{className:"text-label text-ink-muted mt-2",children:t("settings.speech.asr_ux_note")})]}),c&&e.jsx("div",{className:"px-4 py-3 text-label text-warning break-all",role:"alert",children:c==="engine-unavailable"?t("chat.speech.engine_unavailable"):c})]})}function Mt(){const t=te(),m=i.useRef(null),[o,h]=i.useState(null),[u,c]=i.useState(!1),[r,g]=i.useState(null);i.useEffect(()=>{l.dshImportDetect().then(h).catch(()=>h({found:!1,path:null,version:null}))},[]);const x=p=>{c(!0),g(null),p.then(g).catch(C=>g({ok:!1,error:String(C)})).finally(()=>c(!1))};return e.jsxs("div",{className:"p-4 space-y-3","data-testid":"settings-dsh-import",children:[e.jsx("div",{className:"text-label font-medium text-ink-strong",children:t("settings.dsh.title")}),e.jsx("p",{className:"text-label text-ink-muted leading-relaxed",children:t("settings.dsh.desc")}),o==null?null:o.found?e.jsxs("div",{className:"flex flex-wrap items-center gap-2","data-testid":"settings-dsh-detected",children:[e.jsx("span",{className:"text-label text-ink-strong",children:t("settings.dsh.detectFound",{v:o.version??"?"})}),e.jsx("button",{onClick:()=>x(l.dshImportFromPath(o.path??"")),disabled:u,"data-testid":"settings-dsh-import-btn",className:"px-3 py-1.5 rounded-xl text-label font-bold btn-3d-brand disabled:opacity-50",children:t(u?"settings.dsh.importing":"settings.dsh.import")})]}):e.jsx("div",{className:"text-label text-ink-muted","data-testid":"settings-dsh-none",children:t("settings.dsh.detectNone")}),e.jsxs("div",{children:[e.jsx("input",{ref:m,type:"file",accept:".json,application/json",className:"hidden","data-testid":"settings-dsh-file-input",onChange:p=>{var f;const C=(f=p.target.files)==null?void 0:f[0];C&&(C.text().then(y=>x(l.dshImportFromText(y))),p.target.value="")}}),e.jsx("button",{onClick:()=>{var p;return(p=m.current)==null?void 0:p.click()},disabled:u,className:"px-3 py-1.5 rounded-xl text-label font-bold btn-3d-neutral disabled:opacity-50",children:t("settings.dsh.pickFile")})]}),u&&!r?e.jsx("div",{className:"text-label text-ink-muted",children:t("settings.dsh.importing")}):null,r!=null&&r.ok?e.jsxs("div",{className:"text-label text-brand leading-relaxed break-all",role:"status","data-testid":"settings-dsh-result",children:[t("settings.dsh.done",{courses:r.coursesCreated+r.coursesMapped+r.coursesRefreshed,nodes:r.nodes,progress:r.progressRows,srs:r.srsRows,xp:r.xpDelta}),r.skippedCourses.length>0?` · ${t("settings.dsh.skipped",{n:r.skippedCourses.length})}`:""]}):r?e.jsxs("div",{className:"text-label text-warning break-all",role:"alert","data-testid":"settings-dsh-error",children:[t("settings.dsh.failed"),": ",r.error??"unknown"]}):null]})}export{Rt as SettingsView};
@@ -1,4 +1,4 @@
1
- import{r as n,j as e}from"./index-DjO1zEnx.js";import{c as f,u as h,e as b,f as g}from"./main-BbOwLoeH.js";import{R as j}from"./rotate-ccw-D1vRxSpM.js";/**
1
+ import{r as n,j as e}from"./index-DZN4z5wF.js";import{c as f,u as h,e as b,f as g}from"./main-CmJlqSDk.js";import{R as j}from"./rotate-ccw-DhViz0iw.js";/**
2
2
  * @license lucide-react v0.468.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-Bnx3pMW2.js";import{p as f}from"./chunk-JWPE2WC7-Q9MkO98l.js";import{_ as n,l as o}from"./mermaid.core-DUsXuPYV.js";import"./transform-B5_amWNh.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BjNU-j_h.js";import"./main-BbOwLoeH.js";import"./index-DjO1zEnx.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},I={parser:R,db:a,renderer:u,styles:p};export{I as diagram};
1
+ import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-c0FQ_SfU.js";import{p as f}from"./chunk-JWPE2WC7-smESCI0k.js";import{_ as n,l as o}from"./mermaid.core-n1vgOa_E.js";import"./transform-B5_amWNh.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BFZHy-wK.js";import"./main-CmJlqSDk.js";import"./index-DZN4z5wF.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},I={parser:R,db:a,renderer:u,styles:p};export{I as diagram};
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-XCWWM2C3-1jGJbVyZ.js";import{p as f}from"./chunk-VII2H2IX-efS7Zm4t.js";import{M as c,b as d}from"./cynefin-OW5HDTMX-GVF3BKWE-B-NBQ_17.js";import{_ as n,l as o}from"./render-O7CIS3YK-DiJ-EmQM.js";import"./transform-B5_amWNh.js";import"./mermaid-layout-elk.core-hmulpQUA.js";import"./main-BbOwLoeH.js";import"./index-DjO1zEnx.js";import"./_commonjs-dynamic-modules-TDtrdbi3.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),m=t?parseInt(t,10):0,l=s?parseInt(s,10):1/0;return{min:m,max:l}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},D={parser:R,db:a,renderer:u,styles:p};export{D as diagram};
1
+ import{g as p,r as u,d as a}from"./chunk-XCWWM2C3-B3diWYxV.js";import{p as f}from"./chunk-VII2H2IX-CTIhHlIp.js";import{M as c,b as d}from"./cynefin-OW5HDTMX-GVF3BKWE-CLl32jOg.js";import{_ as n,l as o}from"./render-O7CIS3YK-C1DYXW0Z.js";import"./transform-B5_amWNh.js";import"./mermaid-layout-elk.core-h_IjwDpP.js";import"./main-CmJlqSDk.js";import"./index-DZN4z5wF.js";import"./_commonjs-dynamic-modules-TDtrdbi3.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),m=t?parseInt(t,10):0,l=s?parseInt(s,10):1/0;return{min:m,max:l}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},D={parser:R,db:a,renderer:u,styles:p};export{D as diagram};
@@ -0,0 +1 @@
1
+ var v=Object.defineProperty;var f=(o,e,t)=>e in o?v(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var m=(o,e,t)=>f(o,typeof e!="symbol"?e+"":e,t);const y={listCourses:"course:list",getCourseTree:"course:getTree",importCourseFromRepo:"course:importFromRepo",detectLanguages:"course:detectLanguages",getCourseLanguages:"course:getLanguages",setCourseLanguage:"course:setLanguage",getCourseLanguage:"course:getLanguage",analyzeRepo:"course:analyzeRepo",importAnalyzed:"course:importAnalyzed",importLocalFolder:"import:localFolder",importGithub:"import:github",importUrl:"import:url",importText:"import:text",importEpub:"import:epub",importAudio:"import:audio",importCancel:"import:cancel",importResume:"import:resume",importPack:"import:importPack",exportPack:"import:exportPack",generateCourseFromMarkdown:"course:generateFromMarkdown",deleteCourse:"course:delete",restructureCourse:"course:restructure",generateSummaries:"course:generateSummaries",getStarterPrompts:"course:getStarterPrompts",getNodeContent:"course:getNodeContent",getNodeSummary:"course:getNodeSummary",getPracticeForLesson:"course:getPracticeForLesson",getLessonForPractice:"course:getLessonForPractice",listAssetsByNode:"asset:listByNode",listAssetsByCourse:"asset:listByCourse",getAssetDataUrl:"asset:getDataUrl",repairMermaidDiagram:"artifact:repairMermaid",getProgress:"progress:get",updateProgress:"progress:update",markNodeAttempted:"progress:markAttempted",generateExercise:"exercise:generate",listExercises:"exercise:list",submitExerciseAnswer:"exercise:submit",examPrepare:"exam:prepare",examRegenerate:"exam:regenerate",examGetStatus:"exam:getStatus",examStartAttempt:"exam:startAttempt",examRecordAnswer:"exam:recordAnswer",examSubmitAttempt:"exam:submitAttempt",getDueReviews:"srs:getDue",getAllSrsItems:"srs:getAll",recordReview:"srs:record",getStreak:"streak:get",touchStreakToday:"streak:touchToday",listSouls:"soul:list",getSoul:"soul:get",createSoul:"soul:create",setActiveSoul:"soul:setActive",getActiveSoul:"soul:getActive",agentChat:"agent:chat",abortAgentChat:"agent:abort",getChatHistory:"agent:getHistory",clearChatHistory:"agent:clearHistory",agentChatThread:"agent:chatThread",abortAgentChatThread:"agent:abortThread",getContextUsage:"agent:getContextUsage",getSpeechModelStatus:"speech:getModelStatus",ensureSpeechModel:"speech:ensureModel",deleteSpeechModel:"speech:deleteModel",ttsSpeak:"speech:ttsSpeak",ttsStop:"speech:ttsStop",asrTranscribe:"speech:asrTranscribe",testCustomTts:"speech:testCustomTts",testCustomAsr:"speech:testCustomAsr",getAttachmentDataUrl:"attachment:getDataUrl",isAgentReady:"agent:isReady",getProviderPresets:"agent:getProviderPresets",testLlmConnection:"agent:testConnection",testCustomProvider:"agent:testCustomProvider",discoverModels:"agent:discoverModels",discoverProviderModels:"agent:discoverProviderModels",listCustomProviders:"customProvider:list",createCustomProvider:"customProvider:create",updateCustomProvider:"customProvider:update",deleteCustomProvider:"customProvider:delete",listPendingProposals:"proposal:listPending",applyProposal:"proposal:apply",rejectProposal:"proposal:reject",recordQuizAnswer:"quiz:recordAnswer",logFriction:"friction:log",getDashboard:"dashboard:get",searchContent:"search:content",updateMemory:"memory:update",getMemory:"memory:get",consolidateMemory:"consolidate:run",getSetting:"settings:get",setSetting:"settings:set",companionPetSetClickThrough:"companionPet:setClickThrough",dshImportDetect:"dsh:detect",dshImportFromPath:"dsh:importFromPath",dshImportFromText:"dsh:importFromText",companionPackCutFromImage:"companionPack:cutFromImage",companionPackApplyPack:"companionPack:applyPack",companionPackGetActive:"companionPack:getActive",companionPackList:"companionPack:list",companionPackActivate:"companionPack:activate",companionPackDelete:"companionPack:delete",companionPackSetVehicle:"companionPack:setVehicle",getXpStatus:"xp:getStatus",exportCourse:"course:export",canvasList:"canvas:list",canvasSave:"canvas:save",canvasDelete:"canvas:delete",canvasTogglePin:"canvas:togglePin",canvasSaveUserNote:"canvas:saveUserNote",canvasRecordQuizResult:"canvas:recordQuizResult",canvasUpdateUserNoteComment:"canvas:updateUserNoteComment",threadList:"thread:list",threadCreate:"thread:create",threadUpdate:"thread:update",threadDelete:"thread:delete",threadGetMessages:"thread:getMessages",threadFindRecentByNode:"thread:findRecentByNode"},h=1,p="ls-serve-token";function S(){const o=new URLSearchParams(window.location.search).get("token");if(o){try{window.localStorage.setItem(p,o)}catch{}return o}try{return window.localStorage.getItem(p)??""}catch{return""}}class g{constructor(){m(this,"ws",null);m(this,"everOpened",!1);m(this,"pending",new Map);m(this,"listeners",new Map);m(this,"connectPromise",null)}connect(){return this.ws&&this.ws.readyState===WebSocket.OPEN?Promise.resolve(this.ws):this.connectPromise?this.connectPromise:(this.connectPromise=new Promise((e,t)=>{const c=window.location.protocol==="https:"?"wss:":"ws:",s=S(),a=`${c}//${window.location.host}/?token=${encodeURIComponent(s)}`;let i=!1;const d=new WebSocket(a);this.ws=d;const l=window.setTimeout(()=>{i||(i=!0,this.connectPromise=null,t(new Error("连接学习服务超时(serve 未启动?)")))},5e3);d.addEventListener("open",()=>{this.everOpened=!0,window.clearTimeout(l),i||(i=!0,this.connectPromise=null,e(d))}),d.addEventListener("message",u=>{let r=null;try{r=JSON.parse(String(u.data))}catch{return}if(!(!r||r.v!==h)){if(r.type==="res"){const n=this.pending.get(r.id);if(!n)return;this.pending.delete(r.id),window.clearTimeout(n.timer),r.ok?n.resolve(r.result):n.reject(new Error(r.error))}else if(r.type==="event"){const n=this.listeners.get(r.channel);if(n)for(const P of n)P(...r.args)}}}),d.addEventListener("close",u=>{if(this.connectPromise=null,this.ws===d&&(this.ws=null),!i){i=!0,window.clearTimeout(l),t(new Error(C(u)));return}const r=u.code===4001?"学习服务拒绝了连接(token 无效)——请用启动时打印的带 token 链接打开":"与服务端的连接已断开";for(const[,n]of this.pending)window.clearTimeout(n.timer),n.reject(new Error(r));if(u.code===4001&&(this.everOpened=!1),this.pending.clear(),u.code===4001){window.dispatchEvent(new CustomEvent(k));return}this.everOpened&&window.setTimeout(()=>void this.connect().catch(()=>{}),2e3)}),d.addEventListener("error",()=>{})}),this.connectPromise)}static bytesToB64(e){const t=new Uint8Array(e);let c="";const s=32768;for(let a=0;a<t.length;a+=s)c+=String.fromCharCode(...t.subarray(a,a+s));return btoa(c)}async invoke(e,...t){var a,i;const c=await this.connect(),s=((i=(a=globalThis.crypto)==null?void 0:a.randomUUID)==null?void 0:i.call(a))??String(Math.random()).slice(2);return new Promise((d,l)=>{const u=window.setTimeout(()=>{this.pending.delete(s),l(new Error(`调用 ${e} 超时`))},3e5);this.pending.set(s,{resolve:d,reject:l,timer:u});const r=e==="speech:asrTranscribe"&&t[0]instanceof ArrayBuffer?[g.bytesToB64(t[0]),...t.slice(1)]:t;c.send(JSON.stringify({v:h,type:"req",id:s,channel:e,args:r}))})}on(e,t){const c=e==="speech:ttsAudio"?(...a)=>{const i=a[0];if(i&&typeof i.wavBase64=="string"){const d=atob(i.wavBase64),l=new Uint8Array(d.length);for(let n=0;n<d.length;n++)l[n]=d.charCodeAt(n);const{wavBase64:u,...r}=i;t({...r,wavBytes:l.buffer})}else t(...a)}:t;let s=this.listeners.get(e);return s||(s=new Set,this.listeners.set(e,s)),s.add(c),this.connect().catch(()=>{}),()=>{s.delete(c)}}}function T(){if(typeof window>"u")return!1;if(new URLSearchParams(window.location.search).get("token"))return!0;try{return!!window.localStorage.getItem(p)}catch{return!1}}function b(o){try{window.localStorage.setItem(p,o)}catch{}const e=new URL(window.location.href);e.searchParams.set("token",o),window.location.replace(e.toString())}const k="ls-web-token-rejected";function C(o){return o.code===4001?"学习服务拒绝了连接(token 无效)——请用启动时打印的带 token 链接打开":"无法连接学习服务(serve 未启动?)"}let w=!1;async function x(){if(w||window.api)return;w=!0;const o=new g,e={};for(const[t,c]of Object.entries(y))e[t]=(...s)=>o.invoke(c,...s);e.on=(t,c)=>o.on(t,c),window.api=e,window.__lookatstudyWeb=!0}function E(){return new g}export{k as TOKEN_REJECTED_EVENT,E as createWebTransportForTest,T as hasWebToken,x as installWebApi,b as setWebToken};