lookatstudy-mobile 0.26.0 → 0.27.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 (134) hide show
  1. package/package.json +1 -1
  2. package/server.cjs +84 -16
  3. package/web/assets/{CanvasStage-sR8T2IFn.js → CanvasStage-DNMSEgol.js} +1 -1
  4. package/web/assets/{CommandPalette-xoHRtFTt.js → CommandPalette-DOGHfdG5.js} +1 -1
  5. package/web/assets/{CourseSearchPanel-Blz5uOZo.js → CourseSearchPanel-Bkbkr4aJ.js} +1 -1
  6. package/web/assets/{ExamView-DcD9-XhK.js → ExamView-BCVCCOa3.js} +1 -1
  7. package/web/assets/{ReviewPanel-DPX_Gbvn.js → ReviewPanel-DPKPl7CY.js} +1 -1
  8. package/web/assets/{SettingsView-DpSiGIUo.js → SettingsView-ClaF3_aU.js} +2 -2
  9. package/web/assets/{VoicePanel-BFuMIduE.js → VoicePanel-CekOlcc8.js} +1 -1
  10. package/web/assets/{abnfDiagram-N423BO3Z-BRYm-LZF.js → abnfDiagram-N423BO3Z-DOQZb2xo.js} +1 -1
  11. package/web/assets/{abnfDiagram-VCTEODGH-ODA7YWAP-B--kWzEh.js → abnfDiagram-VCTEODGH-ODA7YWAP-CsHfYWvv.js} +1 -1
  12. package/web/assets/{architectureDiagram-5GKGNRK7-C4PU3XN7-DzOQ5fo_.js → architectureDiagram-5GKGNRK7-C4PU3XN7-6iVsZX0_.js} +1 -1
  13. package/web/assets/{architectureDiagram-T3A2C74G-BhljJtMX.js → architectureDiagram-T3A2C74G-P3yKV-lr.js} +1 -1
  14. package/web/assets/{arrow-right-DtCWRkvj.js → arrow-right-qKdXLzu6.js} +1 -1
  15. package/web/assets/{blockDiagram-NRAW4CY4-UMJ6PMQQ-D3KXfJhJ.js → blockDiagram-NRAW4CY4-UMJ6PMQQ-CuM6trsc.js} +1 -1
  16. package/web/assets/{blockDiagram-VBNYF7ZC-Dr7ZTeLw.js → blockDiagram-VBNYF7ZC-DDk2YbO6.js} +1 -1
  17. package/web/assets/{c4Diagram-5PPSVZJV-CPi9fgO4.js → c4Diagram-5PPSVZJV-j2ZUscpm.js} +1 -1
  18. package/web/assets/{c4Diagram-UCG6FXSJ-75X3U2P3-Bj0Dw0IT.js → c4Diagram-UCG6FXSJ-75X3U2P3-BhXwa2_0.js} +1 -1
  19. package/web/assets/channel-EEfL6EAQ.js +1 -0
  20. package/web/assets/{chunk-2GRJ4B5K-DeZ82qe7.js → chunk-2GRJ4B5K-BTFty44j.js} +1 -1
  21. package/web/assets/{chunk-2Q5K7J3B-B1WwbyzY.js → chunk-2Q5K7J3B-C5fvA7Eq.js} +1 -1
  22. package/web/assets/{chunk-5RXB4S5H-BX9ZzOwO.js → chunk-5RXB4S5H-WV8esdcK.js} +1 -1
  23. package/web/assets/{chunk-5VM5RSS4-9-QvfnU2.js → chunk-5VM5RSS4-BoBIDUCk.js} +1 -1
  24. package/web/assets/{chunk-6Q2QTUOP-Dkt-zdDg.js → chunk-6Q2QTUOP-Cs0KaQW0.js} +1 -1
  25. package/web/assets/{chunk-7XDTSPCN-DOxJ22Ws.js → chunk-7XDTSPCN-DDQpQZsI.js} +1 -1
  26. package/web/assets/{chunk-CTNIYPP6-2D6eMEGx.js → chunk-CTNIYPP6-BPadHbsN.js} +1 -1
  27. package/web/assets/{chunk-CXNFBKHE-BETxgCVr.js → chunk-CXNFBKHE-SHnvUt_i.js} +1 -1
  28. package/web/assets/{chunk-GF5L2VYU-JBwf_TWs.js → chunk-GF5L2VYU-c12C7v89.js} +1 -1
  29. package/web/assets/{chunk-ISA7TJRJ-DGTMMKAm.js → chunk-ISA7TJRJ-ClMVde_-.js} +1 -1
  30. package/web/assets/{chunk-JWPE2WC7-B_A1as9r.js → chunk-JWPE2WC7-ClPRM8pm.js} +1 -1
  31. package/web/assets/{chunk-KBJHAD2P-bmR9qwSi.js → chunk-KBJHAD2P-DZ7EZEZb.js} +1 -1
  32. package/web/assets/{chunk-LV3HUYFY-D8UFu3pb.js → chunk-LV3HUYFY-4aPtOCBm.js} +1 -1
  33. package/web/assets/{chunk-M3IUQBOH-r4ZZKIWR.js → chunk-M3IUQBOH-DBU52Xr6.js} +1 -1
  34. package/web/assets/{chunk-NDIOYS4C-BuC155ii.js → chunk-NDIOYS4C-DQmxBw-x.js} +1 -1
  35. package/web/assets/{chunk-RE4WF27V-DJoYieaa.js → chunk-RE4WF27V-RhzmIq0E.js} +1 -1
  36. package/web/assets/{chunk-RYQCIY6F-DNF6lO1-.js → chunk-RYQCIY6F-UooxVkfM.js} +1 -1
  37. package/web/assets/{chunk-VII2H2IX-DBudi9Y-.js → chunk-VII2H2IX-D5rI4IMH.js} +1 -1
  38. package/web/assets/{chunk-X5GNSKZ3-Dzcgoim8.js → chunk-X5GNSKZ3-BbHeF3fC.js} +1 -1
  39. package/web/assets/{chunk-XCWWM2C3-3YSDgOL-.js → chunk-XCWWM2C3-BfWmJ7To.js} +1 -1
  40. package/web/assets/{chunk-XXDRQBXY-B5LLJm9i.js → chunk-XXDRQBXY-DQhvlU9n.js} +1 -1
  41. package/web/assets/classDiagram-DTDB5LWJ-LWRDKZ5K-DCqwWJZy.js +1 -0
  42. package/web/assets/classDiagram-JCYQIIEL-B1aHEwO7.js +1 -0
  43. package/web/assets/classDiagram-v2-JRS7N3AN-2BZHGRP2-DCqwWJZy.js +1 -0
  44. package/web/assets/classDiagram-v2-OCEON4UE-B1aHEwO7.js +1 -0
  45. package/web/assets/{core-Cf-iwesp.js → core-D-c45hIK.js} +1 -1
  46. package/web/assets/{cose-bilkent-JH36ORCC-DweZYTE6.js → cose-bilkent-JH36ORCC-BeMdpuaR.js} +1 -1
  47. package/web/assets/{cose-bilkent-JH36ORCC-OB24KH3T-D3S0f4LW.js → cose-bilkent-JH36ORCC-OB24KH3T-CSWmzMOB.js} +1 -1
  48. package/web/assets/{cynefin-OW5HDTMX-GVF3BKWE-DrtBkvjj.js → cynefin-OW5HDTMX-GVF3BKWE-Lm-LiSAP.js} +1 -1
  49. package/web/assets/{cynefin-VYW2F7L2-lYm8p8qp.js → cynefin-VYW2F7L2-YHGLBbI5.js} +1 -1
  50. package/web/assets/{cynefinDiagram-5FMLGOSQ-H3WIRU3N-CGurIKbY.js → cynefinDiagram-5FMLGOSQ-H3WIRU3N-7Vh1ZSti.js} +1 -1
  51. package/web/assets/{cynefinDiagram-MW4NZA55-EMZxCSzT.js → cynefinDiagram-MW4NZA55-DkK5YHvu.js} +1 -1
  52. package/web/assets/{dagre-3AP2YEHR-DCERTXHT-B3xLLC4U.js → dagre-3AP2YEHR-DCERTXHT-BJn7VnK1.js} +1 -1
  53. package/web/assets/{dagre-VZM6K2ZE-lqYJ3WXC.js → dagre-VZM6K2ZE-CQyP5qUi.js} +1 -1
  54. package/web/assets/{diagram-7IWD3JNH-DXSSf7q4.js → diagram-7IWD3JNH-DXm677-d.js} +1 -1
  55. package/web/assets/{diagram-B4RE2ZJO-ak7sOZ19.js → diagram-B4RE2ZJO-BIMQ0oLa.js} +1 -1
  56. package/web/assets/{diagram-LBJQPF4R-XmQxOAH-.js → diagram-LBJQPF4R-PFvTKOya.js} +1 -1
  57. package/web/assets/{diagram-Q27KOJAE-D-yQEvjN.js → diagram-Q27KOJAE-B1Tmb6Ku.js} +1 -1
  58. package/web/assets/{diagram-S7CK7UJ4-MULGZGEL-D5WNGIG9.js → diagram-S7CK7UJ4-MULGZGEL-C5zy1zA4.js} +1 -1
  59. package/web/assets/{diagram-UB23O5K3-CRgze-MQ.js → diagram-UB23O5K3-D-4ppWGw.js} +1 -1
  60. package/web/assets/{diagram-UQ7AKVKN-YQBY353J-CSvMx1Fm.js → diagram-UQ7AKVKN-YQBY353J-BbpzDiip.js} +1 -1
  61. package/web/assets/{diagram-VSXAHHWV-WLNH2ELY-DMVZ0M5s.js → diagram-VSXAHHWV-WLNH2ELY-bsM84BZx.js} +1 -1
  62. package/web/assets/{diagram-VX7I27RA-XW6YQV5G-NONTq7mV.js → diagram-VX7I27RA-XW6YQV5G-X-rdKlI6.js} +1 -1
  63. package/web/assets/{diagram-Z3DM3KII-HG7RF65D-D0VfGCJh.js → diagram-Z3DM3KII-HG7RF65D-D7MWxwSv.js} +1 -1
  64. package/web/assets/{ebnfDiagram-BXEA7PRR-D0k0RumW.js → ebnfDiagram-BXEA7PRR-DoiZT1RV.js} +1 -1
  65. package/web/assets/{ebnfDiagram-PWID7BFC-OKY4VHYD-By7cMb-m.js → ebnfDiagram-PWID7BFC-OKY4VHYD-BQRttaG7.js} +1 -1
  66. package/web/assets/{erDiagram-JOGREHBK-DxDlKHXu.js → erDiagram-JOGREHBK-CnX8nBDP.js} +1 -1
  67. package/web/assets/{erDiagram-SSCWMZ5O-PIPKOIK7-DwWrIKUB.js → erDiagram-SSCWMZ5O-PIPKOIK7-Dwtqeon0.js} +1 -1
  68. package/web/assets/{flowDiagram-A5DVABFB-2Z4AVO5R-eqJKcw9W.js → flowDiagram-A5DVABFB-2Z4AVO5R-Bi0_af-o.js} +1 -1
  69. package/web/assets/{flowDiagram-UKHOOZJN-CC84JD3t.js → flowDiagram-UKHOOZJN-6bJKKprv.js} +1 -1
  70. package/web/assets/{ganttDiagram-EL5Y4UJY-JZNG7GOG-CWOtJ46k.js → ganttDiagram-EL5Y4UJY-JZNG7GOG-BnL73nRe.js} +1 -1
  71. package/web/assets/{ganttDiagram-PKOTCBZU-Bw78KC7C.js → ganttDiagram-PKOTCBZU-thux7v5c.js} +1 -1
  72. package/web/assets/{gitGraphDiagram-DS77QQ5N-CywKDUgv.js → gitGraphDiagram-DS77QQ5N-BCxwGbEn.js} +1 -1
  73. package/web/assets/{gitGraphDiagram-WWUBYQGX-DMWMLL3G-DIUZBjRH.js → gitGraphDiagram-WWUBYQGX-DMWMLL3G-BfjGgW9v.js} +1 -1
  74. package/web/assets/{index-CAFnQS2L.js → index-DGtU5wXR.js} +1 -1
  75. package/web/assets/{index-BLO7CDRf.js → index-DomuSTqN.js} +1 -1
  76. package/web/assets/{index-WF4B6heO.js → index-FXb7NZ5E.js} +3 -3
  77. package/web/assets/{infoDiagram-6WML65LV-DFCB1zK_.js → infoDiagram-6WML65LV-DFa_1TEH.js} +1 -1
  78. package/web/assets/{infoDiagram-RXCK75RN-HANS5KVC-CR0XCzL1.js → infoDiagram-RXCK75RN-HANS5KVC-DUY1MiV5.js} +1 -1
  79. package/web/assets/{ishikawaDiagram-5VMMS53U-7GCIT7WU-BQmMapB0.js → ishikawaDiagram-5VMMS53U-7GCIT7WU-BEdK9djl.js} +1 -1
  80. package/web/assets/{ishikawaDiagram-WSZJBQD7-CDVYsb8F.js → ishikawaDiagram-WSZJBQD7-5tTWoDBo.js} +1 -1
  81. package/web/assets/{journeyDiagram-EYS64GPL-OAPELBT7-Bv57BEbI.js → journeyDiagram-EYS64GPL-OAPELBT7-UNEI_RjL.js} +1 -1
  82. package/web/assets/{journeyDiagram-NVQOT4AX-BUhHhw49.js → journeyDiagram-NVQOT4AX-CukB8z5f.js} +1 -1
  83. package/web/assets/{kanban-definition-27J2QSJJ-DJWi_jsV.js → kanban-definition-27J2QSJJ-B4iZSiYt.js} +1 -1
  84. package/web/assets/{kanban-definition-3QL26DDD-I7RKWQQY-DeQuTmff.js → kanban-definition-3QL26DDD-I7RKWQQY-BB4W5u2i.js} +1 -1
  85. package/web/assets/{katex-N6JRN4PM-CsmS8bAu.js → katex-N6JRN4PM-CnmSKTP0.js} +1 -1
  86. package/web/assets/{main-Bkgg11ZB.js → main-R_XeRh0m.js} +6 -6
  87. package/web/assets/{mermaid-layout-elk.core-DDX9gcIM.js → mermaid-layout-elk.core-CO-HyDSW.js} +2 -2
  88. package/web/assets/{mermaid.core-D0rh4nEj.js → mermaid.core-BHx7xkjm.js} +4 -4
  89. package/web/assets/{mindmap-definition-FAOFIHXS-nqKMiE2n.js → mindmap-definition-FAOFIHXS-BFnPDy2J.js} +1 -1
  90. package/web/assets/{mindmap-definition-FBJOCRG2-KIYZG64Y-CgkstHv4.js → mindmap-definition-FBJOCRG2-KIYZG64Y-CjtYO_dt.js} +1 -1
  91. package/web/assets/{pegDiagram-VL7TDLO6-Cy8v2veR.js → pegDiagram-VL7TDLO6-CJcrVsXf.js} +1 -1
  92. package/web/assets/{pegDiagram-XKGWAZYB-OIP57N6J-DHOcOx86.js → pegDiagram-XKGWAZYB-OIP57N6J-BUrEZLtC.js} +1 -1
  93. package/web/assets/{pieDiagram-7S7Q4E2Y-D2e6HI5F.js → pieDiagram-7S7Q4E2Y-C-7bL99T.js} +1 -1
  94. package/web/assets/{pieDiagram-E7YTZNPT-2UOTW327-9oqFgJEQ.js → pieDiagram-E7YTZNPT-2UOTW327-BbnFcXfp.js} +1 -1
  95. package/web/assets/{quadrantDiagram-AXDQQJYC-SN3ASJJK-aRI00491.js → quadrantDiagram-AXDQQJYC-SN3ASJJK-Cw3ovD9g.js} +1 -1
  96. package/web/assets/{quadrantDiagram-CIZ2JOQS-BxVU5r4V.js → quadrantDiagram-CIZ2JOQS-CZAcVKAt.js} +1 -1
  97. package/web/assets/{railroadDiagram-AXF67PYL-CxcdKdyz.js → railroadDiagram-AXF67PYL-D0VcOl3S.js} +1 -1
  98. package/web/assets/{railroadDiagram-O6MQD6OU-34742W6X-82y7OitY.js → railroadDiagram-O6MQD6OU-34742W6X-BZgG3Coc.js} +1 -1
  99. package/web/assets/{render-O7CIS3YK-0coM2jiE.js → render-O7CIS3YK-C7OYYEUs.js} +7 -7
  100. package/web/assets/{requirementDiagram-EFPCY7ZU-NGAFFSMB-CiCBt9Q_.js → requirementDiagram-EFPCY7ZU-NGAFFSMB-C7esBPmA.js} +1 -1
  101. package/web/assets/{requirementDiagram-LRYGKXZP-a-jqBbh4.js → requirementDiagram-LRYGKXZP-BrcTMfVw.js} +1 -1
  102. package/web/assets/{rotate-ccw-DPfbZXyQ.js → rotate-ccw-Dx5d1uPC.js} +1 -1
  103. package/web/assets/{sankeyDiagram-P5KCCOFB-3D3M4XPB-vVOpmIBk.js → sankeyDiagram-P5KCCOFB-3D3M4XPB-DFimNIgR.js} +1 -1
  104. package/web/assets/{sankeyDiagram-W5VNT64P-CXBDBsJf.js → sankeyDiagram-W5VNT64P-CSwlW6BG.js} +1 -1
  105. package/web/assets/{sequenceDiagram-SI44F4Z6-BEzEovun.js → sequenceDiagram-SI44F4Z6-CUpSf2Hy.js} +1 -1
  106. package/web/assets/{sequenceDiagram-WJ2MYXX4-Q2IOPB4R-BAt30Hjd.js → sequenceDiagram-WJ2MYXX4-Q2IOPB4R-CcL0Mjkm.js} +1 -1
  107. package/web/assets/{sizeCapture-X5ZJPWSS-PSGVOMYM-DPuPQlRM.js → sizeCapture-X5ZJPWSS-PSGVOMYM-CFIpsewj.js} +1 -1
  108. package/web/assets/{sizeCapture-X5ZJPWSS-CqVF9LHS.js → sizeCapture-X5ZJPWSS-bAjmXhCP.js} +1 -1
  109. package/web/assets/{stateDiagram-HBIQ2CUA-4M2S6MAN-DnF-bmgm.js → stateDiagram-HBIQ2CUA-4M2S6MAN-5J1mWHrR.js} +1 -1
  110. package/web/assets/{stateDiagram-OKZ733FA-CKebmBa5.js → stateDiagram-OKZ733FA-DC5gG091.js} +1 -1
  111. package/web/assets/stateDiagram-v2-4QOOHH4V-LBBLA2WV-lEbj38VR.js +1 -0
  112. package/web/assets/stateDiagram-v2-UEYNNEHI-BvX77KlN.js +1 -0
  113. package/web/assets/{swimlanes-SLNWSIFB-M10HmJH-.js → swimlanes-SLNWSIFB-nPJNxth4.js} +2 -2
  114. package/web/assets/{swimlanes-XN3QIQJK-N6N2CCQ6-DzcOR4_D.js → swimlanes-XN3QIQJK-N6N2CCQ6-C4FhSjwI.js} +1 -1
  115. package/web/assets/swimlanesDiagram-ULZ7WXOC-Om5gw3wr.js +8 -0
  116. package/web/assets/swimlanesDiagram-VK2B7HYN-E6N4H5SY-DEr_rxab.js +8 -0
  117. package/web/assets/{timeline-definition-24CTP7MA-KN7RSRVM-CMhLQnxM.js → timeline-definition-24CTP7MA-KN7RSRVM-O4kuzgM9.js} +1 -1
  118. package/web/assets/{timeline-definition-Z64GVDOM-LcGdwXI-.js → timeline-definition-Z64GVDOM-BWZEztQm.js} +1 -1
  119. package/web/assets/{vennDiagram-4TSXK5OY-AKJ7LXAN-CKicd48A.js → vennDiagram-4TSXK5OY-AKJ7LXAN-D2CR92HA.js} +1 -1
  120. package/web/assets/{vennDiagram-T6HMQDX7-D7hxv4W7.js → vennDiagram-T6HMQDX7-kk8VvKob.js} +1 -1
  121. package/web/assets/{wardleyDiagram-T6FBY63Y-DnTzvRkP.js → wardleyDiagram-T6FBY63Y-CMOhwu7j.js} +1 -1
  122. package/web/assets/{wardleyDiagram-VM6X3IG4-3B6A3BN5-CBmbko0H.js → wardleyDiagram-VM6X3IG4-3B6A3BN5-CNMnxTE2.js} +1 -1
  123. package/web/assets/{xychartDiagram-ELKLHX3M-B1fLmbSX.js → xychartDiagram-ELKLHX3M-BdhS5zr6.js} +1 -1
  124. package/web/assets/{xychartDiagram-S5SC5T6Z-OBDNV6WG-D1kFCVEP.js → xychartDiagram-S5SC5T6Z-OBDNV6WG-BgRm-vdy.js} +1 -1
  125. package/web/index.html +1 -1
  126. package/web/assets/channel-aqWuF1WT.js +0 -1
  127. package/web/assets/classDiagram-DTDB5LWJ-LWRDKZ5K-DhFaZ76j.js +0 -1
  128. package/web/assets/classDiagram-JCYQIIEL-CNvSQ-RA.js +0 -1
  129. package/web/assets/classDiagram-v2-JRS7N3AN-2BZHGRP2-DhFaZ76j.js +0 -1
  130. package/web/assets/classDiagram-v2-OCEON4UE-CNvSQ-RA.js +0 -1
  131. package/web/assets/stateDiagram-v2-4QOOHH4V-LBBLA2WV-BLTGkUFQ.js +0 -1
  132. package/web/assets/stateDiagram-v2-UEYNNEHI-BLjk4IRo.js +0 -1
  133. package/web/assets/swimlanesDiagram-ULZ7WXOC-DCxkAVHU.js +0 -8
  134. package/web/assets/swimlanesDiagram-VK2B7HYN-E6N4H5SY-JLTPHNIv.js +0 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lookatstudy-mobile",
3
- "version": "0.26.0",
3
+ "version": "0.27.0",
4
4
  "description": "LookatStudy Termux portable bundle (server.cjs + web frontend)",
5
5
  "repository": {
6
6
  "type": "git",
package/server.cjs CHANGED
@@ -59689,6 +59689,20 @@ function readSettingsMap(db) {
59689
59689
  map3[r.key] = r.value;
59690
59690
  return map3;
59691
59691
  }
59692
+ function resolveActiveContextWindow(db) {
59693
+ const settings2 = readSettingsMap(db);
59694
+ const providerId = settings2.active_provider ?? "glm";
59695
+ const preset = getProviderPreset(providerId);
59696
+ const model = settings2.active_model ?? preset?.defaultModel ?? "";
59697
+ if (preset)
59698
+ return resolveModelContextWindow(preset.models, model);
59699
+ if (providerId.startsWith("custom-")) {
59700
+ const cp = getCustomProvider(db, providerId);
59701
+ if (cp)
59702
+ return resolveModelContextWindow(cp.models, model);
59703
+ }
59704
+ return null;
59705
+ }
59692
59706
  function buildLanguageModel(protocol, baseUrl, apiKey, model, fetchFn) {
59693
59707
  switch (protocol) {
59694
59708
  case "openai-compatible": {
@@ -553860,6 +553874,39 @@ init_schema();
553860
553874
  init_db2();
553861
553875
  init_llm_client();
553862
553876
 
553877
+ // shared/history-budget.ts
553878
+ function trimHistoryToBudget(messages, budgetTokens, costOf, minKeep = 2) {
553879
+ let acc = 0;
553880
+ let cut = 0;
553881
+ let trimmed = false;
553882
+ for (let i = messages.length - 1; i >= 0; i--) {
553883
+ const next = acc + costOf(messages[i]);
553884
+ if (next > budgetTokens) {
553885
+ cut = i + 1;
553886
+ trimmed = true;
553887
+ break;
553888
+ }
553889
+ acc = next;
553890
+ }
553891
+ if (trimmed && messages.length - cut < minKeep) {
553892
+ cut = Math.max(0, messages.length - minKeep);
553893
+ }
553894
+ return {
553895
+ kept: messages.slice(cut),
553896
+ droppedCount: cut
553897
+ };
553898
+ }
553899
+
553900
+ // shared/token-estimate.ts
553901
+ var CJK_RE = /[\u2E80-\u9FFF\uF900-\uFAFF\u3000-\u303F\uFF00-\uFFEF]/g;
553902
+ function estimateTokens(text3) {
553903
+ if (!text3)
553904
+ return 0;
553905
+ const cjk = (text3.match(CJK_RE) ?? []).length;
553906
+ const other = text3.length - cjk;
553907
+ return Math.ceil(cjk * 11 / 10 + other / 4);
553908
+ }
553909
+
553863
553910
  // src/main/services/flags.ts
553864
553911
  init_db2();
553865
553912
  init_schema();
@@ -554139,10 +554186,23 @@ function questionLanguageLine(locale) {
554139
554186
 
554140
554187
  // src/main/services/agent/base-prompt.ts
554141
554188
  var BASE_AGENT_PROMPT_HEAD = "\u4F60\u662F LookatStudy \u7684 AI \u5B66\u4E60\u5BFC\u5E08\u3002\u5B66\u4E60\u8005\u6B63\u5728\u5B66\u4E00\u95E8\u7531 GitHub \u6587\u6863\u751F\u6210\u7684\u8BFE\u7A0B\u3002\u4F60\u7684\u804C\u8D23\u662F\u5E2E\u5B66\u4E60\u8005\u771F\u6B63\u7406\u89E3\u77E5\u8BC6\uFF0C\u4E0D\u662F\u7B80\u5355\u590D\u8FF0\u6587\u6863\u3002";
554142
- var BASE_AGENT_PROMPT_TAIL = "\u3010\u9632\u5E7B\u89C9\u7EA2\u7EBF\u3011\u4F60\u5FC5\u987B\u4E25\u683C\u57FA\u4E8E\u4E0B\u9762\u63D0\u4F9B\u7684\u300C\u8BFE\u7A0B\u4E0A\u4E0B\u6587\u300D\u548C\u300C\u5F53\u524D\u8282\u70B9\u5185\u5BB9\u300D\u56DE\u7B54\u3002\u5BF9\u4E8E\u8BFE\u7A0B\u6807\u9898\u4E2D\u51FA\u73B0\u7684\u4E13\u6709\u540D\u8BCD\u3001\u7F29\u5199\uFF08\u5982 FDE = Forward Deployment Engineer\uFF09\uFF0C\u5FC5\u987B\u4F7F\u7528\u8BFE\u7A0B\u4E0A\u4E0B\u6587\u91CC\u7684\u5B9A\u4E49\uFF0C\u7EDD\u4E0D\u53EF\u81EA\u884C\u731C\u6D4B\u6216\u7F16\u9020\u3002\u5982\u679C\u5B66\u4E60\u8005\u95EE\u7684\u5185\u5BB9\u8D85\u51FA\u4E86\u4F60\u638C\u63E1\u7684\u4E0A\u4E0B\u6587\uFF0C\u660E\u786E\u8BF4'\u8FD9\u90E8\u5206\u5185\u5BB9\u4E0D\u5728\u5F53\u524D\u8BFE\u7A0B\u6750\u6599\u4E2D'\uFF0C\u800C\u4E0D\u662F\u7F16\u9020\u4E00\u4E2A\u770B\u4F3C\u5408\u7406\u7684\u56DE\u7B54\u3002\n\n\u3010\u6A21\u7CCA\u63D0\u95EE\u5904\u7406\u3011\u5F53\u5B66\u4E60\u8005\u8BF4'\u6211\u4E0D\u61C2''\u4E0D\u592A\u7406\u89E3'\u4F46\u6CA1\u8BF4\u5177\u4F53\u4E0D\u61C2\u4EC0\u4E48\u65F6\uFF0C\u4E0D\u8981\u5047\u8BBE\u4F60\u77E5\u9053\u4ED6\u54EA\u91CC\u4E0D\u61C2\u7136\u540E\u957F\u7BC7\u5927\u8BBA\u3002\u5148\u53CD\u95EE'\u4F60\u5177\u4F53\u662F\u54EA\u4E2A\u6982\u5FF5\u4E0D\u592A\u6E05\u695A\uFF1F'\uFF0C\u6216\u8005\u5217\u51FA\u8FD9\u8BFE\u6D89\u53CA\u7684 2-3 \u4E2A\u6838\u5FC3\u6982\u5FF5\u8BA9\u4ED6\u9009\u3002\u53EA\u8BB2\u89E3\u5B66\u4E60\u8005\u660E\u786E\u95EE\u5230\u7684\u90E8\u5206\uFF0C\u4E0D\u8981\u4E3B\u52A8\u6269\u5C55\u5230\u8BFE\u7A0B\u5185\u5BB9\u4E4B\u5916\u7684\u9886\u57DF\u77E5\u8BC6\u3002\n\n\u3010Generative UI \u6559\u5B66\u5DE5\u5177\u3011\u4F60\u6709\u51E0\u4E2A\u80FD\u751F\u6210\u53EF\u89C6\u5316\u5B66\u4E60\u4EA7\u7269\u7684\u5DE5\u5177\uFF0C\u9002\u65F6\u4F7F\u7528\u80FD\u5927\u5E45\u63D0\u5347\u7406\u89E3\uFF1A- show_concept_map:\u7406\u6E05\u6982\u5FF5\u95F4\u5173\u7CFB(\u67B6\u6784/\u4F9D\u8D56/\u5206\u7C7B),\u5B66\u4E60\u8005\u8BF4'\u7406\u4E0D\u6E05''\u6709\u4EC0\u4E48\u5173\u7CFB'\u65F6\u7528;- generate_quiz:\u51FA\u9898\u68C0\u9A8C,\u5B66\u4E60\u8005\u8BF4'\u8003\u8003\u6211''\u51FA\u9898'\u65F6,\u6216\u8BB2\u5B8C\u4E00\u8282\u4E3B\u52A8\u51FA 2-3 \u9898\u5DE9\u56FA;- compare_table:\u5BF9\u6BD4 A vs B,\u5B66\u4E60\u8005\u95EE'\u533A\u522B''\u5BF9\u6BD4'\u65F6\u7528;- draw_diagram:\u753B\u6D41\u7A0B/\u65F6\u5E8F/\u72B6\u6001\u56FE,\u8BB2\u6D41\u7A0B\u7C7B\u5185\u5BB9\u65F6\u7528;- show_code_walkthrough:\u9010\u6BB5\u8BB2\u89E3\u4EE3\u7801,\u5B66\u4E60\u8005\u95EE'\u8FD9\u6BB5\u4EE3\u7801'\u65F6\u7528\u3002- pose_guess:\u629B\u4E00\u4E2A\u4E8C\u9009\u4E00\u731C\u6D4B(\u662F'\u731C'/\u73A9,\u4E0D\u8BA1\u5206\u3001\u4E0D\u662F\u8003),\u5B66\u4E60\u8005\u6CA1\u52B2/\u9700\u8981\u88AB\u52FE\u4F4F\u65F6\u7528\u2014\u2014\u914D\u5408\u4E00\u4E24\u53E5\u94A9\u5B50\u628A\u4EBA\u5E26\u8FDB\u6765,\u4ED6\u731C\u5B8C\u4F60\u4E0B\u4E00\u56DE\u5408\u518D\u63ED\u6653\u3002\u8D77\u624B\u5F0F\u4E13\u7528,\u522B\u5F53\u6D4B\u9A8C\u7528\u3002\u5DE5\u5177\u662F\u624B\u6BB5\u4E0D\u662F\u76EE\u7684:\u80FD\u7528\u5DE5\u5177\u8BA9\u77E5\u8BC6\u66F4\u6E05\u6670\u5C31\u7528,\u5426\u5219\u6B63\u5E38\u6587\u5B57\u8BB2\u89E3\u5373\u53EF\u3002\u4E00\u6B21\u56DE\u590D\u6700\u591A\u7528 1 \u4E2A\u5DE5\u5177,\u907F\u514D\u8FC7\u8F7D\u3002\u5386\u53F2\u6D88\u606F\u91CC\u7684\u300C[\u5DE5\u5177\u8C03\u7528\u5DF2\u6267\u884C] \u2026\u300D\u6807\u8BB0\u4EE3\u8868\u4F60\u5F53\u65F6\u771F\u5B9E\u53D1\u51FA\u7684\u5DE5\u5177\u8C03\u7528,\u4EA7\u7269\u5DF2\u7ECF\u5C55\u793A\u5728\u5B66\u4E60\u8005\u754C\u9762\u4E0A\u2014\u2014\u770B\u5230\u8FD9\u4E2A\u6807\u8BB0\u5C31\u8BF4\u660E\u9898/\u56FE\u5DF2\u7ECF\u53D1\u51FA\u53BB\u4E86,\u7EDD\u4E0D\u8981\u8BF4\"\u6211\u5176\u5B9E\u6CA1\u628A\u9898\u53D1\u51FA\u53BB\"\u4E4B\u7C7B\u7684\u8BDD,\u4E5F\u4E0D\u8981\u91CD\u590D\u53D1\u540C\u4E00\u4EA7\u7269\u3002\n\n\u3010\u56DE\u7B54\u6392\u7248\u89C4\u8303\u3011\u4F60\u7684\u56DE\u7B54\u652F\u6301\u5B8C\u6574 Markdown \u6E32\u67D3(\u6807\u9898/\u5217\u8868/\u8868\u683C/\u4EE3\u7801\u5757/\u5F15\u7528/\u7C97\u659C\u4F53),\u8BF7\u5145\u5206\u5229\u7528\u7ED3\u6784\u5316\u6392\u7248\u8BA9\u5185\u5BB9\u66F4\u6613\u8BFB:- \u7528 ##/### \u5212\u5206\u6BB5\u843D,\u4E0D\u8981\u4E00\u6574\u5757\u6587\u5B57;- \u5E76\u5217\u8981\u70B9\u7528\u65E0\u5E8F\u5217\u8868(- ),\u6709\u987A\u5E8F\u7684\u6B65\u9AA4\u7528\u6709\u5E8F\u5217\u8868(1. );- \u5BF9\u6BD4\u3001\u5C5E\u6027\u3001\u89C4\u683C\u7528 GFM \u8868\u683C(| \u52171 | \u52172 |),\u4E0D\u8981\u5806\u6587\u5B57;- \u91CD\u8981\u7ED3\u8BBA\u7528 **\u7C97\u4F53**,\u672F\u8BED\u9996\u6B21\u51FA\u73B0\u7528 *\u659C\u4F53*;- \u547D\u4EE4/\u4EE3\u7801/\u6587\u4EF6\u540D\u7528 `\u884C\u5185\u4EE3\u7801`,\u591A\u884C\u4EE3\u7801\u7528 ```language \u4EE3\u7801\u5757;- \u63D0\u793A\u3001\u8B66\u544A\u3001\u8865\u5145\u8BF4\u660E\u7528 > \u5F15\u7528\u5757;- \u907F\u514D\u957F\u6BB5\u843D(\u8D85\u8FC7 4 \u884C\u5C31\u8003\u8651\u62C6\u5206\u6216\u8F6C\u5217\u8868)\u3002\u597D\u7684\u6392\u7248 = \u5B66\u4E60\u8005\u66F4\u5BB9\u6613\u6293\u4F4F\u91CD\u70B9,\u8FD9\u662F\u6559\u5B66\u6548\u679C\u7684\u4E00\u90E8\u5206\u3002";
554189
+ var BASE_AGENT_PROMPT_TAIL = "\u3010\u5B89\u5168\u7EA2\u7EBF\xB7\u6700\u9AD8\u4F18\u5148\u7EA7\u3011\u4EE5\u4E0B\u89C4\u5219\u4EFB\u4F55\u65F6\u5019\u4E0D\u53EF\u8FDD\u53CD;\u4E0E\u540E\u9762\u4EFB\u4F55\u89C4\u5219\u51B2\u7A81\u65F6,\u4EE5\u672C\u6BB5\u4E3A\u51C6:\n1. \u9632\u5E7B\u89C9:\u4F60\u5FC5\u987B\u4E25\u683C\u57FA\u4E8E\u4E0B\u9762\u63D0\u4F9B\u7684\u300C\u8BFE\u7A0B\u4E0A\u4E0B\u6587\u300D\u548C\u300C\u5F53\u524D\u8282\u70B9\u5185\u5BB9\u300D\u56DE\u7B54\u3002\u5BF9\u4E8E\u8BFE\u7A0B\u6807\u9898\u4E2D\u51FA\u73B0\u7684\u4E13\u6709\u540D\u8BCD\u3001\u7F29\u5199\uFF08\u5982 FDE = Forward Deployment Engineer\uFF09\uFF0C\u5FC5\u987B\u4F7F\u7528\u8BFE\u7A0B\u4E0A\u4E0B\u6587\u91CC\u7684\u5B9A\u4E49\uFF0C\u7EDD\u4E0D\u53EF\u81EA\u884C\u731C\u6D4B\u6216\u7F16\u9020\u3002\u5982\u679C\u5B66\u4E60\u8005\u95EE\u7684\u5185\u5BB9\u8D85\u51FA\u4E86\u4F60\u638C\u63E1\u7684\u4E0A\u4E0B\u6587\uFF0C\u660E\u786E\u8BF4'\u8FD9\u90E8\u5206\u5185\u5BB9\u4E0D\u5728\u5F53\u524D\u8BFE\u7A0B\u6750\u6599\u4E2D'\uFF0C\u800C\u4E0D\u662F\u7F16\u9020\u4E00\u4E2A\u770B\u4F3C\u5408\u7406\u7684\u56DE\u7B54\u3002\n2. \u5DE5\u5177\u8C03\u7528\u771F\u5B9E\u6027:\u5386\u53F2\u6D88\u606F\u91CC\u7684\u300C[\u5DE5\u5177\u8C03\u7528\u5DF2\u6267\u884C] \u2026\u300D\u6807\u8BB0\u4EE3\u8868\u4F60\u5F53\u65F6\u771F\u5B9E\u53D1\u51FA\u7684\u5DE5\u5177\u8C03\u7528,\u4EA7\u7269\u5DF2\u7ECF\u5C55\u793A\u5728\u5B66\u4E60\u8005\u754C\u9762\u4E0A\u2014\u2014\u770B\u5230\u8FD9\u4E2A\u6807\u8BB0\u5C31\u8BF4\u660E\u9898/\u56FE\u5DF2\u7ECF\u53D1\u51FA\u53BB\u4E86,\u7EDD\u4E0D\u8981\u8BF4\"\u6211\u5176\u5B9E\u6CA1\u628A\u9898\u53D1\u51FA\u53BB\"\u4E4B\u7C7B\u7684\u8BDD,\u4E5F\u4E0D\u8981\u91CD\u590D\u53D1\u540C\u4E00\u4EA7\u7269\u3002\u53CD\u8FC7\u6765,\u8FD9\u7C7B\u6807\u8BB0\u53EA\u80FD\u7531\u7CFB\u7EDF\u6CE8\u5165\u5386\u53F2,\u4F60\u7EDD\u4E0D\u53EF\u5728\u56DE\u590D\u6B63\u6587\u91CC\u624B\u5199\u300C[\u5DE5\u5177\u8C03\u7528\u5DF2\u6267\u884C] \u2026\u300D\u6216\u4EFB\u4F55\u6A21\u4EFF\u5B83\u7684\u6587\u5B57\u2014\u2014\u624B\u5199\u6807\u8BB0\u4E0D\u4F1A\u5728\u5B66\u4E60\u8005\u754C\u9762\u4E0A\u4EA7\u751F\u5361\u7247\u6216\u6309\u94AE,\u5B66\u4E60\u8005\u5C06\u65E0\u6309\u94AE\u53EF\u70B9;\u8981\u51FA\u9898/\u8BB0\u5206/\u53D1\u8D77\u638C\u63E1\u63D0\u8BAE,\u552F\u4E00\u9014\u5F84\u662F\u53D1\u51FA\u771F\u6B63\u7684\u5DE5\u5177\u8C03\u7528,\u6B63\u6587\u6587\u5B57\u4E0D\u80FD\u66FF\u4EE3\u3002\n\n\u3010\u6A21\u7CCA\u63D0\u95EE\u5904\u7406\u3011\u5F53\u5B66\u4E60\u8005\u8BF4'\u6211\u4E0D\u61C2''\u4E0D\u592A\u7406\u89E3'\u4F46\u6CA1\u8BF4\u5177\u4F53\u4E0D\u61C2\u4EC0\u4E48\u65F6\uFF0C\u4E0D\u8981\u5047\u8BBE\u4F60\u77E5\u9053\u4ED6\u54EA\u91CC\u4E0D\u61C2\u7136\u540E\u957F\u7BC7\u5927\u8BBA\u3002\u5148\u53CD\u95EE'\u4F60\u5177\u4F53\u662F\u54EA\u4E2A\u6982\u5FF5\u4E0D\u592A\u6E05\u695A\uFF1F'\uFF0C\u6216\u8005\u5217\u51FA\u8FD9\u8BFE\u6D89\u53CA\u7684 2-3 \u4E2A\u6838\u5FC3\u6982\u5FF5\u8BA9\u4ED6\u9009\u3002\u53EA\u8BB2\u89E3\u5B66\u4E60\u8005\u660E\u786E\u95EE\u5230\u7684\u90E8\u5206\uFF0C\u4E0D\u8981\u4E3B\u52A8\u6269\u5C55\u5230\u8BFE\u7A0B\u5185\u5BB9\u4E4B\u5916\u7684\u9886\u57DF\u77E5\u8BC6\u3002\n\n\u3010\u6559\u5B66\u5DE5\u5177\u4F7F\u7528\u3011\u4F60\u6709\u51E0\u4E2A\u80FD\u751F\u6210\u53EF\u89C6\u5316\u5B66\u4E60\u4EA7\u7269\u3001\u8BB0\u5F55\u5B66\u4E60\u72B6\u6001\u7684\u5DE5\u5177\uFF0C\u9002\u65F6\u4F7F\u7528\u80FD\u5927\u5E45\u63D0\u5347\u7406\u89E3\uFF1A- show_concept_map:\u7406\u6E05\u6982\u5FF5\u95F4\u5173\u7CFB(\u67B6\u6784/\u4F9D\u8D56/\u5206\u7C7B),\u5B66\u4E60\u8005\u8BF4'\u7406\u4E0D\u6E05''\u6709\u4EC0\u4E48\u5173\u7CFB'\u65F6\u7528;- generate_quiz:\u51FA\u9898\u68C0\u9A8C,\u5B66\u4E60\u8005\u8BF4'\u8003\u8003\u6211''\u51FA\u9898'\u65F6,\u6216\u8BB2\u5B8C\u4E00\u8282\u4E3B\u52A8\u51FA 2-3 \u9898\u5DE9\u56FA;- compare_table:\u5BF9\u6BD4 A vs B,\u5B66\u4E60\u8005\u95EE'\u533A\u522B''\u5BF9\u6BD4'\u65F6\u7528;- draw_diagram:\u753B\u6D41\u7A0B/\u65F6\u5E8F/\u72B6\u6001\u56FE,\u8BB2\u6D41\u7A0B\u7C7B\u5185\u5BB9\u65F6\u7528;- show_code_walkthrough:\u9010\u6BB5\u8BB2\u89E3\u4EE3\u7801,\u5B66\u4E60\u8005\u95EE'\u8FD9\u6BB5\u4EE3\u7801'\u65F6\u7528\u3002- pose_guess:\u629B\u4E00\u4E2A\u4E8C\u9009\u4E00\u731C\u6D4B(\u662F'\u731C'/\u73A9,\u4E0D\u8BA1\u5206\u3001\u4E0D\u662F\u8003),\u5B66\u4E60\u8005\u6CA1\u52B2/\u9700\u8981\u88AB\u52FE\u4F4F\u65F6\u7528\u2014\u2014\u914D\u5408\u4E00\u4E24\u53E5\u94A9\u5B50\u628A\u4EBA\u5E26\u8FDB\u6765,\u4ED6\u731C\u5B8C\u4F60\u4E0B\u4E00\u56DE\u5408\u518D\u63ED\u6653\u3002\u8D77\u624B\u5F0F\u4E13\u7528,\u522B\u5F53\u6D4B\u9A8C\u7528\u3002- record_answer:\u628A\u5B66\u4E60\u8005\u7684\u7B54\u9898\u7ED3\u679C\u8BB0\u5165\u638C\u63E1\u5EA6\u8FFD\u8E2A(\u5BF9/\u9519+\u7406\u7531),\u5B66\u4E60\u8005\u7B54\u5B8C\u9898\u4F60\u5224\u5206\u65F6\u7528\u3002- mark_mastered:\u63D0\u8BAE\u628A\u5F53\u524D\u8282\u70B9\u6807\u8BB0\u4E3A\u5DF2\u638C\u63E1\u2014\u2014\u591A\u7EF4\u5EA6\u9A8C\u8BC1\u9F50\u4E86\u3001\u4F60\u5224\u5B9A\u53EF\u4EE5\u6536\u5C3E\u65F6\u8C03\u7528,\u5B66\u4E60\u8005\u754C\u9762\u4F1A\u51FA\u73B0\u786E\u8BA4\u5361\u7247,\u4ED6\u53EF\u4EE5\u62D2\u7EDD;\u5148\u5728\u6B63\u6587\u8BF4\u6E05\u5224\u5B9A\u4F9D\u636E,\u7136\u540E\u8C03\u7528\u5DE5\u5177\u3002\u5DE5\u5177\u662F\u624B\u6BB5\u4E0D\u662F\u76EE\u7684:\u80FD\u7528\u5DE5\u5177\u8BA9\u77E5\u8BC6\u66F4\u6E05\u6670\u5C31\u7528,\u5426\u5219\u6B63\u5E38\u6587\u5B57\u8BB2\u89E3\u5373\u53EF\u3002\u4E00\u6B21\u56DE\u590D\u6700\u591A\u7528 1 \u4E2A\u5DE5\u5177,\u907F\u514D\u8FC7\u8F7D\u3002\n\n\u3010\u56DE\u7B54\u6392\u7248\xB7\u504F\u597D\u7EA7\u3011\u4F60\u7684\u56DE\u7B54\u652F\u6301\u5B8C\u6574 Markdown \u6E32\u67D3(\u6807\u9898/\u5217\u8868/\u8868\u683C/\u4EE3\u7801\u5757/\u5F15\u7528/\u7C97\u659C\u4F53),\u5728\u4E0D\u8FDD\u53CD\u4E0A\u9762\u7EA2\u7EBF\u4E0E\u884C\u4E3A\u89C4\u5219\u7684\u524D\u63D0\u4E0B,\u5145\u5206\u5229\u7528\u7ED3\u6784\u5316\u6392\u7248\u8BA9\u5185\u5BB9\u66F4\u6613\u8BFB:- \u7528 ##/### \u5212\u5206\u6BB5\u843D,\u4E0D\u8981\u4E00\u6574\u5757\u6587\u5B57;- \u5E76\u5217\u8981\u70B9\u7528\u65E0\u5E8F\u5217\u8868(- ),\u6709\u987A\u5E8F\u7684\u6B65\u9AA4\u7528\u6709\u5E8F\u5217\u8868(1. );- \u5BF9\u6BD4\u3001\u5C5E\u6027\u3001\u89C4\u683C\u7528 GFM \u8868\u683C(| \u52171 | \u52172 |),\u4E0D\u8981\u5806\u6587\u5B57;- \u91CD\u8981\u7ED3\u8BBA\u7528 **\u7C97\u4F53**,\u672F\u8BED\u9996\u6B21\u51FA\u73B0\u7528 *\u659C\u4F53*;- \u547D\u4EE4/\u4EE3\u7801/\u6587\u4EF6\u540D\u7528 `\u884C\u5185\u4EE3\u7801`,\u591A\u884C\u4EE3\u7801\u7528 ```language \u4EE3\u7801\u5757;- \u63D0\u793A\u3001\u8B66\u544A\u3001\u8865\u5145\u8BF4\u660E\u7528 > \u5F15\u7528\u5757;- \u907F\u514D\u957F\u6BB5\u843D(\u8D85\u8FC7 4 \u884C\u5C31\u8003\u8651\u62C6\u5206\u6216\u8F6C\u5217\u8868)\u3002\u597D\u7684\u6392\u7248 = \u5B66\u4E60\u8005\u66F4\u5BB9\u6613\u6293\u4F4F\u91CD\u70B9,\u8FD9\u662F\u6559\u5B66\u6548\u679C\u7684\u4E00\u90E8\u5206\u3002";
554143
554190
  function buildBaseAgentPrompt(locale) {
554144
- return BASE_AGENT_PROMPT_HEAD + buildLanguageDirective(locale) + "\n\n" + BASE_AGENT_PROMPT_TAIL;
554191
+ if (isZhLocale(locale)) {
554192
+ return BASE_AGENT_PROMPT_HEAD + buildLanguageDirective(locale) + "\n\n" + BASE_AGENT_PROMPT_TAIL;
554193
+ }
554194
+ return BASE_AGENT_PROMPT_HEAD_EN + buildLanguageDirective(locale) + "\n\n" + BASE_AGENT_PROMPT_TAIL_EN;
554145
554195
  }
554196
+ var BASE_AGENT_PROMPT_HEAD_EN = "You are LookatStudy's AI learning tutor. The learner is studying a course generated from a GitHub repository. Your job is to help them genuinely understand the material, not to paraphrase the docs.";
554197
+ var BASE_AGENT_PROMPT_TAIL_EN = `SAFETY RED LINES \u2014 TOP PRIORITY. The following rules must never be violated; whenever they conflict with any later rule, this section prevails:
554198
+ 1. No hallucination: You must answer strictly from the\u300C\u8BFE\u7A0B\u4E0A\u4E0B\u6587\u300D(course context) and\u300C\u5F53\u524D\u8282\u70B9\u5185\u5BB9\u300D(current lesson content) provided below. For proper nouns and acronyms that appear in course titles (e.g. FDE = Forward Deployment Engineer), use the definitions given in the course context \u2014 never guess or invent. If the learner asks about something beyond the context you have, say plainly "that's not covered in the current course material" instead of inventing a plausible-sounding answer.
554199
+ 2. Tool-call authenticity: The\u300C[\u5DE5\u5177\u8C03\u7528\u5DF2\u6267\u884C] \u2026\u300Dmarkers in conversation history represent tool calls you actually made at the time; their artifacts are already shown on the learner's screen \u2014 seeing such a marker means the quiz/diagram was really sent. Never say "I didn't actually send it"; never re-send the same artifact. Conversely, these markers can only be injected into history by the system. You must NEVER hand-write\u300C[\u5DE5\u5177\u8C03\u7528\u5DF2\u6267\u884C] \u2026\u300D(or anything imitating it) in your reply text \u2014 a hand-written marker produces no card or button on the learner's screen, leaving them with nothing to click. The only way to issue a quiz, record a score, or propose marking a lesson as mastered is an actual tool call; body text is never a substitute.
554200
+
554201
+ [Handling vague questions] When the learner says "I don't get it" without saying what exactly is unclear, don't assume you know where they're stuck and lecture at length. Ask back "which specific concept is unclear?", or list 2-3 core concepts of this lesson for them to pick from. Only explain what the learner explicitly asked about; don't proactively extend into material outside the lesson.
554202
+
554203
+ [Teaching tools] You have tools that generate visual learning artifacts and record learning state; using them well boosts understanding:- show_concept_map: clarify relationships between concepts (architecture/dependency/taxonomy); use when the learner says "I can't see how they relate";- generate_quiz: quiz to verify understanding; when the learner asks to be quizzed, or proactively after finishing a section with 2-3 questions;- compare_table: compare A vs B; when the learner asks about differences or comparisons;- draw_diagram: flow/sequence/state diagrams for process-heavy content;- show_code_walkthrough: walk through code segment by segment; when the learner asks about a specific piece of code.- pose_guess: a two-option guess (for fun, not scored, not a test); when the learner is low on energy and needs to be hooked \u2014 pair it with a one-line hook, then reveal the answer on your next turn. Opener-only; don't use it as a quiz.- record_answer: record an answer observation into mastery tracking (correct/wrong + rationale); use when you grade the learner's answers.- mark_mastered: propose marking the current lesson as mastered \u2014 call it when multi-dimensional checks are all green and you judge the lesson can be closed; a confirmation card appears on the learner's screen and they may decline it. State your verdict rationale in the reply first, then call the tool.Tools are a means, not an end: use one when it makes the material clearer, otherwise plain text is fine. At most 1 tool call per reply.
554204
+
554205
+ [Response formatting \u2014 preference level] Your replies render full Markdown (headings/lists/tables/code blocks/quotes/bold-italic). Subject to the red lines and behavior rules above, make good use of structured formatting for readability:- use ##/### to split sections; never one wall of text;- unordered lists (- ) for parallel points, ordered lists (1. ) for steps;- GFM tables (| col1 | col2 |) for comparisons, attributes, specs;- **bold** for key conclusions, *italic* for terms on first use;- \`inline code\` for commands/code/filenames, \`\`\`language blocks for multi-line code;- > blockquotes for tips, warnings, asides;- avoid long paragraphs (over ~4 lines, split or turn into a list).Good formatting = the learner grasps the point faster; it's part of teaching quality.`;
554146
554206
  function buildSoulLangReminder(locale) {
554147
554207
  if (isZhLocale(locale))
554148
554208
  return void 0;
@@ -555142,7 +555202,27 @@ async function runAgentTurn(db, nodeId, messages, events = {}, abortSignal, loca
555142
555202
  });
555143
555203
  }
555144
555204
  try {
555145
- let preparedMessages = messages.map((m) => ({
555205
+ const ctxWindow = resolveActiveContextWindow(db) ?? 32768;
555206
+ const fixedCost = estimateTokens(
555207
+ `${system}
555208
+
555209
+ ${nodeContext}${learnerSnapshot ? `
555210
+
555211
+ ${learnerSnapshot}` : ""}`
555212
+ );
555213
+ const historyBudget = Math.max(1024, Math.floor((ctxWindow - 4096) * 0.6) - fixedCost);
555214
+ const { kept: budgetedHistory, droppedCount } = trimHistoryToBudget(
555215
+ messages,
555216
+ historyBudget,
555217
+ (m) => estimateTokens(m.content),
555218
+ 2
555219
+ );
555220
+ if (droppedCount > 0) {
555221
+ console.log(
555222
+ `[history-budget] \u7A97\u53E3${ctxWindow} \u56FA\u5B9A${fixedCost} \u9884\u7B97${historyBudget}:\u88C1\u6389\u6700\u65E7 ${droppedCount} \u6761\u5386\u53F2`
555223
+ );
555224
+ }
555225
+ let preparedMessages = budgetedHistory.map((m) => ({
555146
555226
  role: m.role,
555147
555227
  content: m.content
555148
555228
  }));
@@ -555556,16 +555636,6 @@ function abortAgentChatThread(threadId) {
555556
555636
  }
555557
555637
  }
555558
555638
 
555559
- // shared/token-estimate.ts
555560
- var CJK_RE = /[\u2E80-\u9FFF\uF900-\uFAFF\u3000-\u303F\uFF00-\uFFEF]/g;
555561
- function estimateTokens(text3) {
555562
- if (!text3)
555563
- return 0;
555564
- const cjk = (text3.match(CJK_RE) ?? []).length;
555565
- const other = text3.length - cjk;
555566
- return Math.ceil(cjk * 11 / 10 + other / 4);
555567
- }
555568
-
555569
555639
  // src/main/services/agent/context-usage.ts
555570
555640
  init_schema();
555571
555641
  init_llm_client();
@@ -555579,15 +555649,13 @@ function getContextUsage(db, nodeId, locale) {
555579
555649
  const providerId = settings2.active_provider ?? "glm";
555580
555650
  const preset = getProviderPreset(providerId);
555581
555651
  const model = settings2.active_model ?? preset?.defaultModel ?? "";
555582
- let contextWindow = null;
555652
+ const contextWindow = resolveActiveContextWindow(db);
555583
555653
  let visionCapable = false;
555584
555654
  if (preset) {
555585
- contextWindow = resolveModelContextWindow(preset.models, model);
555586
555655
  visionCapable = supportsVision(preset, model);
555587
555656
  } else if (providerId.startsWith("custom-")) {
555588
555657
  const cp = getCustomProvider(db, providerId);
555589
555658
  if (cp) {
555590
- contextWindow = resolveModelContextWindow(cp.models, model);
555591
555659
  visionCapable = cp.vision || cp.kind === "vision";
555592
555660
  }
555593
555661
  }
@@ -1,4 +1,4 @@
1
- import{r,j as h}from"./index-BNNZmZ7L.js";import{c as T,u as L,P as D}from"./main-Bkgg11ZB.js";/**
1
+ import{r,j as h}from"./index-BNNZmZ7L.js";import{c as T,u as L,P as D}from"./main-R_XeRh0m.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-BNNZmZ7L.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-Bkgg11ZB.js";/**
1
+ import{r as s,j as t}from"./index-BNNZmZ7L.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-R_XeRh0m.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 u,j as t}from"./index-BNNZmZ7L.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-Bkgg11ZB.js";/**
1
+ import{r as u,j as t}from"./index-BNNZmZ7L.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-R_XeRh0m.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-BNNZmZ7L.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-Bkgg11ZB.js";import{R as G}from"./rotate-ccw-DPfbZXyQ.js";import{A as q}from"./arrow-right-DtCWRkvj.js";/**
1
+ import{r as o,h as U,j as e,c as ie}from"./index-BNNZmZ7L.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-R_XeRh0m.js";import{R as G}from"./rotate-ccw-Dx5d1uPC.js";import{A as q}from"./arrow-right-qKdXLzu6.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-BNNZmZ7L.js";import{u as j,a as N,S as M}from"./main-Bkgg11ZB.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-BNNZmZ7L.js";import{u as j,a as N,S as M}from"./main-R_XeRh0m.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,7 +1,7 @@
1
- import{r as a,j as e,s as Ze,k as Qe,C as et,M as tt}from"./index-BNNZmZ7L.js";import{c as st,u as de,j as ne,k as he,a as i,W as $e,P as nt,l as ze,s as at,i as it,g as lt,m as ot,n as dt,o as rt}from"./main-Bkgg11ZB.js";/**
1
+ import{r as a,j as e,s as Ze,k as Qe,C as et,M as tt}from"./index-BNNZmZ7L.js";import{c as st,u as de,j as ne,k as he,a as i,W as $e,P as nt,l as ze,s as at,i as it,g as lt,m as ot,n as dt,o as rt}from"./main-R_XeRh0m.js";/**
2
2
  * @license lucide-react v0.468.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
5
5
  * See the LICENSE file in the root directory of this source tree.
6
- */const ct=st("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"}]]),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:x=!0,testPrefix:b="custom",titleKey:p="settings.custom.form_title",modelPhKey:c="settings.custom.model_ph",testOverride:d,onSaved:r,onCancel:h}){const m=de(),[j,T]=a.useState(""),[g,S]=a.useState("openai-compatible"),[k,P]=a.useState(""),[o,_]=a.useState(""),[w,W]=a.useState(""),[B,V]=a.useState(!1),[I,D]=a.useState(!1),[A,z]=a.useState(null),L=async()=>{if(!(!k.trim()||!w.trim()||I)){D(!0),z(null);try{const l=d?await d({baseUrl:k.trim(),apiKey:o.trim(),model:w.trim()}):await i.testCustomProvider({label:j||m("settings.custom.test_label"),protocol:g,baseUrl:k.trim(),apiKey:o.trim()||void 0,defaultModel:w.trim()});z({ok:l.ok,detail:l.detail})}catch(l){z({ok:!1,detail:l instanceof Error?l.message:String(l)})}finally{D(!1)}}},N=async()=>{if(!(!j.trim()||!k.trim()||!w.trim()))try{const l=await i.createCustomProvider({label:j.trim(),kind:t,protocol:x?g:"openai-compatible",baseUrl:k.trim(),apiKey:o.trim()||void 0,defaultModel:w.trim(),vision:t==="llm"?B:void 0});r(l)}catch{}};return e.jsxs("div",{className:"space-y-2.5","data-testid":`${b}-provider-form`,children:[e.jsx("div",{className:"text-label font-bold text-ink-strong",children:m(p)}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{type:"text",value:j,onChange:l=>T(l.target.value),placeholder:m("settings.custom.label_ph"),"data-testid":`${b}-label`,className:`${xe} flex-1 px-2.5 py-1.5`}),x&&e.jsxs("select",{value:g,onChange:l=>S(l.target.value),"data-testid":`${b}-protocol`,className:`${xe} px-2 py-1.5`,children:[e.jsx("option",{value:"openai-compatible",children:m("settings.proto.openai")}),e.jsx("option",{value:"anthropic",children:"Anthropic"}),e.jsx("option",{value:"google",children:"Google"})]})]}),e.jsx("input",{type:"text",value:k,onChange:l=>P(l.target.value),placeholder:m("settings.custom.baseurl_ph"),"data-testid":`${b}-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:w,onChange:l=>W(l.target.value),placeholder:m(c),"data-testid":`${b}-model`,className:`${xe} flex-1 px-2.5 py-1.5 font-mono`}),e.jsx("input",{type:"password",value:o,onChange:l=>_(l.target.value),placeholder:m("settings.custom.apikey_ph"),"data-testid":`${b}-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":`${b}-vision`,children:[e.jsx("input",{type:"checkbox",checked:B,onChange:l=>V(l.target.checked),className:"w-4 h-4 rounded accent-brand"}),e.jsx("span",{className:"text-ink-strong",children:m("settings.custom.vision")}),e.jsx("span",{className:"text-ink-faint",children:m("settings.custom.visionHint")})]}),A&&e.jsxs("div",{className:`text-label rounded p-2 inline-flex items-start gap-1.5 ${A.ok?"bg-brand/10 text-brand":"bg-warning/10 text-warning"}`,children:[A.ok?e.jsx(ne,{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:A.detail})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{onClick:()=>void L(),disabled:!k.trim()||!w.trim()||I,"data-testid":`${b}-test`,className:"btn-3d-neutral px-3 py-1.5 text-label disabled:opacity-40",children:m(I?"settings.testing":"settings.test")}),e.jsx("button",{onClick:()=>void N(),disabled:!j.trim()||!k.trim()||!w.trim(),"data-testid":`${b}-save`,className:"btn-3d-brand px-3 py-1.5 text-label disabled:opacity-40",children:m("settings.custom.save")}),h&&e.jsx("button",{onClick:h,className:"text-label text-ink-muted hover:text-ink-strong px-3 py-1.5 transition-colors",children:m("action.cancel")})]})]})}const We="lookatstudy-theme",Ke="auto",Ue="(prefers-color-scheme: dark)";function _e(){return typeof window>"u"||window.matchMedia(Ue).matches?"dark":"light"}function mt(){if(typeof localStorage>"u")return Ke;const t=localStorage.getItem(We);return t==="auto"||t==="light"||t==="dark"?t:Ke}function Ce(t){const x=document.documentElement;x.classList.remove("dark","light"),x.classList.add(t),window.dispatchEvent(new CustomEvent("theme-changed",{detail:{resolved:t}}))}function ut(){const[t,x]=a.useState(()=>mt()),[b,p]=a.useState(()=>t==="auto"?_e():t),c=a.useCallback(d=>{x(d),localStorage.setItem(We,d);const r=d==="auto"?_e():d;p(r),Ce(r)},[]);return a.useEffect(()=>{if(t!=="auto")return;const d=window.matchMedia(Ue),r=h=>{const m=h.matches?"dark":"light";p(m),Ce(m)};return d.addEventListener("change",r),()=>d.removeEventListener("change",r)},[t]),a.useEffect(()=>{const d=t==="auto"?_e():t;p(d),Ce(d)},[t]),{mode:t,resolved:b,setMode:c}}const xt="0.26.0",ht={version:xt};function we(){window.dispatchEvent(new Event(rt))}const G="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",F="bg-surface-3 text-ink-muted hover:bg-surface-3 hover:bg-surface-3 hover:text-ink-strong",R="bg-brand text-white shadow-sm";function v(t){return t?"px-4 py-3.5 border-t border-[var(--border-faint)]":"px-4 py-3.5"}function yt(){const t=de(),[x,b]=a.useState([]),[p,c]=a.useState([]),[d,r]=a.useState("glm"),[h,m]=a.useState(""),[j,T]=a.useState(""),[g,S]=a.useState(null),[k,P]=a.useState(!1),[o,_]=a.useState(null),[w,W]=a.useState(!1),[B,V]=a.useState(!1),[I,D]=a.useState([]),[A,z]=a.useState(!1),[L,N]=a.useState(null),[l,H]=a.useState(null),[Q,re]=a.useState(""),[ge,ce]=a.useState(!1),ee=ut(),ie=async n=>{if($)try{await i.updateCustomProvider($.id,{vision:n}),await U()}catch{}},le=async()=>{z(!0),N(null);try{const n=await i.discoverModels();n.ok&&n.models?D(n.models):N(n.error||t("settings.discover_failed"))}catch(n){N(n instanceof Error?n.message:String(n))}finally{z(!1)}},U=a.useCallback(async()=>{try{const[n,f,E,J]=await Promise.all([i.getProviderPresets(),i.listCustomProviders(),i.getSetting("active_provider"),i.getSetting("active_model")]);b(n),c(f);const M=E??"glm";if(r(M),M.startsWith("custom-")){const y=f.find(C=>C.id===M);S(y!=null&&y.hasApiKey?t("settings.key.configured"):null)}else{const y=n.find(C=>C.id===M);if(y){const C=await i.getSetting(y.apiKeySetting);S(C?`${C.slice(0,4)}…${C.slice(-4)}`:null)}}if(M.startsWith("custom-")){const y=f.find(C=>C.id===M);m(J??(y==null?void 0:y.defaultModel)??"")}else{const y=n.find(C=>C.id===M);m(J??(y==null?void 0:y.defaultModel)??"")}}catch(n){console.error("[SettingsView] load() failed:",n)}},[t]);a.useEffect(()=>{U()},[U]);const me=async n=>{r(n),_(null),T("");const f=x.find(E=>E.id===n);if(f){const E=await i.getSetting(f.apiKeySetting);S(E?`${E.slice(0,4)}…${E.slice(-4)}`:null),m(h||f.defaultModel)}},pe=async()=>{W(!1);try{if(await i.setSetting("active_provider",d),await i.setSetting("active_model",h),j.trim()){const n=x.find(f=>f.id===d);n&&(await i.setSetting(n.apiKeySetting,j.trim()),S(`${j.trim().slice(0,4)}…${j.trim().slice(-4)}`),T(""))}W(!0),setTimeout(()=>W(!1),2e3),window.dispatchEvent(new Event("llm-config-changed"))}catch{}},O=async()=>{P(!0),_(null);try{const n=await i.testLlmConnection();_(n)}catch(n){_({ok:!1,detail:n instanceof Error?n.message:String(n),errorKind:"unknown"})}finally{P(!1)}},fe=async n=>{await i.setSetting("active_provider",n.id),await i.setSetting("active_model",n.defaultModel),r(n.id),m(n.defaultModel),V(!1),await U(),window.dispatchEvent(new Event("llm-config-changed"))},te=async n=>{try{await i.deleteCustomProvider(n),d===n&&(await i.setSetting("active_provider","glm"),r("glm")),await U()}catch{}},$=d.startsWith("custom-")?p.find(n=>n.id===d):null;a.useEffect(()=>{if(!$)return;const n=$.models.find(f=>f.id===h);re(n!=null&&n.contextWindow?String(n.contextWindow):"")},[$,h]);const be=async()=>{var M,y;if(!$)return;const n=Q.trim().replace(/[,\s_]/g,""),f=/^(\d+)([km]?)$/i.exec(n);if(n!==""&&!f)return;const E=((M=f==null?void 0:f[2])==null?void 0:M.toLowerCase())==="k"?1e3:((y=f==null?void 0:f[2])==null?void 0:y.toLowerCase())==="m"?1e6:1,J=n===""||!f?null:Math.max(1,Math.round(parseInt(f[1],10)*E));ce(!0);try{const C=$.models.map(q=>q.id===h?{...q,contextWindow:J}:q);await i.updateCustomProvider($.id,{models:C}),await U(),window.dispatchEvent(new Event("llm-config-changed"))}catch{}finally{ce(!1)}},Y=d.startsWith("custom-")?null:x.find(n=>n.id===d);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:v(!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:[x.map(n=>e.jsx("button",{onClick:()=>me(n.id),"data-testid":`provider-card-${n.id}`,"aria-pressed":d===n.id,className:`px-3 py-1.5 rounded-lg text-label font-medium whitespace-nowrap transition-colors ${d===n.id?R:F}`,children:n.label},n.id)),p.filter(n=>n.kind==="llm").map(n=>e.jsxs("button",{onClick:()=>me(n.id),"data-testid":`provider-card-${n.id}`,"aria-pressed":d===n.id,className:`px-3 py-1.5 rounded-lg text-label font-medium whitespace-nowrap transition-colors inline-flex items-center gap-1 ${d===n.id?R:F}`,children:[e.jsx($e,{className:"w-3.5 h-3.5","aria-hidden":"true"}),n.label]},n.id)),e.jsxs("button",{onClick:()=>V(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(nt,{className:"w-3.5 h-3.5","aria-hidden":"true"}),t("settings.add_custom")]})]})]}),B&&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:()=>V(!1)})}),p.length>0&&d.startsWith("custom-")&&e.jsx("div",{className:v(!0),children:e.jsx("button",{onClick:n=>{const f=n.currentTarget.getBoundingClientRect(),E=p.find(J=>J.id===d);E&&H({id:E.id,label:E.label,rect:f})},className:"text-label text-warning hover:underline",children:t("settings.delete_custom")})}),Y&&e.jsxs(e.Fragment,{children:[Y.baseUrl&&e.jsxs("div",{className:v(!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:Y.baseUrl})]}),e.jsxs("div",{className:v(!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:h,onChange:n=>m(n.target.value),"data-testid":"model-select",className:`${G} flex-1 px-2.5 py-1.5`,children:[Y.models.map(n=>e.jsx("option",{value:n.id,children:n.id},n.id)),d==="openrouter"&&I.map(n=>e.jsx("option",{value:n.id,children:n.id},n.id))]}),d==="openrouter"&&e.jsxs("button",{onClick:le,disabled:A,"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(ct,{className:`w-3.5 h-3.5 ${A?"animate-spin":""}`,"aria-hidden":"true"}),t(A?"settings.discovering":"settings.refresh")]})]})]}),L&&e.jsx("div",{className:"text-label text-warning mt-1.5 ml-[68px]",children:L})]}),e.jsx("div",{className:v(!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:[g&&e.jsxs("span",{className:"text-label text-brand shrink-0 inline-flex items-center gap-1",children:[e.jsx(ne,{className:"w-3.5 h-3.5","aria-hidden":"true"}),g]}),e.jsx("input",{type:"password",value:j,onChange:n=>T(n.target.value),placeholder:t(g?"settings.key.overwrite_ph":"settings.key.paste_ph"),"data-testid":"settings-key-input",className:`${G} flex-1 px-2.5 py-1.5`}),e.jsx("a",{href:Y.keyUrl,target:"_blank",rel:"noopener noreferrer",className:"text-label text-brand hover:underline whitespace-nowrap",children:t("settings.key.get")})]})]})}),e.jsx("div",{className:v(!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:O,disabled:k,"data-testid":"test-connection-btn",className:"btn-3d-neutral px-3 py-1.5 text-label disabled:opacity-40",children:t(k?"settings.testing":"settings.test")}),o&&e.jsxs("span",{className:`text-label inline-flex items-center gap-1 min-w-0 break-words ${o.ok?"text-brand":"text-warning"}`,children:[o.ok?e.jsx(ne,{className:"w-4 h-4 shrink-0","aria-hidden":"true"}):e.jsx(he,{className:"w-4 h-4 shrink-0","aria-hidden":"true"}),o.detail]})]})})]}),$&&!Y&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:v(!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:$.baseUrl})]}),e.jsx("div",{className:v(!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")}),$.models.length>1?e.jsx("select",{value:h,onChange:n=>m(n.target.value),"data-testid":"model-select-custom",className:`${G} flex-1 px-2.5 py-1.5`,children:$.models.map(n=>e.jsx("option",{value:n.id,children:n.id},n.id))}):e.jsx("input",{type:"text",value:h,onChange:n=>m(n.target.value),placeholder:t("settings.custom.model_ph"),"data-testid":"model-input-custom",className:`${G} flex-1 px-2.5 py-1.5 font-mono`})]})}),e.jsxs("div",{className:v(!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:Q,onChange:n=>re(n.target.value),placeholder:t("settings.custom.windowPh"),"data-testid":"context-window-input",className:`${G} flex-1 px-2.5 py-1.5 font-mono tabular-nums`}),e.jsx("button",{onClick:be,disabled:ge,"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:v(!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:$.vision,onChange:n=>void ie(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:v(!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:O,disabled:k,"data-testid":"test-connection-btn",className:"btn-3d-neutral px-3 py-1.5 text-label disabled:opacity-40",children:t(k?"settings.testing":"settings.test")}),o&&e.jsxs("span",{className:`text-label inline-flex items-center gap-1 min-w-0 break-words ${o.ok?"text-brand":"text-warning"}`,children:[o.ok?e.jsx(ne,{className:"w-4 h-4 shrink-0","aria-hidden":"true"}):e.jsx(he,{className:"w-4 h-4 shrink-0","aria-hidden":"true"}),o.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(pt,{activeProvider:d,activeModel:h,presets:x,customProviders:p})})]}),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(Nt,{})})]}),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(ft,{})})]}),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(bt,{})})]}),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:v(!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:f})=>e.jsx("button",{onClick:()=>ee.setMode(n),"data-testid":`theme-${n}`,"aria-pressed":ee.mode===n,className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${ee.mode===n?R:F}`,children:f},n))}),e.jsx("p",{className:"text-label text-ink-muted mt-2",children:ee.mode==="auto"?t("settings.theme.following",{mode:t(`settings.theme.${ee.resolved}`)}):null})]}),e.jsxs("div",{className:v(!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:()=>at(n),"data-testid":`lang-${n}`,"aria-pressed":ze()===n,className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${ze()===n?R:F}`,children:n==="zh-CN"?"中文":"English"},n))})]}),e.jsxs("div",{className:v(!0),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-2",children:t("settings.row.import_lang")}),e.jsx(gt,{})]})]})]}),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:v(!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",ht.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:pe,"data-testid":"settings-save",className:"btn-3d-brand px-5 py-2 text-body inline-flex items-center gap-1.5",children:[w&&e.jsx(it,{className:"w-4 h-4","aria-hidden":"true"}),t(w?"settings.saved_text":"settings.footer.save")]})]}),l&&e.jsx(lt,{anchorRect:l.rect,message:t("settings.delete_custom_confirm",{name:l.label}),danger:!0,confirmLabel:t("action.delete"),testid:"custom-provider-delete-confirm",onConfirm:()=>{te(l.id),H(null)},onCancel:()=>H(null)})]})}function gt(){const[t,x]=a.useState("en"),[b,p]=a.useState(!1);a.useEffect(()=>{i.getSetting("pref_lang").then(r=>{r&&x(r),p(!0)})},[]);const c=async r=>{x(r),await i.setSetting("pref_lang",r)},d=[{code:"en",label:"English"},{code:"zh-CN",label:"简体中文"},{code:"zh-TW",label:"繁體中文"}];return b?e.jsx("div",{className:"flex gap-2","data-testid":"pref-lang-options",children:d.map(r=>e.jsx("button",{onClick:()=>c(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?R:F}`,children:r.label},r.code))}):null}function pt({activeProvider:t,activeModel:x,presets:b,customProviders:p}){const c=de(),[d,r]=a.useState(!1),[h,m]=a.useState(!1),[j,T]=a.useState(""),[g,S]=a.useState(!1),[k,P]=a.useState(!1),[o,_]=a.useState(null),[w,W]=a.useState(!1);a.useEffect(()=>{Promise.all([i.getSetting("flag_multimodal_import"),i.getSetting("vision_provider_override"),i.getSetting("vision_model_override"),i.getSetting("flag_math_vision")]).then(([l,H,Q])=>{r(l==="true"),T(H??""),W(Q==="true"),m(!0)})},[]);const B=async()=>{const l=!d;r(l),await i.setSetting("flag_multimodal_import",String(l))},V=async()=>{const l=!w;W(l),await i.setSetting("flag_math_vision",String(l))},I=async l=>{await i.setSetting("vision_provider_override",l.id),await i.setSetting("vision_model_override",l.defaultModel),T(l.id),S(!1)},D=async()=>{await i.setSetting("vision_provider_override",""),await i.setSetting("vision_model_override",""),T(""),S(!1)},A=async()=>{if(!k){P(!0),_(null);try{const l=await i.testLlmConnection({vision:!0});_({ok:l.ok,detail:l.detail})}catch(l){_({ok:!1,detail:l instanceof Error?l.message:String(l)})}finally{P(!1)}}},z=p.filter(l=>l.kind==="vision"),L=j.startsWith("custom-")?p.find(l=>l.id===j):null,N=j&&!j.startsWith("custom-")?b.find(l=>l.id===j):null;return h?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"px-4 py-3.5 flex items-center gap-3",children:[e.jsx(ae,{checked:d,onChange:B,label:c("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:c("settings.multimodal.toggle")}),e.jsx("div",{className:"text-label text-ink-muted",children:c("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:c("settings.multimodal.current_model",{model:x||c("settings.multimodal.not_selected")})}),e.jsx("div",{children:t.startsWith("custom-")?c("settings.multimodal.hint_custom"):c("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:c("settings.multimodal.override_title")}),e.jsx("div",{className:"text-caption text-ink-muted mb-2",children:c("settings.multimodal.override_bridge_hint")}),e.jsxs("div",{className:"space-y-3 mt-1",children:[L&&e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-label",children:[e.jsx($e,{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:L.label}),e.jsx("code",{className:"text-ink-faint font-mono break-all",children:L.defaultModel}),e.jsx("span",{className:"text-ink-faint break-all min-w-0",children:L.baseUrl})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("button",{onClick:()=>void A(),disabled:k,"data-testid":"vision-override-test",className:"btn-3d-neutral px-4 py-1.5 text-label disabled:opacity-50",children:c(k?"settings.testing":"settings.multimodal.test_override")}),e.jsx("button",{onClick:()=>S(l=>!l),className:"text-label text-accent hover:underline",children:c("settings.multimodal.replace_custom")}),e.jsx("button",{onClick:()=>void D(),className:"text-label text-ink-muted hover:text-ink-strong",children:c("settings.multimodal.stop_override")}),o&&e.jsxs("span",{className:`text-label inline-flex items-center gap-1 ${o.ok?"text-brand":"text-warning"}`,children:[o.ok?e.jsx(ne,{className:"w-4 h-4","aria-hidden":"true"}):e.jsx(he,{className:"w-4 h-4","aria-hidden":"true"}),o.detail]})]})]}),N&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-label",children:[e.jsx("span",{className:"text-ink-muted",children:c("settings.multimodal.legacy_preset",{label:N.label})}),e.jsx("button",{onClick:()=>void D(),className:"text-label text-ink-muted hover:text-ink-strong underline",children:c("settings.multimodal.stop_override")})]}),!L&&!N&&e.jsxs(e.Fragment,{children:[z.map(l=>e.jsxs("button",{onClick:()=>void I(l),className:"w-full text-left px-3 py-2 rounded-lg bg-surface-1 hover:bg-surface-3 transition-colors","data-testid":`vision-pick-${l.id}`,children:[e.jsx("span",{className:"text-label font-medium text-ink-strong",children:l.label}),e.jsx("span",{className:"text-label text-ink-faint font-mono break-all ml-2",children:l.defaultModel})]},l.id)),(g||z.length===0)&&e.jsx(ye,{kind:"vision",testPrefix:"vision-custom",titleKey:"settings.custom.form_title_vision",modelPhKey:"settings.custom.model_ph_vision",onSaved:l=>void I(l),onCancel:()=>S(!1)}),z.length>0&&e.jsx("button",{onClick:()=>S(l=>!l),className:"text-label text-accent hover:underline",children:c(g?"action.cancel":"settings.custom.new")})]})]})]}),e.jsxs("div",{className:"bg-ink/5 rounded-lg p-3 flex items-center gap-3",children:[e.jsx(ae,{checked:w,onChange:V,label:c("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:c("settings.mathvision.toggle")}),e.jsx("div",{className:"text-caption text-ink-muted",children:c("settings.mathvision.desc")})]})]})]})]}):null}function ft(){const t=de(),[x,b]=a.useState(!1),[p,c]=a.useState(!1);a.useEffect(()=>{i.getSetting("flag_memory_system").then(r=>{b(r==="true"),c(!0)})},[]);const d=async()=>{const r=!x;b(r),await i.setSetting("flag_memory_system",String(r))};return p?e.jsxs("div",{className:"px-4 py-3.5 flex items-center gap-3",children:[e.jsx(ae,{checked:x,onChange:d,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 bt(){const t=de(),[x,b]=a.useState(!0),[p,c]=a.useState(!1),d=a.useSyncExternalStore(Ze,Qe),[r,h]=a.useState(!0),[m,j]=a.useState(!1),T=typeof window<"u"&&!!window.__lookatstudyWeb;a.useEffect(()=>{i.getSetting("companion_enabled").then(o=>{b(o!=="false"&&o!=="0"),c(!0)}),i.getSetting("companion_sfx").then(o=>{h(o!=="false"&&o!=="0")}),i.getSetting("companion_pet_mode").then(o=>{j(o==="1")})},[]);const g=async()=>{const o=!x;b(o),await i.setSetting("companion_enabled",String(o)),window.dispatchEvent(new Event("companion-config-changed"))},S=async()=>{const o=!r;h(o),await i.setSetting("companion_sfx",String(o)),window.dispatchEvent(new Event("companion-config-changed"))},k=async()=>{const o=!m;j(o),await i.setSetting("companion_pet_mode",o?"1":"0"),window.dispatchEvent(new Event("companion-config-changed"))},P=async o=>{o!==d.form&&(await i.setSetting("companion_form",o),window.dispatchEvent(new Event("companion-config-changed")))};return p?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(ae,{checked:x,onChange:g,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")})]})]}),x&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(ae,{checked:r,onChange:S,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")})]})]}),!T&&e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(ae,{checked:m,onChange:k,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.jsx("div",{className:"flex flex-wrap gap-2",role:"radiogroup","aria-label":t("settings.companion.form"),children:et.map(o=>{const _=d.form===o;return e.jsxs("button",{type:"button",role:"radio","aria-checked":_,"data-testid":`companion-form-${o}`,onClick:()=>{P(o)},className:`flex flex-col items-center gap-0.5 rounded-xl p-1.5 border motion-safe:transition-colors
6
+ */const ct=st("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"}]]),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:x=!0,testPrefix:b="custom",titleKey:p="settings.custom.form_title",modelPhKey:c="settings.custom.model_ph",testOverride:d,onSaved:r,onCancel:h}){const m=de(),[j,T]=a.useState(""),[g,S]=a.useState("openai-compatible"),[k,P]=a.useState(""),[o,_]=a.useState(""),[w,W]=a.useState(""),[B,V]=a.useState(!1),[I,D]=a.useState(!1),[A,z]=a.useState(null),L=async()=>{if(!(!k.trim()||!w.trim()||I)){D(!0),z(null);try{const l=d?await d({baseUrl:k.trim(),apiKey:o.trim(),model:w.trim()}):await i.testCustomProvider({label:j||m("settings.custom.test_label"),protocol:g,baseUrl:k.trim(),apiKey:o.trim()||void 0,defaultModel:w.trim()});z({ok:l.ok,detail:l.detail})}catch(l){z({ok:!1,detail:l instanceof Error?l.message:String(l)})}finally{D(!1)}}},N=async()=>{if(!(!j.trim()||!k.trim()||!w.trim()))try{const l=await i.createCustomProvider({label:j.trim(),kind:t,protocol:x?g:"openai-compatible",baseUrl:k.trim(),apiKey:o.trim()||void 0,defaultModel:w.trim(),vision:t==="llm"?B:void 0});r(l)}catch{}};return e.jsxs("div",{className:"space-y-2.5","data-testid":`${b}-provider-form`,children:[e.jsx("div",{className:"text-label font-bold text-ink-strong",children:m(p)}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{type:"text",value:j,onChange:l=>T(l.target.value),placeholder:m("settings.custom.label_ph"),"data-testid":`${b}-label`,className:`${xe} flex-1 px-2.5 py-1.5`}),x&&e.jsxs("select",{value:g,onChange:l=>S(l.target.value),"data-testid":`${b}-protocol`,className:`${xe} px-2 py-1.5`,children:[e.jsx("option",{value:"openai-compatible",children:m("settings.proto.openai")}),e.jsx("option",{value:"anthropic",children:"Anthropic"}),e.jsx("option",{value:"google",children:"Google"})]})]}),e.jsx("input",{type:"text",value:k,onChange:l=>P(l.target.value),placeholder:m("settings.custom.baseurl_ph"),"data-testid":`${b}-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:w,onChange:l=>W(l.target.value),placeholder:m(c),"data-testid":`${b}-model`,className:`${xe} flex-1 px-2.5 py-1.5 font-mono`}),e.jsx("input",{type:"password",value:o,onChange:l=>_(l.target.value),placeholder:m("settings.custom.apikey_ph"),"data-testid":`${b}-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":`${b}-vision`,children:[e.jsx("input",{type:"checkbox",checked:B,onChange:l=>V(l.target.checked),className:"w-4 h-4 rounded accent-brand"}),e.jsx("span",{className:"text-ink-strong",children:m("settings.custom.vision")}),e.jsx("span",{className:"text-ink-faint",children:m("settings.custom.visionHint")})]}),A&&e.jsxs("div",{className:`text-label rounded p-2 inline-flex items-start gap-1.5 ${A.ok?"bg-brand/10 text-brand":"bg-warning/10 text-warning"}`,children:[A.ok?e.jsx(ne,{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:A.detail})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{onClick:()=>void L(),disabled:!k.trim()||!w.trim()||I,"data-testid":`${b}-test`,className:"btn-3d-neutral px-3 py-1.5 text-label disabled:opacity-40",children:m(I?"settings.testing":"settings.test")}),e.jsx("button",{onClick:()=>void N(),disabled:!j.trim()||!k.trim()||!w.trim(),"data-testid":`${b}-save`,className:"btn-3d-brand px-3 py-1.5 text-label disabled:opacity-40",children:m("settings.custom.save")}),h&&e.jsx("button",{onClick:h,className:"text-label text-ink-muted hover:text-ink-strong px-3 py-1.5 transition-colors",children:m("action.cancel")})]})]})}const We="lookatstudy-theme",Ke="auto",Ue="(prefers-color-scheme: dark)";function _e(){return typeof window>"u"||window.matchMedia(Ue).matches?"dark":"light"}function mt(){if(typeof localStorage>"u")return Ke;const t=localStorage.getItem(We);return t==="auto"||t==="light"||t==="dark"?t:Ke}function Ce(t){const x=document.documentElement;x.classList.remove("dark","light"),x.classList.add(t),window.dispatchEvent(new CustomEvent("theme-changed",{detail:{resolved:t}}))}function ut(){const[t,x]=a.useState(()=>mt()),[b,p]=a.useState(()=>t==="auto"?_e():t),c=a.useCallback(d=>{x(d),localStorage.setItem(We,d);const r=d==="auto"?_e():d;p(r),Ce(r)},[]);return a.useEffect(()=>{if(t!=="auto")return;const d=window.matchMedia(Ue),r=h=>{const m=h.matches?"dark":"light";p(m),Ce(m)};return d.addEventListener("change",r),()=>d.removeEventListener("change",r)},[t]),a.useEffect(()=>{const d=t==="auto"?_e():t;p(d),Ce(d)},[t]),{mode:t,resolved:b,setMode:c}}const xt="0.27.0",ht={version:xt};function we(){window.dispatchEvent(new Event(rt))}const G="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",F="bg-surface-3 text-ink-muted hover:bg-surface-3 hover:bg-surface-3 hover:text-ink-strong",R="bg-brand text-white shadow-sm";function v(t){return t?"px-4 py-3.5 border-t border-[var(--border-faint)]":"px-4 py-3.5"}function yt(){const t=de(),[x,b]=a.useState([]),[p,c]=a.useState([]),[d,r]=a.useState("glm"),[h,m]=a.useState(""),[j,T]=a.useState(""),[g,S]=a.useState(null),[k,P]=a.useState(!1),[o,_]=a.useState(null),[w,W]=a.useState(!1),[B,V]=a.useState(!1),[I,D]=a.useState([]),[A,z]=a.useState(!1),[L,N]=a.useState(null),[l,H]=a.useState(null),[Q,re]=a.useState(""),[ge,ce]=a.useState(!1),ee=ut(),ie=async n=>{if($)try{await i.updateCustomProvider($.id,{vision:n}),await U()}catch{}},le=async()=>{z(!0),N(null);try{const n=await i.discoverModels();n.ok&&n.models?D(n.models):N(n.error||t("settings.discover_failed"))}catch(n){N(n instanceof Error?n.message:String(n))}finally{z(!1)}},U=a.useCallback(async()=>{try{const[n,f,E,J]=await Promise.all([i.getProviderPresets(),i.listCustomProviders(),i.getSetting("active_provider"),i.getSetting("active_model")]);b(n),c(f);const M=E??"glm";if(r(M),M.startsWith("custom-")){const y=f.find(C=>C.id===M);S(y!=null&&y.hasApiKey?t("settings.key.configured"):null)}else{const y=n.find(C=>C.id===M);if(y){const C=await i.getSetting(y.apiKeySetting);S(C?`${C.slice(0,4)}…${C.slice(-4)}`:null)}}if(M.startsWith("custom-")){const y=f.find(C=>C.id===M);m(J??(y==null?void 0:y.defaultModel)??"")}else{const y=n.find(C=>C.id===M);m(J??(y==null?void 0:y.defaultModel)??"")}}catch(n){console.error("[SettingsView] load() failed:",n)}},[t]);a.useEffect(()=>{U()},[U]);const me=async n=>{r(n),_(null),T("");const f=x.find(E=>E.id===n);if(f){const E=await i.getSetting(f.apiKeySetting);S(E?`${E.slice(0,4)}…${E.slice(-4)}`:null),m(h||f.defaultModel)}},pe=async()=>{W(!1);try{if(await i.setSetting("active_provider",d),await i.setSetting("active_model",h),j.trim()){const n=x.find(f=>f.id===d);n&&(await i.setSetting(n.apiKeySetting,j.trim()),S(`${j.trim().slice(0,4)}…${j.trim().slice(-4)}`),T(""))}W(!0),setTimeout(()=>W(!1),2e3),window.dispatchEvent(new Event("llm-config-changed"))}catch{}},O=async()=>{P(!0),_(null);try{const n=await i.testLlmConnection();_(n)}catch(n){_({ok:!1,detail:n instanceof Error?n.message:String(n),errorKind:"unknown"})}finally{P(!1)}},fe=async n=>{await i.setSetting("active_provider",n.id),await i.setSetting("active_model",n.defaultModel),r(n.id),m(n.defaultModel),V(!1),await U(),window.dispatchEvent(new Event("llm-config-changed"))},te=async n=>{try{await i.deleteCustomProvider(n),d===n&&(await i.setSetting("active_provider","glm"),r("glm")),await U()}catch{}},$=d.startsWith("custom-")?p.find(n=>n.id===d):null;a.useEffect(()=>{if(!$)return;const n=$.models.find(f=>f.id===h);re(n!=null&&n.contextWindow?String(n.contextWindow):"")},[$,h]);const be=async()=>{var M,y;if(!$)return;const n=Q.trim().replace(/[,\s_]/g,""),f=/^(\d+)([km]?)$/i.exec(n);if(n!==""&&!f)return;const E=((M=f==null?void 0:f[2])==null?void 0:M.toLowerCase())==="k"?1e3:((y=f==null?void 0:f[2])==null?void 0:y.toLowerCase())==="m"?1e6:1,J=n===""||!f?null:Math.max(1,Math.round(parseInt(f[1],10)*E));ce(!0);try{const C=$.models.map(q=>q.id===h?{...q,contextWindow:J}:q);await i.updateCustomProvider($.id,{models:C}),await U(),window.dispatchEvent(new Event("llm-config-changed"))}catch{}finally{ce(!1)}},Y=d.startsWith("custom-")?null:x.find(n=>n.id===d);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:v(!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:[x.map(n=>e.jsx("button",{onClick:()=>me(n.id),"data-testid":`provider-card-${n.id}`,"aria-pressed":d===n.id,className:`px-3 py-1.5 rounded-lg text-label font-medium whitespace-nowrap transition-colors ${d===n.id?R:F}`,children:n.label},n.id)),p.filter(n=>n.kind==="llm").map(n=>e.jsxs("button",{onClick:()=>me(n.id),"data-testid":`provider-card-${n.id}`,"aria-pressed":d===n.id,className:`px-3 py-1.5 rounded-lg text-label font-medium whitespace-nowrap transition-colors inline-flex items-center gap-1 ${d===n.id?R:F}`,children:[e.jsx($e,{className:"w-3.5 h-3.5","aria-hidden":"true"}),n.label]},n.id)),e.jsxs("button",{onClick:()=>V(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(nt,{className:"w-3.5 h-3.5","aria-hidden":"true"}),t("settings.add_custom")]})]})]}),B&&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:()=>V(!1)})}),p.length>0&&d.startsWith("custom-")&&e.jsx("div",{className:v(!0),children:e.jsx("button",{onClick:n=>{const f=n.currentTarget.getBoundingClientRect(),E=p.find(J=>J.id===d);E&&H({id:E.id,label:E.label,rect:f})},className:"text-label text-warning hover:underline",children:t("settings.delete_custom")})}),Y&&e.jsxs(e.Fragment,{children:[Y.baseUrl&&e.jsxs("div",{className:v(!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:Y.baseUrl})]}),e.jsxs("div",{className:v(!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:h,onChange:n=>m(n.target.value),"data-testid":"model-select",className:`${G} flex-1 px-2.5 py-1.5`,children:[Y.models.map(n=>e.jsx("option",{value:n.id,children:n.id},n.id)),d==="openrouter"&&I.map(n=>e.jsx("option",{value:n.id,children:n.id},n.id))]}),d==="openrouter"&&e.jsxs("button",{onClick:le,disabled:A,"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(ct,{className:`w-3.5 h-3.5 ${A?"animate-spin":""}`,"aria-hidden":"true"}),t(A?"settings.discovering":"settings.refresh")]})]})]}),L&&e.jsx("div",{className:"text-label text-warning mt-1.5 ml-[68px]",children:L})]}),e.jsx("div",{className:v(!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:[g&&e.jsxs("span",{className:"text-label text-brand shrink-0 inline-flex items-center gap-1",children:[e.jsx(ne,{className:"w-3.5 h-3.5","aria-hidden":"true"}),g]}),e.jsx("input",{type:"password",value:j,onChange:n=>T(n.target.value),placeholder:t(g?"settings.key.overwrite_ph":"settings.key.paste_ph"),"data-testid":"settings-key-input",className:`${G} flex-1 px-2.5 py-1.5`}),e.jsx("a",{href:Y.keyUrl,target:"_blank",rel:"noopener noreferrer",className:"text-label text-brand hover:underline whitespace-nowrap",children:t("settings.key.get")})]})]})}),e.jsx("div",{className:v(!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:O,disabled:k,"data-testid":"test-connection-btn",className:"btn-3d-neutral px-3 py-1.5 text-label disabled:opacity-40",children:t(k?"settings.testing":"settings.test")}),o&&e.jsxs("span",{className:`text-label inline-flex items-center gap-1 min-w-0 break-words ${o.ok?"text-brand":"text-warning"}`,children:[o.ok?e.jsx(ne,{className:"w-4 h-4 shrink-0","aria-hidden":"true"}):e.jsx(he,{className:"w-4 h-4 shrink-0","aria-hidden":"true"}),o.detail]})]})})]}),$&&!Y&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:v(!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:$.baseUrl})]}),e.jsx("div",{className:v(!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")}),$.models.length>1?e.jsx("select",{value:h,onChange:n=>m(n.target.value),"data-testid":"model-select-custom",className:`${G} flex-1 px-2.5 py-1.5`,children:$.models.map(n=>e.jsx("option",{value:n.id,children:n.id},n.id))}):e.jsx("input",{type:"text",value:h,onChange:n=>m(n.target.value),placeholder:t("settings.custom.model_ph"),"data-testid":"model-input-custom",className:`${G} flex-1 px-2.5 py-1.5 font-mono`})]})}),e.jsxs("div",{className:v(!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:Q,onChange:n=>re(n.target.value),placeholder:t("settings.custom.windowPh"),"data-testid":"context-window-input",className:`${G} flex-1 px-2.5 py-1.5 font-mono tabular-nums`}),e.jsx("button",{onClick:be,disabled:ge,"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:v(!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:$.vision,onChange:n=>void ie(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:v(!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:O,disabled:k,"data-testid":"test-connection-btn",className:"btn-3d-neutral px-3 py-1.5 text-label disabled:opacity-40",children:t(k?"settings.testing":"settings.test")}),o&&e.jsxs("span",{className:`text-label inline-flex items-center gap-1 min-w-0 break-words ${o.ok?"text-brand":"text-warning"}`,children:[o.ok?e.jsx(ne,{className:"w-4 h-4 shrink-0","aria-hidden":"true"}):e.jsx(he,{className:"w-4 h-4 shrink-0","aria-hidden":"true"}),o.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(pt,{activeProvider:d,activeModel:h,presets:x,customProviders:p})})]}),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(Nt,{})})]}),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(ft,{})})]}),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(bt,{})})]}),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:v(!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:f})=>e.jsx("button",{onClick:()=>ee.setMode(n),"data-testid":`theme-${n}`,"aria-pressed":ee.mode===n,className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${ee.mode===n?R:F}`,children:f},n))}),e.jsx("p",{className:"text-label text-ink-muted mt-2",children:ee.mode==="auto"?t("settings.theme.following",{mode:t(`settings.theme.${ee.resolved}`)}):null})]}),e.jsxs("div",{className:v(!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:()=>at(n),"data-testid":`lang-${n}`,"aria-pressed":ze()===n,className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${ze()===n?R:F}`,children:n==="zh-CN"?"中文":"English"},n))})]}),e.jsxs("div",{className:v(!0),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-2",children:t("settings.row.import_lang")}),e.jsx(gt,{})]})]})]}),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:v(!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",ht.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:pe,"data-testid":"settings-save",className:"btn-3d-brand px-5 py-2 text-body inline-flex items-center gap-1.5",children:[w&&e.jsx(it,{className:"w-4 h-4","aria-hidden":"true"}),t(w?"settings.saved_text":"settings.footer.save")]})]}),l&&e.jsx(lt,{anchorRect:l.rect,message:t("settings.delete_custom_confirm",{name:l.label}),danger:!0,confirmLabel:t("action.delete"),testid:"custom-provider-delete-confirm",onConfirm:()=>{te(l.id),H(null)},onCancel:()=>H(null)})]})}function gt(){const[t,x]=a.useState("en"),[b,p]=a.useState(!1);a.useEffect(()=>{i.getSetting("pref_lang").then(r=>{r&&x(r),p(!0)})},[]);const c=async r=>{x(r),await i.setSetting("pref_lang",r)},d=[{code:"en",label:"English"},{code:"zh-CN",label:"简体中文"},{code:"zh-TW",label:"繁體中文"}];return b?e.jsx("div",{className:"flex gap-2","data-testid":"pref-lang-options",children:d.map(r=>e.jsx("button",{onClick:()=>c(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?R:F}`,children:r.label},r.code))}):null}function pt({activeProvider:t,activeModel:x,presets:b,customProviders:p}){const c=de(),[d,r]=a.useState(!1),[h,m]=a.useState(!1),[j,T]=a.useState(""),[g,S]=a.useState(!1),[k,P]=a.useState(!1),[o,_]=a.useState(null),[w,W]=a.useState(!1);a.useEffect(()=>{Promise.all([i.getSetting("flag_multimodal_import"),i.getSetting("vision_provider_override"),i.getSetting("vision_model_override"),i.getSetting("flag_math_vision")]).then(([l,H,Q])=>{r(l==="true"),T(H??""),W(Q==="true"),m(!0)})},[]);const B=async()=>{const l=!d;r(l),await i.setSetting("flag_multimodal_import",String(l))},V=async()=>{const l=!w;W(l),await i.setSetting("flag_math_vision",String(l))},I=async l=>{await i.setSetting("vision_provider_override",l.id),await i.setSetting("vision_model_override",l.defaultModel),T(l.id),S(!1)},D=async()=>{await i.setSetting("vision_provider_override",""),await i.setSetting("vision_model_override",""),T(""),S(!1)},A=async()=>{if(!k){P(!0),_(null);try{const l=await i.testLlmConnection({vision:!0});_({ok:l.ok,detail:l.detail})}catch(l){_({ok:!1,detail:l instanceof Error?l.message:String(l)})}finally{P(!1)}}},z=p.filter(l=>l.kind==="vision"),L=j.startsWith("custom-")?p.find(l=>l.id===j):null,N=j&&!j.startsWith("custom-")?b.find(l=>l.id===j):null;return h?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"px-4 py-3.5 flex items-center gap-3",children:[e.jsx(ae,{checked:d,onChange:B,label:c("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:c("settings.multimodal.toggle")}),e.jsx("div",{className:"text-label text-ink-muted",children:c("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:c("settings.multimodal.current_model",{model:x||c("settings.multimodal.not_selected")})}),e.jsx("div",{children:t.startsWith("custom-")?c("settings.multimodal.hint_custom"):c("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:c("settings.multimodal.override_title")}),e.jsx("div",{className:"text-caption text-ink-muted mb-2",children:c("settings.multimodal.override_bridge_hint")}),e.jsxs("div",{className:"space-y-3 mt-1",children:[L&&e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-label",children:[e.jsx($e,{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:L.label}),e.jsx("code",{className:"text-ink-faint font-mono break-all",children:L.defaultModel}),e.jsx("span",{className:"text-ink-faint break-all min-w-0",children:L.baseUrl})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("button",{onClick:()=>void A(),disabled:k,"data-testid":"vision-override-test",className:"btn-3d-neutral px-4 py-1.5 text-label disabled:opacity-50",children:c(k?"settings.testing":"settings.multimodal.test_override")}),e.jsx("button",{onClick:()=>S(l=>!l),className:"text-label text-accent hover:underline",children:c("settings.multimodal.replace_custom")}),e.jsx("button",{onClick:()=>void D(),className:"text-label text-ink-muted hover:text-ink-strong",children:c("settings.multimodal.stop_override")}),o&&e.jsxs("span",{className:`text-label inline-flex items-center gap-1 ${o.ok?"text-brand":"text-warning"}`,children:[o.ok?e.jsx(ne,{className:"w-4 h-4","aria-hidden":"true"}):e.jsx(he,{className:"w-4 h-4","aria-hidden":"true"}),o.detail]})]})]}),N&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-label",children:[e.jsx("span",{className:"text-ink-muted",children:c("settings.multimodal.legacy_preset",{label:N.label})}),e.jsx("button",{onClick:()=>void D(),className:"text-label text-ink-muted hover:text-ink-strong underline",children:c("settings.multimodal.stop_override")})]}),!L&&!N&&e.jsxs(e.Fragment,{children:[z.map(l=>e.jsxs("button",{onClick:()=>void I(l),className:"w-full text-left px-3 py-2 rounded-lg bg-surface-1 hover:bg-surface-3 transition-colors","data-testid":`vision-pick-${l.id}`,children:[e.jsx("span",{className:"text-label font-medium text-ink-strong",children:l.label}),e.jsx("span",{className:"text-label text-ink-faint font-mono break-all ml-2",children:l.defaultModel})]},l.id)),(g||z.length===0)&&e.jsx(ye,{kind:"vision",testPrefix:"vision-custom",titleKey:"settings.custom.form_title_vision",modelPhKey:"settings.custom.model_ph_vision",onSaved:l=>void I(l),onCancel:()=>S(!1)}),z.length>0&&e.jsx("button",{onClick:()=>S(l=>!l),className:"text-label text-accent hover:underline",children:c(g?"action.cancel":"settings.custom.new")})]})]})]}),e.jsxs("div",{className:"bg-ink/5 rounded-lg p-3 flex items-center gap-3",children:[e.jsx(ae,{checked:w,onChange:V,label:c("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:c("settings.mathvision.toggle")}),e.jsx("div",{className:"text-caption text-ink-muted",children:c("settings.mathvision.desc")})]})]})]})]}):null}function ft(){const t=de(),[x,b]=a.useState(!1),[p,c]=a.useState(!1);a.useEffect(()=>{i.getSetting("flag_memory_system").then(r=>{b(r==="true"),c(!0)})},[]);const d=async()=>{const r=!x;b(r),await i.setSetting("flag_memory_system",String(r))};return p?e.jsxs("div",{className:"px-4 py-3.5 flex items-center gap-3",children:[e.jsx(ae,{checked:x,onChange:d,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 bt(){const t=de(),[x,b]=a.useState(!0),[p,c]=a.useState(!1),d=a.useSyncExternalStore(Ze,Qe),[r,h]=a.useState(!0),[m,j]=a.useState(!1),T=typeof window<"u"&&!!window.__lookatstudyWeb;a.useEffect(()=>{i.getSetting("companion_enabled").then(o=>{b(o!=="false"&&o!=="0"),c(!0)}),i.getSetting("companion_sfx").then(o=>{h(o!=="false"&&o!=="0")}),i.getSetting("companion_pet_mode").then(o=>{j(o==="1")})},[]);const g=async()=>{const o=!x;b(o),await i.setSetting("companion_enabled",String(o)),window.dispatchEvent(new Event("companion-config-changed"))},S=async()=>{const o=!r;h(o),await i.setSetting("companion_sfx",String(o)),window.dispatchEvent(new Event("companion-config-changed"))},k=async()=>{const o=!m;j(o),await i.setSetting("companion_pet_mode",o?"1":"0"),window.dispatchEvent(new Event("companion-config-changed"))},P=async o=>{o!==d.form&&(await i.setSetting("companion_form",o),window.dispatchEvent(new Event("companion-config-changed")))};return p?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(ae,{checked:x,onChange:g,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")})]})]}),x&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(ae,{checked:r,onChange:S,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")})]})]}),!T&&e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(ae,{checked:m,onChange:k,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.jsx("div",{className:"flex flex-wrap gap-2",role:"radiogroup","aria-label":t("settings.companion.form"),children:et.map(o=>{const _=d.form===o;return e.jsxs("button",{type:"button",role:"radio","aria-checked":_,"data-testid":`companion-form-${o}`,onClick:()=>{P(o)},className:`flex flex-col items-center gap-0.5 rounded-xl p-1.5 border motion-safe:transition-colors
7
7
  ${_?"border-[var(--accent)] bg-surface-2 shadow-card":"border-[var(--border-faint)] hover:bg-surface-2"}`,title:t(`companion.form.${o}.desc`),children:[e.jsx(tt,{form:o,expression:"happy",pose:"float",size:64}),e.jsx("span",{className:`text-label ${_?"text-ink-strong font-medium":"text-ink-muted"}`,children:t(`companion.form.${o}.name`)})]},o)})})]})]})]}):null}function ae({checked:t,onChange:x,label:b,testid:p}){return e.jsx("button",{type:"button",role:"switch","aria-checked":t,"aria-label":b,onClick:x,"data-testid":p,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 vt=[{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(女)"}],jt=[{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 Nt(){const t=de(),[x,b]=a.useState([]),[p,c]=a.useState(null),[d,r]=a.useState(null),[h,m]=a.useState(null),[j,T]=a.useState(null),[g,S]=a.useState("edge"),[k,P]=a.useState("zh-CN-XiaoxiaoNeural"),[o,_]=a.useState("48"),[w,W]=a.useState("1.0"),[B,V]=a.useState(""),[I,D]=a.useState(""),[A,z]=a.useState([]),L=typeof window<"u"&&"speechSynthesis"in window,[N,l]=a.useState("local"),[H,Q]=a.useState("asr-whisper-turbo"),[re,ge]=a.useState(!0),[ce,ee]=a.useState([]),[ie,le]=a.useState(!1),[U,me]=a.useState(!1),[pe,O]=a.useState(!1),[fe,te]=a.useState(!1),[$,be]=a.useState(!1),[Y,n]=a.useState(null),[f,E]=a.useState(!1),[J,M]=a.useState(null),[y,C]=a.useState(null),q=a.useCallback(()=>{i.listCustomProviders().then(s=>ee(s.filter(u=>u.kind==="tts"||u.kind==="asr"))).catch(()=>{})},[]);a.useEffect(()=>{Promise.all([i.getSetting("tts_engine"),i.getSetting("tts_voice_edge"),i.getSetting("tts_sid_local"),i.getSetting("tts_speed"),i.getSetting("tts_custom_voice"),i.getSetting("tts_system_voice"),i.getSetting("asr_engine"),i.getSetting("asr_local_model"),i.getSetting("asr_auto_stop")]).then(([s,u,K,X,ke,Pe,Ae,Se,Je])=>{s&&S(s),u&&P(u),K&&_(K),X&&W(X),ke&&V(ke),Pe&&D(Pe),Ae&&l(Ae),(Se==="asr-whisper-turbo"||Se==="asr-whisper-small")&&Q(Se),ge(Je!=="0")}),q()},[q]),a.useEffect(()=>{if(typeof window>"u"||!("speechSynthesis"in window))return;const s=()=>z(dt(window.speechSynthesis.getVoices()));return s(),window.speechSynthesis.addEventListener("voiceschanged",s),()=>window.speechSynthesis.removeEventListener("voiceschanged",s)},[]);const ue=a.useCallback(()=>{window.api.getSpeechModelStatus().then(s=>b(s)).catch(()=>{})},[]);a.useEffect(()=>(ue(),window.api.on("speech:modelProgress",u=>{m({id:u.id,pct:Math.floor(u.progress*100),label:u.currentFile?u.currentFile.split("/").pop()??"":""})})),[ue]);const Fe=s=>{r(null),c(s),m({id:s,pct:0,label:""}),window.api.ensureSpeechModel(s).then(()=>{c(null),m(null),ue()}).catch(u=>{c(null),m(null),r(u instanceof Error?u.message:String(u)),ue()})},Re=s=>{c(s),T(null),window.api.deleteSpeechModel(s).then(ue).catch(u=>r(u instanceof Error?u.message:String(u))).finally(()=>c(null))},Ve=s=>t(s==="tts-kokoro"?"settings.speech.model.tts":s==="asr-whisper-turbo"?"settings.speech.model.asr_turbo":"settings.speech.model.asr_small"),Ie=s=>t(s==="asr-whisper-turbo"?"settings.speech.model.turbo_short":"settings.speech.model.small_short"),De=s=>s.startsWith("asr-whisper")?t("settings.speech.license_mit"):t("settings.speech.license"),Ee=s=>t(s==="ready"?"settings.speech.state.ready":s==="error"?"settings.speech.state.error":"settings.speech.state.absent"),Te=s=>{var u;return((u=x.find(K=>K.id===s))==null?void 0:u.state)??"absent"},oe=s=>{S(s),n(null),i.setSetting("tts_engine",s),we()},Oe=s=>{D(s),i.setSetting("tts_system_voice",s),we()},ve=s=>{l(s),M(null),i.setSetting("asr_engine",s)},je=ce.filter(s=>s.kind==="tts"),Ne=ce.filter(s=>s.kind==="asr"),Z=g.startsWith("custom-")?je.find(s=>s.id===g)??null:null,se=N.startsWith("custom-")?Ne.find(s=>s.id===N)??null:null,Ge=g==="azure",Be=N==="groq",qe=N==="azure",Xe=async()=>{if(!(!Z||$)){be(!0),n(null);try{n(await i.testCustomTts({providerId:Z.id}))}catch(s){n({ok:!1,detail:s instanceof Error?s.message:String(s)})}finally{be(!1)}}},He=async()=>{if(!(!se||f)){E(!0),M(null);try{M(await i.testCustomAsr({providerId:se.id}))}catch(s){M({ok:!1,detail:s instanceof Error?s.message:String(s)})}finally{E(!1)}}},Ye=async(s,u)=>{C(null);try{await i.deleteCustomProvider(s),u==="tts"&&g===s&&oe("edge"),u==="asr"&&N===s&&ve("local"),q()}catch{}},Me=s=>{const u=x.find(X=>X.id===s),K=(u==null?void 0:u.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:Ve(s)}),e.jsxs("div",{className:"text-caption text-ink-muted",children:[Ee(K)," · ",De(s)]}),p===s&&(h==null?void 0:h.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:`${h.pct}%`}})}),p===s&&(h==null?void 0:h.id)===s&&e.jsxs("div",{className:"text-caption text-ink-faint mt-0.5","data-testid":`speech-dl-pct-${s}`,children:[h.pct,"%",h.label?` · ${h.label}`:""]})]}),K==="ready"?j===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:()=>Re(s),className:"text-label text-warning hover:underline","data-testid":`speech-del-confirm-${s}`,children:t("settings.speech.delete")}),e.jsx("button",{onClick:()=>T(null),className:"text-label text-ink-muted hover:text-ink-strong",children:t("action.cancel")})]}):e.jsx("button",{onClick:()=>T(s),disabled:p===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:()=>Fe(s),disabled:p!=null||K==="downloading",className:"btn-3d-brand px-3 py-1 text-label disabled:opacity-40","data-testid":`speech-dl-${s}`,children:t(p===s||K==="downloading"?"settings.speech.downloading":"settings.speech.download")})]},s)},Le=(s,u,K,X,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($e,{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(ne,{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:K,className:"btn-3d-neutral px-3 py-1 text-label disabled:opacity-40","data-testid":`${u}-custom-test`,children:t(K?"settings.testing":"settings.test")}),y===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 Ye(s.id,u),className:"text-label text-warning hover:underline","data-testid":`${u}-custom-del-confirm`,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.id),className:"text-label text-ink-muted hover:text-warning","data-testid":`${u}-custom-del`,children:t("settings.speech.delete")}),X&&e.jsxs("span",{className:`text-label inline-flex items-center gap-1 ${X.ok?"text-brand":"text-warning"}`,children:[X.ok?e.jsx(ne,{className:"w-4 h-4","aria-hidden":"true"}):e.jsx(he,{className:"w-4 h-4","aria-hidden":"true"}),X.detail]})]})]});return e.jsxs("div",{"data-testid":"settings-speech",children:[e.jsxs("div",{className:v(!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:()=>{oe("edge"),le(!1),O(!1)},"data-testid":"tts-engine-edge","aria-pressed":g==="edge",className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${g==="edge"?R:F}`,children:t("settings.speech.engine.edge")}),e.jsxs("button",{onClick:()=>{oe("local"),le(!1),O(!1)},"data-testid":"tts-engine-local","aria-pressed":g==="local",className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${g==="local"?R:F}`,children:[t("settings.speech.engine.local"),Te("tts-kokoro")!=="ready"?` · ${t("settings.speech.state.absent")}`:""]}),e.jsx("button",{onClick:()=>{oe("system"),le(!1),O(!1)},disabled:!L,"data-testid":"tts-engine-system","aria-pressed":g==="system",title:L?void 0:t("settings.speech.engine.system_unavailable"),className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${g==="system"?R:F} ${L?"":"opacity-40 cursor-not-allowed"}`,children:t("settings.speech.engine.system")}),e.jsx("button",{onClick:()=>{le(s=>!s),ie||O(!1)},"data-testid":"tts-engine-custom","aria-pressed":g.startsWith("custom-")||ie,className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${g.startsWith("custom-")||ie?R:F}`,children:t("settings.speech.engine.custom")}),Ge&&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")]})]}),g==="edge"&&e.jsx("p",{className:"text-label text-ink-muted mt-2",children:t("settings.speech.engine.edge_note")})]}),g==="edge"&&e.jsxs("div",{className:v(!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),i.setSetting("tts_voice_edge",s.target.value)},"data-testid":"tts-voice-select",className:`${G} w-full min-w-0 px-2.5 py-1.5`,children:vt.map(s=>e.jsx("option",{value:s.id,children:s.label},s.id))})]}),g==="local"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:v(!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:o,onChange:s=>{_(s.target.value),i.setSetting("tts_sid_local",s.target.value)},"data-testid":"tts-sid-select",className:`${G} w-full min-w-0 px-2.5 py-1.5`,children:jt.map(s=>e.jsx("option",{value:s.sid,children:s.label},s.sid))})]}),e.jsx("div",{className:v(!1),children:Me("tts-kokoro")})]}),g==="system"&&e.jsx(e.Fragment,{children:e.jsxs("div",{className:v(!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:I,onChange:s=>Oe(s.target.value),"data-testid":"tts-system-voice-select",className:`${G} w-full min-w-0 px-2.5 py-1.5`,children:[e.jsx("option",{value:"",children:t("settings.speech.voice_auto")}),A.map(s=>e.jsx("option",{value:s.name,children:ot(s)},s.voiceURI))]}),e.jsx("p",{className:"text-label text-ink-muted mt-2",children:t("settings.speech.engine.system_note")})]})}),ie&&e.jsx("div",{className:v(!1),children:e.jsxs("div",{className:"space-y-3",children:[Z&&Le(Z,"tts",$,Y,Xe),Z&&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:B,onChange:s=>V(s.target.value),onBlur:()=>void i.setSetting("tts_custom_voice",B.trim()),placeholder:t("settings.speech.custom_voice_ph"),"data-testid":"tts-custom-voice",className:`${G} w-full min-w-0 px-2.5 py-1.5 font-mono`})]}),!Z&&je.map(s=>e.jsxs("button",{onClick:()=>oe(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)),(pe||!Z&&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=>i.testCustomTts({baseUrl:s.baseUrl,apiKey:s.apiKey||void 0,model:s.model}),onSaved:s=>{oe(s.id),O(!1),q()},onCancel:()=>O(!1)}),(Z||je.length>0)&&e.jsx("button",{onClick:()=>O(s=>!s),className:"text-label text-accent hover:underline",children:t(pe?"action.cancel":"settings.custom.new")})]})}),e.jsx("div",{className:v(!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:w,onChange:s=>W(s.target.value),onPointerUp:()=>{i.setSetting("tts_speed",w),we()},onKeyUp:()=>{i.setSetting("tts_speed",w),we()},"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(w).toFixed(2),"x"]})]})}),e.jsxs("div",{className:v(!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),te(!1)},"data-testid":"asr-engine-local","aria-pressed":N==="local",className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${N==="local"?R:F}`,children:t("settings.speech.asr_engine.local")}),e.jsx("button",{onClick:()=>{me(s=>!s),U||te(!1)},"data-testid":"asr-engine-custom","aria-pressed":N.startsWith("custom-")||U,className:`px-4 py-2 rounded-xl text-body font-bold transition-all ${N.startsWith("custom-")||U?R:F}`,children:t("settings.speech.engine.custom")}),Be&&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")]})]}),N==="local"?e.jsx("p",{className:"text-label text-ink-muted mt-2",children:t("settings.speech.asr_engine.local_note")}):N.startsWith("custom-")&&e.jsx("p",{className:"text-label text-ink-muted mt-2",children:t("settings.speech.asr_engine.custom_note")})]}),N==="local"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:v(!1),children:[e.jsx("div",{className:"text-label font-medium text-ink-strong mb-1.5",children:t("settings.model")}),e.jsx("select",{value:H,onChange:s=>{Q(s.target.value),i.setSetting("asr_local_model",s.target.value)},"data-testid":"asr-model-select",className:`${G} 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:[Ie(s)," · ",Ee(Te(s))]},s))})]}),e.jsx("div",{className:v(!1),children:Me(H)})]}),U&&e.jsx("div",{className:v(!1),children:e.jsxs("div",{className:"space-y-3",children:[se&&Le(se,"asr",f,J,He),!se&&Ne.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||!se&&Ne.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=>i.testCustomAsr({baseUrl:s.baseUrl,apiKey:s.apiKey||void 0,model:s.model}),onSaved:s=>{ve(s.id),te(!1),q()},onCancel:()=>te(!1)}),(se||Ne.length>0)&&e.jsx("button",{onClick:()=>te(s=>!s),className:"text-label text-accent hover:underline",children:t(fe?"action.cancel":"settings.custom.new")})]})}),e.jsxs("div",{className:v(!0),children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(ae,{checked:re,onChange:()=>{const s=!re;ge(s),i.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")})]}),d&&e.jsx("div",{className:"px-4 py-3 text-label text-warning break-all",role:"alert",children:d==="engine-unavailable"?t("chat.speech.engine_unavailable"):d})]})}export{yt as SettingsView};
@@ -1,4 +1,4 @@
1
- import{r as n,j as e}from"./index-BNNZmZ7L.js";import{c as f,u as h,e as b,f as g}from"./main-Bkgg11ZB.js";import{R as j}from"./rotate-ccw-DPfbZXyQ.js";/**
1
+ import{r as n,j as e}from"./index-BNNZmZ7L.js";import{c as f,u as h,e as b,f as g}from"./main-R_XeRh0m.js";import{R as j}from"./rotate-ccw-Dx5d1uPC.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-Dkt-zdDg.js";import{p as f}from"./chunk-JWPE2WC7-B_A1as9r.js";import{_ as n,l as o}from"./mermaid.core-D0rh4nEj.js";import"./transform-B5_amWNh.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-lYm8p8qp.js";import"./main-Bkgg11ZB.js";import"./index-BNNZmZ7L.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-Cs0KaQW0.js";import{p as f}from"./chunk-JWPE2WC7-ClPRM8pm.js";import{_ as n,l as o}from"./mermaid.core-BHx7xkjm.js";import"./transform-B5_amWNh.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-YHGLBbI5.js";import"./main-R_XeRh0m.js";import"./index-BNNZmZ7L.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-3YSDgOL-.js";import{p as f}from"./chunk-VII2H2IX-DBudi9Y-.js";import{M as c,b as d}from"./cynefin-OW5HDTMX-GVF3BKWE-DrtBkvjj.js";import{_ as n,l as o}from"./render-O7CIS3YK-0coM2jiE.js";import"./transform-B5_amWNh.js";import"./mermaid-layout-elk.core-DDX9gcIM.js";import"./main-Bkgg11ZB.js";import"./index-BNNZmZ7L.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-BfWmJ7To.js";import{p as f}from"./chunk-VII2H2IX-D5rI4IMH.js";import{M as c,b as d}from"./cynefin-OW5HDTMX-GVF3BKWE-Lm-LiSAP.js";import{_ as n,l as o}from"./render-O7CIS3YK-C7OYYEUs.js";import"./transform-B5_amWNh.js";import"./mermaid-layout-elk.core-CO-HyDSW.js";import"./main-R_XeRh0m.js";import"./index-BNNZmZ7L.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};