lookatstudy-mobile 0.38.3 → 0.39.1

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 (145) hide show
  1. package/package.json +1 -1
  2. package/server.cjs +127 -13
  3. package/web/assets/{CanvasStage-w4ZeJwrQ.js → CanvasStage-DoyzBHb8.js} +1 -1
  4. package/web/assets/{CommandPalette-BM6fHoJ7.js → CommandPalette-C43PBT15.js} +1 -1
  5. package/web/assets/{CompanionBotLab-DHmGbQJd.js → CompanionBotLab-C_wamdK2.js} +1 -1
  6. package/web/assets/{CourseSearchPanel-chOLEM5d.js → CourseSearchPanel-BFLxNbd3.js} +1 -1
  7. package/web/assets/{ExamView-hFAGAt4m.js → ExamView-EHaZqips.js} +1 -1
  8. package/web/assets/{MermaidArtifact-BtfzDUc2.js → MermaidArtifact-ChF2nySD.js} +3 -3
  9. package/web/assets/{ModelManagerModal-t24x8RiW.js → ModelManagerModal-BrsaM237.js} +1 -1
  10. package/web/assets/{PersonalProfileModal-C9R-U5ko.js → PersonalProfileModal-GrvIcBg_.js} +1 -1
  11. package/web/assets/{ReviewPanel-BbKE9VQ3.js → ReviewPanel-togH-4UW.js} +1 -1
  12. package/web/assets/{SettingsView-CePUegaH.js → SettingsView-S4q8zPbq.js} +2 -2
  13. package/web/assets/{Toggle-CEibZGBQ.js → Toggle-vfz_fm_Z.js} +1 -1
  14. package/web/assets/{VoicePanel-J1z6FBe_.js → VoicePanel-SvowGVyA.js} +1 -1
  15. package/web/assets/{abnfDiagram-VCTEODGH-BxbIkM1L.js → abnfDiagram-VCTEODGH-CJb6Kerx.js} +1 -1
  16. package/web/assets/{abnfDiagram-VCTEODGH-ODA7YWAP-fRKkh3HS.js → abnfDiagram-VCTEODGH-ODA7YWAP-of1pEs-b.js} +1 -1
  17. package/web/assets/{architectureDiagram-5GKGNRK7-C4PU3XN7-DFv0wzx5.js → architectureDiagram-5GKGNRK7-C4PU3XN7-DtbERjiA.js} +1 -1
  18. package/web/assets/{architectureDiagram-5GKGNRK7-CklerPXK.js → architectureDiagram-5GKGNRK7-DRQKp8Yd.js} +1 -1
  19. package/web/assets/{blockDiagram-I7D4REHJ-CZMNIs1u.js → blockDiagram-I7D4REHJ-DFe3KBpT.js} +1 -1
  20. package/web/assets/{blockDiagram-NRAW4CY4-UMJ6PMQQ-BbKpMB5c.js → blockDiagram-NRAW4CY4-UMJ6PMQQ-CTv5WLR3.js} +1 -1
  21. package/web/assets/{c4Diagram-7LVT6UL2-ymdQRNht.js → c4Diagram-7LVT6UL2-CymNL7TD.js} +1 -1
  22. package/web/assets/{c4Diagram-UCG6FXSJ-75X3U2P3-ok_lhBVm.js → c4Diagram-UCG6FXSJ-75X3U2P3-DjSLo2yQ.js} +1 -1
  23. package/web/assets/channel-BpJLewgh.js +1 -0
  24. package/web/assets/{chunk-2Q5K7J3B-Cn7zPcaJ.js → chunk-2Q5K7J3B-FAvBhLik.js} +1 -1
  25. package/web/assets/{chunk-5VM5RSS4-Dxe5CD6c.js → chunk-5VM5RSS4-DmlVCXQo.js} +1 -1
  26. package/web/assets/{chunk-7XDTSPCN-TnCUb370.js → chunk-7XDTSPCN-B_Zt3ODu.js} +1 -1
  27. package/web/assets/{chunk-CTNIYPP6-CHE3_Njo.js → chunk-CTNIYPP6-kw9W82h8.js} +1 -1
  28. package/web/assets/{chunk-CXNFBKHE-DBmJAlZJ.js → chunk-CXNFBKHE-VA0WRlVc.js} +1 -1
  29. package/web/assets/{chunk-F27PBJKO-B7CY6nEv.js → chunk-F27PBJKO-BN95WTYU.js} +1 -1
  30. package/web/assets/{chunk-IMKFNOWR-D2aOJHTs.js → chunk-IMKFNOWR-Zx_of3s-.js} +1 -1
  31. package/web/assets/{chunk-ISA7TJRJ-DZXqmUMR.js → chunk-ISA7TJRJ-DmTvFEf1.js} +1 -1
  32. package/web/assets/{chunk-JWPE2WC7-tf0-quEp.js → chunk-JWPE2WC7-CmeF3qRj.js} +1 -1
  33. package/web/assets/{chunk-LV3HUYFY-B1bzmBj2.js → chunk-LV3HUYFY-DV28L6zT.js} +1 -1
  34. package/web/assets/{chunk-M3IUQBOH-C2wfMx5k.js → chunk-M3IUQBOH-BSLHlTe-.js} +1 -1
  35. package/web/assets/{chunk-NDIOYS4C-CURLPJwt.js → chunk-NDIOYS4C-D4DFkIww.js} +1 -1
  36. package/web/assets/{chunk-POPQ4Y6H-aZiKp-fA.js → chunk-POPQ4Y6H-CD5F-aHM.js} +1 -1
  37. package/web/assets/{chunk-RE4WF27V-CBC0f21B.js → chunk-RE4WF27V-kXREIDC4.js} +1 -1
  38. package/web/assets/{chunk-SVP7TREG-Buu4yZv5.js → chunk-SVP7TREG-DJYuaaGu.js} +1 -1
  39. package/web/assets/{chunk-TICWLB2K-tR6FMC3v.js → chunk-TICWLB2K-c8Bbk-BO.js} +1 -1
  40. package/web/assets/{chunk-VII2H2IX-IGIGE2ZG.js → chunk-VII2H2IX-Cy_lqB3B.js} +1 -1
  41. package/web/assets/{chunk-X5GNSKZ3-C4Kk2u7a.js → chunk-X5GNSKZ3-CGz4AR0E.js} +1 -1
  42. package/web/assets/{chunk-XCWWM2C3-Cz8rOu4p.js → chunk-XCWWM2C3-DIKc00dc.js} +1 -1
  43. package/web/assets/{chunk-XXDRQBXY-CatzKTit.js → chunk-XXDRQBXY-BMuygSvi.js} +1 -1
  44. package/web/assets/classDiagram-DTDB5LWJ-LWRDKZ5K-HovMFWGh.js +1 -0
  45. package/web/assets/classDiagram-ZZMXUADV-CA1kz79C.js +1 -0
  46. package/web/assets/classDiagram-v2-JRS7N3AN-2BZHGRP2-HovMFWGh.js +1 -0
  47. package/web/assets/classDiagram-v2-VYDZK3BY-CA1kz79C.js +1 -0
  48. package/web/assets/{core-CRqJ4Q_E.js → core-TgZs29Ke.js} +1 -1
  49. package/web/assets/{cose-bilkent-JH36ORCC-CkqCOeTo.js → cose-bilkent-JH36ORCC-DPs3Kx2u.js} +1 -1
  50. package/web/assets/{cose-bilkent-JH36ORCC-OB24KH3T-juOdC4FR.js → cose-bilkent-JH36ORCC-OB24KH3T-BAKd3jPo.js} +1 -1
  51. package/web/assets/{cynefin-OW5HDTMX-BFgrQtp9.js → cynefin-OW5HDTMX-DR5iOKRr.js} +1 -1
  52. package/web/assets/{cynefin-OW5HDTMX-GVF3BKWE-BOd2wBp9.js → cynefin-OW5HDTMX-GVF3BKWE-Dr41qnrZ.js} +1 -1
  53. package/web/assets/{cynefinDiagram-5FMLGOSQ-H3WIRU3N-Ck9-Pv8t.js → cynefinDiagram-5FMLGOSQ-H3WIRU3N-FKxCq6hH.js} +1 -1
  54. package/web/assets/{cynefinDiagram-5FMLGOSQ-BB2YPlQ9.js → cynefinDiagram-5FMLGOSQ-ypaNgMeu.js} +1 -1
  55. package/web/assets/{dagre-3AP2YEHR-DCERTXHT-CSU8gN1L.js → dagre-3AP2YEHR-DCERTXHT-CP0jdk4y.js} +1 -1
  56. package/web/assets/{dagre-GXQ25YYZ-Mk7z790X.js → dagre-GXQ25YYZ-F9NedoD2.js} +1 -1
  57. package/web/assets/{diagram-S7CK7UJ4-Bz52TUEp.js → diagram-S7CK7UJ4-DTA4hDxG.js} +1 -1
  58. package/web/assets/{diagram-S7CK7UJ4-MULGZGEL-BgGTSOao.js → diagram-S7CK7UJ4-MULGZGEL-BaxVI-fQ.js} +1 -1
  59. package/web/assets/{diagram-UQ7AKVKN-CVb_IQ6L.js → diagram-UQ7AKVKN-Cv7BJmMk.js} +1 -1
  60. package/web/assets/{diagram-UQ7AKVKN-YQBY353J-CKMdDCHN.js → diagram-UQ7AKVKN-YQBY353J-Brv9DD2O.js} +1 -1
  61. package/web/assets/{diagram-VSXAHHWV-CWZZvHwV.js → diagram-VSXAHHWV-DLkh4cfu.js} +1 -1
  62. package/web/assets/{diagram-VSXAHHWV-WLNH2ELY-CbhSz0AY.js → diagram-VSXAHHWV-WLNH2ELY-wjvXqSl_.js} +1 -1
  63. package/web/assets/{diagram-VX7I27RA-XW6YQV5G-B48SGxWw.js → diagram-VX7I27RA-XW6YQV5G-CDLJW6bg.js} +1 -1
  64. package/web/assets/{diagram-VX7I27RA-50sXDHFK.js → diagram-VX7I27RA-ZDGx2SPA.js} +1 -1
  65. package/web/assets/{diagram-Z3DM3KII-Ma5O7Wvc.js → diagram-Z3DM3KII-DvWyNGwM.js} +1 -1
  66. package/web/assets/{diagram-Z3DM3KII-HG7RF65D-DZHe0N9Q.js → diagram-Z3DM3KII-HG7RF65D-DwXpxYDf.js} +1 -1
  67. package/web/assets/{ebnfDiagram-PWID7BFC-E4R6x3BG.js → ebnfDiagram-PWID7BFC-BSOI7QUT.js} +1 -1
  68. package/web/assets/{ebnfDiagram-PWID7BFC-OKY4VHYD-B_GNL-lf.js → ebnfDiagram-PWID7BFC-OKY4VHYD-X2DasBXZ.js} +1 -1
  69. package/web/assets/{elk.bundled-Cez1bZui.js → elk.bundled-BBYPM_mJ.js} +1 -1
  70. package/web/assets/{erDiagram-RLTQ6QDP-BEILk2jW.js → erDiagram-RLTQ6QDP-BLWyIkyZ.js} +1 -1
  71. package/web/assets/{erDiagram-SSCWMZ5O-PIPKOIK7-dRh-n90X.js → erDiagram-SSCWMZ5O-PIPKOIK7-DpBjxnz_.js} +1 -1
  72. package/web/assets/{flowDiagram-A5DVABFB-2Z4AVO5R-CsnXAa8R.js → flowDiagram-A5DVABFB-2Z4AVO5R-0iEFyCER.js} +1 -1
  73. package/web/assets/{flowDiagram-HODETNUW-D5iNQK_m.js → flowDiagram-HODETNUW-BarKyY-s.js} +1 -1
  74. package/web/assets/{ganttDiagram-EL5Y4UJY-JZNG7GOG-BUbATXbl.js → ganttDiagram-EL5Y4UJY-JZNG7GOG-ByiuMOrG.js} +1 -1
  75. package/web/assets/{ganttDiagram-EL5Y4UJY-D5Ul8pOV.js → ganttDiagram-EL5Y4UJY-O8G7kJZM.js} +1 -1
  76. package/web/assets/{gitGraphDiagram-WWUBYQGX-D300RUA5.js → gitGraphDiagram-WWUBYQGX-7kLwXOsf.js} +1 -1
  77. package/web/assets/{gitGraphDiagram-WWUBYQGX-DMWMLL3G-B9UXyVFP.js → gitGraphDiagram-WWUBYQGX-DMWMLL3G-DPngt-gs.js} +1 -1
  78. package/web/assets/{index-DAPahbzX.js → index-B0rJ3jRg.js} +1 -1
  79. package/web/assets/index-B7IHDZbN.css +1 -0
  80. package/web/assets/{index-DQE3KX7b.js → index-CZWJlKh8.js} +1 -1
  81. package/web/assets/{index-DiBF8331.js → index-DA7FbDZK.js} +3 -3
  82. package/web/assets/{infoDiagram-27XIBGKW-Cta6ZmOB.js → infoDiagram-27XIBGKW-o-3MRUnI.js} +1 -1
  83. package/web/assets/{infoDiagram-RXCK75RN-HANS5KVC-Cj6Eokea.js → infoDiagram-RXCK75RN-HANS5KVC-OUfCEMgh.js} +1 -1
  84. package/web/assets/{ishikawaDiagram-5VMMS53U-7GCIT7WU-B4XQCJUp.js → ishikawaDiagram-5VMMS53U-7GCIT7WU-D2NflP3i.js} +1 -1
  85. package/web/assets/{ishikawaDiagram-5VMMS53U-BhZLGqyX.js → ishikawaDiagram-5VMMS53U-Dy1qnNNX.js} +1 -1
  86. package/web/assets/{journeyDiagram-3NMN7TZE-I7ckWi8V.js → journeyDiagram-3NMN7TZE-DeXgoBhQ.js} +1 -1
  87. package/web/assets/{journeyDiagram-EYS64GPL-OAPELBT7-Bu5JWfMr.js → journeyDiagram-EYS64GPL-OAPELBT7-C53O1gfy.js} +1 -1
  88. package/web/assets/{kanban-definition-3QL26DDD-I7RKWQQY-CF3_TQDj.js → kanban-definition-3QL26DDD-I7RKWQQY-2MLfe3P2.js} +1 -1
  89. package/web/assets/{kanban-definition-UXKFOSKX-D4wFp2-H.js → kanban-definition-UXKFOSKX-DuIfjXjq.js} +1 -1
  90. package/web/assets/{katex-N6JRN4PM-Cbi2gBGQ.js → katex-N6JRN4PM-AQVUI2c5.js} +1 -1
  91. package/web/assets/{layout-fmIRuN-x.js → layout-BfB6E2v9.js} +1 -1
  92. package/web/assets/main-_pTgysch.js +554 -0
  93. package/web/assets/{mermaid-layout-elk.core-BP9RfmyE.js → mermaid-layout-elk.core-Cz784PwA.js} +2 -2
  94. package/web/assets/{mermaid.core-CFB6SYUU.js → mermaid.core-DtWjB5Tg.js} +5 -5
  95. package/web/assets/{mindmap-definition-FBJOCRG2-KIYZG64Y-BBlEaFu2.js → mindmap-definition-FBJOCRG2-KIYZG64Y-CQrGLBlo.js} +1 -1
  96. package/web/assets/{mindmap-definition-YA3MSWOX-DxLi9G-Q.js → mindmap-definition-YA3MSWOX-BY1easDZ.js} +1 -1
  97. package/web/assets/{pegDiagram-XKGWAZYB-BYmlUVbe.js → pegDiagram-XKGWAZYB-BNZ0nHlg.js} +1 -1
  98. package/web/assets/{pegDiagram-XKGWAZYB-OIP57N6J-D-sZdpuJ.js → pegDiagram-XKGWAZYB-OIP57N6J-kRUvGHO3.js} +1 -1
  99. package/web/assets/{pet-7_82JHov.js → pet-B7T4HZar.js} +1 -1
  100. package/web/assets/{pieDiagram-E7YTZNPT-2UOTW327-CTWSlXqZ.js → pieDiagram-E7YTZNPT-2UOTW327-DM0Vpkpj.js} +1 -1
  101. package/web/assets/{pieDiagram-E7YTZNPT-CQvUEqRo.js → pieDiagram-E7YTZNPT-t7uRJmyN.js} +1 -1
  102. package/web/assets/{quadrantDiagram-AXDQQJYC-Ked2QFzx.js → quadrantDiagram-AXDQQJYC-BxX8n0GV.js} +1 -1
  103. package/web/assets/{quadrantDiagram-AXDQQJYC-SN3ASJJK-BztrBW6X.js → quadrantDiagram-AXDQQJYC-SN3ASJJK-Ng1GDQe7.js} +1 -1
  104. package/web/assets/{railroadDiagram-O6MQD6OU-34742W6X-DDJXRDYw.js → railroadDiagram-O6MQD6OU-34742W6X-CujwXjBQ.js} +1 -1
  105. package/web/assets/{railroadDiagram-O6MQD6OU-CKs6vckE.js → railroadDiagram-O6MQD6OU-D6PbbsGo.js} +1 -1
  106. package/web/assets/{render-O7CIS3YK-DrLxIH3C.js → render-O7CIS3YK-CjoH73ct.js} +7 -7
  107. package/web/assets/{requirementDiagram-BXWQKSXE-Df5nIsY_.js → requirementDiagram-BXWQKSXE-Tf_VgTyJ.js} +1 -1
  108. package/web/assets/{requirementDiagram-EFPCY7ZU-NGAFFSMB-BGzUUTlQ.js → requirementDiagram-EFPCY7ZU-NGAFFSMB-CP9z6ffj.js} +1 -1
  109. package/web/assets/{rotate-ccw-ChWz7hYv.js → rotate-ccw-BIQ3H8e1.js} +1 -1
  110. package/web/assets/{sankeyDiagram-P5KCCOFB-3D3M4XPB-CYhPEOwJ.js → sankeyDiagram-P5KCCOFB-3D3M4XPB-pHC9lTLC.js} +1 -1
  111. package/web/assets/{sankeyDiagram-P5KCCOFB-CFl3aUTC.js → sankeyDiagram-P5KCCOFB-DV_yq5pZ.js} +1 -1
  112. package/web/assets/{sequenceDiagram-WJ2MYXX4-qUrCnsuJ.js → sequenceDiagram-WJ2MYXX4-D8dFQBig.js} +1 -1
  113. package/web/assets/{sequenceDiagram-WJ2MYXX4-Q2IOPB4R-C9m9xSMo.js → sequenceDiagram-WJ2MYXX4-Q2IOPB4R-GBQYMhG9.js} +1 -1
  114. package/web/assets/{sizeCapture-INFHLROL-RI5EIZzr.js → sizeCapture-INFHLROL-C637ZCYp.js} +1 -1
  115. package/web/assets/{sizeCapture-X5ZJPWSS-PSGVOMYM-DkjTfTNV.js → sizeCapture-X5ZJPWSS-PSGVOMYM-qEYHLLBJ.js} +1 -1
  116. package/web/assets/{stateDiagram-D77RDMKH-OQpvIHR8.js → stateDiagram-D77RDMKH-DuRGEPvl.js} +1 -1
  117. package/web/assets/{stateDiagram-HBIQ2CUA-4M2S6MAN-C09CBNgu.js → stateDiagram-HBIQ2CUA-4M2S6MAN-Yld8ZtXO.js} +1 -1
  118. package/web/assets/stateDiagram-v2-4QOOHH4V-LBBLA2WV-DenkcOCg.js +1 -0
  119. package/web/assets/stateDiagram-v2-MP3YSRHH-Bt6aSiBy.js +1 -0
  120. package/web/assets/{swimlanes-42K2YHIH-ZxQbibd3.js → swimlanes-42K2YHIH-CwhdWKu0.js} +1 -1
  121. package/web/assets/{swimlanes-XN3QIQJK-N6N2CCQ6-5djqGOFq.js → swimlanes-XN3QIQJK-N6N2CCQ6-Dnfqd5ZC.js} +1 -1
  122. package/web/assets/swimlanesDiagram-VK2B7HYN-E6N4H5SY-DR9s6vUf.js +8 -0
  123. package/web/assets/swimlanesDiagram-VR7AAH4N-pTBx6UhY.js +8 -0
  124. package/web/assets/{timeline-definition-24CTP7MA-BKQhun4x.js → timeline-definition-24CTP7MA-BESd5a_C.js} +1 -1
  125. package/web/assets/{timeline-definition-24CTP7MA-KN7RSRVM-BWTEPsS3.js → timeline-definition-24CTP7MA-KN7RSRVM-Dyx22I2I.js} +1 -1
  126. package/web/assets/{vennDiagram-4TSXK5OY-AKJ7LXAN-CoRIQzN3.js → vennDiagram-4TSXK5OY-AKJ7LXAN-DkQzmEAM.js} +1 -1
  127. package/web/assets/{vennDiagram-4TSXK5OY-B0jff-Yf.js → vennDiagram-4TSXK5OY-Bty9d744.js} +1 -1
  128. package/web/assets/{wardleyDiagram-VM6X3IG4-3B6A3BN5-DTHtAh1_.js → wardleyDiagram-VM6X3IG4-3B6A3BN5-C0aJKvvU.js} +1 -1
  129. package/web/assets/{wardleyDiagram-VM6X3IG4-CCFEp1LK.js → wardleyDiagram-VM6X3IG4-D2dmSKO9.js} +1 -1
  130. package/web/assets/{xychartDiagram-S5SC5T6Z-DehkcgWB.js → xychartDiagram-S5SC5T6Z-DV-RGT-Y.js} +1 -1
  131. package/web/assets/{xychartDiagram-S5SC5T6Z-OBDNV6WG-CqYw05pP.js → xychartDiagram-S5SC5T6Z-OBDNV6WG-BTwes02g.js} +1 -1
  132. package/web/index.html +3 -3
  133. package/web/pet.html +3 -3
  134. package/web/assets/channel-BtlWkm43.js +0 -1
  135. package/web/assets/classDiagram-DTDB5LWJ-LWRDKZ5K-BSR-3up6.js +0 -1
  136. package/web/assets/classDiagram-ZZMXUADV-EyERu_sO.js +0 -1
  137. package/web/assets/classDiagram-v2-JRS7N3AN-2BZHGRP2-BSR-3up6.js +0 -1
  138. package/web/assets/classDiagram-v2-VYDZK3BY-EyERu_sO.js +0 -1
  139. package/web/assets/index-CS4Wtfwl.css +0 -1
  140. package/web/assets/main-BG2k-Vog.js +0 -537
  141. package/web/assets/stateDiagram-v2-4QOOHH4V-LBBLA2WV-B-9boNOx.js +0 -1
  142. package/web/assets/stateDiagram-v2-MP3YSRHH-BNdisWni.js +0 -1
  143. package/web/assets/swimlanesDiagram-VK2B7HYN-E6N4H5SY-aUoktW6T.js +0 -8
  144. package/web/assets/swimlanesDiagram-VR7AAH4N-Q0TWUgro.js +0 -8
  145. /package/web/assets/{index-jKxnKPxh.js → index-88125dOi.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lookatstudy-mobile",
3
- "version": "0.38.3",
3
+ "version": "0.39.1",
4
4
  "description": "LookatStudy Termux portable bundle (server.cjs + web frontend)",
5
5
  "repository": {
6
6
  "type": "git",
package/server.cjs CHANGED
@@ -12945,6 +12945,7 @@ var init_schema = __esm({
12945
12945
  /** 主焦点节点(可空,影响 AI 注入的节点上下文) */
12946
12946
  focusNodeId: text("focus_node_id"),
12947
12947
  status: text("status", { enum: ["active", "archived"] }).notNull().default("active"),
12948
+ kind: text("kind", { enum: ["chat", "review"] }).notNull().default("chat"),
12948
12949
  createdAt: text("created_at").notNull().default(sql`(CURRENT_TIMESTAMP)`),
12949
12950
  updatedAt: text("updated_at").notNull().default(sql`(CURRENT_TIMESTAMP)`),
12950
12951
  messageCount: integer("message_count").notNull().default(0)
@@ -13329,6 +13330,7 @@ CREATE TABLE IF NOT EXISTS threads (
13329
13330
  title TEXT, -- \u7528\u6237\u8D77\u7684\u540D,\u5982"\u6CE8\u610F\u529B\u673A\u5236\u6DF1\u6316"
13330
13331
  focus_node_id TEXT, -- \u4E3B\u7126\u70B9\u8282\u70B9(\u53EF\u7A7A,\u5F71\u54CD AI \u6CE8\u5165\u7684\u8282\u70B9\u4E0A\u4E0B\u6587)
13331
13332
  status TEXT NOT NULL DEFAULT 'active', -- active / archived
13333
+ kind TEXT NOT NULL DEFAULT 'chat', -- chat / review(\u590D\u4E60\u4F1A\u8BDD\u7EBF\u7A0B:\u5F15\u64CE\u6CE8\u5165\u590D\u4E60\u5BFC\u5E08\u59FF\u6001,tab \u52A0\u5FBD\u6807)
13332
13334
  created_at TEXT NOT NULL DEFAULT (CURRENT_TIMESTAMP),
13333
13335
  updated_at TEXT NOT NULL DEFAULT (CURRENT_TIMESTAMP),
13334
13336
  message_count INTEGER NOT NULL DEFAULT 0
@@ -13502,6 +13504,7 @@ function runMigrations(db) {
13502
13504
  addColumnIfMissing("canvas_items", "last_result", "TEXT");
13503
13505
  addColumnIfMissing("canvas_items", "result_at", "TEXT");
13504
13506
  addColumnIfMissing("chat_messages", "display_text", "TEXT");
13507
+ addColumnIfMissing("threads", "kind", "TEXT NOT NULL DEFAULT 'chat'");
13505
13508
  ensureExamTypeAllowed(db);
13506
13509
  migrateSoulRename(db);
13507
13510
  }
@@ -527710,7 +527713,7 @@ init_drizzle_orm();
527710
527713
  var import_node_crypto26 = require("node:crypto");
527711
527714
 
527712
527715
  // package.json
527713
- var version2 = "0.38.3";
527716
+ var version2 = "0.39.1";
527714
527717
 
527715
527718
  // src/main/lib/update-check.ts
527716
527719
  var RELEASES_PAGE = "https://github.com/Kaiji-Z/LookatStudy/releases";
@@ -529710,12 +529713,14 @@ function recordReviewDb(db, nodeId, quality) {
529710
529713
  lastReviewedAt: nowIso
529711
529714
  }).run();
529712
529715
  }
529716
+ return result;
529713
529717
  }
529714
529718
 
529715
529719
  // src/main/services/srs.ts
529716
529720
  function recordReview(nodeId, quality) {
529717
- recordReviewDb(getDb(), nodeId, quality);
529721
+ const result = recordReviewDb(getDb(), nodeId, quality);
529718
529722
  markDirty();
529723
+ return result;
529719
529724
  }
529720
529725
  function getDueReviewNodeIds(now2 = /* @__PURE__ */ new Date()) {
529721
529726
  const db = getDb();
@@ -529966,6 +529971,7 @@ function createThread(input) {
529966
529971
  title: input.title ?? null,
529967
529972
  focusNodeId: input.focusNodeId ?? null,
529968
529973
  status: "active",
529974
+ kind: input.kind ?? "chat",
529969
529975
  createdAt: now2,
529970
529976
  updatedAt: now2,
529971
529977
  messageCount: 0
@@ -559287,6 +559293,49 @@ function buildSoulLangReminder(locale) {
559287
559293
  const name19 = localeToLanguageName(locale);
559288
559294
  return `Reminder: the persona body above defines teaching behavior only \u2014 ignore its language. Everything you output, tool parameters included, stays in ${name19}.`;
559289
559295
  }
559296
+ function buildReviewTutorBlock(locale) {
559297
+ if (isZhLocale(locale)) {
559298
+ return "\u3010\u590D\u4E60\u5BFC\u5E08\u59FF\u6001\u3011\u8FD9\u573A\u4F1A\u8BDD\u662F\u95F4\u9694\u590D\u4E60\u2014\u2014\u5B66\u4E60\u8005\u5DF2\u7ECF\u5B66\u8FC7\u672C\u8BFE,\u73B0\u5728\u68C0\u9A8C\u5E76\u5DE9\u56FA\u8BB0\u5FC6,\u4E0D\u662F\u65B0\u6388\u8BFE:\n- \u5148\u5FC6\u540E\u770B:\u5F00\u573A\u4E0E\u6574\u4E2A\u590D\u4E60\u8FC7\u7A0B\u90FD\u4E0D\u8981\u4E3B\u52A8\u8D34\u51FA\u8BFE\u6587\u539F\u6587\u6216\u5927\u6BB5\u91CD\u8BB2\u3002\u5148\u7528 1 \u4E2A\u56DE\u5FC6\u6027\u95EE\u9898\u8BA9\u5B66\u4E60\u8005\u51ED\u8BB0\u5FC6\u4F5C\u7B54,\u6839\u636E\u56DE\u7B54\u51B3\u5B9A\u4E0B\u4E00\u6B65;\n- \u5BF9\u51C6\u5F31\u9879:\u4F18\u5148\u8003\u5BDF\u638C\u63E1\u5EA6\u504F\u4F4E\u7684\u77E5\u8BC6\u70B9(\u4E0A\u65B9\u6E05\u5355\u91CC\u6807\u6CE8\u504F\u4F4E\u7684)\u4E0E\u5B66\u4E60\u8005\u66FE\u7ECF\u7684\u5361\u70B9;\u4E0A\u4E00\u8F6E\u590D\u4E60\u6536\u675F\u8BB0\u5F55\u91CC\u7559\u4E0B\u7684\u8584\u5F31\u70B9\u662F\u7B2C\u4E00\u63D0\u95EE\u5BF9\u8C61;\n- \u9519\u4E86\u624D\u8BB2:\u5B66\u4E60\u8005\u7B54\u9519\u6216\u60F3\u4E0D\u8D77\u6765,\u624D\u9488\u5BF9\u90A3\u4E00\u4E2A\u7F3A\u53E3\u7B80\u77ED\u56DE\u8BB2,\u8BB2\u5B8C\u8BF7\u4ED6\u7528\u81EA\u5DF1\u7684\u8BDD\u590D\u8FF0\u4E00\u904D;\u7B54\u5BF9\u5C31\u786E\u8BA4\u5E76\u63A8\u8FDB,\u4E0D\u91CD\u590D\u8BB2\u89E3;\n- \u8BA1\u5206\u68C0\u9A8C:\u590D\u4E60\u4E2D\u9014\u7528 generate_quiz \u51FA 2~4 \u9898\u5C0F\u6D4B(\u5BF9\u51C6\u5F31\u9879),\u7B54\u9898\u4F1A\u88AB\u7CFB\u7EDF\u81EA\u52A8\u5224\u5206\u5E76\u8BA1\u5165\u638C\u63E1\u5EA6;\u81EA\u7531\u95EE\u7B54\u7684\u5224\u5206\u7528 record_answer;\n- \u9002\u65F6\u6536\u675F:\u590D\u4E60 3~6 \u8F6E\u540E,\u6216\u5B66\u4E60\u8005\u660E\u786E\u8868\u793A\u8981\u7ED3\u675F,\u8C03\u7528 end_review_session \u6536\u675F\u2014\u2014quality \u6309\u6807\u5C3A\u8BC4\u5B9A(1=\u51E0\u4E4E\u4E0D\u8BB0\u5F97/2=\u591A\u6570\u5FD8\u4E86/3=\u52C9\u5F3A\u60F3\u8D77/4=\u8BB0\u5F97/5=\u5F88\u719F),summary \u7528\u4E00\u4E24\u53E5\u6982\u62EC\u672C\u6B21\u8868\u73B0,weakPoints \u5217\u51FA\u4E0B\u6B21\u8981\u91CD\u70B9\u8003\u5BDF\u7684\u8584\u5F31\u70B9;\n- \u6536\u675F\u56DE\u5408\u653E\u5BBD\u5DE5\u5177\u9650\u5236:\u6700\u540E\u4E00\u6761\u56DE\u590D\u53EF\u4EE5\u540C\u65F6\u53D1 generate_quiz \u548C end_review_session;\u5176\u4F59\u56DE\u5408\u4ECD\u9075\u5B88\u300C\u4E00\u6B21\u56DE\u590D\u6700\u591A 1 \u4E2A\u5DE5\u5177\u300D;\n- \u590D\u4E60\u4F1A\u8BDD\u4E2D\u4E0D\u8981\u8C03\u7528 mark_mastered\u2014\u2014\u590D\u4E60\u4E0D\u53D1\u8D77\u6BD5\u4E1A\u5224\u5B9A,\u638C\u63E1\u5EA6\u4EA4\u7ED9\u7B54\u9898\u89C2\u6D4B\u81EA\u7136\u6F14\u8FDB\u3002";
559299
+ }
559300
+ return "[Review-tutor posture] This conversation is a spaced-review session \u2014 the learner has already studied this lesson; you are testing and consolidating memory, not teaching it fresh:\n- Recall first, reveal later: never open with the lesson text or a long re-teach \u2014 not at the start, not mid-session. Begin with one recall question and let the learner answer from memory; decide the next step from their answer;\n- Target weak spots: prioritize knowledge components marked low in the list above and the learner's past friction points; weak points left in the previous session's closing record are your first questions;\n- Explain only what failed: when the learner is wrong or cannot recall, give a short, targeted re-teach of exactly that gap, then ask them to restate it in their own words; when they're right, confirm and move on \u2014 no re-explaining;\n- Scored check: mid-session, use generate_quiz for a 2-4 question check (aimed at weak spots) \u2014 answers are auto-graded by the system and feed mastery; judge free-text answers via record_answer;\n- Close in time: after 3-6 rounds, or when the learner clearly wants to stop, call end_review_session \u2014 grade quality on the scale (1=remember almost nothing / 2=most of it gone / 3=barely recalled / 4=remembered / 5=solid), write a one-or-two-sentence summary, and list weakPoints to focus on next time;\n- The one-tool-per-reply limit is relaxed on the closing reply only: you may send generate_quiz together with end_review_session; other replies still respect the limit;\n- Do not call mark_mastered in a review session \u2014 reviews never initiate graduation; mastery evolves only through graded answer observations.";
559301
+ }
559302
+
559303
+ // shared/review-session.ts
559304
+ var REVIEW_END_TOOL_NAME = "end_review_session";
559305
+ var REVIEW_KICKOFF_MARKER = "[[review-kickoff]]";
559306
+ function reviewXpKindForQuality(quality) {
559307
+ if (quality >= 4)
559308
+ return "correct";
559309
+ if (quality <= 2)
559310
+ return "wrong";
559311
+ return null;
559312
+ }
559313
+ function reviewRoundState(messages) {
559314
+ for (let i = messages.length - 1; i >= 0; i--) {
559315
+ const m = messages[i];
559316
+ if (m.role === "assistant" && m.partsJson && partsHaveEnd(jsonParts(m.partsJson)))
559317
+ return "ended";
559318
+ if (m.role === "user" && m.content.includes(REVIEW_KICKOFF_MARKER))
559319
+ return "open";
559320
+ }
559321
+ return "open";
559322
+ }
559323
+ function jsonParts(partsJson) {
559324
+ try {
559325
+ const parts = JSON.parse(partsJson);
559326
+ return Array.isArray(parts) ? parts : [];
559327
+ } catch {
559328
+ return [];
559329
+ }
559330
+ }
559331
+ function partsHaveEnd(parts) {
559332
+ for (const part of parts) {
559333
+ if (part.type === "tool-call" && part.toolName === REVIEW_END_TOOL_NAME && part.state === "output-available") {
559334
+ return true;
559335
+ }
559336
+ }
559337
+ return false;
559338
+ }
559290
559339
 
559291
559340
  // src/main/services/learner-model-service.ts
559292
559341
  init_drizzle_orm();
@@ -559330,6 +559379,10 @@ function describeOne(toolName, output) {
559330
559379
  const o = output ?? {};
559331
559380
  const title = typeof o.title === "string" && o.title ? `\u300A${o.title}\u300B` : "";
559332
559381
  switch (o.artifactType ?? toolName) {
559382
+ case REVIEW_END_TOOL_NAME: {
559383
+ const wp = Array.isArray(o.weakPoints) ? o.weakPoints.filter((w) => typeof w === "string") : [];
559384
+ return `\u5DF2\u6536\u675F\u672C\u8F6E\u590D\u4E60(\u8D28\u91CF ${o.quality ?? "?"}/5${wp.length > 0 ? `,\u4E0B\u6B21\u91CD\u70B9:${wp.join("\u3001")}` : ""})`;
559385
+ }
559333
559386
  case "quiz":
559334
559387
  return `\u5DF2\u5411\u5B66\u4E60\u8005\u53D1\u51FA\u4EA4\u4E92\u7B54\u9898\u5361${title}(\u5171 ${o.questions?.length ?? "?"} \u9898),\u5B66\u4E60\u8005\u53EF\u76F4\u63A5\u4F5C\u7B54`;
559335
559388
  case "concept_map":
@@ -559418,7 +559471,7 @@ function extractInlineDataImages(content) {
559418
559471
  out.push(m[1]);
559419
559472
  return out;
559420
559473
  }
559421
- function assembleContextBlocks(db, nodeId, locale) {
559474
+ function assembleContextBlocks(db, nodeId, locale, opts) {
559422
559475
  const node = db.select().from(contentNodes).where(eq(contentNodes.id, nodeId)).get();
559423
559476
  const nodeProgress = db.select().from(progress).where(eq(progress.nodeId, nodeId)).get();
559424
559477
  const courseId = node?.courseId;
@@ -559426,7 +559479,7 @@ function assembleContextBlocks(db, nodeId, locale) {
559426
559479
  const outLang = resolveOutputLang(locale);
559427
559480
  const system = buildSystemPrompt(
559428
559481
  db,
559429
- buildBaseAgentPrompt(outLang, course?.languageTarget ?? null),
559482
+ buildBaseAgentPrompt(outLang, course?.languageTarget ?? null) + (opts?.reviewMode ? "\n\n" + buildReviewTutorBlock(outLang) : ""),
559430
559483
  buildSoulLangReminder(outLang)
559431
559484
  );
559432
559485
  const courseSections = courseId ? db.select().from(contentNodes).where(eq(contentNodes.courseId, courseId)).all().filter((n) => n.type === "section").sort((a, b) => a.orderIdx - b.orderIdx) : [];
@@ -559465,13 +559518,21 @@ ${kcContext}` : "") : "(\u65E0\u5F53\u524D\u8282\u70B9\u4E0A\u4E0B\u6587)";
559465
559518
  );
559466
559519
  return { system, nodeContext, learnerSnapshot, profileBlock, node, nodeProgress };
559467
559520
  }
559468
- async function runAgentTurn(db, nodeId, messages, events = {}, abortSignal, locale, attachments) {
559521
+ async function runAgentTurn(db, nodeId, messages, events = {}, abortSignal, locale, attachments, opts) {
559469
559522
  const llm = resolveLlm(db);
559470
- const { system, nodeContext, learnerSnapshot, profileBlock, node, nodeProgress } = assembleContextBlocks(db, nodeId, locale);
559523
+ const reviewMode = opts?.reviewMode === true;
559524
+ const { system, nodeContext, learnerSnapshot, profileBlock, node, nodeProgress } = assembleContextBlocks(
559525
+ db,
559526
+ nodeId,
559527
+ locale,
559528
+ { reviewMode }
559529
+ );
559530
+ const systemPrompt = reviewMode && opts?.reviewAlreadyEnded ? system + "\n\n(\u7CFB\u7EDF\u63D0\u793A:\u672C\u590D\u4E60\u4F1A\u8BDD\u5DF2\u7ECF\u6536\u675F\u8FC7,\u73B0\u5728\u6B63\u5E38\u7B54\u7591\u5373\u53EF,\u4E0D\u8981\u518D\u8C03\u7528 end_review_session\u3002)" : system;
559471
559531
  const mainVisionCapable = supportsVision(llm.provider, llm.model);
559472
559532
  const routing = visionRouting(mainVisionCapable, getVisionOverride(db) !== null);
559473
559533
  let recordAnswerCalls = 0;
559474
559534
  const RECORD_ANSWER_TURN_LIMIT = 8;
559535
+ let endReviewCalls = 0;
559475
559536
  const tools = {
559476
559537
  get_node_info: tool({
559477
559538
  description: "\u8BFB\u53D6\u5F53\u524D\u5B66\u4E60\u8282\u70B9\u7684\u8BE6\u7EC6\u4FE1\u606F\uFF08\u6807\u9898\u3001\u5185\u5BB9\u3001\u638C\u63E1\u5EA6\uFF09\u3002\u53EA\u8BFB\u3002",
@@ -559624,6 +559685,47 @@ async function runAgentTurn(db, nodeId, messages, events = {}, abortSignal, loca
559624
559685
  return { proposalId: proposal.id, status: "pending", message: rationale };
559625
559686
  }
559626
559687
  }),
559688
+ // v0.39 复习会话收束工具(仅 kind=review 线程注册):AI 评定 quality 1~5 喂 SM-2 排期。
559689
+ // 纪律(srs:record Phase D 同口径):只写 SRS 排期 + XP + streak,不写 BKT 掌握度;
559690
+ // 掌握度只由客观答题观测(quiz/exercise/record_answer)驱动。
559691
+ ...reviewMode ? {
559692
+ [REVIEW_END_TOOL_NAME]: tool({
559693
+ description: "\u6536\u675F\u672C\u6B21\u590D\u4E60\u4F1A\u8BDD:\u6309\u6807\u5C3A\u8BC4\u5B9A\u672C\u6B21\u590D\u4E60\u8D28\u91CF,\u7CFB\u7EDF\u4F1A\u636E\u6B64\u5B89\u6392\u4E0B\u6B21\u590D\u4E60\u65F6\u95F4(SM-2)\u3002\u6BCF\u573A\u4F1A\u8BDD\u53EA\u80FD\u8C03\u7528\u4E00\u6B21,\u6536\u675F\u540E\u6B63\u5E38\u9053\u522B\u5373\u53EF\u3002",
559694
+ inputSchema: external_exports2.object({
559695
+ quality: external_exports2.union([external_exports2.literal(1), external_exports2.literal(2), external_exports2.literal(3), external_exports2.literal(4), external_exports2.literal(5)]).describe("\u672C\u6B21\u590D\u4E60\u8D28\u91CF\u6807\u5C3A:1=\u51E0\u4E4E\u4E0D\u8BB0\u5F97/2=\u591A\u6570\u5FD8\u4E86/3=\u52C9\u5F3A\u60F3\u8D77/4=\u8BB0\u5F97/5=\u5F88\u719F"),
559696
+ summary: external_exports2.string().describe("\u4E00\u4E24\u53E5\u6982\u62EC\u672C\u6B21\u590D\u4E60\u8868\u73B0(\u4F1A\u5C55\u793A\u7ED9\u5B66\u4E60\u8005)"),
559697
+ weakPoints: external_exports2.array(external_exports2.string()).optional().describe("\u4E0B\u6B21\u590D\u4E60\u8981\u91CD\u70B9\u8003\u5BDF\u7684\u8584\u5F31\u70B9(\u6982\u5FF5\u540D\u5217\u8868)")
559698
+ }),
559699
+ execute: async (input) => {
559700
+ const { quality, summary, weakPoints } = input;
559701
+ if (++endReviewCalls > 1) {
559702
+ return { status: "rejected", message: "\u672C\u56DE\u5408\u5DF2\u6536\u675F\u8FC7,\u4E0D\u8981\u91CD\u590D\u8C03\u7528 end_review_session\u3002" };
559703
+ }
559704
+ if (opts?.reviewAlreadyEnded) {
559705
+ return { status: "rejected", message: "\u672C\u4F1A\u8BDD\u5DF2\u6536\u675F\u8FC7,\u4E0D\u80FD\u518D\u8C03\u7528 end_review_session\u3002" };
559706
+ }
559707
+ events.onToolCall?.(REVIEW_END_TOOL_NAME, { quality });
559708
+ const result = recordReview(nodeId, quality);
559709
+ const xpKind = reviewXpKindForQuality(quality);
559710
+ if (xpKind === "correct")
559711
+ addXpCorrect(db);
559712
+ else if (xpKind === "wrong")
559713
+ addXpWrong(db);
559714
+ else
559715
+ emitStateChange("xp");
559716
+ touchStreakToday();
559717
+ return {
559718
+ status: "ended",
559719
+ quality,
559720
+ summary,
559721
+ weakPoints: weakPoints ?? [],
559722
+ intervalDays: result.intervalDays,
559723
+ nextDueAt: result.dueAt,
559724
+ message: `\u590D\u4E60\u5DF2\u6536\u675F:\u8D28\u91CF ${quality}/5,\u4E0B\u6B21\u590D\u4E60\u7EA6 ${result.intervalDays} \u5929\u540E\u3002`
559725
+ };
559726
+ }
559727
+ })
559728
+ } : {},
559627
559729
  update_learner_profile: tool({
559628
559730
  description: "\u63D0\u8BAE\u66F4\u65B0\u5B66\u4E60\u8005\u753B\u50CF\uFF08\u79F0\u547C/MBTI/\u6559\u5B66\u98CE\u683C\u504F\u597D/\u5174\u8DA3\u70B9\uFF09\u3002\u751F\u6210 Proposal \u7B49\u4EBA\u786E\u8BA4\uFF08\u4EBA\u53EF\u4EE5\u62D2\u7EDD\uFF09\u3002\u63D0\u8BAE\u4E0D\u4F1A\u6253\u65AD\u5BF9\u8BDD\u2014\u2014\u5B83\u4F1A\u51FA\u73B0\u5728\u5B66\u4E60\u8005\u7684\u300C\u4E2A\u4EBA\u8D44\u6599\u300D\u7A97\u53E3\u91CC\uFF0C\u7531\u5B66\u4E60\u8005\u5728\u5176\u4E2D\u91C7\u7EB3\u6216\u5FFD\u7565\uFF1B\u53EA\u6709\u5F53\u4F60\u89C2\u5BDF\u5230\u4E0E\u73B0\u6709\u753B\u50CF\u4E0D\u7B26\u7684\u5B66\u4E60\u6A21\u5F0F\u3001\u4E14\u8BC1\u636E\u51FA\u73B0\u4E86\u81F3\u5C11 2 \u6B21\u65F6\u624D\u8C03\u7528\uFF0C\u5E76\u5728\u5B66\u4E60\u8005\u5B8C\u6210\u7B54\u9898/\u8282\u70B9\u6536\u5C3E\u7B49\u81EA\u7136\u505C\u987F\u5904\u53D1\u8D77\uFF0C\u4E0D\u8981\u5728\u8BB2\u89E3\u4E2D\u9014\u6253\u65AD\uFF1B\u63D0\u8BAE\u88AB\u5FFD\u7565\u540E\u4E0D\u8981\u5728\u540C\u4E00\u95EE\u9898\u4E0A\u91CD\u590D\u7EA0\u7F20\u3002",
559629
559731
  inputSchema: external_exports2.object({
@@ -559993,7 +560095,7 @@ ${learnerSnapshot}` : ""}`
559993
560095
  const result = streamText({
559994
560096
  model: chatModel,
559995
560097
  ...providerOptions ? { providerOptions } : {},
559996
- system: `${system}
560098
+ system: `${systemPrompt}
559997
560099
 
559998
560100
  ${nodeContext}${learnerSnapshot ? `
559999
560101
 
@@ -560221,6 +560323,8 @@ ${s}` : s;
560221
560323
  );
560222
560324
  const threadRow = db.select().from(threads).where(eq(threads.id, threadId)).get();
560223
560325
  const focusNodeId = threadRow?.focusNodeId ?? threadId;
560326
+ const reviewMode = threadRow?.kind === "review";
560327
+ const reviewAlreadyEnded = reviewMode && reviewRoundState(rawMsgs) === "ended";
560224
560328
  const ctrlKey = `thread:${threadId}`;
560225
560329
  if (abortControllers.has(ctrlKey)) {
560226
560330
  throw new Error("\u8BE5\u5BF9\u8BDD\u6B63\u5728\u56DE\u590D\u4E2D\uFF0C\u8BF7\u5148\u505C\u6B62\u6216\u7B49\u5F85\u672C\u8F6E\u7ED3\u675F");
@@ -560245,7 +560349,8 @@ ${s}` : s;
560245
560349
  },
560246
560350
  controller.signal,
560247
560351
  locale,
560248
- imageAtts.map((a) => ({ mediaType: a.mime, base64: a.data }))
560352
+ imageAtts.map((a) => ({ mediaType: a.mime, base64: a.data })),
560353
+ { reviewMode, reviewAlreadyEnded }
560249
560354
  );
560250
560355
  } finally {
560251
560356
  abortControllers.delete(ctrlKey);
@@ -560284,8 +560389,8 @@ init_llm_client();
560284
560389
  init_llm_presets();
560285
560390
  init_model_catalog();
560286
560391
  init_custom_provider_service();
560287
- function getContextUsage(db, nodeId, locale) {
560288
- const blocks = assembleContextBlocks(db, nodeId, locale);
560392
+ function getContextUsage(db, nodeId, locale, reviewMode) {
560393
+ const blocks = assembleContextBlocks(db, nodeId, locale, { reviewMode });
560289
560394
  if (!blocks.node)
560290
560395
  return null;
560291
560396
  const settings2 = readSettingsMap(db);
@@ -562371,11 +562476,20 @@ function registerSrsHandlers() {
562371
562476
  handle(
562372
562477
  "srs:record",
562373
562478
  async (_e, nodeId, quality) => {
562374
- recordReview(nodeId, quality);
562479
+ const result = recordReview(nodeId, quality);
562375
562480
  if (quality >= 4)
562376
562481
  addXpCorrect(getDb());
562377
562482
  else if (quality <= 2)
562378
562483
  addXpWrong(getDb());
562484
+ else
562485
+ emitStateChange("xp");
562486
+ touchStreakToday();
562487
+ return {
562488
+ ok: true,
562489
+ quality,
562490
+ intervalDays: result.intervalDays,
562491
+ nextDueAt: result.dueAt
562492
+ };
562379
562493
  }
562380
562494
  );
562381
562495
  }
@@ -562536,8 +562650,8 @@ function registerAgentHandlers(deps) {
562536
562650
  handle("agent:abortThread", async (_e, threadId) => {
562537
562651
  abortAgentChatThread(threadId);
562538
562652
  });
562539
- handle("agent:getContextUsage", async (_e, nodeId, locale) => {
562540
- return getContextUsage(getDb(), nodeId, locale);
562653
+ handle("agent:getContextUsage", async (_e, nodeId, locale, reviewMode) => {
562654
+ return getContextUsage(getDb(), nodeId, locale, reviewMode);
562541
562655
  });
562542
562656
  handle("attachment:getDataUrl", async (_e, file2) => {
562543
562657
  return readAttachmentDataUrl(file2);
@@ -1,4 +1,4 @@
1
- import{r,j as h}from"./index-jKxnKPxh.js";import{c as T,u as L,t as D}from"./main-BG2k-Vog.js";/**
1
+ import{r,j as h}from"./index-88125dOi.js";import{c as T,u as L,t as D}from"./main-_pTgysch.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-jKxnKPxh.js";import{c as y,u as v,d as k,L as j,F as N,M as w,G as C,T as M,e as _}from"./main-BG2k-Vog.js";/**
1
+ import{r as s,j as t}from"./index-88125dOi.js";import{c as y,u as v,d as k,L as j,F as N,M as w,G as C,T as M,e as _}from"./main-_pTgysch.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{u as G,r as v,j as c,o as ie,p as ce,c as le}from"./index-jKxnKPxh.js";function A(e,t){return{code:e,message:t}}function me(e,t={}){const n=t.minSide??256,u=t.maxSide??4096,i=t.marginRatio??.02,o=t.alphaThreshold??128,r=t.minBlobAreaRatio??.05,h=t.maxSamples??1e6,l=[],g=(s,p=0,w=0)=>({ok:!1,issues:s.map(([T,C])=>A(T,C)),opaqueRatio:p,blobCount:w}),{width:a,height:m,rgba:b}=e;if(!Number.isFinite(a)||!Number.isFinite(m)||a<=0||m<=0||!Number.isInteger(a)||!Number.isInteger(m))return g([["BAD_DIMENSIONS",`非法尺寸 ${a}x${m}`]]);if(Math.min(a,m)<n&&l.push(A("TOO_SMALL",`短边 ${Math.min(a,m)}px < ${n}px`)),Math.max(a,m)>u&&l.push(A("TOO_LARGE",`长边 ${Math.max(a,m)}px > ${u}px(导入时自动缩放)`)),!b||b.length!==a*m*4)return l.push(A("BAD_PIXEL_BUFFER",`rgba 长度 ${(b==null?void 0:b.length)??0} ≠ ${a}*${m}*4`)),{ok:!1,issues:l,opaqueRatio:0,blobCount:0};const x=Math.max(1,Math.ceil(Math.sqrt(a*m/h))),d=Math.floor((a-1)/x)+1,f=Math.floor((m-1)/x)+1,y=new Uint8Array(d*f);let L=0,M=0,N=255,S=d,R=-1,k=f,Y=-1;for(let s=0;s<f;s++){const p=s*x;for(let w=0;w<d;w++){const T=w*x,C=b[(p*a+T)*4+3];M++,C<N&&(N=C),C>=o&&(y[s*d+w]=1,L++,w<S&&(S=w),w>R&&(R=w),s<k&&(k=s),s>Y&&(Y=s))}}const J=M>0?L/M:0;if(L===0)return l.push(A("ALL_TRANSPARENT","整图无不透明像素(空图/坏抠图)")),{ok:l.length===0,issues:l,opaqueRatio:J,blobCount:0};if(N===255&&l.push(A("NO_ALPHA","未检出任何透明像素——需要透明底 PNG(可一键抠图/豆包抠图)")),S===0||k===0||R===d-1||Y===f-1){const s=a*i,p=m*i;(S*x<s||k*x<p||R*x+x-1>a-1-s||Y*x+x-1>m-1-p)&&l.push(A("EDGE_TOUCH","主体贴边——四周留 5~10% 空白,给跳跃/挤压变换留余地"))}const _=new Uint8Array(d*f),B=[],$=[];for(let s=0;s<y.length;s++){if(!y[s]||_[s])continue;let p=0,w=d,T=-1,C=f,O=-1;for($.push(s),_[s]=1;$.length>0;){const E=$.pop();p++;const P=E%d,X=(E-P)/d;P<w&&(w=P),P>T&&(T=P),X<C&&(C=X),X>O&&(O=X);const D=I=>{y[I]&&!_[I]&&(_[I]=1,$.push(I))};P>0&&D(E-1),P<d-1&&D(E+1),X>0&&D(E-d),X<f-1&&D(E+d)}B.push({area:p,minX:w,maxX:T,minY:C,maxY:O})}const se=B.length>0?Math.max(...B.map(s=>s.area)):0,Z=B.filter(s=>s.area>=se*r),re=(s,p)=>s.minX>=p.minX&&s.maxX<=p.maxX&&s.minY>=p.minY&&s.maxY<=p.maxY,oe=(s,p)=>{const w=Math.min(s.maxX,p.maxX)-Math.max(s.minX,p.minX),T=Math.min(s.maxY,p.maxY)-Math.max(s.minY,p.minY);if(w<=0||T<=0)return 0;const C=w*T,O=(s.maxX-s.minX+1)*(s.maxY-s.minY+1),E=(p.maxX-p.minX+1)*(p.maxY-p.minY+1);return C/Math.min(O,E)},F=Z.filter(s=>!Z.some(p=>p!==s&&p.area>=s.area&&(re(s,p)||oe(s,p)>=.4))).length;return F>=2&&l.push(A("MULTI_BLOB",`检出 ${F} 个独立主体——请裁剪到单角色`)),{ok:l.length===0,issues:l,opaqueRatio:J,blobCount:F}}function de(e){return typeof e.poseHoldMs=="number"?e.poseHoldMs:1200}const ue=""+new URL("alien-idle-D2VKjYsl.png",import.meta.url).href,fe=""+new URL("alien-happy-Ci3JfpxD.png",import.meta.url).href,he=""+new URL("alien-thinking-gWKA2xDz.png",import.meta.url).href,pe=""+new URL("alien-keyL-C_tZriGQ.png",import.meta.url).href,xe=""+new URL("alien-keyL-C_tZriGQ.png",import.meta.url).href,z=""+new URL("alien-head-CS10QxqG.png",import.meta.url).href,be=""+new URL("alien-body-DXq5WJRs.png",import.meta.url).href,j={head:{x:.3,y:.05,w:.4,h:.2726},body:{x:.3,y:.3226,w:.4,h:.2841}},ee={x:.5,y:.3226},ye={formatVersion:1,id:"lab-alien",name:"Lab 小宇航员(Kenney)",author:"Kenney",license:"CC0-1.0 (Kenney Platformer Characters)",tier:"bongo",states:{idle:"idle.png",keyL:"keyl.png",keyR:"keyr.png",happy:"happy.png",thinking:"thinking.png"},poseHoldMs:1100};async function ge(){const e={idle:ue,keyL:pe,keyR:xe,happy:fe,thinking:he},t=await we(z),n=document.createElement("canvas");n.width=512,n.height=512;const u=n.getContext("2d");u.drawImage(t,0,0);const i=u.getImageData(0,0,512,512),o=me({width:512,height:512,rgba:i.data});return{srcs:e,parts:{head:z,body:be},selfSpec:o}}function we(e){return new Promise((t,n)=>{const u=new Image;u.onload=()=>t(u),u.onerror=()=>n(new Error(`image load failed: ${e}`)),u.src=e})}function te(e,t,n){const{x:u,y:i,w:o,h:r,t:h,deform:l}=n,g=n.cols??6,a=n.rows??8,m=n.src??{x:0,y:0,w:t.width,h:t.height},b=[];for(let d=0;d<=a;d++)for(let f=0;f<=g;f++){const y=f/g,L=d/a,M=l(y,L,h);b.push([u+y*o+M.dx,i+L*r+M.dy])}const x=(d,f)=>b[f*(g+1)+d];for(let d=0;d<a;d++)for(let f=0;f<g;f++){const y=x(f,d),L=x(f+1,d),M=x(f,d+1),N=x(f+1,d+1),S=m.x+f/g*m.w,R=m.y+d/a*m.h,k=m.x+(f+1)/g*m.w,Y=m.y+(d+1)/a*m.h;ne(e,t,[S,R],[k,R],[S,Y],y,L,M),ne(e,t,[k,R],[k,Y],[S,Y],L,N,M)}}function ne(e,t,n,u,i,o,r,h){const l=(u[0]-n[0])*(i[1]-n[1])-(i[0]-n[0])*(u[1]-n[1]);if(Math.abs(l)<1e-8)return;const g=((r[0]-o[0])*(i[1]-n[1])-(h[0]-o[0])*(u[1]-n[1]))/l,a=((h[0]-o[0])*(u[0]-n[0])-(r[0]-o[0])*(i[0]-n[0]))/l,m=((r[1]-o[1])*(i[1]-n[1])-(h[1]-o[1])*(u[1]-n[1]))/l,b=((h[1]-o[1])*(u[0]-n[0])-(r[1]-o[1])*(i[0]-n[0]))/l,x=o[0]-g*n[0]-a*n[1],d=o[1]-m*n[0]-b*n[1];e.save(),e.beginPath(),e.moveTo(o[0],o[1]),e.lineTo(r[0],r[1]),e.lineTo(h[0],h[1]),e.closePath(),e.clip(),e.transform(g,m,a,b,x,d),e.drawImage(t,0,0),e.restore()}function K(e){const t=v.useRef(e);t.current=e,v.useEffect(()=>{const n={side:1},u=r=>{if(r.repeat)return;const h=ce(r.code,n.side);n.side=n.side===1?-1:1,t.current(h===1?"keyR":"keyL")},i=r=>t.current(r.detail?"thinking":"idle"),o=ie(r=>t.current(r.kind==="wrong"?"wrong":"happy"));return window.addEventListener("keydown",u,{passive:!0}),window.addEventListener("companion-streaming",i),()=>{window.removeEventListener("keydown",u),window.removeEventListener("companion-streaming",i),o()}},[])}function H(){const[e,t]=v.useState("idle"),n=v.useRef(null),u=v.useCallback((i,o=0)=>{n.current!==null&&window.clearTimeout(n.current),n.current=null,t(i);const r=o>0?o:0;r>0&&i!=="idle"&&(n.current=window.setTimeout(()=>t("idle"),r))},[]);return v.useEffect(()=>()=>{n.current!==null&&window.clearTimeout(n.current)},[]),{pose:e,setTimed:u}}function Q(e,t){t||!e||typeof e.animate!="function"||e.animate([{transform:"translateY(0)"},{transform:"translateY(-12%)"},{transform:"translateY(2%)"},{transform:"translateY(0)"}],{duration:380,easing:"cubic-bezier(0.2, 1.4, 0.4, 1)"})}function V(e,t){t||!e||typeof e.animate!="function"||e.animate([{transform:"rotate(0deg)"},{transform:"rotate(-6deg)"},{transform:"rotate(6deg)"},{transform:"rotate(0deg)"}],{duration:280})}function q(e,t){t||!e||typeof e.animate!="function"||e.animate([{transform:"translateY(0px) scale(1, 1)"},{transform:"translateY(2.5px) scale(1.045, 0.93)",offset:.42},{transform:"translateY(0px) scale(1, 1)"}],{duration:185,easing:"ease-out",composite:"add"})}const W=`
1
+ import{u as G,r as v,j as c,o as ie,p as ce,c as le}from"./index-88125dOi.js";function A(e,t){return{code:e,message:t}}function me(e,t={}){const n=t.minSide??256,u=t.maxSide??4096,i=t.marginRatio??.02,o=t.alphaThreshold??128,r=t.minBlobAreaRatio??.05,h=t.maxSamples??1e6,l=[],g=(s,p=0,w=0)=>({ok:!1,issues:s.map(([T,C])=>A(T,C)),opaqueRatio:p,blobCount:w}),{width:a,height:m,rgba:b}=e;if(!Number.isFinite(a)||!Number.isFinite(m)||a<=0||m<=0||!Number.isInteger(a)||!Number.isInteger(m))return g([["BAD_DIMENSIONS",`非法尺寸 ${a}x${m}`]]);if(Math.min(a,m)<n&&l.push(A("TOO_SMALL",`短边 ${Math.min(a,m)}px < ${n}px`)),Math.max(a,m)>u&&l.push(A("TOO_LARGE",`长边 ${Math.max(a,m)}px > ${u}px(导入时自动缩放)`)),!b||b.length!==a*m*4)return l.push(A("BAD_PIXEL_BUFFER",`rgba 长度 ${(b==null?void 0:b.length)??0} ≠ ${a}*${m}*4`)),{ok:!1,issues:l,opaqueRatio:0,blobCount:0};const x=Math.max(1,Math.ceil(Math.sqrt(a*m/h))),d=Math.floor((a-1)/x)+1,f=Math.floor((m-1)/x)+1,y=new Uint8Array(d*f);let L=0,M=0,N=255,S=d,R=-1,k=f,Y=-1;for(let s=0;s<f;s++){const p=s*x;for(let w=0;w<d;w++){const T=w*x,C=b[(p*a+T)*4+3];M++,C<N&&(N=C),C>=o&&(y[s*d+w]=1,L++,w<S&&(S=w),w>R&&(R=w),s<k&&(k=s),s>Y&&(Y=s))}}const J=M>0?L/M:0;if(L===0)return l.push(A("ALL_TRANSPARENT","整图无不透明像素(空图/坏抠图)")),{ok:l.length===0,issues:l,opaqueRatio:J,blobCount:0};if(N===255&&l.push(A("NO_ALPHA","未检出任何透明像素——需要透明底 PNG(可一键抠图/豆包抠图)")),S===0||k===0||R===d-1||Y===f-1){const s=a*i,p=m*i;(S*x<s||k*x<p||R*x+x-1>a-1-s||Y*x+x-1>m-1-p)&&l.push(A("EDGE_TOUCH","主体贴边——四周留 5~10% 空白,给跳跃/挤压变换留余地"))}const _=new Uint8Array(d*f),B=[],$=[];for(let s=0;s<y.length;s++){if(!y[s]||_[s])continue;let p=0,w=d,T=-1,C=f,O=-1;for($.push(s),_[s]=1;$.length>0;){const E=$.pop();p++;const P=E%d,X=(E-P)/d;P<w&&(w=P),P>T&&(T=P),X<C&&(C=X),X>O&&(O=X);const D=I=>{y[I]&&!_[I]&&(_[I]=1,$.push(I))};P>0&&D(E-1),P<d-1&&D(E+1),X>0&&D(E-d),X<f-1&&D(E+d)}B.push({area:p,minX:w,maxX:T,minY:C,maxY:O})}const se=B.length>0?Math.max(...B.map(s=>s.area)):0,Z=B.filter(s=>s.area>=se*r),re=(s,p)=>s.minX>=p.minX&&s.maxX<=p.maxX&&s.minY>=p.minY&&s.maxY<=p.maxY,oe=(s,p)=>{const w=Math.min(s.maxX,p.maxX)-Math.max(s.minX,p.minX),T=Math.min(s.maxY,p.maxY)-Math.max(s.minY,p.minY);if(w<=0||T<=0)return 0;const C=w*T,O=(s.maxX-s.minX+1)*(s.maxY-s.minY+1),E=(p.maxX-p.minX+1)*(p.maxY-p.minY+1);return C/Math.min(O,E)},F=Z.filter(s=>!Z.some(p=>p!==s&&p.area>=s.area&&(re(s,p)||oe(s,p)>=.4))).length;return F>=2&&l.push(A("MULTI_BLOB",`检出 ${F} 个独立主体——请裁剪到单角色`)),{ok:l.length===0,issues:l,opaqueRatio:J,blobCount:F}}function de(e){return typeof e.poseHoldMs=="number"?e.poseHoldMs:1200}const ue=""+new URL("alien-idle-D2VKjYsl.png",import.meta.url).href,fe=""+new URL("alien-happy-Ci3JfpxD.png",import.meta.url).href,he=""+new URL("alien-thinking-gWKA2xDz.png",import.meta.url).href,pe=""+new URL("alien-keyL-C_tZriGQ.png",import.meta.url).href,xe=""+new URL("alien-keyL-C_tZriGQ.png",import.meta.url).href,z=""+new URL("alien-head-CS10QxqG.png",import.meta.url).href,be=""+new URL("alien-body-DXq5WJRs.png",import.meta.url).href,j={head:{x:.3,y:.05,w:.4,h:.2726},body:{x:.3,y:.3226,w:.4,h:.2841}},ee={x:.5,y:.3226},ye={formatVersion:1,id:"lab-alien",name:"Lab 小宇航员(Kenney)",author:"Kenney",license:"CC0-1.0 (Kenney Platformer Characters)",tier:"bongo",states:{idle:"idle.png",keyL:"keyl.png",keyR:"keyr.png",happy:"happy.png",thinking:"thinking.png"},poseHoldMs:1100};async function ge(){const e={idle:ue,keyL:pe,keyR:xe,happy:fe,thinking:he},t=await we(z),n=document.createElement("canvas");n.width=512,n.height=512;const u=n.getContext("2d");u.drawImage(t,0,0);const i=u.getImageData(0,0,512,512),o=me({width:512,height:512,rgba:i.data});return{srcs:e,parts:{head:z,body:be},selfSpec:o}}function we(e){return new Promise((t,n)=>{const u=new Image;u.onload=()=>t(u),u.onerror=()=>n(new Error(`image load failed: ${e}`)),u.src=e})}function te(e,t,n){const{x:u,y:i,w:o,h:r,t:h,deform:l}=n,g=n.cols??6,a=n.rows??8,m=n.src??{x:0,y:0,w:t.width,h:t.height},b=[];for(let d=0;d<=a;d++)for(let f=0;f<=g;f++){const y=f/g,L=d/a,M=l(y,L,h);b.push([u+y*o+M.dx,i+L*r+M.dy])}const x=(d,f)=>b[f*(g+1)+d];for(let d=0;d<a;d++)for(let f=0;f<g;f++){const y=x(f,d),L=x(f+1,d),M=x(f,d+1),N=x(f+1,d+1),S=m.x+f/g*m.w,R=m.y+d/a*m.h,k=m.x+(f+1)/g*m.w,Y=m.y+(d+1)/a*m.h;ne(e,t,[S,R],[k,R],[S,Y],y,L,M),ne(e,t,[k,R],[k,Y],[S,Y],L,N,M)}}function ne(e,t,n,u,i,o,r,h){const l=(u[0]-n[0])*(i[1]-n[1])-(i[0]-n[0])*(u[1]-n[1]);if(Math.abs(l)<1e-8)return;const g=((r[0]-o[0])*(i[1]-n[1])-(h[0]-o[0])*(u[1]-n[1]))/l,a=((h[0]-o[0])*(u[0]-n[0])-(r[0]-o[0])*(i[0]-n[0]))/l,m=((r[1]-o[1])*(i[1]-n[1])-(h[1]-o[1])*(u[1]-n[1]))/l,b=((h[1]-o[1])*(u[0]-n[0])-(r[1]-o[1])*(i[0]-n[0]))/l,x=o[0]-g*n[0]-a*n[1],d=o[1]-m*n[0]-b*n[1];e.save(),e.beginPath(),e.moveTo(o[0],o[1]),e.lineTo(r[0],r[1]),e.lineTo(h[0],h[1]),e.closePath(),e.clip(),e.transform(g,m,a,b,x,d),e.drawImage(t,0,0),e.restore()}function K(e){const t=v.useRef(e);t.current=e,v.useEffect(()=>{const n={side:1},u=r=>{if(r.repeat)return;const h=ce(r.code,n.side);n.side=n.side===1?-1:1,t.current(h===1?"keyR":"keyL")},i=r=>t.current(r.detail?"thinking":"idle"),o=ie(r=>t.current(r.kind==="wrong"?"wrong":"happy"));return window.addEventListener("keydown",u,{passive:!0}),window.addEventListener("companion-streaming",i),()=>{window.removeEventListener("keydown",u),window.removeEventListener("companion-streaming",i),o()}},[])}function H(){const[e,t]=v.useState("idle"),n=v.useRef(null),u=v.useCallback((i,o=0)=>{n.current!==null&&window.clearTimeout(n.current),n.current=null,t(i);const r=o>0?o:0;r>0&&i!=="idle"&&(n.current=window.setTimeout(()=>t("idle"),r))},[]);return v.useEffect(()=>()=>{n.current!==null&&window.clearTimeout(n.current)},[]),{pose:e,setTimed:u}}function Q(e,t){t||!e||typeof e.animate!="function"||e.animate([{transform:"translateY(0)"},{transform:"translateY(-12%)"},{transform:"translateY(2%)"},{transform:"translateY(0)"}],{duration:380,easing:"cubic-bezier(0.2, 1.4, 0.4, 1)"})}function V(e,t){t||!e||typeof e.animate!="function"||e.animate([{transform:"rotate(0deg)"},{transform:"rotate(-6deg)"},{transform:"rotate(6deg)"},{transform:"rotate(0deg)"}],{duration:280})}function q(e,t){t||!e||typeof e.animate!="function"||e.animate([{transform:"translateY(0px) scale(1, 1)"},{transform:"translateY(2.5px) scale(1.045, 0.93)",offset:.42},{transform:"translateY(0px) scale(1, 1)"}],{duration:185,easing:"ease-out",composite:"add"})}const W=`
2
2
  .cbot { position: relative; display: inline-block; line-height: 0;
3
3
  animation: cbot-breath 3.4s ease-in-out infinite; transform-origin: 50% 62%; }
4
4
  .cbot img, .cbot canvas { display: block; user-select: none; }
@@ -1,4 +1,4 @@
1
- import{r as u,j as t}from"./index-jKxnKPxh.js";import{c as I,U as C,u as y,a as L,e as S,X as N,B as M,T as E,h as R}from"./main-BG2k-Vog.js";/**
1
+ import{r as u,j as t}from"./index-88125dOi.js";import{c as I,U as C,u as y,a as L,e as S,X as N,B as M,T as E,h as R}from"./main-_pTgysch.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-jKxnKPxh.js";import{c as te,u as ce,a as j,n as de,T as z,q as Y,A as q,L as V,r as oe,X as xe}from"./main-BG2k-Vog.js";import{R as G}from"./rotate-ccw-ChWz7hYv.js";/**
1
+ import{r as o,h as U,j as e,c as ie}from"./index-88125dOi.js";import{c as te,u as ce,a as j,n as de,T as z,q as Y,A as q,L as V,r as oe,X as xe}from"./main-_pTgysch.js";import{R as G}from"./rotate-ccw-BIQ3H8e1.js";/**
2
2
  * @license lucide-react v0.468.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,9 +1,9 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./mermaid.core-CFB6SYUU.js","./main-BG2k-Vog.js","./index-jKxnKPxh.js","./index-CS4Wtfwl.css","./main-D9IB7N5p.css","./transform-Bd_a5eGM.js","./mermaid-layout-elk.core-BP9RfmyE.js"])))=>i.map(i=>d[i]);
2
- import{r as o,j as t}from"./index-jKxnKPxh.js";import{c as K,_ as B,u as O,d as H,D as U,X,E as L}from"./main-BG2k-Vog.js";import{M as Y,C as G}from"./CanvasStage-w4ZeJwrQ.js";/**
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./mermaid.core-DtWjB5Tg.js","./main-_pTgysch.js","./index-88125dOi.js","./index-B7IHDZbN.css","./main-D9IB7N5p.css","./transform-Bd_a5eGM.js","./mermaid-layout-elk.core-Cz784PwA.js"])))=>i.map(i=>d[i]);
2
+ import{r as o,j as t}from"./index-88125dOi.js";import{c as K,_ as B,u as O,d as H,D as U,X,E as L}from"./main-_pTgysch.js";import{M as Y,C as G}from"./CanvasStage-DoyzBHb8.js";/**
3
3
  * @license lucide-react v0.468.0 - ISC
4
4
  *
5
5
  * This source code is licensed under the ISC license.
6
6
  * See the LICENSE file in the root directory of this source tree.
7
7
  */const J=K("Workflow",[["rect",{width:"8",height:"8",x:"3",y:"3",rx:"2",key:"by2w9f"}],["path",{d:"M7 11v4a2 2 0 0 0 2 2h4",key:"xkn7yn"}],["rect",{width:"8",height:"8",x:"13",y:"13",rx:"2",key:"1cgmvn"}]]);function Q(e){const i=e.split(`
8
8
  `);for(let r=0;r<i.length;r++){const a=i[r]??"",s=a.trim();if(!(!s||s.startsWith("%%")))return/^flowchart-elk\b/i.test(s)?e:/^(flowchart|graph)\b/i.test(s)?(i[r]=a.replace(/^(\s*)(flowchart|graph)\b/i,"$1flowchart-elk"),i.join(`
9
- `)):e}return e}let p=null;function ee(){return p||(p=B(()=>import("./mermaid.core-CFB6SYUU.js").then(e=>e.bI),__vite__mapDeps([0,1,2,3,4,5]),import.meta.url).then(async e=>{const i=e.default,{default:r}=await B(async()=>{const{default:a}=await import("./mermaid-layout-elk.core-BP9RfmyE.js").then(s=>s.m);return{default:a}},__vite__mapDeps([6,1,2,3,4]),import.meta.url);return i.registerLayoutLoaders(r),i.initialize({startOnLoad:!1,theme:"base",securityLevel:"strict",themeVariables:te(),flowchart:{useMaxWidth:!0,htmlLabels:!0,curve:"basis",nodeSpacing:42,rankSpacing:54,padding:10},sequence:{useMaxWidth:!0,boxMargin:8,noteMargin:8,messageMargin:32}}),i})),p}function te(){const e=(r,a)=>{if(typeof document>"u")return a;const s=getComputedStyle(document.documentElement).getPropertyValue(r).trim();return s?`rgb(${s})`:a};return{background:"transparent",fontFamily:typeof document<"u"&&getComputedStyle(document.body).fontFamily||"ui-sans-serif, system-ui, sans-serif",fontSize:"14px",primaryColor:e("--surface-3-rgb","rgb(42 43 46)"),primaryBorderColor:e("--border-rgb","rgb(37 38 41)"),primaryTextColor:e("--ink-strong-rgb","rgb(250 250 250)"),secondaryColor:e("--surface-2-rgb","rgb(32 33 36)"),secondaryBorderColor:e("--border-faint-rgb","rgb(26 26 29)"),secondaryTextColor:e("--ink-rgb","rgb(245 245 250)"),tertiaryColor:e("--surface-1-rgb","rgb(24 25 27)"),tertiaryBorderColor:e("--border-faint-rgb","rgb(26 26 29)"),tertiaryTextColor:e("--ink-rgb","rgb(245 245 250)"),lineColor:e("--ink-faint-rgb","rgb(117 117 126)"),textColor:e("--ink-rgb","rgb(245 245 250)"),edgeLabelBackground:e("--surface-0-rgb","rgb(12 13 15)"),clusterBkg:e("--surface-1-rgb","rgb(24 25 27)"),clusterBorder:e("--border-faint-rgb","rgb(26 26 29)"),nodeBorder:e("--border-rgb","rgb(37 38 41)"),mainBkg:e("--surface-3-rgb","rgb(42 43 46)"),nodeTextColor:e("--ink-rgb","rgb(245 245 250)"),arrowheadColor:e("--ink-faint-rgb","rgb(117 117 126)"),actorBkg:e("--surface-3-rgb","rgb(42 43 46)"),actorBorder:e("--border-rgb","rgb(37 38 41)"),actorTextColor:e("--ink-strong-rgb","rgb(250 250 250)"),activationBkgColor:e("--surface-3-rgb","rgb(42 43 46)"),activationBorderColor:e("--border-rgb","rgb(37 38 41)"),signalColor:e("--ink-rgb","rgb(245 245 250)"),signalTextColor:e("--ink-rgb","rgb(245 245 250)"),labelBoxBkgColor:e("--surface-2-rgb","rgb(32 33 36)"),labelBoxBorderColor:e("--border-rgb","rgb(37 38 41)"),labelTextColor:e("--ink-rgb","rgb(245 245 250)"),loopTextColor:e("--ink-strong-rgb","rgb(250 250 250)"),noteBkgColor:"rgb(255 200 0 / 0.12)",noteBorderColor:"rgb(255 200 0 / 0.4)",noteTextColor:e("--ink-rgb","rgb(245 245 250)")}}typeof window<"u"&&window.addEventListener("theme-changed",()=>{p=null});async function re(e,i){const r=await ee(),a=Q(i);try{await r.parse(a)}catch(c){throw new Error(`mermaid 语法校验失败: ${c instanceof Error?c.message:String(c)}`)}const{svg:s}=await r.render(e,a);if(s.includes('aria-roledescription="error"')||s.includes('class="error-text"')||s.includes("Syntax error"))throw new Error("mermaid 渲染失败(语法错误或节点 label 含未转义特殊字符)");return s}function ae({title:e,onClose:i,children:r}){const a=O(),s=o.useRef(null);return H(s,!0),o.useEffect(()=>{const c=d=>{d.key==="Escape"&&i()};return window.addEventListener("keydown",c),()=>window.removeEventListener("keydown",c)},[i]),U.createPortal(t.jsxs("div",{className:"fixed inset-0 z-50 flex flex-col bg-black/80","data-testid":"diagram-viewer-modal","data-noswipe":"",role:"dialog","aria-modal":"true","aria-label":e,children:[t.jsxs("div",{className:"flex items-center justify-between gap-3 px-4 py-2.5 shrink-0",onClick:c=>c.stopPropagation(),children:[t.jsx("h3",{className:"text-body font-bold text-white truncate",children:e}),t.jsxs("div",{className:"flex items-center gap-3 shrink-0",children:[t.jsx("span",{className:"text-caption text-white/50 hidden sm:inline",children:a("artifact.viewer.hint")}),t.jsx("button",{onClick:i,"data-testid":"diagram-viewer-close","aria-label":a("action.close"),"data-tooltip":a("action.close"),className:"text-white/70 hover:text-white w-9 h-9 flex items-center justify-center rounded-lg hover:bg-white/10 transition-colors",children:t.jsx(X,{className:"w-5 h-5"})})]})]}),t.jsx("div",{className:"flex-1 min-h-0 px-2 pb-2",onClick:i,children:t.jsx("div",{ref:s,className:"h-full w-full",onClick:c=>c.stopPropagation(),children:r})})]}),document.body)}function z(e){let i=5381;for(let r=0;r<e.length;r++)i=(i<<5)+i+e.charCodeAt(r)>>>0;return i.toString(36)}const v=.3,k=3,x=.2;function I({data:e,variant:i="card"}){const r=e,a=O(),s={flowchart:a("artifact.diagram.flowchart"),sequence:a("artifact.diagram.sequence"),state:a("artifact.diagram.state")},c=o.useId().replace(/[:]/g,"_"),[d,w]=o.useState({status:"loading"}),[u,A]=o.useState(()=>{try{return sessionStorage.getItem(`mmdfix:${r.mermaid.length}:${z(r.mermaid)}`)??r.mermaid}catch{return r.mermaid}}),[j,P]=o.useState(!1),[C,N]=o.useState(!1),[R,$]=o.useState(0);o.useEffect(()=>{const n=()=>$(l=>l+1);return window.addEventListener("theme-changed",n),()=>window.removeEventListener("theme-changed",n)},[]);const[m,M]=o.useState(null),[g,b]=o.useState(1),[F,y]=o.useState(!1);o.useEffect(()=>{let n=!1;return w({status:"loading"}),M(null),re(`mmd-${c}`,u).then(l=>{if(!n&&(w({status:"rendered",svg:l}),u!==r.mermaid))try{sessionStorage.setItem(`mmdfix:${r.mermaid.length}:${z(r.mermaid)}`,u)}catch{}}).catch(l=>{n||(console.error("[MermaidArtifact] render failed:",l),w({status:"error",message:l instanceof Error?l.message:String(l)}))}),()=>{n=!0}},[u,c,R,r.mermaid]),o.useEffect(()=>{var n;d.status!=="error"||j||(P(!0),u===r.mermaid&&(n=window.api)!=null&&n.repairMermaidDiagram&&(N(!0),window.api.repairMermaidDiagram({mermaid:u,errorMessage:d.message,diagramType:r.diagramType}).then(l=>{l.ok&&l.mermaid.trim()&&A(l.mermaid)}).catch(()=>{}).finally(()=>N(!1))))},[d,j,u,r.mermaid,r.diagramType]);const D=`https://mermaid.live/edit#${encodeURIComponent(u)}`,V=o.useCallback(()=>b(n=>Math.min(k,+(n+x).toFixed(2))),[]),W=o.useCallback(()=>b(n=>Math.max(v,+(n-x).toFixed(2))),[]),q=o.useCallback(()=>b(1),[]),Z=o.useCallback(n=>{if(!n.ctrlKey&&!n.metaKey)return;n.preventDefault();const l=n.deltaY>0?-x:x;b(h=>Math.min(k,Math.max(v,+(h+l).toFixed(2))))},[]),E=d.status==="rendered"?t.jsx("div",{ref:n=>{var l;if(n&&!m){const h=n.querySelector("svg");if(h){const S=h.getBoundingClientRect(),f=(l=h.viewBox)==null?void 0:l.baseVal,T=f&&f.width?f.width:S.width,_=f&&f.height?f.height:S.height;T>0&&_>0&&M({width:T,height:_})}}},style:{width:(m==null?void 0:m.width)??void 0,height:(m==null?void 0:m.height)??void 0},dangerouslySetInnerHTML:{__html:d.svg},"data-testid":"mermaid-svg"}):null;return i==="canvas"?t.jsx("div",{"data-testid":"mermaid-canvas-content",children:E}):t.jsxs("div",{className:"surface-card p-4","data-testid":"artifact-mermaid",children:[t.jsxs("div",{className:"flex items-center justify-between mb-3 gap-2",children:[t.jsxs("div",{className:"flex items-center gap-2 flex-1 min-w-0",children:[t.jsx(J,{className:"w-4 h-4 text-ink-muted shrink-0"}),t.jsx("h3",{className:"text-body font-bold text-ink truncate",children:r.title}),t.jsx("span",{className:"text-caption font-bold px-1.5 py-0.5 rounded bg-accent/15 text-accent shrink-0",children:s[r.diagramType]??r.diagramType})]}),t.jsxs("div",{className:"flex items-center gap-1.5 shrink-0",children:[d.status==="rendered"&&t.jsxs("div",{className:"flex items-center gap-1","data-testid":"mermaid-zoom-controls",children:[t.jsx("button",{onClick:W,disabled:g<=v,className:"w-6 h-6 rounded border border-[var(--border)] text-ink-muted hover:bg-surface-1 hover:bg-surface-3 disabled:opacity-30 text-label font-bold flex items-center justify-center",title:a("artifact.zoomOut"),"data-testid":"mermaid-zoom-out",children:"−"}),t.jsxs("button",{onClick:q,className:"px-1.5 h-6 rounded border border-[var(--border)] text-ink-muted hover:bg-surface-1 hover:bg-surface-3 text-caption font-bold tabular-nums",title:a("artifact.zoomReset"),"data-testid":"mermaid-zoom-reset",children:[Math.round(g*100),"%"]}),t.jsx("button",{onClick:V,disabled:g>=k,className:"w-6 h-6 rounded border border-[var(--border)] text-ink-muted hover:bg-surface-1 hover:bg-surface-3 disabled:opacity-30 text-label font-bold flex items-center justify-center",title:a("artifact.zoomIn"),"data-testid":"mermaid-zoom-in",children:"+"})]}),d.status==="rendered"&&t.jsx("button",{onClick:()=>y(!0),"data-testid":"mermaid-expand","aria-label":a("artifact.viewer.open"),"data-tooltip":a("artifact.viewer.open"),className:"w-6 h-6 rounded border border-[var(--border)] text-ink-muted hover:bg-surface-3 flex items-center justify-center",children:t.jsx(Y,{className:"w-3.5 h-3.5"})})]}),t.jsx("button",{onClick:()=>window.open(D,"_blank"),className:"text-caption text-accent hover:underline font-bold shrink-0","data-testid":"mermaid-open-live",title:a("artifact.mermaid.openLive"),children:"mermaid.live ↗"})]}),t.jsxs("div",{onClick:()=>{d.status==="rendered"&&y(!0)},onWheel:Z,className:"bg-surface-0/40 rounded-lg p-3 overflow-auto min-h-[120px] max-h-[500px] select-none",style:{touchAction:"pan-x pan-y"},"data-testid":"mermaid-render-area","data-noswipe":"",children:[d.status==="loading"&&t.jsxs("div",{className:"flex items-center gap-2 text-body text-ink-muted my-8 justify-center","data-testid":"mermaid-loading",children:[t.jsx("span",{className:"typing-dot w-1.5 h-1.5 bg-accent rounded-full inline-block"}),t.jsx("span",{children:a("artifact.mermaid.rendering")})]}),d.status==="rendered"&&t.jsx("div",{style:{width:m?m.width*g:"auto",height:m?m.height*g:"auto",margin:"0 auto"},children:t.jsx("div",{style:{transform:`scale(${g})`,transformOrigin:"top left"},children:E})}),d.status==="error"&&C&&t.jsxs("div",{className:"flex items-center gap-2 text-body text-ink-muted my-8 justify-center","data-testid":"mermaid-repairing",children:[t.jsx("span",{className:"typing-dot w-1.5 h-1.5 bg-accent rounded-full inline-block"}),t.jsx("span",{children:a("artifact.mermaid.repairing")})]}),d.status==="error"&&!C&&t.jsxs("div",{className:"w-full text-center my-4","data-testid":"mermaid-fallback",children:[t.jsxs("div",{className:"text-body text-warning mb-2 flex items-center justify-center gap-1.5",children:[t.jsx(L,{className:"w-4 h-4 shrink-0"}),t.jsx("span",{children:a("artifact.mermaid.renderFailed")})]}),t.jsx("pre",{className:"text-label bg-surface-1/60 rounded p-2 overflow-x-auto text-ink-muted font-mono text-left",children:u}),t.jsx("div",{className:"text-caption text-ink-muted mt-2",children:a("artifact.mermaid.errorPrefix",{msg:d.message})})]})]}),d.status==="rendered"&&t.jsx("div",{className:"mt-1.5 text-caption text-ink-muted flex items-center gap-2",children:t.jsx("span",{children:a("artifact.mermaid.hint")})}),F&&d.status==="rendered"&&t.jsx(ae,{title:r.title,onClose:()=>y(!1),children:t.jsx("div",{className:"h-full w-full rounded-xl overflow-hidden bg-surface-0/60",children:t.jsx(G,{testid:"mermaid-modal-stage",children:t.jsx(I,{data:e,variant:"canvas"})})})}),r.warnings&&r.warnings.length>0&&t.jsxs("div",{className:"mt-2 text-caption text-warning flex items-start gap-1","data-testid":"artifact-warnings",children:[t.jsx(L,{className:"w-3.5 h-3.5 shrink-0 mt-0.5"}),t.jsx("span",{children:r.warnings.join("; ")})]})]})}const oe=Object.freeze(Object.defineProperty({__proto__:null,MermaidArtifact:I},Symbol.toStringTag,{value:"Module"}));export{ae as D,I as M,oe as a};
9
+ `)):e}return e}let p=null;function ee(){return p||(p=B(()=>import("./mermaid.core-DtWjB5Tg.js").then(e=>e.bI),__vite__mapDeps([0,1,2,3,4,5]),import.meta.url).then(async e=>{const i=e.default,{default:r}=await B(async()=>{const{default:a}=await import("./mermaid-layout-elk.core-Cz784PwA.js").then(s=>s.m);return{default:a}},__vite__mapDeps([6,1,2,3,4]),import.meta.url);return i.registerLayoutLoaders(r),i.initialize({startOnLoad:!1,theme:"base",securityLevel:"strict",themeVariables:te(),flowchart:{useMaxWidth:!0,htmlLabels:!0,curve:"basis",nodeSpacing:42,rankSpacing:54,padding:10},sequence:{useMaxWidth:!0,boxMargin:8,noteMargin:8,messageMargin:32}}),i})),p}function te(){const e=(r,a)=>{if(typeof document>"u")return a;const s=getComputedStyle(document.documentElement).getPropertyValue(r).trim();return s?`rgb(${s})`:a};return{background:"transparent",fontFamily:typeof document<"u"&&getComputedStyle(document.body).fontFamily||"ui-sans-serif, system-ui, sans-serif",fontSize:"14px",primaryColor:e("--surface-3-rgb","rgb(42 43 46)"),primaryBorderColor:e("--border-rgb","rgb(37 38 41)"),primaryTextColor:e("--ink-strong-rgb","rgb(250 250 250)"),secondaryColor:e("--surface-2-rgb","rgb(32 33 36)"),secondaryBorderColor:e("--border-faint-rgb","rgb(26 26 29)"),secondaryTextColor:e("--ink-rgb","rgb(245 245 250)"),tertiaryColor:e("--surface-1-rgb","rgb(24 25 27)"),tertiaryBorderColor:e("--border-faint-rgb","rgb(26 26 29)"),tertiaryTextColor:e("--ink-rgb","rgb(245 245 250)"),lineColor:e("--ink-faint-rgb","rgb(117 117 126)"),textColor:e("--ink-rgb","rgb(245 245 250)"),edgeLabelBackground:e("--surface-0-rgb","rgb(12 13 15)"),clusterBkg:e("--surface-1-rgb","rgb(24 25 27)"),clusterBorder:e("--border-faint-rgb","rgb(26 26 29)"),nodeBorder:e("--border-rgb","rgb(37 38 41)"),mainBkg:e("--surface-3-rgb","rgb(42 43 46)"),nodeTextColor:e("--ink-rgb","rgb(245 245 250)"),arrowheadColor:e("--ink-faint-rgb","rgb(117 117 126)"),actorBkg:e("--surface-3-rgb","rgb(42 43 46)"),actorBorder:e("--border-rgb","rgb(37 38 41)"),actorTextColor:e("--ink-strong-rgb","rgb(250 250 250)"),activationBkgColor:e("--surface-3-rgb","rgb(42 43 46)"),activationBorderColor:e("--border-rgb","rgb(37 38 41)"),signalColor:e("--ink-rgb","rgb(245 245 250)"),signalTextColor:e("--ink-rgb","rgb(245 245 250)"),labelBoxBkgColor:e("--surface-2-rgb","rgb(32 33 36)"),labelBoxBorderColor:e("--border-rgb","rgb(37 38 41)"),labelTextColor:e("--ink-rgb","rgb(245 245 250)"),loopTextColor:e("--ink-strong-rgb","rgb(250 250 250)"),noteBkgColor:"rgb(255 200 0 / 0.12)",noteBorderColor:"rgb(255 200 0 / 0.4)",noteTextColor:e("--ink-rgb","rgb(245 245 250)")}}typeof window<"u"&&window.addEventListener("theme-changed",()=>{p=null});async function re(e,i){const r=await ee(),a=Q(i);try{await r.parse(a)}catch(c){throw new Error(`mermaid 语法校验失败: ${c instanceof Error?c.message:String(c)}`)}const{svg:s}=await r.render(e,a);if(s.includes('aria-roledescription="error"')||s.includes('class="error-text"')||s.includes("Syntax error"))throw new Error("mermaid 渲染失败(语法错误或节点 label 含未转义特殊字符)");return s}function ae({title:e,onClose:i,children:r}){const a=O(),s=o.useRef(null);return H(s,!0),o.useEffect(()=>{const c=d=>{d.key==="Escape"&&i()};return window.addEventListener("keydown",c),()=>window.removeEventListener("keydown",c)},[i]),U.createPortal(t.jsxs("div",{className:"fixed inset-0 z-50 flex flex-col bg-black/80","data-testid":"diagram-viewer-modal","data-noswipe":"",role:"dialog","aria-modal":"true","aria-label":e,children:[t.jsxs("div",{className:"flex items-center justify-between gap-3 px-4 py-2.5 shrink-0",onClick:c=>c.stopPropagation(),children:[t.jsx("h3",{className:"text-body font-bold text-white truncate",children:e}),t.jsxs("div",{className:"flex items-center gap-3 shrink-0",children:[t.jsx("span",{className:"text-caption text-white/50 hidden sm:inline",children:a("artifact.viewer.hint")}),t.jsx("button",{onClick:i,"data-testid":"diagram-viewer-close","aria-label":a("action.close"),"data-tooltip":a("action.close"),className:"text-white/70 hover:text-white w-9 h-9 flex items-center justify-center rounded-lg hover:bg-white/10 transition-colors",children:t.jsx(X,{className:"w-5 h-5"})})]})]}),t.jsx("div",{className:"flex-1 min-h-0 px-2 pb-2",onClick:i,children:t.jsx("div",{ref:s,className:"h-full w-full",onClick:c=>c.stopPropagation(),children:r})})]}),document.body)}function z(e){let i=5381;for(let r=0;r<e.length;r++)i=(i<<5)+i+e.charCodeAt(r)>>>0;return i.toString(36)}const v=.3,k=3,x=.2;function I({data:e,variant:i="card"}){const r=e,a=O(),s={flowchart:a("artifact.diagram.flowchart"),sequence:a("artifact.diagram.sequence"),state:a("artifact.diagram.state")},c=o.useId().replace(/[:]/g,"_"),[d,w]=o.useState({status:"loading"}),[u,A]=o.useState(()=>{try{return sessionStorage.getItem(`mmdfix:${r.mermaid.length}:${z(r.mermaid)}`)??r.mermaid}catch{return r.mermaid}}),[j,P]=o.useState(!1),[C,N]=o.useState(!1),[R,$]=o.useState(0);o.useEffect(()=>{const n=()=>$(l=>l+1);return window.addEventListener("theme-changed",n),()=>window.removeEventListener("theme-changed",n)},[]);const[m,M]=o.useState(null),[g,b]=o.useState(1),[F,y]=o.useState(!1);o.useEffect(()=>{let n=!1;return w({status:"loading"}),M(null),re(`mmd-${c}`,u).then(l=>{if(!n&&(w({status:"rendered",svg:l}),u!==r.mermaid))try{sessionStorage.setItem(`mmdfix:${r.mermaid.length}:${z(r.mermaid)}`,u)}catch{}}).catch(l=>{n||(console.error("[MermaidArtifact] render failed:",l),w({status:"error",message:l instanceof Error?l.message:String(l)}))}),()=>{n=!0}},[u,c,R,r.mermaid]),o.useEffect(()=>{var n;d.status!=="error"||j||(P(!0),u===r.mermaid&&(n=window.api)!=null&&n.repairMermaidDiagram&&(N(!0),window.api.repairMermaidDiagram({mermaid:u,errorMessage:d.message,diagramType:r.diagramType}).then(l=>{l.ok&&l.mermaid.trim()&&A(l.mermaid)}).catch(()=>{}).finally(()=>N(!1))))},[d,j,u,r.mermaid,r.diagramType]);const D=`https://mermaid.live/edit#${encodeURIComponent(u)}`,V=o.useCallback(()=>b(n=>Math.min(k,+(n+x).toFixed(2))),[]),W=o.useCallback(()=>b(n=>Math.max(v,+(n-x).toFixed(2))),[]),q=o.useCallback(()=>b(1),[]),Z=o.useCallback(n=>{if(!n.ctrlKey&&!n.metaKey)return;n.preventDefault();const l=n.deltaY>0?-x:x;b(h=>Math.min(k,Math.max(v,+(h+l).toFixed(2))))},[]),E=d.status==="rendered"?t.jsx("div",{ref:n=>{var l;if(n&&!m){const h=n.querySelector("svg");if(h){const S=h.getBoundingClientRect(),f=(l=h.viewBox)==null?void 0:l.baseVal,T=f&&f.width?f.width:S.width,_=f&&f.height?f.height:S.height;T>0&&_>0&&M({width:T,height:_})}}},style:{width:(m==null?void 0:m.width)??void 0,height:(m==null?void 0:m.height)??void 0},dangerouslySetInnerHTML:{__html:d.svg},"data-testid":"mermaid-svg"}):null;return i==="canvas"?t.jsx("div",{"data-testid":"mermaid-canvas-content",children:E}):t.jsxs("div",{className:"surface-card p-4","data-testid":"artifact-mermaid",children:[t.jsxs("div",{className:"flex items-center justify-between mb-3 gap-2",children:[t.jsxs("div",{className:"flex items-center gap-2 flex-1 min-w-0",children:[t.jsx(J,{className:"w-4 h-4 text-ink-muted shrink-0"}),t.jsx("h3",{className:"text-body font-bold text-ink truncate",children:r.title}),t.jsx("span",{className:"text-caption font-bold px-1.5 py-0.5 rounded bg-accent/15 text-accent shrink-0",children:s[r.diagramType]??r.diagramType})]}),t.jsxs("div",{className:"flex items-center gap-1.5 shrink-0",children:[d.status==="rendered"&&t.jsxs("div",{className:"flex items-center gap-1","data-testid":"mermaid-zoom-controls",children:[t.jsx("button",{onClick:W,disabled:g<=v,className:"w-6 h-6 rounded border border-[var(--border)] text-ink-muted hover:bg-surface-1 hover:bg-surface-3 disabled:opacity-30 text-label font-bold flex items-center justify-center",title:a("artifact.zoomOut"),"data-testid":"mermaid-zoom-out",children:"−"}),t.jsxs("button",{onClick:q,className:"px-1.5 h-6 rounded border border-[var(--border)] text-ink-muted hover:bg-surface-1 hover:bg-surface-3 text-caption font-bold tabular-nums",title:a("artifact.zoomReset"),"data-testid":"mermaid-zoom-reset",children:[Math.round(g*100),"%"]}),t.jsx("button",{onClick:V,disabled:g>=k,className:"w-6 h-6 rounded border border-[var(--border)] text-ink-muted hover:bg-surface-1 hover:bg-surface-3 disabled:opacity-30 text-label font-bold flex items-center justify-center",title:a("artifact.zoomIn"),"data-testid":"mermaid-zoom-in",children:"+"})]}),d.status==="rendered"&&t.jsx("button",{onClick:()=>y(!0),"data-testid":"mermaid-expand","aria-label":a("artifact.viewer.open"),"data-tooltip":a("artifact.viewer.open"),className:"w-6 h-6 rounded border border-[var(--border)] text-ink-muted hover:bg-surface-3 flex items-center justify-center",children:t.jsx(Y,{className:"w-3.5 h-3.5"})})]}),t.jsx("button",{onClick:()=>window.open(D,"_blank"),className:"text-caption text-accent hover:underline font-bold shrink-0","data-testid":"mermaid-open-live",title:a("artifact.mermaid.openLive"),children:"mermaid.live ↗"})]}),t.jsxs("div",{onClick:()=>{d.status==="rendered"&&y(!0)},onWheel:Z,className:"bg-surface-0/40 rounded-lg p-3 overflow-auto min-h-[120px] max-h-[500px] select-none",style:{touchAction:"pan-x pan-y"},"data-testid":"mermaid-render-area","data-noswipe":"",children:[d.status==="loading"&&t.jsxs("div",{className:"flex items-center gap-2 text-body text-ink-muted my-8 justify-center","data-testid":"mermaid-loading",children:[t.jsx("span",{className:"typing-dot w-1.5 h-1.5 bg-accent rounded-full inline-block"}),t.jsx("span",{children:a("artifact.mermaid.rendering")})]}),d.status==="rendered"&&t.jsx("div",{style:{width:m?m.width*g:"auto",height:m?m.height*g:"auto",margin:"0 auto"},children:t.jsx("div",{style:{transform:`scale(${g})`,transformOrigin:"top left"},children:E})}),d.status==="error"&&C&&t.jsxs("div",{className:"flex items-center gap-2 text-body text-ink-muted my-8 justify-center","data-testid":"mermaid-repairing",children:[t.jsx("span",{className:"typing-dot w-1.5 h-1.5 bg-accent rounded-full inline-block"}),t.jsx("span",{children:a("artifact.mermaid.repairing")})]}),d.status==="error"&&!C&&t.jsxs("div",{className:"w-full text-center my-4","data-testid":"mermaid-fallback",children:[t.jsxs("div",{className:"text-body text-warning mb-2 flex items-center justify-center gap-1.5",children:[t.jsx(L,{className:"w-4 h-4 shrink-0"}),t.jsx("span",{children:a("artifact.mermaid.renderFailed")})]}),t.jsx("pre",{className:"text-label bg-surface-1/60 rounded p-2 overflow-x-auto text-ink-muted font-mono text-left",children:u}),t.jsx("div",{className:"text-caption text-ink-muted mt-2",children:a("artifact.mermaid.errorPrefix",{msg:d.message})})]})]}),d.status==="rendered"&&t.jsx("div",{className:"mt-1.5 text-caption text-ink-muted flex items-center gap-2",children:t.jsx("span",{children:a("artifact.mermaid.hint")})}),F&&d.status==="rendered"&&t.jsx(ae,{title:r.title,onClose:()=>y(!1),children:t.jsx("div",{className:"h-full w-full rounded-xl overflow-hidden bg-surface-0/60",children:t.jsx(G,{testid:"mermaid-modal-stage",children:t.jsx(I,{data:e,variant:"canvas"})})})}),r.warnings&&r.warnings.length>0&&t.jsxs("div",{className:"mt-2 text-caption text-warning flex items-start gap-1","data-testid":"artifact-warnings",children:[t.jsx(L,{className:"w-3.5 h-3.5 shrink-0 mt-0.5"}),t.jsx("span",{children:r.warnings.join("; ")})]})]})}const oe=Object.freeze(Object.defineProperty({__proto__:null,MermaidArtifact:I},Symbol.toStringTag,{value:"Module"}));export{ae as D,I as M,oe as a};
@@ -1,4 +1,4 @@
1
- import{r,j as e}from"./index-jKxnKPxh.js";import{c as ee,u as R,X as G,r as V,a as u,W as z,C as B,b as H,n as J,d as te,e as se,t as ae,v as ne}from"./main-BG2k-Vog.js";import{T as X,C as Y}from"./Toggle-CEibZGBQ.js";/**
1
+ import{r,j as e}from"./index-88125dOi.js";import{c as ee,u as R,X as G,r as V,a as u,W as z,C as B,b as H,n as J,d as te,e as se,t as ae,v as ne}from"./main-_pTgysch.js";import{T as X,C as Y}from"./Toggle-vfz_fm_Z.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 n,j as e}from"./index-jKxnKPxh.js";import{c as L,u as I,i as T,d as G,j as F,a as c,k as H,X as q,l as K,P as O,L as V,A as X,C as J,m as Q,n as U,o as W,s as Y,p as Z}from"./main-BG2k-Vog.js";/**
1
+ import{r as n,j as e}from"./index-88125dOi.js";import{c as L,u as I,i as T,d as G,j as F,a as c,k as H,X as q,l as K,P as O,L as V,A as X,C as J,m as Q,n as U,o as W,s as Y,p as Z}from"./main-_pTgysch.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-jKxnKPxh.js";import{u as j,a as N,S as M}from"./main-BG2k-Vog.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-88125dOi.js";import{u as j,a as N,S as M}from"./main-_pTgysch.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};