@piwitests/server 0.26.0 → 0.26.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 (382) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/{BdQ7kfxJ.js → 1QWBzxLM.js} +4 -4
  3. package/.output/public/_nuxt/{CY1UsEbI.js → 4hW9LHwA.js} +1 -1
  4. package/.output/public/_nuxt/96uxfdYT.js +1 -0
  5. package/.output/public/_nuxt/{HGYIpJtg.js → AbnDY6Zr.js} +1 -1
  6. package/.output/public/_nuxt/{CZ6WR7uw.js → B-1zt4pp.js} +1 -1
  7. package/.output/public/_nuxt/{Sx5-c-bZ.js → B1iYmAt_.js} +1 -1
  8. package/.output/public/_nuxt/{CbzgEkmW.js → B2bxEmbR.js} +1 -1
  9. package/.output/public/_nuxt/B3hAvaCe.js +4 -0
  10. package/.output/public/_nuxt/{CyWOerIG.js → B4lvHjBe.js} +1 -1
  11. package/.output/public/_nuxt/B5S7BkC3.js +1 -0
  12. package/.output/public/_nuxt/{Bb_1uAHn.js → B6j5Ornu.js} +1 -1
  13. package/.output/public/_nuxt/{CrsaY0R_.js → B82vqOZe.js} +1 -1
  14. package/.output/public/_nuxt/{CTFUlsXp.js → B9oXlGro.js} +1 -1
  15. package/.output/public/_nuxt/{CsJ9Ce4U.js → BABCH5kE.js} +1 -1
  16. package/.output/public/_nuxt/{Gn1Ns00e.js → BF5qB58w.js} +1 -1
  17. package/.output/public/_nuxt/{CsGsLxHg.js → BFLa9ZEP.js} +1 -1
  18. package/.output/public/_nuxt/BIlohx1E.js +1 -0
  19. package/.output/public/_nuxt/{B6djubIK.js → BM5C-Oec.js} +1 -1
  20. package/.output/public/_nuxt/{CrZhoZuI.js → BOA-I6S9.js} +1 -1
  21. package/.output/public/_nuxt/{Bp2zrrkV.js → BQUhoGCh.js} +1 -1
  22. package/.output/public/_nuxt/{DUC3QnqW.js → BQYLGX9o.js} +1 -1
  23. package/.output/public/_nuxt/{CUjzhXN1.js → BRMeEHXd.js} +1 -1
  24. package/.output/public/_nuxt/{Cf_a8ynB.js → BRtaKOKv.js} +2 -2
  25. package/.output/public/_nuxt/{B7uPoZ7T.js → BS91Og__.js} +1 -1
  26. package/.output/public/_nuxt/{DKgbchez.js → BTGAvMoT.js} +1 -1
  27. package/.output/public/_nuxt/{BIamiwb7.js → BaLX92Wz.js} +1 -1
  28. package/.output/public/_nuxt/{LWIyaZKe.js → Bc6Zr-Xn.js} +1 -1
  29. package/.output/public/_nuxt/{R7AVOWi_.js → BceMEnJt.js} +1 -1
  30. package/.output/public/_nuxt/{Q2oJNyXL.js → BeCAVtCK.js} +1 -1
  31. package/.output/public/_nuxt/{D_SD71Qf.js → Bf119e7x.js} +1 -1
  32. package/.output/public/_nuxt/BfRcdz11.js +9 -0
  33. package/.output/public/_nuxt/{CxwnFFD0.js → Bl0xzETD.js} +1 -1
  34. package/.output/public/_nuxt/{C_eXufkv.js → BnUQ3i5l.js} +1 -1
  35. package/.output/public/_nuxt/{rPG7kzfL.js → Bp1WeQ0_.js} +1 -1
  36. package/.output/public/_nuxt/{BL8cYWsR.js → Bp31ZRcA.js} +1 -1
  37. package/.output/public/_nuxt/{Drh1_ASq.js → BrxUH8qL.js} +1 -1
  38. package/.output/public/_nuxt/{D72Ce8Ff.js → BsdfEbVC.js} +1 -1
  39. package/.output/public/_nuxt/BtGI4ZbP.js +1 -0
  40. package/.output/public/_nuxt/{BV8EzO8q.js → BuMX-4RF.js} +1 -1
  41. package/.output/public/_nuxt/{DPPhFZOr.js → BuXJR5tn.js} +1 -1
  42. package/.output/public/_nuxt/{Bh2WA4IJ.js → Bx_lfKHl.js} +1 -1
  43. package/.output/public/_nuxt/{vcSKeWsW.js → C4UKyPQn.js} +1 -1
  44. package/.output/public/_nuxt/{IoE3eJ9F.js → C9XCTbtQ.js} +1 -1
  45. package/.output/public/_nuxt/{BilJoEne.js → CEPU6VkU.js} +1 -1
  46. package/.output/public/_nuxt/CHz7LJIX.js +1 -0
  47. package/.output/public/_nuxt/{BPhGDGAR.js → CMhd8IBr.js} +1 -1
  48. package/.output/public/_nuxt/{C5X_N4R7.js → CN1M6i4K.js} +33 -33
  49. package/.output/public/_nuxt/CQLkowA3.js +1 -0
  50. package/.output/public/_nuxt/{DTtizz85.js → CU_2YLhT.js} +1 -1
  51. package/.output/public/_nuxt/{CMVTTE_g.js → CXkXHtcx.js} +1 -1
  52. package/.output/public/_nuxt/{igDJCTgt.js → CZeKW-zP.js} +1 -1
  53. package/.output/public/_nuxt/{9oKY4Zb7.js → CapSEET7.js} +1 -1
  54. package/.output/public/_nuxt/{j2eGYaRa.js → CeExxGSu.js} +1 -1
  55. package/.output/public/_nuxt/{CEgRB8H9.js → CfwpqSe7.js} +1 -1
  56. package/.output/public/_nuxt/{CFKbXp6V.js → ChOtLYkd.js} +1 -1
  57. package/.output/public/_nuxt/ChuJzPWz.js +1 -0
  58. package/.output/public/_nuxt/{Bo73sAu8.js → CiCUZGFZ.js} +1 -1
  59. package/.output/public/_nuxt/{C6R4tyud.js → CkL_oDa8.js} +1 -1
  60. package/.output/public/_nuxt/{DtGJeysS.js → CkhOMiiO.js} +1 -1
  61. package/.output/public/_nuxt/ClmHMP65.js +2 -0
  62. package/.output/public/_nuxt/{BtcDY0Du.js → Cnm0d_7S.js} +1 -1
  63. package/.output/public/_nuxt/{CK2AMqz_.js → CtQMagSz.js} +1 -1
  64. package/.output/public/_nuxt/{B1KjIR-q.js → Ctnn3S3-.js} +1 -1
  65. package/.output/public/_nuxt/{DCeZxpxe.js → CywiLuOD.js} +4 -4
  66. package/.output/public/_nuxt/{oA84LLqO.js → CzRkZLB4.js} +1 -1
  67. package/.output/public/_nuxt/CzyCEdYP.js +1 -0
  68. package/.output/public/_nuxt/{D56yp7m9.js → D-F0Rhjj.js} +1 -1
  69. package/.output/public/_nuxt/D4mPjHHR.js +2 -0
  70. package/.output/public/_nuxt/{BsGvSoPC.js → D4v7lLm3.js} +1 -1
  71. package/.output/public/_nuxt/{CxRTKV-K.js → D6B0WKO0.js} +1 -1
  72. package/.output/public/_nuxt/{jv8U_Tup.js → DAg6jtav.js} +1 -1
  73. package/.output/public/_nuxt/DBXXb0w8.js +1 -0
  74. package/.output/public/_nuxt/{ChlP20A5.js → DHN2t5Vt.js} +1 -1
  75. package/.output/public/_nuxt/{B8tezsWe.js → DJKHXfNS.js} +1 -1
  76. package/.output/public/_nuxt/{CFg5qdS0.js → DMqAUHFN.js} +1 -1
  77. package/.output/public/_nuxt/{C9A3sPDo.js → DURme_kn.js} +1 -1
  78. package/.output/public/_nuxt/{C2hIM5f9.js → DVo_e_uj.js} +1 -1
  79. package/.output/public/_nuxt/{DKhqIou2.js → DXh8q5KY.js} +1 -1
  80. package/.output/public/_nuxt/{CZXeJs2k.js → DXz1Kb4-.js} +1 -1
  81. package/.output/public/_nuxt/{CPrVhXJk.js → DYdwHaco.js} +1 -1
  82. package/.output/public/_nuxt/{WZXZeGYt.js → D_ZAGxCQ.js} +1 -1
  83. package/.output/public/_nuxt/{D5SN7rPK.js → D_dhjJvR.js} +1 -1
  84. package/.output/public/_nuxt/{DR1jFptD.js → DamZHy5M.js} +1 -1
  85. package/.output/public/_nuxt/{xKX9IHe3.js → DbtjJCra.js} +1 -1
  86. package/.output/public/_nuxt/{r6zkA1SE.js → DcOlL-oi.js} +1 -1
  87. package/.output/public/_nuxt/{CxspCKpR.js → DeQ9sIia.js} +1 -1
  88. package/.output/public/_nuxt/{BkHJoHpc.js → DjX1bLZD.js} +1 -1
  89. package/.output/public/_nuxt/{Be0bwdsi.js → Dly7wCCl.js} +1 -1
  90. package/.output/public/_nuxt/DmeogbGY.js +1 -0
  91. package/.output/public/_nuxt/{CfV2N201.js → Dn_-RkxP.js} +1 -1
  92. package/.output/public/_nuxt/{dg6uXTyR.js → DoDo3VF2.js} +1 -1
  93. package/.output/public/_nuxt/{BMlKQMjM.js → DoVHTl-K.js} +1 -1
  94. package/.output/public/_nuxt/DpM8IgHL.js +1 -0
  95. package/.output/public/_nuxt/{B4NjylBn.js → Dpwj_1H5.js} +1 -1
  96. package/.output/public/_nuxt/{DzJa19LG.js → DvSHenmZ.js} +1 -1
  97. package/.output/public/_nuxt/DvYU87_a.js +1 -0
  98. package/.output/public/_nuxt/{G2J1dVVb.js → Dx41arC8.js} +1 -1
  99. package/.output/public/_nuxt/DxBrlj7b.js +1 -0
  100. package/.output/public/_nuxt/{r-HZNbp3.js → JNpNdV-o.js} +1 -1
  101. package/.output/public/_nuxt/Lz9MmwKY.js +1 -0
  102. package/.output/public/_nuxt/OMI0cmZ0.js +1 -0
  103. package/.output/public/_nuxt/{CUWrUpTl.js → UAmyrRCI.js} +1 -1
  104. package/.output/public/_nuxt/{EJllK0wm.js → VBTxfbqU.js} +1 -1
  105. package/.output/public/_nuxt/VbedPPFH.js +1 -0
  106. package/.output/public/_nuxt/{BY9A1aOT.js → _okd7MfH.js} +1 -1
  107. package/.output/public/_nuxt/{BOn5q0rT.js → bmAf49LT.js} +1 -1
  108. package/.output/public/_nuxt/builds/latest.json +1 -1
  109. package/.output/public/_nuxt/builds/meta/0174ebd8-8fa5-4698-aa79-7a8dd2f6527f.json +1 -0
  110. package/.output/public/_nuxt/{D0XWJGhG.js → e-GZmCeP.js} +1 -1
  111. package/.output/public/_nuxt/entry.Dv52uAyn.css +1 -0
  112. package/.output/public/_nuxt/{DVIIj6Vv.js → f9TbT3AM.js} +1 -1
  113. package/.output/public/_nuxt/gdlHFfN6.js +1 -0
  114. package/.output/public/_nuxt/{BTG_PmM5.js → huBoAZeM.js} +1 -1
  115. package/.output/public/_nuxt/{DadksxQ9.js → mYw4b7uY.js} +1 -1
  116. package/.output/public/_nuxt/{B0eHOux4.js → mi7tdFxN.js} +1 -1
  117. package/.output/public/_nuxt/sFe4Zr5j.js +1 -0
  118. package/.output/public/_nuxt/{CLrLFf3s.js → uspGXbik.js} +1 -1
  119. package/.output/public/_nuxt/{DLN-CQXF.js → w7KxwWEv.js} +1 -1
  120. package/.output/public/_nuxt/{Bp55g9gr.js → wa4k1aDz.js} +1 -1
  121. package/.output/public/_nuxt/{C2yZcDch.js → xuB8n0QL.js} +1 -1
  122. package/.output/public/favicon.ico +0 -0
  123. package/.output/public/trace-viewer/assets/codeMirrorModule-LEHpjmcn.js +32 -0
  124. package/.output/public/trace-viewer/assets/defaultSettingsView-BNmKHKpQ.js +264 -0
  125. package/.output/public/trace-viewer/assets/urlMatch-BYQrIQwR.js +1 -0
  126. package/.output/public/trace-viewer/assets/xtermModule-CsJ4vdCR.js +9 -0
  127. package/.output/public/trace-viewer/codeMirrorModule.DYBRYzYX.css +1 -0
  128. package/.output/public/trace-viewer/codicon.DCmgc-ay.ttf +0 -0
  129. package/.output/public/trace-viewer/defaultSettingsView.CjdS-WJx.css +1 -0
  130. package/.output/public/trace-viewer/index.CzXZzn5A.css +1 -0
  131. package/.output/public/trace-viewer/index.DMMX1gXU.js +2 -0
  132. package/.output/public/trace-viewer/index.html +44 -0
  133. package/.output/public/trace-viewer/manifest.webmanifest +16 -0
  134. package/.output/public/trace-viewer/playwright-logo.svg +9 -0
  135. package/.output/public/trace-viewer/snapshot.html +10 -0
  136. package/.output/public/trace-viewer/snapshot.v8KI4P3m.js +2 -0
  137. package/.output/public/trace-viewer/sw.bundle.js +5 -0
  138. package/.output/public/trace-viewer/uiMode.BZQ54Kgt.css +1 -0
  139. package/.output/public/trace-viewer/uiMode.Ut8wwJNp.js +6 -0
  140. package/.output/public/trace-viewer/uiMode.html +18 -0
  141. package/.output/public/trace-viewer/xtermModule.DYP7pi_n.css +32 -0
  142. package/.output/server/chunks/_/users.mjs +1 -1
  143. package/.output/server/chunks/build/{BreadcrumbNav-DBnGj5Jq.mjs → BreadcrumbNav-Bg4QGX0k.mjs} +11 -4
  144. package/.output/server/chunks/build/BreadcrumbNav-Bg4QGX0k.mjs.map +1 -0
  145. package/.output/server/chunks/build/{BrowserBadge-vFb1ERG_.mjs → BrowserBadge-yMgLTBUu.mjs} +17 -9
  146. package/.output/server/chunks/build/BrowserBadge-yMgLTBUu.mjs.map +1 -0
  147. package/.output/server/chunks/build/{ChartMarkerLines-BXqUpUcs.mjs → ChartMarkerLines-D0cTRlxF.mjs} +3 -3
  148. package/.output/server/chunks/build/ChartMarkerLines-D0cTRlxF.mjs.map +1 -0
  149. package/.output/server/chunks/build/{ChartTooltip-DoF6Smyc.mjs → ChartTooltip-B2t6VYYH.mjs} +3 -3
  150. package/.output/server/chunks/build/ChartTooltip-B2t6VYYH.mjs.map +1 -0
  151. package/.output/server/chunks/build/Checkbox-ChSYhiUz.mjs +1 -1
  152. package/.output/server/chunks/build/ClientDate-U97Z1p6-.mjs +32 -0
  153. package/.output/server/chunks/build/ClientDate-U97Z1p6-.mjs.map +1 -0
  154. package/.output/server/chunks/build/{CodeBlock-CmvKHaq8.mjs → CodeBlock-DuWhmcI2.mjs} +3 -3
  155. package/.output/server/chunks/build/CodeBlock-DuWhmcI2.mjs.map +1 -0
  156. package/.output/server/chunks/build/DashboardSidebarToggle-a5KYecZ0.mjs +1 -1
  157. package/.output/server/chunks/build/DashboardToolbar-BZoGc0ri.mjs +72 -0
  158. package/.output/server/chunks/build/DashboardToolbar-BZoGc0ri.mjs.map +1 -0
  159. package/.output/server/chunks/build/{DataLocationCard-ChV02QJj.mjs → DataLocationCard-DCdhQBIY.mjs} +2 -2
  160. package/.output/server/chunks/build/DataLocationCard-DCdhQBIY.mjs.map +1 -0
  161. package/.output/server/chunks/build/{DesktopRunLocallyButton-BfmbZpiL.mjs → DesktopRunLocallyButton-ChHg3GqK.mjs} +5 -5
  162. package/.output/server/chunks/build/{DesktopRunLocallyButton-BfmbZpiL.mjs.map → DesktopRunLocallyButton-ChHg3GqK.mjs.map} +1 -1
  163. package/.output/server/chunks/build/{DiagnosisPanel-C_ndadzP.mjs → DiagnosisPanel-DE-r2UV8.mjs} +5 -5
  164. package/.output/server/chunks/build/DiagnosisPanel-DE-r2UV8.mjs.map +1 -0
  165. package/.output/server/chunks/build/{DiagnosisResult-GAjo6Lt3.mjs → DiagnosisResult-CrGK--xh.mjs} +16 -10
  166. package/.output/server/chunks/build/DiagnosisResult-CrGK--xh.mjs.map +1 -0
  167. package/.output/server/chunks/build/{DurationValue-CObiBDnH.mjs → DurationValue-Dn06XQk3.mjs} +2 -2
  168. package/.output/server/chunks/build/DurationValue-Dn06XQk3.mjs.map +1 -0
  169. package/.output/server/chunks/build/EntityLinks-BcpvMt_V.mjs +1 -1
  170. package/.output/server/chunks/build/EnvManagedBadge-_8GfjWjE.mjs +1 -1
  171. package/.output/server/chunks/build/{FeatureUnavailable-Buoyoqx1.mjs → FeatureUnavailable-IaBjVCqQ.mjs} +2 -2
  172. package/.output/server/chunks/build/FeatureUnavailable-IaBjVCqQ.mjs.map +1 -0
  173. package/.output/server/chunks/build/{GetStartedWizard-tL3U_qM1.mjs → GetStartedWizard-BiyxEXWP.mjs} +3 -3
  174. package/.output/server/chunks/build/GetStartedWizard-BiyxEXWP.mjs.map +1 -0
  175. package/.output/server/chunks/build/{HelpHint-C96TlqxY.mjs → HelpHint-CdBz6deq.mjs} +2 -2
  176. package/.output/server/chunks/build/HelpHint-CdBz6deq.mjs.map +1 -0
  177. package/.output/server/chunks/build/{MetaStripGroup-Cp2WCQf7.mjs → MetaStripGroup-CDyGlsNt.mjs} +94 -21
  178. package/.output/server/chunks/build/MetaStripGroup-CDyGlsNt.mjs.map +1 -0
  179. package/.output/server/chunks/build/{NavbarActions-VCHW0u67.mjs → NavbarActions-BTWxKCVI.mjs} +2 -2
  180. package/.output/server/chunks/build/NavbarActions-BTWxKCVI.mjs.map +1 -0
  181. package/.output/server/chunks/build/NavigationMenu-D4ZpdCm_.mjs +1 -1
  182. package/.output/server/chunks/build/OpenInIdeLink-Bnl-_som.mjs +1 -1
  183. package/.output/server/chunks/build/{ProjectTestCasesTable-saHYJoyQ.mjs → ProjectTestCasesTable-DJDAZ9NQ.mjs} +9 -9
  184. package/.output/server/chunks/build/ProjectTestCasesTable-DJDAZ9NQ.mjs.map +1 -0
  185. package/.output/server/chunks/build/{RunReports-CKYYRC59.mjs → RunReports-BSo2cCNx.mjs} +4 -4
  186. package/.output/server/chunks/build/RunReports-BSo2cCNx.mjs.map +1 -0
  187. package/.output/server/chunks/build/{RunStatusBadge-CWhmAmKb.mjs → RunStatusBadge-zfeSwcTx.mjs} +2 -2
  188. package/.output/server/chunks/build/RunStatusBadge-zfeSwcTx.mjs.map +1 -0
  189. package/.output/server/chunks/build/{SectionCard-BB1O3uXd.mjs → SectionCard-CKD1s0eF.mjs} +2 -2
  190. package/.output/server/chunks/build/SectionCard-CKD1s0eF.mjs.map +1 -0
  191. package/.output/server/chunks/build/Select-COU8NARj.mjs +1 -1
  192. package/.output/server/chunks/build/SelectMenu-BUwwc3Qt.mjs +1 -1
  193. package/.output/server/chunks/build/{SettingsField-CEasBHu3.mjs → SettingsField-CDnUtiCM.mjs} +3 -3
  194. package/.output/server/chunks/build/SettingsField-CDnUtiCM.mjs.map +1 -0
  195. package/.output/server/chunks/build/Table-BET-DOtX.mjs +1 -1
  196. package/.output/server/chunks/build/{TestCaseHistoryChart-BgI6P_zS.mjs → TestCaseHistoryChart-Do7WK-ZY.mjs} +16 -17
  197. package/.output/server/chunks/build/TestCaseHistoryChart-Do7WK-ZY.mjs.map +1 -0
  198. package/.output/server/chunks/build/{TestStatusBar-DR8jM5th.mjs → TestStatusBar-BipoEOzd.mjs} +15 -6
  199. package/.output/server/chunks/build/TestStatusBar-BipoEOzd.mjs.map +1 -0
  200. package/.output/server/chunks/build/Tooltip-CK0ucuXC.mjs +1 -1
  201. package/.output/server/chunks/build/{_id_-rQhFY0fN.mjs → _id_-BLPB189b.mjs} +16 -16
  202. package/.output/server/chunks/build/{_id_-rQhFY0fN.mjs.map → _id_-BLPB189b.mjs.map} +1 -1
  203. package/.output/server/chunks/build/{_id_-kkexEH_q.mjs → _id_-BeGJOSxY.mjs} +16 -16
  204. package/.output/server/chunks/build/_id_-BeGJOSxY.mjs.map +1 -0
  205. package/.output/server/chunks/build/{_id_-B7Dw490u.mjs → _id_-CfLEW45H.mjs} +472 -304
  206. package/.output/server/chunks/build/_id_-CfLEW45H.mjs.map +1 -0
  207. package/.output/server/chunks/build/{_id_-DVPb1S93.mjs → _id_-DxHe32cW.mjs} +654 -453
  208. package/.output/server/chunks/build/_id_-DxHe32cW.mjs.map +1 -0
  209. package/.output/server/chunks/build/{about-C4AbyQ4q.mjs → about-FLAssVsA.mjs} +5 -5
  210. package/.output/server/chunks/build/about-FLAssVsA.mjs.map +1 -0
  211. package/.output/server/chunks/build/{account-B45bYZd1.mjs → account-Cvz6KkYu.mjs} +4 -4
  212. package/.output/server/chunks/build/account-Cvz6KkYu.mjs.map +1 -0
  213. package/.output/server/chunks/build/{ai-CgN9xXFf.mjs → ai-DR9Zry7B.mjs} +8 -8
  214. package/.output/server/chunks/build/{ai-CgN9xXFf.mjs.map → ai-DR9Zry7B.mjs.map} +1 -1
  215. package/.output/server/chunks/build/{analytics-BRkiUpwa.mjs → analytics-CCAQayhv.mjs} +9 -9
  216. package/.output/server/chunks/build/{analytics-BRkiUpwa.mjs.map → analytics-CCAQayhv.mjs.map} +1 -1
  217. package/.output/server/chunks/build/{auto-heal-BnTdKHQq.mjs → auto-heal-ngiiiVmq.mjs} +4 -4
  218. package/.output/server/chunks/build/auto-heal-ngiiiVmq.mjs.map +1 -0
  219. package/.output/server/chunks/build/client.precomputed.mjs +1 -1
  220. package/.output/server/chunks/build/{default-BGOdM_zA.mjs → default-wYpdMMvh.mjs} +15 -13
  221. package/.output/server/chunks/build/{default-BGOdM_zA.mjs.map → default-wYpdMMvh.mjs.map} +1 -1
  222. package/.output/server/chunks/build/{docs-D7R5eJ1Z.mjs → docs-BX9DoKOI.mjs} +4 -4
  223. package/.output/server/chunks/build/{docs-D7R5eJ1Z.mjs.map → docs-BX9DoKOI.mjs.map} +1 -1
  224. package/.output/server/chunks/build/{edit-BbL3k6c3.mjs → edit-DnyBC4uC.mjs} +7 -7
  225. package/.output/server/chunks/build/{edit-BbL3k6c3.mjs.map → edit-DnyBC4uC.mjs.map} +1 -1
  226. package/.output/server/chunks/build/fetch-DOcN2mHf.mjs +1 -1
  227. package/.output/server/chunks/build/{help-content-BK3jcgLw.mjs → help-content-3QLSe6Vd.mjs} +3 -3
  228. package/.output/server/chunks/build/help-content-3QLSe6Vd.mjs.map +1 -0
  229. package/.output/server/chunks/build/{import-ibAn_HB9.mjs → import-S-w3MXez.mjs} +8 -8
  230. package/.output/server/chunks/build/import-S-w3MXez.mjs.map +1 -0
  231. package/.output/server/chunks/build/{index-D5A0DW7Y.mjs → index-BFr7JW_2.mjs} +4 -4
  232. package/.output/server/chunks/build/index-BFr7JW_2.mjs.map +1 -0
  233. package/.output/server/chunks/build/{index-CqinXTVs.mjs → index-CdzYiYiu.mjs} +9 -9
  234. package/.output/server/chunks/build/{index-CqinXTVs.mjs.map → index-CdzYiYiu.mjs.map} +1 -1
  235. package/.output/server/chunks/build/{index-DreB_S-d.mjs → index-CgYJur1z.mjs} +31 -23
  236. package/.output/server/chunks/build/index-CgYJur1z.mjs.map +1 -0
  237. package/.output/server/chunks/build/{index-2GmuPNF-.mjs → index-CjnZ521K.mjs} +22 -4
  238. package/.output/server/chunks/build/index-CjnZ521K.mjs.map +1 -0
  239. package/.output/server/chunks/build/{index-KsRegEjT.mjs → index-xgA4P1ht.mjs} +3218 -4087
  240. package/.output/server/chunks/build/index-xgA4P1ht.mjs.map +1 -0
  241. package/.output/server/chunks/build/isValueEqualOrExist-D4lZ8uRY.mjs +1 -1
  242. package/.output/server/chunks/build/login-DueFS2RU.mjs +1 -1
  243. package/.output/server/chunks/build/{mcp-Dwj29-uG.mjs → mcp-DlZzubUF.mjs} +7 -7
  244. package/.output/server/chunks/build/mcp-DlZzubUF.mjs.map +1 -0
  245. package/.output/server/chunks/build/{notifications-CjAn5FJj.mjs → notifications-ByPVhyPX.mjs} +6 -6
  246. package/.output/server/chunks/build/notifications-ByPVhyPX.mjs.map +1 -0
  247. package/.output/server/chunks/build/{performance-DRzcu_c7.mjs → performance-Dc9FhaJr.mjs} +6 -6
  248. package/.output/server/chunks/build/performance-Dc9FhaJr.mjs.map +1 -0
  249. package/.output/server/chunks/build/{pr-feedback-DR60oGBf.mjs → pr-feedback-5kC_UmKG.mjs} +4 -4
  250. package/.output/server/chunks/build/pr-feedback-5kC_UmKG.mjs.map +1 -0
  251. package/.output/server/chunks/build/{selections-BjjolRZ9.mjs → selections-C6J9mI0s.mjs} +9 -9
  252. package/.output/server/chunks/build/selections-C6J9mI0s.mjs.map +1 -0
  253. package/.output/server/chunks/build/server.mjs +33 -33
  254. package/.output/server/chunks/build/{settings-B3NWV9tu.mjs → settings-DcCAv0U4.mjs} +17 -81
  255. package/.output/server/chunks/build/settings-DcCAv0U4.mjs.map +1 -0
  256. package/.output/server/chunks/build/{settings-metadata-DwJk8uSt.mjs → settings-metadata-B684YiW4.mjs} +2 -2
  257. package/.output/server/chunks/build/settings-metadata-B684YiW4.mjs.map +1 -0
  258. package/.output/server/chunks/build/{setup-BlgFTixN.mjs → setup-Cf3Mzf-W.mjs} +8 -8
  259. package/.output/server/chunks/build/{setup-BlgFTixN.mjs.map → setup-Cf3Mzf-W.mjs.map} +1 -1
  260. package/.output/server/chunks/build/{storage-C1O-FC0U.mjs → storage-B4VySiv3.mjs} +7 -7
  261. package/.output/server/chunks/build/storage-B4VySiv3.mjs.map +1 -0
  262. package/.output/server/chunks/build/{tags-dsvYrnii.mjs → tags-BvWdsd1F.mjs} +25 -11
  263. package/.output/server/chunks/build/tags-BvWdsd1F.mjs.map +1 -0
  264. package/.output/server/chunks/build/{test-cases-CFiOuyK6.mjs → test-cases-LIIu7dMu.mjs} +11 -11
  265. package/.output/server/chunks/build/test-cases-LIIu7dMu.mjs.map +1 -0
  266. package/.output/server/chunks/build/{test-functions-CbmBi6az.mjs → test-functions-Dv8nezrM.mjs} +8 -8
  267. package/.output/server/chunks/build/test-functions-Dv8nezrM.mjs.map +1 -0
  268. package/.output/server/chunks/build/{useCopyRich-DPKZKHvZ.mjs → useCopyRich-DRRKIts2.mjs} +17 -14
  269. package/.output/server/chunks/build/{useCopyRich-DPKZKHvZ.mjs.map → useCopyRich-DRRKIts2.mjs.map} +1 -1
  270. package/.output/server/chunks/build/{useDesktopDownload-R_RWSgUV.mjs → useDesktopDownload-CK-5nATq.mjs} +2 -2
  271. package/.output/server/chunks/build/useDesktopDownload-CK-5nATq.mjs.map +1 -0
  272. package/.output/server/chunks/build/{useDesktopLocalRuns-BdELBy0Y.mjs → useDesktopLocalRuns-BHZic4MJ.mjs} +3 -3
  273. package/.output/server/chunks/build/useDesktopLocalRuns-BHZic4MJ.mjs.map +1 -0
  274. package/.output/server/chunks/build/{useDesktopProjectLink-IUN7SIP2.mjs → useDesktopProjectLink-CqBvnXwG.mjs} +2 -2
  275. package/.output/server/chunks/build/useDesktopProjectLink-CqBvnXwG.mjs.map +1 -0
  276. package/.output/server/chunks/build/useOpenInIde-DS4YXevu.mjs +1 -1
  277. package/.output/server/chunks/build/{useSettingsNav-Dg87E7kY.mjs → useSettingsNav-dyHz-2Bz.mjs} +2 -2
  278. package/.output/server/chunks/build/useSettingsNav-dyHz-2Bz.mjs.map +1 -0
  279. package/.output/server/chunks/build/{users-DgsoiXxQ.mjs → users-CluLB8DL.mjs} +31 -13
  280. package/.output/server/chunks/build/users-CluLB8DL.mjs.map +1 -0
  281. package/.output/server/chunks/nitro/nitro.mjs +839 -680
  282. package/.output/server/chunks/routes/__piwi/session.get.mjs +1 -1
  283. package/.output/server/chunks/routes/api/test-runs/_id/case-files.post.mjs +5 -2
  284. package/.output/server/chunks/routes/api/test-runs/_id/case-files.post.mjs.map +1 -1
  285. package/.output/server/chunks/routes/api/test-runs/_id/events.post.mjs +1 -1
  286. package/.output/server/chunks/routes/api/test-runs/_id/failure-groups.get.mjs +1 -1
  287. package/.output/server/chunks/routes/api/test-runs/_id/finish.post.mjs +42 -26
  288. package/.output/server/chunks/routes/api/test-runs/_id/finish.post.mjs.map +1 -1
  289. package/.output/server/chunks/routes/api/test-runs/_id/gate.post.mjs +1 -1
  290. package/.output/server/chunks/routes/api/test-runs/_id/heartbeat.post.mjs +1 -1
  291. package/.output/server/chunks/routes/api/test-runs/_id/insights.get.mjs +1 -1
  292. package/.output/server/chunks/routes/api/test-runs/_id/network-requests.get.mjs +1 -1
  293. package/.output/server/chunks/routes/api/test-runs/_id/regression-context.get.mjs +1 -1
  294. package/.output/server/chunks/routes/api/test-runs/_id/summary.get.mjs +1 -1
  295. package/.output/server/chunks/routes/api/test-runs/import/check.post.mjs +1 -1
  296. package/.output/server/chunks/routes/api/test-runs/recent.get.mjs +1 -1
  297. package/.output/server/chunks/routes/api/test-runs/submit.post.mjs +1 -1
  298. package/.output/server/chunks/routes/api/test-runs/upload.post.mjs +1 -1
  299. package/.output/server/chunks/routes/api/tests/cleanup.delete.mjs +1 -0
  300. package/.output/server/chunks/routes/api/tests/cleanup.delete.mjs.map +1 -1
  301. package/.output/server/chunks/routes/api/traces/check.post.mjs +1 -1
  302. package/.output/server/chunks/routes/api/users/_id/index.post.mjs +1 -1
  303. package/.output/server/chunks/routes/api/users/_id/invite.post.mjs +1 -1
  304. package/.output/server/chunks/routes/api/users/_id/projects.get.mjs +1 -1
  305. package/.output/server/chunks/routes/api/users/_id/projects.put.mjs +1 -1
  306. package/.output/server/chunks/routes/mcp.post.mjs +1 -1
  307. package/.output/server/chunks/routes/renderer.mjs +1 -1
  308. package/.output/server/chunks/routes/share/_token_.get.mjs +1 -1
  309. package/.output/server/index.mjs +1 -1
  310. package/.output/server/package.json +1 -1
  311. package/package.json +1 -1
  312. package/.output/public/_nuxt/3HmftUHT.js +0 -1
  313. package/.output/public/_nuxt/B7zo6PK8.js +0 -1
  314. package/.output/public/_nuxt/BO4sfkbw.js +0 -1
  315. package/.output/public/_nuxt/BdyXNI2_.js +0 -1
  316. package/.output/public/_nuxt/Bg63qh8W.js +0 -1
  317. package/.output/public/_nuxt/BnhWd06P.js +0 -1
  318. package/.output/public/_nuxt/CHWW6xiX.js +0 -1
  319. package/.output/public/_nuxt/CIPvUOic.js +0 -2
  320. package/.output/public/_nuxt/CVcFbORW.js +0 -9
  321. package/.output/public/_nuxt/CZlz5y13.js +0 -1
  322. package/.output/public/_nuxt/CkV_UG8j.js +0 -1
  323. package/.output/public/_nuxt/D0TpBpCc.js +0 -1
  324. package/.output/public/_nuxt/D3LyIeiJ.js +0 -1
  325. package/.output/public/_nuxt/DcccidY5.js +0 -4
  326. package/.output/public/_nuxt/DqkCbAzo.js +0 -1
  327. package/.output/public/_nuxt/DwH4SIZE.js +0 -1
  328. package/.output/public/_nuxt/DwZS0oRm.js +0 -2
  329. package/.output/public/_nuxt/DxPZIuWy.js +0 -1
  330. package/.output/public/_nuxt/Dyb1FouX.js +0 -1
  331. package/.output/public/_nuxt/builds/meta/a5fb24cc-65e3-4e55-aa12-038fe2de4754.json +0 -1
  332. package/.output/public/_nuxt/entry.BFe0Ua9k.css +0 -1
  333. package/.output/public/_nuxt/i7znB42v.js +0 -1
  334. package/.output/server/chunks/build/BreadcrumbNav-DBnGj5Jq.mjs.map +0 -1
  335. package/.output/server/chunks/build/BrowserBadge-vFb1ERG_.mjs.map +0 -1
  336. package/.output/server/chunks/build/ChartMarkerLines-BXqUpUcs.mjs.map +0 -1
  337. package/.output/server/chunks/build/ChartTooltip-DoF6Smyc.mjs.map +0 -1
  338. package/.output/server/chunks/build/CodeBlock-CmvKHaq8.mjs.map +0 -1
  339. package/.output/server/chunks/build/DataLocationCard-ChV02QJj.mjs.map +0 -1
  340. package/.output/server/chunks/build/DiagnosisPanel-C_ndadzP.mjs.map +0 -1
  341. package/.output/server/chunks/build/DiagnosisResult-GAjo6Lt3.mjs.map +0 -1
  342. package/.output/server/chunks/build/DurationValue-CObiBDnH.mjs.map +0 -1
  343. package/.output/server/chunks/build/FeatureUnavailable-Buoyoqx1.mjs.map +0 -1
  344. package/.output/server/chunks/build/GetStartedWizard-tL3U_qM1.mjs.map +0 -1
  345. package/.output/server/chunks/build/HelpHint-C96TlqxY.mjs.map +0 -1
  346. package/.output/server/chunks/build/MetaStripGroup-Cp2WCQf7.mjs.map +0 -1
  347. package/.output/server/chunks/build/NavbarActions-VCHW0u67.mjs.map +0 -1
  348. package/.output/server/chunks/build/ProjectTestCasesTable-saHYJoyQ.mjs.map +0 -1
  349. package/.output/server/chunks/build/RunReports-CKYYRC59.mjs.map +0 -1
  350. package/.output/server/chunks/build/RunStatusBadge-CWhmAmKb.mjs.map +0 -1
  351. package/.output/server/chunks/build/SectionCard-BB1O3uXd.mjs.map +0 -1
  352. package/.output/server/chunks/build/SettingsField-CEasBHu3.mjs.map +0 -1
  353. package/.output/server/chunks/build/TestCaseHistoryChart-BgI6P_zS.mjs.map +0 -1
  354. package/.output/server/chunks/build/TestStatusBar-DR8jM5th.mjs.map +0 -1
  355. package/.output/server/chunks/build/_id_-B7Dw490u.mjs.map +0 -1
  356. package/.output/server/chunks/build/_id_-DVPb1S93.mjs.map +0 -1
  357. package/.output/server/chunks/build/_id_-kkexEH_q.mjs.map +0 -1
  358. package/.output/server/chunks/build/about-C4AbyQ4q.mjs.map +0 -1
  359. package/.output/server/chunks/build/account-B45bYZd1.mjs.map +0 -1
  360. package/.output/server/chunks/build/auto-heal-BnTdKHQq.mjs.map +0 -1
  361. package/.output/server/chunks/build/help-content-BK3jcgLw.mjs.map +0 -1
  362. package/.output/server/chunks/build/import-ibAn_HB9.mjs.map +0 -1
  363. package/.output/server/chunks/build/index-2GmuPNF-.mjs.map +0 -1
  364. package/.output/server/chunks/build/index-D5A0DW7Y.mjs.map +0 -1
  365. package/.output/server/chunks/build/index-DreB_S-d.mjs.map +0 -1
  366. package/.output/server/chunks/build/index-KsRegEjT.mjs.map +0 -1
  367. package/.output/server/chunks/build/mcp-Dwj29-uG.mjs.map +0 -1
  368. package/.output/server/chunks/build/notifications-CjAn5FJj.mjs.map +0 -1
  369. package/.output/server/chunks/build/performance-DRzcu_c7.mjs.map +0 -1
  370. package/.output/server/chunks/build/pr-feedback-DR60oGBf.mjs.map +0 -1
  371. package/.output/server/chunks/build/selections-BjjolRZ9.mjs.map +0 -1
  372. package/.output/server/chunks/build/settings-B3NWV9tu.mjs.map +0 -1
  373. package/.output/server/chunks/build/settings-metadata-DwJk8uSt.mjs.map +0 -1
  374. package/.output/server/chunks/build/storage-C1O-FC0U.mjs.map +0 -1
  375. package/.output/server/chunks/build/tags-dsvYrnii.mjs.map +0 -1
  376. package/.output/server/chunks/build/test-cases-CFiOuyK6.mjs.map +0 -1
  377. package/.output/server/chunks/build/test-functions-CbmBi6az.mjs.map +0 -1
  378. package/.output/server/chunks/build/useDesktopDownload-R_RWSgUV.mjs.map +0 -1
  379. package/.output/server/chunks/build/useDesktopLocalRuns-BdELBy0Y.mjs.map +0 -1
  380. package/.output/server/chunks/build/useDesktopProjectLink-IUN7SIP2.mjs.map +0 -1
  381. package/.output/server/chunks/build/useSettingsNav-Dg87E7kY.mjs.map +0 -1
  382. package/.output/server/chunks/build/users-DgsoiXxQ.mjs.map +0 -1
@@ -1 +1 @@
1
- import{_ as Ee,a as Re}from"./CUjzhXN1.js";import{d as H,K as le,a as se,o as l,e as w,f as c,g as s,h as r,I as G,x as W,b as o,c as p,_ as ne,F as U,z as F,i as ie,k as A,t as P,l as x,L as X,r as R,v as D,M as $e,j as re,w as ae,q as Oe,ac as Le,J as z}from"./BdQ7kfxJ.js";import{_ as Be}from"./CrsaY0R_.js";import{_ as me}from"./9oKY4Zb7.js";import{_ as fe}from"./D0XWJGhG.js";import{_ as ve}from"./CyWOerIG.js";import{_ as ge}from"./CbzgEkmW.js";import{_ as Fe}from"./CK2AMqz_.js";import{h as We}from"./Bg63qh8W.js";import{_ as ye}from"./BOn5q0rT.js";import{_ as Ne}from"./LWIyaZKe.js";import{u as oe}from"./DTtizz85.js";import{_ as De}from"./dg6uXTyR.js";import{p as Xe,g as qe}from"./CMVTTE_g.js";import"./CZ6WR7uw.js";import"./CxwnFFD0.js";import"./i7znB42v.js";import"./BO4sfkbw.js";import"./rPG7kzfL.js";import"./C_eXufkv.js";import"./HGYIpJtg.js";import"./DwZS0oRm.js";const Ke={class:"space-y-3"},je={key:0,class:"flex items-center justify-center gap-2 py-8 text-gray-400"},ze={key:1,class:"py-8 text-center text-sm text-gray-400"},He={key:2,class:"max-h-96 overflow-y-auto space-y-px"},Ge=["onClick"],Qe={class:"flex-1 min-w-0"},Ye={class:"text-sm font-medium leading-snug truncate"},Ze={key:0,class:"text-gray-500 font-normal"},Je={class:"text-xs text-gray-400 leading-snug mt-0.5"},et={key:3,class:"italic text-gray-500"},tt={key:0,class:"flex items-center gap-1 shrink-0 pt-0.5"},st=["title"],at=["title"],ot={key:0,class:"py-8 text-center text-sm text-gray-400"},lt=H({__name:"ModelPickerModal",props:X({models:{},selected:{},loading:{type:Boolean}},{open:{type:Boolean,required:!0},openModifiers:{}}),emits:X(["select"],["update:open"]),setup(a,{emit:M}){function C(y){return y?y>=1e6?`${(y/1e6).toFixed(1)}M`:y>=1e3?`${Math.round(y/1e3)}K`:String(y):""}const v=a,i=M,I=le(a,"open"),_=R(null),d=R("");se(I,y=>{y&&$e(()=>_.value?.focus())});const n=D(()=>{const y=d.value.toLowerCase();return y?v.models.filter(h=>h.id.toLowerCase().includes(y)||(h.label?.toLowerCase()??"").includes(y)):v.models}),k={image:{icon:"i-lucide-image",label:"Image input"},pdf:{icon:"i-lucide-file-text",label:"PDF input"},code:{icon:"i-lucide-code",label:"Code execution"},thinking:{icon:"i-lucide-brain",label:"Extended thinking"},json:{icon:"i-lucide-braces",label:"Structured output"},text:{icon:"i-lucide-type",label:"Text"},audio:{icon:"i-lucide-music",label:"Audio"}};function V(y){return y.map(h=>{const g=h.indexOf("→");if(g!==-1){const E=h.slice(0,g),O=h.slice(g+1);return{inputs:E.split("+").filter(Boolean),outputs:O.split("+").filter(Boolean)}}return{inputs:[h],outputs:[]}})}function $(y){i("select",y),I.value=!1,d.value=""}return(y,h)=>{const g=G,E=ne,O=Fe;return l(),w(O,{open:I.value,"onUpdate:open":h[1]||(h[1]=f=>I.value=f),title:"Select a model",ui:{content:"max-w-2xl"}},{body:c(()=>[s("div",Ke,[r(g,{ref_key:"searchInput",ref:_,modelValue:o(d),"onUpdate:modelValue":h[0]||(h[0]=f=>W(d)?d.value=f:null),placeholder:"Search models…",icon:"i-lucide-search",size:"sm"},null,8,["modelValue"]),a.models.length===0&&a.loading?(l(),p("div",je,[r(E,{name:"i-lucide-loader-2",class:"size-4 animate-spin"}),h[2]||(h[2]=s("span",{class:"text-sm"},"Loading models…",-1))])):a.models.length===0?(l(),p("div",ze," No models available — check your provider configuration ")):(l(),p("div",He,[(l(!0),p(U,null,F(o(n),f=>(l(),p("button",{key:f.id,class:ie(["w-full text-left px-4 py-3 rounded-lg hover:bg-elevated transition-colors border border-transparent hover:border-default flex items-start gap-4",a.selected===f.id?"bg-primary/10 ring-1 ring-inset ring-primary/30 border-primary/30":""]),onClick:b=>$(f.id)},[s("div",Qe,[s("p",Ye,[A(P(f.id)+" ",1),f.label&&f.label!==f.id?(l(),p("span",Ze," — "+P(f.label),1)):x("",!0)]),s("p",Je,[f.contextLength?(l(),p(U,{key:0},[A(P(C(f.contextLength))+" ctx",1)],64)):x("",!0),f.maxTokens?(l(),p(U,{key:1},[A(" · up to "+P(C(f.maxTokens))+" out",1)],64)):x("",!0),f.pricing?.prompt?(l(),p(U,{key:2},[A(" · $"+P(f.pricing.prompt)+" / $"+P(f.pricing.completion??"?")+" per 1M",1)],64)):x("",!0),!f.contextLength&&!f.maxTokens&&!f.pricing?.prompt?(l(),p("span",et,"No additional info")):x("",!0)])]),f.modalities?.length?(l(),p("div",tt,[(l(!0),p(U,null,F(V(f.modalities),b=>(l(),p(U,{key:b.inputs.join()+"→"+b.outputs.join()},[(l(!0),p(U,null,F(b.inputs,T=>(l(),p("span",{key:"in-"+T,title:k[T]?.label??T,class:"inline-flex items-center justify-center size-6 rounded-md bg-gray-100 dark:bg-gray-800 text-gray-500 hover:text-primary transition-colors"},[r(E,{name:k[T]?.icon??"i-lucide-cpu",class:"size-3.5"},null,8,["name"])],8,st))),128)),b.outputs.length?(l(),w(E,{key:0,name:"i-lucide-arrow-right",class:"size-3 text-gray-400 shrink-0"})):x("",!0),(l(!0),p(U,null,F(b.outputs,T=>(l(),p("span",{key:"out-"+T,title:k[T]?.label??T,class:"inline-flex items-center justify-center size-6 rounded-md bg-gray-100 dark:bg-gray-800 text-gray-500 hover:text-primary transition-colors"},[r(E,{name:k[T]?.icon??"i-lucide-cpu",class:"size-3.5"},null,8,["name"])],8,at))),128))],64))),128))])):x("",!0)],10,Ge))),128)),o(n).length===0?(l(),p("div",ot,' No models match "'+P(o(d))+'" ',1)):x("",!0)]))])]),_:1},8,["open"])}}}),nt=Object.assign(lt,{__name:"ModelPickerModal"}),it={class:"flex gap-2"},rt=H({__name:"ModelFieldInput",props:X({provider:{},providerResolved:{},reuse:{type:Boolean},models:{},loadingModels:{type:Boolean},placeholderAnthropic:{},placeholderOpenai:{}},{modelValue:{required:!0},modelModifiers:{}}),emits:X(["loadModels"],["update:modelValue"]),setup(a,{emit:M}){const C=M,v=le(a,"modelValue"),i=R(!1);return(I,_)=>{const d=G,n=re,k=nt;return l(),p(U,null,[s("div",it,[r(d,{modelValue:v.value,"onUpdate:modelValue":_[0]||(_[0]=V=>v.value=V),placeholder:a.providerResolved==="anthropic"?a.placeholderAnthropic:a.placeholderOpenai,class:"flex-1"},null,8,["modelValue","placeholder"]),a.providerResolved?(l(),w(n,{key:0,size:"sm",variant:"soft",onClick:_[1]||(_[1]=V=>{C("loadModels"),i.value=!0})},{default:c(()=>[..._[4]||(_[4]=[A(" Choose model… ",-1)])]),_:1})):x("",!0)]),r(k,{open:o(i),"onUpdate:open":_[2]||(_[2]=V=>W(i)?i.value=V:null),models:a.models,selected:v.value,loading:a.loadingModels,onSelect:_[3]||(_[3]=V=>v.value=V)},null,8,["open","models","selected","loading"])],64)}}}),dt=Object.assign(rt,{__name:"ModelFieldInput"}),ct={class:"flex items-start justify-between gap-3"},ut={class:"flex items-start gap-2"},pt={class:"font-medium inline-flex items-center gap-1"},mt={class:"text-sm text-gray-500"},ft={class:"inline-flex items-center gap-1"},vt={class:"inline-flex items-center gap-1"},gt={class:"inline-flex items-center gap-1"},yt={key:3,class:"flex justify-end"},ht=H({__name:"AiRoleConfigForm",props:X({meta:{},hasApiKey:{type:Boolean},reuseOptions:{},providerOptions:{},presetOptions:{},disabled:{type:Boolean},envManaged:{type:Boolean},models:{},loadingModels:{type:Boolean},providerResolved:{},testing:{type:Boolean}},{modelValue:{required:!0},modelModifiers:{}}),emits:X(["applyPreset","loadModels","test"],["update:modelValue"]),setup(a,{emit:M}){const C=a,v=M,i=le(a,"modelValue"),I=D({get:()=>i.value.reuse??"own",set:d=>i.value.reuse=d==="own"?null:d}),_=D(()=>We(C.meta.help));return(d,n)=>{const k=ne,V=Be,$=me,y=fe,h=ve,g=ge,E=G,O=dt,f=re;return l(),p("div",{class:ie(["rounded-lg border border-default p-4 space-y-4",a.meta.optional&&!i.value.enabled?"opacity-80":""])},[s("div",ct,[s("div",ut,[r(k,{name:a.meta.icon,class:"size-5 mt-0.5 text-primary"},null,8,["name"]),s("div",null,[s("p",pt,[A(P(a.meta.title)+" ",1),r(V,{topic:a.meta.help},null,8,["topic"])]),s("p",mt,P(a.meta.blurb),1)])]),a.meta.optional?(l(),w($,{key:0,modelValue:i.value.enabled,"onUpdate:modelValue":n[0]||(n[0]=b=>i.value.enabled=b),disabled:a.disabled&&!a.envManaged,"aria-label":a.meta.enableLabel},null,8,["modelValue","disabled","aria-label"])):x("",!0)]),!a.meta.optional||i.value.enabled?(l(),p(U,{key:0},[a.meta.reuseTargets.length?(l(),w(h,{key:0,label:"Provider source"},{default:c(()=>[r(y,{modelValue:o(I),"onUpdate:modelValue":n[1]||(n[1]=b=>W(I)?I.value=b:null),items:a.reuseOptions,disabled:a.disabled&&!a.envManaged,class:"w-full"},null,8,["modelValue","items","disabled"])]),_:1})):x("",!0),i.value.reuse?x("",!0):(l(),p(U,{key:1},[r(h,{label:"Provider"},{label:c(()=>[s("span",ft,[n[9]||(n[9]=A(" Provider ",-1)),a.disabled?(l(),w(g,{key:0,"env-vars":o(_)},null,8,["env-vars"])):x("",!0)])]),default:c(()=>[r(y,{modelValue:i.value.provider,"onUpdate:modelValue":n[2]||(n[2]=b=>i.value.provider=b),items:a.providerOptions,disabled:a.disabled,placeholder:"Choose a provider…",class:"w-full"},null,8,["modelValue","items","disabled"])]),_:1}),i.value.provider==="openai"?(l(),w(h,{key:0,label:"Preset",description:"Pick a known provider to auto-fill the URL and model, then adjust as needed"},{default:c(()=>[r(y,{items:a.presetOptions,placeholder:"Choose a preset…",disabled:a.disabled,class:"w-full","onUpdate:modelValue":n[3]||(n[3]=b=>v("applyPreset",b))},null,8,["items","disabled"])]),_:1})):x("",!0),i.value.provider?(l(),w(h,{key:1,label:"API key",description:a.hasApiKey?"Leave empty to keep the stored key, clear and save to remove it":"Required for Anthropic; optional for local OpenAI-compatible servers"},{label:c(()=>[s("span",vt,[n[10]||(n[10]=A(" API key ",-1)),a.disabled?(l(),w(g,{key:0,"env-vars":o(_)},null,8,["env-vars"])):x("",!0)])]),default:c(()=>[r(E,{modelValue:i.value.apiKey,"onUpdate:modelValue":n[4]||(n[4]=b=>i.value.apiKey=b),type:"password",placeholder:a.hasApiKey?"•••••••• (unchanged)":"sk-…",disabled:a.disabled,class:"w-full font-mono"},null,8,["modelValue","placeholder","disabled"])]),_:1},8,["description"])):x("",!0),i.value.provider==="openai"?(l(),w(h,{key:2,label:"Base URL",description:"Required, e.g. http://localhost:11434/v1"},{label:c(()=>[s("span",gt,[n[11]||(n[11]=A(" Base URL ",-1)),a.disabled?(l(),w(g,{key:0,"env-vars":o(_)},null,8,["env-vars"])):x("",!0)])]),default:c(()=>[r(E,{modelValue:i.value.baseUrl,"onUpdate:modelValue":n[5]||(n[5]=b=>i.value.baseUrl=b),placeholder:"http://localhost:11434/v1",disabled:a.disabled,class:"w-full"},null,8,["modelValue","disabled"])]),_:1})):x("",!0)],64)),i.value.reuse||i.value.provider?(l(),w(h,{key:2,label:"Model",description:i.value.reuse?"Leave empty to use the reused role's model":void 0},{default:c(()=>[r(O,{modelValue:i.value.model,"onUpdate:modelValue":n[6]||(n[6]=b=>i.value.model=b),provider:i.value.provider,"provider-resolved":a.providerResolved,reuse:!!i.value.reuse,models:a.models,"loading-models":a.loadingModels,"placeholder-anthropic":a.meta.modelPlaceholderAnthropic,"placeholder-openai":a.meta.modelPlaceholderOpenai,onLoadModels:n[7]||(n[7]=b=>v("loadModels"))},null,8,["modelValue","provider","provider-resolved","reuse","models","loading-models","placeholder-anthropic","placeholder-openai"])]),_:1},8,["description"])):x("",!0),a.providerResolved?(l(),p("div",yt,[r(f,{size:"xs",color:"neutral",variant:"soft",icon:"i-lucide-plug",loading:a.testing,onClick:n[8]||(n[8]=b=>v("test"))},{default:c(()=>[...n[12]||(n[12]=[A(" Test connection ",-1)])]),_:1},8,["loading"])])):x("",!0)],64)):x("",!0)],2)}}}),bt=Object.assign(ht,{__name:"AiRoleConfigForm"}),_t={key:0,class:"space-y-3"},xt={class:"text-sm text-gray-500"},kt={key:0,class:"text-sm text-gray-500"},It={key:1,class:"overflow-x-auto"},At={class:"w-full text-sm"},Mt={class:"px-2 py-2"},St={class:"font-mono text-xs"},Vt={class:"text-xs text-gray-400"},Pt={class:"text-right px-2 py-2"},Tt=["title"],wt=["title"],Ct={class:"text-right px-2 py-2"},Ut={key:1,class:"flex items-center gap-2 py-4 text-muted"},Et=H({__name:"AiUsagePanel",async setup(a){let M,C;const v=R(30),i=[{label:"Last 7 days",value:7},{label:"Last 30 days",value:30},{label:"Last 90 days",value:90}],{data:I,pending:_}=([M,C]=ae(()=>oe("/api/settings/ai/usage",{query:{days:v}},"$Q4bVv0_V0W")),M=await M,C(),M);function d(n){return n>=1e6?`${(n/1e6).toFixed(1)}M`:n>=1e3?`${(n/1e3).toFixed(1)}k`:String(n)}return(n,k)=>{const V=fe,$=Ne,y=ne,h=ye;return l(),w(h,{icon:"i-lucide-activity",title:"AI usage"},{actions:c(()=>[r(V,{modelValue:o(v),"onUpdate:modelValue":k[0]||(k[0]=g=>W(v)?v.value=g:null),items:i,size:"sm",class:"w-36"},null,8,["modelValue"])]),default:c(()=>[o(I)?(l(),p("div",_t,[s("p",xt,P(d(o(I).totals.diagnoses))+" diagnoses · "+P(d(o(I).totals.inputTokens))+" input tokens · "+P(d(o(I).totals.outputTokens))+" output tokens ",1),o(I).byModel.length===0?(l(),p("p",kt,"No AI calls recorded in this period.")):(l(),p("div",It,[s("table",At,[k[1]||(k[1]=s("thead",null,[s("tr",{class:"text-xs text-gray-500 uppercase tracking-wider border-b border-default"},[s("th",{class:"text-left px-2 py-2 font-medium"},"Model"),s("th",{class:"text-right px-2 py-2 font-medium"},"Diagnoses"),s("th",{class:"text-right px-2 py-2 font-medium"},"Failed"),s("th",{class:"text-right px-2 py-2 font-medium"},"Input tokens"),s("th",{class:"text-right px-2 py-2 font-medium"},"Output tokens"),s("th",{class:"text-right px-2 py-2 font-medium"},"Avg duration")])],-1)),s("tbody",null,[(l(!0),p(U,null,F(o(I).byModel,g=>(l(),p("tr",{key:`${g.provider??"unknown"}/${g.model}`,class:"border-b last:border-b-0 border-default"},[s("td",Mt,[s("span",St,P(g.model),1),s("span",Vt," · "+P(g.provider??"unknown"),1)]),s("td",Pt,P(g.diagnoses),1),s("td",{class:ie(["text-right px-2 py-2",g.failed>0?"text-red-600 dark:text-red-400":""])},P(g.failed),3),s("td",{class:"text-right px-2 py-2",title:g.inputTokens.toLocaleString()},P(d(g.inputTokens)),9,Tt),s("td",{class:"text-right px-2 py-2",title:g.outputTokens.toLocaleString()},P(d(g.outputTokens)),9,wt),s("td",Ct,[r($,{ms:g.avgDurationMs},null,8,["ms"])])]))),128))])])]))])):o(_)?(l(),p("div",Ut,[r(y,{name:"i-lucide-loader-circle",class:"size-4 animate-spin"}),k[2]||(k[2]=s("span",{class:"text-sm"},"Loading usage…",-1))])):x("",!0)]),_:1})}}}),Rt=Object.assign(Et,{__name:"AiUsagePanel"}),$t=[{key:"sampleErrorChars",label:"Error text characters",envVar:"PIWI_AI_MAX_SAMPLE_ERROR_CHARS",description:"Max characters of raw error text (per error block).",min:200,max:5e4},{key:"scmPatchBudget",label:"SCM patch budget",envVar:"PIWI_AI_MAX_SCM_PATCH_BUDGET",description:"Total characters of diff patches across changed files.",min:0,max:5e4},{key:"affectedTests",label:"Affected tests",envVar:"PIWI_AI_MAX_AFFECTED_TESTS",description:"Max affected tests listed.",min:1,max:200},{key:"steps",label:"Test steps",envVar:"PIWI_AI_MAX_STEPS",description:"Max recent test steps included.",min:1,max:200},{key:"consoleEntries",label:"Console entries",envVar:"PIWI_AI_MAX_CONSOLE_ENTRIES",description:"Max console error/warning entries included.",min:0,max:200},{key:"consoleEntryChars",label:"Console entry characters",envVar:"PIWI_AI_MAX_CONSOLE_ENTRY_CHARS",description:"Max characters per console entry.",min:50,max:5e3},{key:"networkRequests",label:"Network requests",envVar:"PIWI_AI_MAX_NETWORK_REQUESTS",description:"Max failed network requests included.",min:0,max:200},{key:"ariaSnapshotChars",label:"ARIA snapshot characters",envVar:"PIWI_AI_MAX_ARIA_SNAPSHOT_CHARS",description:"Max characters of the page ARIA snapshot.",min:0,max:5e4},{key:"testSourceChars",label:"Test source characters",envVar:"PIWI_AI_MAX_TEST_SOURCE_CHARS",description:"Max characters of the test source snippet.",min:0,max:5e4},{key:"maxSourceFiles",label:"Full source files",envVar:"PIWI_AI_MAX_SOURCE_FILES",description:"Max full source files fetched from SCM to ground patches (0 disables).",min:0,max:20},{key:"sourceFileChars",label:"Source file characters",envVar:"PIWI_AI_MAX_SOURCE_FILE_CHARS",description:"Max characters per fetched full source file.",min:0,max:5e4},{key:"serverLogEntries",label:"Server log entries",envVar:"PIWI_AI_MAX_SERVER_LOG_ENTRIES",description:"Max backend server log entries (from X-Piwi-Logs header) included.",min:0,max:200},{key:"serverLogEntryChars",label:"Server log entry characters",envVar:"PIWI_AI_MAX_SERVER_LOG_ENTRY_CHARS",description:"Max characters per backend server log entry.",min:50,max:5e3},{key:"serverTraceSpans",label:"Server trace spans",envVar:"PIWI_AI_MAX_SERVER_TRACE_SPANS",description:"Max backend server spans (from X-Piwi-Trace header) included (0 disables).",min:0,max:500},{key:"maxImages",label:"Max screenshots",envVar:"PIWI_AI_MAX_IMAGES",description:"Max screenshots auto-included in the diagnosis context.",min:0,max:20},{key:"maxPassedPeers",label:"Max passed peers",envVar:"PIWI_AI_MAX_PASSED_PEERS",description:"Max peer tests in the same file listed when they passed.",min:0,max:100},{key:"maxConsoleWindow",label:"Console window entries",envVar:"PIWI_AI_MAX_CONSOLE_WINDOW",description:"Max console entries of any type in the window before failure.",min:0,max:200},{key:"slowRequestMs",label:"Slow request threshold (ms)",envVar:"PIWI_AI_SLOW_REQUEST_MS",description:"Network request duration threshold for flagging as slow.",min:100,max:3e4},{key:"maxTraceActions",label:"Trace actions",envVar:"PIWI_AI_MAX_TRACE_ACTIONS",description:"Max actions extracted from trace ZIP for failing-action context (0 disables).",min:0,max:50},{key:"traceDomChars",label:"Trace DOM excerpt characters",envVar:"PIWI_AI_TRACE_DOM_CHARS",description:"Max characters for the trace-derived DOM/ARIA excerpt in failing-action context.",min:0,max:2e4},{key:"traceStackFrames",label:"Trace stack frames",envVar:"PIWI_AI_MAX_TRACE_STACK_FRAMES",description:"Max call-stack frames (with source windows) from the trace (0 disables).",min:0,max:50},{key:"traceNetworkRequests",label:"Trace network requests",envVar:"PIWI_AI_MAX_TRACE_NETWORK_REQUESTS",description:"Max requests from the trace network stream (0 disables).",min:0,max:200},{key:"domSnapshotChars",label:"DOM snapshot characters",envVar:"PIWI_AI_MAX_DOM_SNAPSHOT_CHARS",description:"Max characters of the failure-time DOM snapshot rendered from the trace (0 disables).",min:0,max:5e4},{key:"imageMaxEdge",label:"Screenshot max edge (px)",envVar:"PIWI_AI_IMAGE_MAX_EDGE",description:"Screenshots are downscaled to at most this many pixels on the long edge before being sent.",min:512,max:8192},{key:"aiStepIntents",label:"AI-step intents",envVar:"PIWI_AI_MAX_STEP_INTENTS",description:"Max AI-step intent mappings (prompt → compiled locator) included (0 disables the section).",min:0,max:100}],Ot={class:"space-y-6"},Lt={class:"space-y-5"},Bt={class:"flex items-center gap-3"},Ft={class:"flex items-center gap-2 justify-end"},Wt={class:"flex justify-end"},Nt={class:"flex justify-end"},Dt={class:"grid grid-cols-1 sm:grid-cols-2 gap-x-4 gap-y-3"},Xt={class:"flex justify-end gap-2"},ps=H({__name:"ai",async setup(a){let M,C;const v=Oe(),{data:i,refresh:I}=([M,C]=ae(()=>oe("/api/settings/ai","$5FSQHzGDZ4")),M=await M,C(),M);function _(){return{enabled:!1,reuse:null,provider:"",model:"",baseUrl:"",apiKey:""}}const d=z({diagnosis:_(),research:_(),embedding:_()}),n=R(!1),k=R(""),V=R(""),$=R(!1),y=R(!1),h=R(!1),g=z({diagnosis:!1,research:!1,embedding:!1}),E=z({diagnosis:[],research:[],embedding:[]}),O=z({diagnosis:!1,research:!1,embedding:!1});function f(t){const e=d[t];return e.reuse?d[e.reuse]?.provider||"":e.provider}async function b(t){const e=d[t],m=f(t),S=e.reuse?d[e.reuse]:e,ee=S.apiKey||void 0;O[t]=!0;try{const te=await $fetch("/api/settings/ai/models",{method:"POST",body:{role:t,provider:m,baseUrl:S.baseUrl||void 0,apiKey:ee}});E[t]=te.models}catch{E[t]=[]}finally{O[t]=!1}}const T=[{key:"diagnosis",title:"Diagnosis model",icon:"i-lucide-stethoscope",help:"settings.ai-provider",optional:!1,enableLabel:"",blurb:"The main model that writes the final diagnosis. Required to enable AI features.",reuseTargets:[],modelPlaceholderAnthropic:"claude-opus-4-8",modelPlaceholderOpenai:"e.g. gpt-4o, llama3.1"},{key:"research",title:"Research model",icon:"i-lucide-search",help:"settings.ai-research",optional:!0,enableLabel:"Two-stage diagnosis",blurb:"A cheaper/faster model that pre-analyzes the failure before the diagnosis model writes the final answer. Also used for cluster naming and merge adjudication.",reuseTargets:["diagnosis"],modelPlaceholderAnthropic:"e.g. claude-haiku-4-5",modelPlaceholderOpenai:"e.g. llama-3.1-8b-instant"},{key:"embedding",title:"Embedding model",icon:"i-lucide-vector-square",help:"settings.embedding-model",optional:!0,enableLabel:"Semantic clustering",blurb:"Embeds failures so semantically-similar errors group together (used by failure clustering).",reuseTargets:["diagnosis","research"],modelPlaceholderAnthropic:"— Anthropic has no embeddings API —",modelPlaceholderOpenai:"e.g. text-embedding-3-small"}],de=[{label:"Anthropic API",value:"anthropic"},{label:"OpenAI-compatible",value:"openai"}],he=de.filter(t=>t.value!=="anthropic"),be=D(()=>{const t={};for(const e of T)t[e.key]=[{label:"Configure its own provider",value:"own"},...e.reuseTargets.filter(m=>d[m].enabled||m==="diagnosis").filter(m=>e.key!=="embedding"||d[m].provider==="openai").map(m=>({label:`Reuse ${T.find(S=>S.key===m).title.toLowerCase()}`,value:m}))];return t}),N=D(()=>!!i.value?.envManaged),_e=Xe(qe("ai"));se(i,t=>{if(t){for(const e of T){const m=t.roles[e.key],S=d[e.key];S.enabled=!!m,S.reuse=m?.reuse??null,S.provider=m?.provider??"",S.model=m?.model??"",S.baseUrl=m?.baseUrl??"",S.apiKey=""}n.value=t.autoDiagnose,k.value=t.customInstructions||""}},{immediate:!0});function xe(t){return!!i.value?.roles[t]?.hasApiKey}const ce=[{label:"ollama (local)",baseUrl:"http://localhost:11434/v1",model:"llama3.1"},{label:"LM Studio (local)",baseUrl:"http://localhost:1234/v1",model:""},{label:"OpenRouter",baseUrl:"https://openrouter.ai/api/v1",model:"meta-llama/llama-3.1-8b-instruct"},{label:"Groq",baseUrl:"https://api.groq.com/openai/v1",model:"llama-3.1-8b-instant"},{label:"OpenAI",baseUrl:"https://api.openai.com/v1",model:"gpt-4o"},{label:"Mistral AI",baseUrl:"https://api.mistral.ai/v1",model:"mistral-small-latest"},{label:"Custom",baseUrl:"",model:""}],ke=ce.map(t=>({label:t.label,value:t.label}));function Ie(t,e){const m=ce.find(S=>S.label===e);!m||m.label==="Custom"||(d[t].baseUrl=m.baseUrl,d[t].model=m.model)}function Q(t){const e=d[t];if(!e.enabled)return null;if(e.reuse)return{reuse:e.reuse,model:e.model||void 0};const m={provider:e.provider,model:e.model||void 0,baseUrl:e.baseUrl||void 0};return e.apiKey!==""&&(m.apiKey=e.apiKey),m}async function Ae(){$.value=!0;try{!N&&(!d.diagnosis.enabled||!d.diagnosis.provider)?await $fetch("/api/settings/ai",{method:"PUT",body:{roles:null,autoDiagnose:n.value}}):await $fetch("/api/settings/ai",{method:"PUT",body:{roles:{diagnosis:Q("diagnosis"),research:Q("research"),embedding:Q("embedding")},autoDiagnose:n.value}}),await I();for(const t of T)d[t.key].apiKey="";v.add({title:"Settings saved",color:"success"})}catch(t){v.add({title:"Save failed",description:String(t?.message??t),color:"error"})}finally{$.value=!1}}async function Me(){h.value=!0;try{await $fetch("/api/settings/ai",{method:"PUT",body:{scmToken:V.value||null}}),await I(),V.value="",v.add({title:"SCM token saved",color:"success"})}catch(t){v.add({title:"Save failed",description:String(t?.message??t),color:"error"})}finally{h.value=!1}}async function Se(){y.value=!0;try{await $fetch("/api/settings/ai",{method:"PUT",body:{customInstructions:k.value||null}}),await I(),v.add({title:"Instructions saved",color:"success"})}catch(t){v.add({title:"Save failed",description:String(t?.message??t),color:"error"})}finally{y.value=!1}}async function Ve(t){g[t]=!0;try{const e=d[t],m=e.reuse?d[e.reuse]:e,S=await $fetch("/api/settings/ai/test",{method:"POST",body:{role:t,provider:m.provider||void 0,apiKey:m.apiKey||void 0,model:e.model||(e.reuse?m.model:"")||void 0,baseUrl:m.baseUrl||void 0}});S.success?v.add({title:"Connection successful",description:`Model: ${S.model}`,color:"success"}):v.add({title:"Connection failed",description:S.error||"Unknown error",color:"error"})}catch(e){v.add({title:"Connection failed",description:String(e?.message??e),color:"error"})}finally{g[t]=!1}}const{data:L}=([M,C]=ae(()=>oe("/api/settings/ai/limits","$qHhpP8mBYb")),M=await M,C(),M),Y=$t,q=z({}),Z=R(!1),J=D(()=>new Set(L.value?.envManaged??[]));se(L,t=>{if(t)for(const e of Y)q[e.key]=t.limits[e.key]},{immediate:!0});async function Pe(){Z.value=!0;try{L.value=await $fetch("/api/settings/ai/limits",{method:"PUT",body:{limits:q}}),v.add({title:"Context limits saved",color:"success"})}catch(t){v.add({title:"Failed to save context limits",description:String(t?.message??t),color:"error"})}finally{Z.value=!1}}function Te(){if(L.value)for(const t of Y)J.value.has(t.key)||(q[t.key]=L.value.defaults[t.key])}return(t,e)=>{const m=Ee,S=bt,ee=me,te=Re,K=re,j=ye,we=Rt,ue=G,pe=ve,Ce=De,Ue=ge;return l(),p("div",Ot,[o(N)?(l(),w(m,{key:0,"env-vars":o(_e)},null,8,["env-vars"])):x("",!0),r(j,{icon:"i-lucide-sparkles",title:"Model providers",help:"settings.ai-provider"},{subtitle:c(()=>[...e[3]||(e[3]=[A(" Configure a complete provider for each model role. Optional roles can reuse another role's provider so you don't re-enter credentials. ",-1)])]),footer:c(()=>[s("div",Ft,[r(K,{color:"primary",loading:o($),icon:"i-lucide-save",onClick:Ae},{default:c(()=>[...e[5]||(e[5]=[A(" Save ",-1)])]),_:1},8,["loading"])])]),default:c(()=>[s("div",Lt,[(l(),p(U,null,F(T,u=>r(S,{key:u.key,modelValue:o(d)[u.key],"onUpdate:modelValue":B=>o(d)[u.key]=B,meta:u,"has-api-key":xe(u.key),"reuse-options":o(be)[u.key],"provider-options":u.key==="embedding"?o(he):de,"preset-options":o(ke),disabled:o(N),"env-managed":o(N),"provider-resolved":f(u.key),models:o(E)[u.key],"loading-models":o(O)[u.key],testing:o(g)[u.key],onApplyPreset:B=>Ie(u.key,B),onLoadModels:B=>b(u.key),onTest:B=>Ve(u.key)},null,8,["modelValue","onUpdate:modelValue","meta","has-api-key","reuse-options","provider-options","preset-options","disabled","env-managed","provider-resolved","models","loading-models","testing","onApplyPreset","onLoadModels","onTest"])),64)),r(te,{label:"Auto-diagnose",help:"settings.auto-diagnose","env-managed":o(N)},{default:c(()=>[s("div",Bt,[r(ee,{modelValue:o(n),"onUpdate:modelValue":e[0]||(e[0]=u=>W(n)?n.value=u:null),disabled:o(N)||!o(d).diagnosis.enabled},null,8,["modelValue","disabled"]),e[4]||(e[4]=s("span",{class:"text-sm text-gray-500"}," Automatically diagnose new failure clusters when a run finishes — up to 3 clusters per run (research + diagnosis call each), plus one batched call to title new clusters ",-1))])]),_:1},8,["env-managed"])])]),_:1}),r(we),r(j,{title:"Repository access",help:"project.scm-token"},{subtitle:c(()=>[...e[6]||(e[6]=[A(" Optional — required for private repositories. Per-project tokens override this. ",-1)])]),footer:c(()=>[s("div",Wt,[r(K,{color:"primary",loading:o(h),icon:"i-lucide-save",onClick:Me},{default:c(()=>[...e[7]||(e[7]=[A(" Save token ",-1)])]),_:1},8,["loading"])])]),default:c(()=>[r(pe,{label:"SCM token",description:o(i)?.hasScmToken?"Leave empty to keep the stored token, enter a new value to replace it, or save empty to remove it":"Personal access token with read access to repository contents. Supports GitHub (ghp_), GitLab (glpat-), and Bitbucket tokens."},{default:c(()=>[r(ue,{modelValue:o(V),"onUpdate:modelValue":e[1]||(e[1]=u=>W(V)?V.value=u:null),type:"password",placeholder:o(i)?.hasScmToken?"•••••••• (unchanged)":"ghp_..., glpat-..., or Bitbucket token",class:"w-full font-mono"},null,8,["modelValue","placeholder"])]),_:1},8,["description"])]),_:1}),r(j,{title:"Global analysis instructions",help:"settings.ai-instructions"},{footer:c(()=>[s("div",Nt,[r(K,{color:"primary",loading:o(y),icon:"i-lucide-save",onClick:Se},{default:c(()=>[...e[8]||(e[8]=[A(" Save instructions ",-1)])]),_:1},8,["loading"])])]),default:c(()=>[r(Ce,{modelValue:o(k),"onUpdate:modelValue":e[2]||(e[2]=u=>W(k)?k.value=u:null),rows:6,placeholder:"e.g. Always suggest running failing tests with --repeat-each 5 to confirm flakiness. Prefer network-level evidence over ARIA snapshots. Recommend git bisect when a commit range is available.",class:"w-full font-mono text-sm"},null,8,["modelValue"]),e[9]||(e[9]=s("p",{class:"text-xs text-gray-400 mt-2"}," These instructions are appended to the base system prompt. They shape how the AI analyzes failures but cannot override the response schema or confidence requirement. ",-1))]),_:1}),r(j,{title:"Diagnosis context limits",help:"settings.ai-limits"},{subtitle:c(()=>[...e[10]||(e[10]=[A(" Leave a field empty to use its default; env-managed fields are read-only. ",-1)])]),footer:c(()=>[s("div",Xt,[r(K,{color:"neutral",variant:"ghost",size:"sm",onClick:Te},{default:c(()=>[...e[11]||(e[11]=[A("Reset to defaults",-1)])]),_:1}),r(K,{color:"primary",loading:o(Z),icon:"i-lucide-save",size:"sm",onClick:Pe},{default:c(()=>[...e[12]||(e[12]=[A(" Save limits ",-1)])]),_:1},8,["loading"])])]),default:c(()=>[s("div",Dt,[(l(!0),p(U,null,F(o(Y),u=>(l(),w(pe,{key:u.key,label:u.label,description:u.description,hint:`default ${o(L)?.defaults[u.key]??""}`},{default:c(()=>[r(ue,{modelValue:o(q)[u.key],"onUpdate:modelValue":B=>o(q)[u.key]=B,modelModifiers:{number:!0},type:"number",min:u.min,max:u.max,disabled:o(J).has(u.key),placeholder:`default ${o(L)?.defaults[u.key]??""}`,class:"w-full"},Le({_:2},[o(J).has(u.key)?{name:"trailing",fn:c(()=>[r(Ue,{"env-vars":[u.envVar]},null,8,["env-vars"])]),key:"0"}:void 0]),1032,["modelValue","onUpdate:modelValue","min","max","disabled","placeholder"])]),_:2},1032,["label","description","hint"]))),128))])]),_:1}),r(j,{icon:"i-lucide-shield-check",title:"Privacy notice",help:"settings.privacy"},{default:c(()=>[...e[13]||(e[13]=[s("div",{class:"space-y-2 text-sm text-gray-600 dark:text-gray-400"},[s("p",null,"When diagnosing a failure cluster, the following data is sent to the configured LLM provider:"),s("ul",{class:"list-disc list-inside space-y-1 ml-2"},[s("li",null,"Normalized error signature and sample raw error text"),s("li",null,"Test titles and file paths for affected tests"),s("li",null,"Browser info, test steps, console error/warning entries (excerpts)"),s("li",null,"Failed network request URLs and status codes"),s("li",null,"ARIA page snapshot (if collected)"),s("li",null," Commit SHA range since last passing run, plus changed file names and diff patches fetched from GitHub/GitLab/Bitbucket (if a repository token is configured or the repo is public) ")]),s("p",{class:"mt-2"},[A(" API keys are stored encrypted in the application database (admin-only access). For stricter setups, use the "),s("code",{class:"font-mono text-xs"},"PIWI_AI_*"),A(" environment variables instead of the UI. ")])],-1)])]),_:1})])}}});export{ps as default};
1
+ import{_ as Ee,a as Re}from"./BRMeEHXd.js";import{d as H,K as le,a as se,o as l,e as w,f as c,g as s,h as r,I as G,x as W,b as o,c as p,_ as ne,F as U,z as F,i as ie,k as A,t as P,l as x,L as X,r as R,v as D,M as $e,j as re,w as ae,q as Oe,ac as Le,J as z}from"./1QWBzxLM.js";import{_ as Be}from"./B82vqOZe.js";import{_ as me}from"./CapSEET7.js";import{_ as fe}from"./e-GZmCeP.js";import{_ as ve}from"./B4lvHjBe.js";import{_ as ge}from"./B2bxEmbR.js";import{_ as Fe}from"./CtQMagSz.js";import{h as We}from"./CHz7LJIX.js";import{_ as ye}from"./bmAf49LT.js";import{_ as Ne}from"./Bc6Zr-Xn.js";import{u as oe}from"./CU_2YLhT.js";import{_ as De}from"./DoDo3VF2.js";import{p as Xe,g as qe}from"./CXkXHtcx.js";import"./B-1zt4pp.js";import"./Bl0xzETD.js";import"./DpM8IgHL.js";import"./DBXXb0w8.js";import"./Bp1WeQ0_.js";import"./BnUQ3i5l.js";import"./AbnDY6Zr.js";import"./D4mPjHHR.js";const Ke={class:"space-y-3"},je={key:0,class:"flex items-center justify-center gap-2 py-8 text-gray-400"},ze={key:1,class:"py-8 text-center text-sm text-gray-400"},He={key:2,class:"max-h-96 overflow-y-auto space-y-px"},Ge=["onClick"],Qe={class:"flex-1 min-w-0"},Ye={class:"text-sm font-medium leading-snug truncate"},Ze={key:0,class:"text-gray-500 font-normal"},Je={class:"text-xs text-gray-400 leading-snug mt-0.5"},et={key:3,class:"italic text-gray-500"},tt={key:0,class:"flex items-center gap-1 shrink-0 pt-0.5"},st=["title"],at=["title"],ot={key:0,class:"py-8 text-center text-sm text-gray-400"},lt=H({__name:"ModelPickerModal",props:X({models:{},selected:{},loading:{type:Boolean}},{open:{type:Boolean,required:!0},openModifiers:{}}),emits:X(["select"],["update:open"]),setup(a,{emit:M}){function C(y){return y?y>=1e6?`${(y/1e6).toFixed(1)}M`:y>=1e3?`${Math.round(y/1e3)}K`:String(y):""}const v=a,i=M,I=le(a,"open"),_=R(null),d=R("");se(I,y=>{y&&$e(()=>_.value?.focus())});const n=D(()=>{const y=d.value.toLowerCase();return y?v.models.filter(h=>h.id.toLowerCase().includes(y)||(h.label?.toLowerCase()??"").includes(y)):v.models}),k={image:{icon:"i-lucide-image",label:"Image input"},pdf:{icon:"i-lucide-file-text",label:"PDF input"},code:{icon:"i-lucide-code",label:"Code execution"},thinking:{icon:"i-lucide-brain",label:"Extended thinking"},json:{icon:"i-lucide-braces",label:"Structured output"},text:{icon:"i-lucide-type",label:"Text"},audio:{icon:"i-lucide-music",label:"Audio"}};function V(y){return y.map(h=>{const g=h.indexOf("→");if(g!==-1){const E=h.slice(0,g),O=h.slice(g+1);return{inputs:E.split("+").filter(Boolean),outputs:O.split("+").filter(Boolean)}}return{inputs:[h],outputs:[]}})}function $(y){i("select",y),I.value=!1,d.value=""}return(y,h)=>{const g=G,E=ne,O=Fe;return l(),w(O,{open:I.value,"onUpdate:open":h[1]||(h[1]=f=>I.value=f),title:"Select a model",ui:{content:"max-w-2xl"}},{body:c(()=>[s("div",Ke,[r(g,{ref_key:"searchInput",ref:_,modelValue:o(d),"onUpdate:modelValue":h[0]||(h[0]=f=>W(d)?d.value=f:null),placeholder:"Search models…",icon:"i-lucide-search",size:"sm"},null,8,["modelValue"]),a.models.length===0&&a.loading?(l(),p("div",je,[r(E,{name:"i-lucide-loader-2",class:"size-4 animate-spin"}),h[2]||(h[2]=s("span",{class:"text-sm"},"Loading models…",-1))])):a.models.length===0?(l(),p("div",ze," No models available — check your provider configuration ")):(l(),p("div",He,[(l(!0),p(U,null,F(o(n),f=>(l(),p("button",{key:f.id,class:ie(["w-full text-left px-4 py-3 rounded-lg hover:bg-elevated transition-colors border border-transparent hover:border-default flex items-start gap-4",a.selected===f.id?"bg-primary/10 ring-1 ring-inset ring-primary/30 border-primary/30":""]),onClick:b=>$(f.id)},[s("div",Qe,[s("p",Ye,[A(P(f.id)+" ",1),f.label&&f.label!==f.id?(l(),p("span",Ze," — "+P(f.label),1)):x("",!0)]),s("p",Je,[f.contextLength?(l(),p(U,{key:0},[A(P(C(f.contextLength))+" ctx",1)],64)):x("",!0),f.maxTokens?(l(),p(U,{key:1},[A(" · up to "+P(C(f.maxTokens))+" out",1)],64)):x("",!0),f.pricing?.prompt?(l(),p(U,{key:2},[A(" · $"+P(f.pricing.prompt)+" / $"+P(f.pricing.completion??"?")+" per 1M",1)],64)):x("",!0),!f.contextLength&&!f.maxTokens&&!f.pricing?.prompt?(l(),p("span",et,"No additional info")):x("",!0)])]),f.modalities?.length?(l(),p("div",tt,[(l(!0),p(U,null,F(V(f.modalities),b=>(l(),p(U,{key:b.inputs.join()+"→"+b.outputs.join()},[(l(!0),p(U,null,F(b.inputs,T=>(l(),p("span",{key:"in-"+T,title:k[T]?.label??T,class:"inline-flex items-center justify-center size-6 rounded-md bg-gray-100 dark:bg-gray-800 text-gray-500 hover:text-primary transition-colors"},[r(E,{name:k[T]?.icon??"i-lucide-cpu",class:"size-3.5"},null,8,["name"])],8,st))),128)),b.outputs.length?(l(),w(E,{key:0,name:"i-lucide-arrow-right",class:"size-3 text-gray-400 shrink-0"})):x("",!0),(l(!0),p(U,null,F(b.outputs,T=>(l(),p("span",{key:"out-"+T,title:k[T]?.label??T,class:"inline-flex items-center justify-center size-6 rounded-md bg-gray-100 dark:bg-gray-800 text-gray-500 hover:text-primary transition-colors"},[r(E,{name:k[T]?.icon??"i-lucide-cpu",class:"size-3.5"},null,8,["name"])],8,at))),128))],64))),128))])):x("",!0)],10,Ge))),128)),o(n).length===0?(l(),p("div",ot,' No models match "'+P(o(d))+'" ',1)):x("",!0)]))])]),_:1},8,["open"])}}}),nt=Object.assign(lt,{__name:"ModelPickerModal"}),it={class:"flex gap-2"},rt=H({__name:"ModelFieldInput",props:X({provider:{},providerResolved:{},reuse:{type:Boolean},models:{},loadingModels:{type:Boolean},placeholderAnthropic:{},placeholderOpenai:{}},{modelValue:{required:!0},modelModifiers:{}}),emits:X(["loadModels"],["update:modelValue"]),setup(a,{emit:M}){const C=M,v=le(a,"modelValue"),i=R(!1);return(I,_)=>{const d=G,n=re,k=nt;return l(),p(U,null,[s("div",it,[r(d,{modelValue:v.value,"onUpdate:modelValue":_[0]||(_[0]=V=>v.value=V),placeholder:a.providerResolved==="anthropic"?a.placeholderAnthropic:a.placeholderOpenai,class:"flex-1"},null,8,["modelValue","placeholder"]),a.providerResolved?(l(),w(n,{key:0,size:"sm",variant:"soft",onClick:_[1]||(_[1]=V=>{C("loadModels"),i.value=!0})},{default:c(()=>[..._[4]||(_[4]=[A(" Choose model… ",-1)])]),_:1})):x("",!0)]),r(k,{open:o(i),"onUpdate:open":_[2]||(_[2]=V=>W(i)?i.value=V:null),models:a.models,selected:v.value,loading:a.loadingModels,onSelect:_[3]||(_[3]=V=>v.value=V)},null,8,["open","models","selected","loading"])],64)}}}),dt=Object.assign(rt,{__name:"ModelFieldInput"}),ct={class:"flex items-start justify-between gap-3"},ut={class:"flex items-start gap-2"},pt={class:"font-medium inline-flex items-center gap-1"},mt={class:"text-sm text-gray-500"},ft={class:"inline-flex items-center gap-1"},vt={class:"inline-flex items-center gap-1"},gt={class:"inline-flex items-center gap-1"},yt={key:3,class:"flex justify-end"},ht=H({__name:"AiRoleConfigForm",props:X({meta:{},hasApiKey:{type:Boolean},reuseOptions:{},providerOptions:{},presetOptions:{},disabled:{type:Boolean},envManaged:{type:Boolean},models:{},loadingModels:{type:Boolean},providerResolved:{},testing:{type:Boolean}},{modelValue:{required:!0},modelModifiers:{}}),emits:X(["applyPreset","loadModels","test"],["update:modelValue"]),setup(a,{emit:M}){const C=a,v=M,i=le(a,"modelValue"),I=D({get:()=>i.value.reuse??"own",set:d=>i.value.reuse=d==="own"?null:d}),_=D(()=>We(C.meta.help));return(d,n)=>{const k=ne,V=Be,$=me,y=fe,h=ve,g=ge,E=G,O=dt,f=re;return l(),p("div",{class:ie(["rounded-lg border border-default p-4 space-y-4",a.meta.optional&&!i.value.enabled?"opacity-80":""])},[s("div",ct,[s("div",ut,[r(k,{name:a.meta.icon,class:"size-5 mt-0.5 text-primary"},null,8,["name"]),s("div",null,[s("p",pt,[A(P(a.meta.title)+" ",1),r(V,{topic:a.meta.help},null,8,["topic"])]),s("p",mt,P(a.meta.blurb),1)])]),a.meta.optional?(l(),w($,{key:0,modelValue:i.value.enabled,"onUpdate:modelValue":n[0]||(n[0]=b=>i.value.enabled=b),disabled:a.disabled&&!a.envManaged,"aria-label":a.meta.enableLabel},null,8,["modelValue","disabled","aria-label"])):x("",!0)]),!a.meta.optional||i.value.enabled?(l(),p(U,{key:0},[a.meta.reuseTargets.length?(l(),w(h,{key:0,label:"Provider source"},{default:c(()=>[r(y,{modelValue:o(I),"onUpdate:modelValue":n[1]||(n[1]=b=>W(I)?I.value=b:null),items:a.reuseOptions,disabled:a.disabled&&!a.envManaged,class:"w-full"},null,8,["modelValue","items","disabled"])]),_:1})):x("",!0),i.value.reuse?x("",!0):(l(),p(U,{key:1},[r(h,{label:"Provider"},{label:c(()=>[s("span",ft,[n[9]||(n[9]=A(" Provider ",-1)),a.disabled?(l(),w(g,{key:0,"env-vars":o(_)},null,8,["env-vars"])):x("",!0)])]),default:c(()=>[r(y,{modelValue:i.value.provider,"onUpdate:modelValue":n[2]||(n[2]=b=>i.value.provider=b),items:a.providerOptions,disabled:a.disabled,placeholder:"Choose a provider…",class:"w-full"},null,8,["modelValue","items","disabled"])]),_:1}),i.value.provider==="openai"?(l(),w(h,{key:0,label:"Preset",description:"Pick a known provider to auto-fill the URL and model, then adjust as needed"},{default:c(()=>[r(y,{items:a.presetOptions,placeholder:"Choose a preset…",disabled:a.disabled,class:"w-full","onUpdate:modelValue":n[3]||(n[3]=b=>v("applyPreset",b))},null,8,["items","disabled"])]),_:1})):x("",!0),i.value.provider?(l(),w(h,{key:1,label:"API key",description:a.hasApiKey?"Leave empty to keep the stored key, clear and save to remove it":"Required for Anthropic; optional for local OpenAI-compatible servers"},{label:c(()=>[s("span",vt,[n[10]||(n[10]=A(" API key ",-1)),a.disabled?(l(),w(g,{key:0,"env-vars":o(_)},null,8,["env-vars"])):x("",!0)])]),default:c(()=>[r(E,{modelValue:i.value.apiKey,"onUpdate:modelValue":n[4]||(n[4]=b=>i.value.apiKey=b),type:"password",placeholder:a.hasApiKey?"•••••••• (unchanged)":"sk-…",disabled:a.disabled,class:"w-full font-mono"},null,8,["modelValue","placeholder","disabled"])]),_:1},8,["description"])):x("",!0),i.value.provider==="openai"?(l(),w(h,{key:2,label:"Base URL",description:"Required, e.g. http://localhost:11434/v1"},{label:c(()=>[s("span",gt,[n[11]||(n[11]=A(" Base URL ",-1)),a.disabled?(l(),w(g,{key:0,"env-vars":o(_)},null,8,["env-vars"])):x("",!0)])]),default:c(()=>[r(E,{modelValue:i.value.baseUrl,"onUpdate:modelValue":n[5]||(n[5]=b=>i.value.baseUrl=b),placeholder:"http://localhost:11434/v1",disabled:a.disabled,class:"w-full"},null,8,["modelValue","disabled"])]),_:1})):x("",!0)],64)),i.value.reuse||i.value.provider?(l(),w(h,{key:2,label:"Model",description:i.value.reuse?"Leave empty to use the reused role's model":void 0},{default:c(()=>[r(O,{modelValue:i.value.model,"onUpdate:modelValue":n[6]||(n[6]=b=>i.value.model=b),provider:i.value.provider,"provider-resolved":a.providerResolved,reuse:!!i.value.reuse,models:a.models,"loading-models":a.loadingModels,"placeholder-anthropic":a.meta.modelPlaceholderAnthropic,"placeholder-openai":a.meta.modelPlaceholderOpenai,onLoadModels:n[7]||(n[7]=b=>v("loadModels"))},null,8,["modelValue","provider","provider-resolved","reuse","models","loading-models","placeholder-anthropic","placeholder-openai"])]),_:1},8,["description"])):x("",!0),a.providerResolved?(l(),p("div",yt,[r(f,{size:"xs",color:"neutral",variant:"soft",icon:"i-lucide-plug",loading:a.testing,onClick:n[8]||(n[8]=b=>v("test"))},{default:c(()=>[...n[12]||(n[12]=[A(" Test connection ",-1)])]),_:1},8,["loading"])])):x("",!0)],64)):x("",!0)],2)}}}),bt=Object.assign(ht,{__name:"AiRoleConfigForm"}),_t={key:0,class:"space-y-3"},xt={class:"text-sm text-gray-500"},kt={key:0,class:"text-sm text-gray-500"},It={key:1,class:"overflow-x-auto"},At={class:"w-full text-sm"},Mt={class:"px-2 py-2"},St={class:"font-mono text-xs"},Vt={class:"text-xs text-gray-400"},Pt={class:"text-right px-2 py-2"},Tt=["title"],wt=["title"],Ct={class:"text-right px-2 py-2"},Ut={key:1,class:"flex items-center gap-2 py-4 text-muted"},Et=H({__name:"AiUsagePanel",async setup(a){let M,C;const v=R(30),i=[{label:"Last 7 days",value:7},{label:"Last 30 days",value:30},{label:"Last 90 days",value:90}],{data:I,pending:_}=([M,C]=ae(()=>oe("/api/settings/ai/usage",{query:{days:v}},"$Q4bVv0_V0W")),M=await M,C(),M);function d(n){return n>=1e6?`${(n/1e6).toFixed(1)}M`:n>=1e3?`${(n/1e3).toFixed(1)}k`:String(n)}return(n,k)=>{const V=fe,$=Ne,y=ne,h=ye;return l(),w(h,{icon:"i-lucide-activity",title:"AI usage"},{actions:c(()=>[r(V,{modelValue:o(v),"onUpdate:modelValue":k[0]||(k[0]=g=>W(v)?v.value=g:null),items:i,size:"sm",class:"w-36"},null,8,["modelValue"])]),default:c(()=>[o(I)?(l(),p("div",_t,[s("p",xt,P(d(o(I).totals.diagnoses))+" diagnoses · "+P(d(o(I).totals.inputTokens))+" input tokens · "+P(d(o(I).totals.outputTokens))+" output tokens ",1),o(I).byModel.length===0?(l(),p("p",kt,"No AI calls recorded in this period.")):(l(),p("div",It,[s("table",At,[k[1]||(k[1]=s("thead",null,[s("tr",{class:"text-xs text-gray-500 uppercase tracking-wider border-b border-default"},[s("th",{class:"text-left px-2 py-2 font-medium"},"Model"),s("th",{class:"text-right px-2 py-2 font-medium"},"Diagnoses"),s("th",{class:"text-right px-2 py-2 font-medium"},"Failed"),s("th",{class:"text-right px-2 py-2 font-medium"},"Input tokens"),s("th",{class:"text-right px-2 py-2 font-medium"},"Output tokens"),s("th",{class:"text-right px-2 py-2 font-medium"},"Avg duration")])],-1)),s("tbody",null,[(l(!0),p(U,null,F(o(I).byModel,g=>(l(),p("tr",{key:`${g.provider??"unknown"}/${g.model}`,class:"border-b last:border-b-0 border-default"},[s("td",Mt,[s("span",St,P(g.model),1),s("span",Vt," · "+P(g.provider??"unknown"),1)]),s("td",Pt,P(g.diagnoses),1),s("td",{class:ie(["text-right px-2 py-2",g.failed>0?"text-red-600 dark:text-red-400":""])},P(g.failed),3),s("td",{class:"text-right px-2 py-2",title:g.inputTokens.toLocaleString()},P(d(g.inputTokens)),9,Tt),s("td",{class:"text-right px-2 py-2",title:g.outputTokens.toLocaleString()},P(d(g.outputTokens)),9,wt),s("td",Ct,[r($,{ms:g.avgDurationMs},null,8,["ms"])])]))),128))])])]))])):o(_)?(l(),p("div",Ut,[r(y,{name:"i-lucide-loader-circle",class:"size-4 animate-spin"}),k[2]||(k[2]=s("span",{class:"text-sm"},"Loading usage…",-1))])):x("",!0)]),_:1})}}}),Rt=Object.assign(Et,{__name:"AiUsagePanel"}),$t=[{key:"sampleErrorChars",label:"Error text characters",envVar:"PIWI_AI_MAX_SAMPLE_ERROR_CHARS",description:"Max characters of raw error text (per error block).",min:200,max:5e4},{key:"scmPatchBudget",label:"SCM patch budget",envVar:"PIWI_AI_MAX_SCM_PATCH_BUDGET",description:"Total characters of diff patches across changed files.",min:0,max:5e4},{key:"affectedTests",label:"Affected tests",envVar:"PIWI_AI_MAX_AFFECTED_TESTS",description:"Max affected tests listed.",min:1,max:200},{key:"steps",label:"Test steps",envVar:"PIWI_AI_MAX_STEPS",description:"Max recent test steps included.",min:1,max:200},{key:"consoleEntries",label:"Console entries",envVar:"PIWI_AI_MAX_CONSOLE_ENTRIES",description:"Max console error/warning entries included.",min:0,max:200},{key:"consoleEntryChars",label:"Console entry characters",envVar:"PIWI_AI_MAX_CONSOLE_ENTRY_CHARS",description:"Max characters per console entry.",min:50,max:5e3},{key:"networkRequests",label:"Network requests",envVar:"PIWI_AI_MAX_NETWORK_REQUESTS",description:"Max failed network requests included.",min:0,max:200},{key:"ariaSnapshotChars",label:"ARIA snapshot characters",envVar:"PIWI_AI_MAX_ARIA_SNAPSHOT_CHARS",description:"Max characters of the page ARIA snapshot.",min:0,max:5e4},{key:"testSourceChars",label:"Test source characters",envVar:"PIWI_AI_MAX_TEST_SOURCE_CHARS",description:"Max characters of the test source snippet.",min:0,max:5e4},{key:"maxSourceFiles",label:"Full source files",envVar:"PIWI_AI_MAX_SOURCE_FILES",description:"Max full source files fetched from SCM to ground patches (0 disables).",min:0,max:20},{key:"sourceFileChars",label:"Source file characters",envVar:"PIWI_AI_MAX_SOURCE_FILE_CHARS",description:"Max characters per fetched full source file.",min:0,max:5e4},{key:"serverLogEntries",label:"Server log entries",envVar:"PIWI_AI_MAX_SERVER_LOG_ENTRIES",description:"Max backend server log entries (from X-Piwi-Logs header) included.",min:0,max:200},{key:"serverLogEntryChars",label:"Server log entry characters",envVar:"PIWI_AI_MAX_SERVER_LOG_ENTRY_CHARS",description:"Max characters per backend server log entry.",min:50,max:5e3},{key:"serverTraceSpans",label:"Server trace spans",envVar:"PIWI_AI_MAX_SERVER_TRACE_SPANS",description:"Max backend server spans (from X-Piwi-Trace header) included (0 disables).",min:0,max:500},{key:"maxImages",label:"Max screenshots",envVar:"PIWI_AI_MAX_IMAGES",description:"Max screenshots auto-included in the diagnosis context.",min:0,max:20},{key:"maxPassedPeers",label:"Max passed peers",envVar:"PIWI_AI_MAX_PASSED_PEERS",description:"Max peer tests in the same file listed when they passed.",min:0,max:100},{key:"maxConsoleWindow",label:"Console window entries",envVar:"PIWI_AI_MAX_CONSOLE_WINDOW",description:"Max console entries of any type in the window before failure.",min:0,max:200},{key:"slowRequestMs",label:"Slow request threshold (ms)",envVar:"PIWI_AI_SLOW_REQUEST_MS",description:"Network request duration threshold for flagging as slow.",min:100,max:3e4},{key:"maxTraceActions",label:"Trace actions",envVar:"PIWI_AI_MAX_TRACE_ACTIONS",description:"Max actions extracted from trace ZIP for failing-action context (0 disables).",min:0,max:50},{key:"traceDomChars",label:"Trace DOM excerpt characters",envVar:"PIWI_AI_TRACE_DOM_CHARS",description:"Max characters for the trace-derived DOM/ARIA excerpt in failing-action context.",min:0,max:2e4},{key:"traceStackFrames",label:"Trace stack frames",envVar:"PIWI_AI_MAX_TRACE_STACK_FRAMES",description:"Max call-stack frames (with source windows) from the trace (0 disables).",min:0,max:50},{key:"traceNetworkRequests",label:"Trace network requests",envVar:"PIWI_AI_MAX_TRACE_NETWORK_REQUESTS",description:"Max requests from the trace network stream (0 disables).",min:0,max:200},{key:"domSnapshotChars",label:"DOM snapshot characters",envVar:"PIWI_AI_MAX_DOM_SNAPSHOT_CHARS",description:"Max characters of the failure-time DOM snapshot rendered from the trace (0 disables).",min:0,max:5e4},{key:"imageMaxEdge",label:"Screenshot max edge (px)",envVar:"PIWI_AI_IMAGE_MAX_EDGE",description:"Screenshots are downscaled to at most this many pixels on the long edge before being sent.",min:512,max:8192},{key:"aiStepIntents",label:"AI-step intents",envVar:"PIWI_AI_MAX_STEP_INTENTS",description:"Max AI-step intent mappings (prompt → compiled locator) included (0 disables the section).",min:0,max:100}],Ot={class:"space-y-6"},Lt={class:"space-y-5"},Bt={class:"flex items-center gap-3"},Ft={class:"flex items-center gap-2 justify-end"},Wt={class:"flex justify-end"},Nt={class:"flex justify-end"},Dt={class:"grid grid-cols-1 sm:grid-cols-2 gap-x-4 gap-y-3"},Xt={class:"flex justify-end gap-2"},ps=H({__name:"ai",async setup(a){let M,C;const v=Oe(),{data:i,refresh:I}=([M,C]=ae(()=>oe("/api/settings/ai","$5FSQHzGDZ4")),M=await M,C(),M);function _(){return{enabled:!1,reuse:null,provider:"",model:"",baseUrl:"",apiKey:""}}const d=z({diagnosis:_(),research:_(),embedding:_()}),n=R(!1),k=R(""),V=R(""),$=R(!1),y=R(!1),h=R(!1),g=z({diagnosis:!1,research:!1,embedding:!1}),E=z({diagnosis:[],research:[],embedding:[]}),O=z({diagnosis:!1,research:!1,embedding:!1});function f(t){const e=d[t];return e.reuse?d[e.reuse]?.provider||"":e.provider}async function b(t){const e=d[t],m=f(t),S=e.reuse?d[e.reuse]:e,ee=S.apiKey||void 0;O[t]=!0;try{const te=await $fetch("/api/settings/ai/models",{method:"POST",body:{role:t,provider:m,baseUrl:S.baseUrl||void 0,apiKey:ee}});E[t]=te.models}catch{E[t]=[]}finally{O[t]=!1}}const T=[{key:"diagnosis",title:"Diagnosis model",icon:"i-lucide-stethoscope",help:"settings.ai-provider",optional:!1,enableLabel:"",blurb:"The main model that writes the final diagnosis. Required to enable AI features.",reuseTargets:[],modelPlaceholderAnthropic:"claude-opus-4-8",modelPlaceholderOpenai:"e.g. gpt-4o, llama3.1"},{key:"research",title:"Research model",icon:"i-lucide-search",help:"settings.ai-research",optional:!0,enableLabel:"Two-stage diagnosis",blurb:"A cheaper/faster model that pre-analyzes the failure before the diagnosis model writes the final answer. Also used for cluster naming and merge adjudication.",reuseTargets:["diagnosis"],modelPlaceholderAnthropic:"e.g. claude-haiku-4-5",modelPlaceholderOpenai:"e.g. llama-3.1-8b-instant"},{key:"embedding",title:"Embedding model",icon:"i-lucide-vector-square",help:"settings.embedding-model",optional:!0,enableLabel:"Semantic clustering",blurb:"Embeds failures so semantically-similar errors group together (used by failure clustering).",reuseTargets:["diagnosis","research"],modelPlaceholderAnthropic:"— Anthropic has no embeddings API —",modelPlaceholderOpenai:"e.g. text-embedding-3-small"}],de=[{label:"Anthropic API",value:"anthropic"},{label:"OpenAI-compatible",value:"openai"}],he=de.filter(t=>t.value!=="anthropic"),be=D(()=>{const t={};for(const e of T)t[e.key]=[{label:"Configure its own provider",value:"own"},...e.reuseTargets.filter(m=>d[m].enabled||m==="diagnosis").filter(m=>e.key!=="embedding"||d[m].provider==="openai").map(m=>({label:`Reuse ${T.find(S=>S.key===m).title.toLowerCase()}`,value:m}))];return t}),N=D(()=>!!i.value?.envManaged),_e=Xe(qe("ai"));se(i,t=>{if(t){for(const e of T){const m=t.roles[e.key],S=d[e.key];S.enabled=!!m,S.reuse=m?.reuse??null,S.provider=m?.provider??"",S.model=m?.model??"",S.baseUrl=m?.baseUrl??"",S.apiKey=""}n.value=t.autoDiagnose,k.value=t.customInstructions||""}},{immediate:!0});function xe(t){return!!i.value?.roles[t]?.hasApiKey}const ce=[{label:"ollama (local)",baseUrl:"http://localhost:11434/v1",model:"llama3.1"},{label:"LM Studio (local)",baseUrl:"http://localhost:1234/v1",model:""},{label:"OpenRouter",baseUrl:"https://openrouter.ai/api/v1",model:"meta-llama/llama-3.1-8b-instruct"},{label:"Groq",baseUrl:"https://api.groq.com/openai/v1",model:"llama-3.1-8b-instant"},{label:"OpenAI",baseUrl:"https://api.openai.com/v1",model:"gpt-4o"},{label:"Mistral AI",baseUrl:"https://api.mistral.ai/v1",model:"mistral-small-latest"},{label:"Custom",baseUrl:"",model:""}],ke=ce.map(t=>({label:t.label,value:t.label}));function Ie(t,e){const m=ce.find(S=>S.label===e);!m||m.label==="Custom"||(d[t].baseUrl=m.baseUrl,d[t].model=m.model)}function Q(t){const e=d[t];if(!e.enabled)return null;if(e.reuse)return{reuse:e.reuse,model:e.model||void 0};const m={provider:e.provider,model:e.model||void 0,baseUrl:e.baseUrl||void 0};return e.apiKey!==""&&(m.apiKey=e.apiKey),m}async function Ae(){$.value=!0;try{!N&&(!d.diagnosis.enabled||!d.diagnosis.provider)?await $fetch("/api/settings/ai",{method:"PUT",body:{roles:null,autoDiagnose:n.value}}):await $fetch("/api/settings/ai",{method:"PUT",body:{roles:{diagnosis:Q("diagnosis"),research:Q("research"),embedding:Q("embedding")},autoDiagnose:n.value}}),await I();for(const t of T)d[t.key].apiKey="";v.add({title:"Settings saved",color:"success"})}catch(t){v.add({title:"Save failed",description:String(t?.message??t),color:"error"})}finally{$.value=!1}}async function Me(){h.value=!0;try{await $fetch("/api/settings/ai",{method:"PUT",body:{scmToken:V.value||null}}),await I(),V.value="",v.add({title:"SCM token saved",color:"success"})}catch(t){v.add({title:"Save failed",description:String(t?.message??t),color:"error"})}finally{h.value=!1}}async function Se(){y.value=!0;try{await $fetch("/api/settings/ai",{method:"PUT",body:{customInstructions:k.value||null}}),await I(),v.add({title:"Instructions saved",color:"success"})}catch(t){v.add({title:"Save failed",description:String(t?.message??t),color:"error"})}finally{y.value=!1}}async function Ve(t){g[t]=!0;try{const e=d[t],m=e.reuse?d[e.reuse]:e,S=await $fetch("/api/settings/ai/test",{method:"POST",body:{role:t,provider:m.provider||void 0,apiKey:m.apiKey||void 0,model:e.model||(e.reuse?m.model:"")||void 0,baseUrl:m.baseUrl||void 0}});S.success?v.add({title:"Connection successful",description:`Model: ${S.model}`,color:"success"}):v.add({title:"Connection failed",description:S.error||"Unknown error",color:"error"})}catch(e){v.add({title:"Connection failed",description:String(e?.message??e),color:"error"})}finally{g[t]=!1}}const{data:L}=([M,C]=ae(()=>oe("/api/settings/ai/limits","$qHhpP8mBYb")),M=await M,C(),M),Y=$t,q=z({}),Z=R(!1),J=D(()=>new Set(L.value?.envManaged??[]));se(L,t=>{if(t)for(const e of Y)q[e.key]=t.limits[e.key]},{immediate:!0});async function Pe(){Z.value=!0;try{L.value=await $fetch("/api/settings/ai/limits",{method:"PUT",body:{limits:q}}),v.add({title:"Context limits saved",color:"success"})}catch(t){v.add({title:"Failed to save context limits",description:String(t?.message??t),color:"error"})}finally{Z.value=!1}}function Te(){if(L.value)for(const t of Y)J.value.has(t.key)||(q[t.key]=L.value.defaults[t.key])}return(t,e)=>{const m=Ee,S=bt,ee=me,te=Re,K=re,j=ye,we=Rt,ue=G,pe=ve,Ce=De,Ue=ge;return l(),p("div",Ot,[o(N)?(l(),w(m,{key:0,"env-vars":o(_e)},null,8,["env-vars"])):x("",!0),r(j,{icon:"i-lucide-sparkles",title:"Model providers",help:"settings.ai-provider"},{subtitle:c(()=>[...e[3]||(e[3]=[A(" Configure a complete provider for each model role. Optional roles can reuse another role's provider so you don't re-enter credentials. ",-1)])]),footer:c(()=>[s("div",Ft,[r(K,{color:"primary",loading:o($),icon:"i-lucide-save",onClick:Ae},{default:c(()=>[...e[5]||(e[5]=[A(" Save ",-1)])]),_:1},8,["loading"])])]),default:c(()=>[s("div",Lt,[(l(),p(U,null,F(T,u=>r(S,{key:u.key,modelValue:o(d)[u.key],"onUpdate:modelValue":B=>o(d)[u.key]=B,meta:u,"has-api-key":xe(u.key),"reuse-options":o(be)[u.key],"provider-options":u.key==="embedding"?o(he):de,"preset-options":o(ke),disabled:o(N),"env-managed":o(N),"provider-resolved":f(u.key),models:o(E)[u.key],"loading-models":o(O)[u.key],testing:o(g)[u.key],onApplyPreset:B=>Ie(u.key,B),onLoadModels:B=>b(u.key),onTest:B=>Ve(u.key)},null,8,["modelValue","onUpdate:modelValue","meta","has-api-key","reuse-options","provider-options","preset-options","disabled","env-managed","provider-resolved","models","loading-models","testing","onApplyPreset","onLoadModels","onTest"])),64)),r(te,{label:"Auto-diagnose",help:"settings.auto-diagnose","env-managed":o(N)},{default:c(()=>[s("div",Bt,[r(ee,{modelValue:o(n),"onUpdate:modelValue":e[0]||(e[0]=u=>W(n)?n.value=u:null),disabled:o(N)||!o(d).diagnosis.enabled},null,8,["modelValue","disabled"]),e[4]||(e[4]=s("span",{class:"text-sm text-gray-500"}," Automatically diagnose new failure clusters when a run finishes — up to 3 clusters per run (research + diagnosis call each), plus one batched call to title new clusters ",-1))])]),_:1},8,["env-managed"])])]),_:1}),r(we),r(j,{title:"Repository access",help:"project.scm-token"},{subtitle:c(()=>[...e[6]||(e[6]=[A(" Optional — required for private repositories. Per-project tokens override this. ",-1)])]),footer:c(()=>[s("div",Wt,[r(K,{color:"primary",loading:o(h),icon:"i-lucide-save",onClick:Me},{default:c(()=>[...e[7]||(e[7]=[A(" Save token ",-1)])]),_:1},8,["loading"])])]),default:c(()=>[r(pe,{label:"SCM token",description:o(i)?.hasScmToken?"Leave empty to keep the stored token, enter a new value to replace it, or save empty to remove it":"Personal access token with read access to repository contents. Supports GitHub (ghp_), GitLab (glpat-), and Bitbucket tokens."},{default:c(()=>[r(ue,{modelValue:o(V),"onUpdate:modelValue":e[1]||(e[1]=u=>W(V)?V.value=u:null),type:"password",placeholder:o(i)?.hasScmToken?"•••••••• (unchanged)":"ghp_..., glpat-..., or Bitbucket token",class:"w-full font-mono"},null,8,["modelValue","placeholder"])]),_:1},8,["description"])]),_:1}),r(j,{title:"Global analysis instructions",help:"settings.ai-instructions"},{footer:c(()=>[s("div",Nt,[r(K,{color:"primary",loading:o(y),icon:"i-lucide-save",onClick:Se},{default:c(()=>[...e[8]||(e[8]=[A(" Save instructions ",-1)])]),_:1},8,["loading"])])]),default:c(()=>[r(Ce,{modelValue:o(k),"onUpdate:modelValue":e[2]||(e[2]=u=>W(k)?k.value=u:null),rows:6,placeholder:"e.g. Always suggest running failing tests with --repeat-each 5 to confirm flakiness. Prefer network-level evidence over ARIA snapshots. Recommend git bisect when a commit range is available.",class:"w-full font-mono text-sm"},null,8,["modelValue"]),e[9]||(e[9]=s("p",{class:"text-xs text-gray-400 mt-2"}," These instructions are appended to the base system prompt. They shape how the AI analyzes failures but cannot override the response schema or confidence requirement. ",-1))]),_:1}),r(j,{title:"Diagnosis context limits",help:"settings.ai-limits"},{subtitle:c(()=>[...e[10]||(e[10]=[A(" Leave a field empty to use its default; env-managed fields are read-only. ",-1)])]),footer:c(()=>[s("div",Xt,[r(K,{color:"neutral",variant:"ghost",size:"sm",onClick:Te},{default:c(()=>[...e[11]||(e[11]=[A("Reset to defaults",-1)])]),_:1}),r(K,{color:"primary",loading:o(Z),icon:"i-lucide-save",size:"sm",onClick:Pe},{default:c(()=>[...e[12]||(e[12]=[A(" Save limits ",-1)])]),_:1},8,["loading"])])]),default:c(()=>[s("div",Dt,[(l(!0),p(U,null,F(o(Y),u=>(l(),w(pe,{key:u.key,label:u.label,description:u.description,hint:`default ${o(L)?.defaults[u.key]??""}`},{default:c(()=>[r(ue,{modelValue:o(q)[u.key],"onUpdate:modelValue":B=>o(q)[u.key]=B,modelModifiers:{number:!0},type:"number",min:u.min,max:u.max,disabled:o(J).has(u.key),placeholder:`default ${o(L)?.defaults[u.key]??""}`,class:"w-full"},Le({_:2},[o(J).has(u.key)?{name:"trailing",fn:c(()=>[r(Ue,{"env-vars":[u.envVar]},null,8,["env-vars"])]),key:"0"}:void 0]),1032,["modelValue","onUpdate:modelValue","min","max","disabled","placeholder"])]),_:2},1032,["label","description","hint"]))),128))])]),_:1}),r(j,{icon:"i-lucide-shield-check",title:"Privacy notice",help:"settings.privacy"},{default:c(()=>[...e[13]||(e[13]=[s("div",{class:"space-y-2 text-sm text-gray-600 dark:text-gray-400"},[s("p",null,"When diagnosing a failure cluster, the following data is sent to the configured LLM provider:"),s("ul",{class:"list-disc list-inside space-y-1 ml-2"},[s("li",null,"Normalized error signature and sample raw error text"),s("li",null,"Test titles and file paths for affected tests"),s("li",null,"Browser info, test steps, console error/warning entries (excerpts)"),s("li",null,"Failed network request URLs and status codes"),s("li",null,"ARIA page snapshot (if collected)"),s("li",null," Commit SHA range since last passing run, plus changed file names and diff patches fetched from GitHub/GitLab/Bitbucket (if a repository token is configured or the repo is public) ")]),s("p",{class:"mt-2"},[A(" API keys are stored encrypted in the application database (admin-only access). For stricter setups, use the "),s("code",{class:"font-mono text-xs"},"PIWI_AI_*"),A(" environment variables instead of the UI. ")])],-1)])]),_:1})])}}});export{ps as default};
@@ -0,0 +1 @@
1
+ import{_ as p,a as u}from"./BuMX-4RF.js";import{_ as d,a as g}from"./BS91Og__.js";import{_ as h}from"./DMqAUHFN.js";import{_ as b}from"./BIlohx1E.js";import{C as v,r as x,d as w,s as $,e as B,f as n,o as M,g as N,h as t,aH as S,b as U}from"./1QWBzxLM.js";import{u as D}from"./gdlHFfN6.js";import"./CiCUZGFZ.js";import"./BTGAvMoT.js";import"./BnUQ3i5l.js";import"./CXkXHtcx.js";import"./CHz7LJIX.js";import"./CzyCEdYP.js";function k(){const s=x({account:!1,users:!1,notifications:!1,tags:!1,storage:!1,performance:!1,"pr-feedback":!1,"auto-heal":!1,ai:!1,about:!1});async function o(){const e=[];e.push($fetch("/api/settings/ai").then(a=>{s.value.ai=!!a.envManaged}).catch(()=>{})),e.push($fetch("/api/settings/wasted-waits").then(a=>{s.value.performance=!!a.envManaged}).catch(()=>{})),e.push($fetch("/api/settings/smtp").then(a=>{s.value.notifications=!!(a.envManaged&&a.configured)}).catch(()=>{})),await Promise.all(e)}return v(()=>{o()}),{envManaged:s,refresh:o}}const y={class:"flex flex-col gap-4 sm:gap-6 lg:gap-12 w-full lg:max-w-4xl mx-auto"},J=w({__name:"settings",setup(s){$({title:"Settings — Piwi Dashboard"});const{envManaged:o}=k(),e=D(o);return(a,C)=>{const i=p,c=u,r=g,l=h,m=b,_=S,f=d;return M(),B(f,{id:"settings",ui:{body:"lg:py-12"}},{header:n(()=>[t(r,null,{leading:n(()=>[t(i),t(c,{items:[{label:"Home",icon:"i-lucide-house",to:"/"},{label:"Settings"}]})]),_:1}),t(m,null,{default:n(()=>[t(l,{items:U(e),highlight:"",class:"-mx-1 flex-1",ui:{list:"overflow-x-auto",root:"min-w-0"}},null,8,["items"])]),_:1})]),body:n(()=>[N("div",y,[t(_)])]),_:1})}}});export{J as default};
@@ -1 +1 @@
1
- import{a2 as m,a3 as y,a5 as g,o as i,e as h,f as b,b as t,c as l,i as o,U as d,k as u,t as c,l as n,W as k,v as x,a8 as C}from"./BdQ7kfxJ.js";const q={slots:{root:"rounded-lg overflow-hidden",header:"p-4 sm:px-6",title:"text-highlighted font-semibold",description:"mt-1 text-muted text-sm",body:"p-4 sm:p-6",footer:"p-4 sm:px-6"},variants:{variant:{solid:{root:"bg-inverted text-inverted",title:"text-inverted",description:"text-dimmed"},outline:{root:"bg-default ring ring-default divide-y divide-default"},soft:{root:"bg-elevated/50 divide-y divide-default"},subtle:{root:"bg-elevated/50 ring ring-default divide-y divide-default"}}},defaultVariants:{variant:"outline"}},_={__name:"UCard",props:{as:{type:null,required:!1},title:{type:String,required:!1},description:{type:String,required:!1},variant:{type:null,required:!1},class:{type:null,required:!1},ui:{type:Object,required:!1}},setup(p){const v=p,s=m(),e=y("card",v),f=g(),a=x(()=>C({extend:q,...f.ui?.card||{}})({variant:e.variant}));return(r,S)=>(i(),h(t(k),{as:t(e).as,"data-slot":"root",class:o(a.value.root({class:[t(e).ui?.root,t(e).class]}))},{default:b(()=>[s.header||t(e).title||s.title||t(e).description||s.description?(i(),l("div",{key:0,"data-slot":"header",class:o(a.value.header({class:t(e).ui?.header}))},[d(r.$slots,"header",{},()=>[t(e).title||s.title?(i(),l("div",{key:0,"data-slot":"title",class:o(a.value.title({class:t(e).ui?.title}))},[d(r.$slots,"title",{},()=>[u(c(t(e).title),1)])],2)):n("",!0),t(e).description||s.description?(i(),l("div",{key:1,"data-slot":"description",class:o(a.value.description({class:t(e).ui?.description}))},[d(r.$slots,"description",{},()=>[u(c(t(e).description),1)])],2)):n("",!0)])],2)):n("",!0),s.default?(i(),l("div",{key:1,"data-slot":"body",class:o(a.value.body({class:t(e).ui?.body}))},[d(r.$slots,"default")],2)):n("",!0),s.footer?(i(),l("div",{key:2,"data-slot":"footer",class:o(a.value.footer({class:t(e).ui?.footer}))},[d(r.$slots,"footer")],2)):n("",!0)]),_:3},8,["as","class"]))}};export{_};
1
+ import{a2 as m,a3 as y,a5 as g,o as i,e as h,f as b,b as t,c as l,i as o,U as d,k as u,t as c,l as n,W as k,v as x,a8 as C}from"./1QWBzxLM.js";const q={slots:{root:"rounded-lg overflow-hidden",header:"p-4 sm:px-6",title:"text-highlighted font-semibold",description:"mt-1 text-muted text-sm",body:"p-4 sm:p-6",footer:"p-4 sm:px-6"},variants:{variant:{solid:{root:"bg-inverted text-inverted",title:"text-inverted",description:"text-dimmed"},outline:{root:"bg-default ring ring-default divide-y divide-default"},soft:{root:"bg-elevated/50 divide-y divide-default"},subtle:{root:"bg-elevated/50 ring ring-default divide-y divide-default"}}},defaultVariants:{variant:"outline"}},_={__name:"UCard",props:{as:{type:null,required:!1},title:{type:String,required:!1},description:{type:String,required:!1},variant:{type:null,required:!1},class:{type:null,required:!1},ui:{type:Object,required:!1}},setup(p){const v=p,s=m(),e=y("card",v),f=g(),a=x(()=>C({extend:q,...f.ui?.card||{}})({variant:e.variant}));return(r,S)=>(i(),h(t(k),{as:t(e).as,"data-slot":"root",class:o(a.value.root({class:[t(e).ui?.root,t(e).class]}))},{default:b(()=>[s.header||t(e).title||s.title||t(e).description||s.description?(i(),l("div",{key:0,"data-slot":"header",class:o(a.value.header({class:t(e).ui?.header}))},[d(r.$slots,"header",{},()=>[t(e).title||s.title?(i(),l("div",{key:0,"data-slot":"title",class:o(a.value.title({class:t(e).ui?.title}))},[d(r.$slots,"title",{},()=>[u(c(t(e).title),1)])],2)):n("",!0),t(e).description||s.description?(i(),l("div",{key:1,"data-slot":"description",class:o(a.value.description({class:t(e).ui?.description}))},[d(r.$slots,"description",{},()=>[u(c(t(e).description),1)])],2)):n("",!0)])],2)):n("",!0),s.default?(i(),l("div",{key:1,"data-slot":"body",class:o(a.value.body({class:t(e).ui?.body}))},[d(r.$slots,"default")],2)):n("",!0),s.footer?(i(),l("div",{key:2,"data-slot":"footer",class:o(a.value.footer({class:t(e).ui?.footer}))},[d(r.$slots,"footer")],2)):n("",!0)]),_:3},8,["as","class"]))}};export{_};
@@ -1 +1 @@
1
- import{a2 as $,a3 as S,a4 as C,a5 as V,o as a,e as l,f as j,U as c,b as r,aG as B,V as d,_ as A,i as s,l as o,g as N,c as u,k as m,t as x,F as b,z as w,j as p,W as O,v as P,a8 as F}from"./BdQ7kfxJ.js";const I={slots:{root:"relative overflow-hidden w-full rounded-lg p-4 flex gap-2.5",wrapper:"min-w-0 flex-1 flex flex-col",title:"text-sm font-medium",description:"text-sm opacity-90",icon:"shrink-0 size-5",avatar:"shrink-0",avatarSize:"2xl",actions:"flex flex-wrap gap-1.5 shrink-0",close:"p-0"},variants:{color:{primary:"",secondary:"",success:"",info:"",warning:"",error:"",neutral:""},variant:{solid:"",outline:"",soft:"",subtle:""},orientation:{horizontal:{root:"items-center",actions:"items-center"},vertical:{root:"items-start",actions:"items-start mt-2.5"}},title:{true:{description:"mt-1"}}},compoundVariants:[{color:"primary",variant:"solid",class:{root:"bg-primary text-inverted"}},{color:"secondary",variant:"solid",class:{root:"bg-secondary text-inverted"}},{color:"success",variant:"solid",class:{root:"bg-success text-inverted"}},{color:"info",variant:"solid",class:{root:"bg-info text-inverted"}},{color:"warning",variant:"solid",class:{root:"bg-warning text-inverted"}},{color:"error",variant:"solid",class:{root:"bg-error text-inverted"}},{color:"primary",variant:"outline",class:{root:"text-primary ring ring-inset ring-primary/25"}},{color:"secondary",variant:"outline",class:{root:"text-secondary ring ring-inset ring-secondary/25"}},{color:"success",variant:"outline",class:{root:"text-success ring ring-inset ring-success/25"}},{color:"info",variant:"outline",class:{root:"text-info ring ring-inset ring-info/25"}},{color:"warning",variant:"outline",class:{root:"text-warning ring ring-inset ring-warning/25"}},{color:"error",variant:"outline",class:{root:"text-error ring ring-inset ring-error/25"}},{color:"primary",variant:"soft",class:{root:"bg-primary/10 text-primary"}},{color:"secondary",variant:"soft",class:{root:"bg-secondary/10 text-secondary"}},{color:"success",variant:"soft",class:{root:"bg-success/10 text-success"}},{color:"info",variant:"soft",class:{root:"bg-info/10 text-info"}},{color:"warning",variant:"soft",class:{root:"bg-warning/10 text-warning"}},{color:"error",variant:"soft",class:{root:"bg-error/10 text-error"}},{color:"primary",variant:"subtle",class:{root:"bg-primary/10 text-primary ring ring-inset ring-primary/25"}},{color:"secondary",variant:"subtle",class:{root:"bg-secondary/10 text-secondary ring ring-inset ring-secondary/25"}},{color:"success",variant:"subtle",class:{root:"bg-success/10 text-success ring ring-inset ring-success/25"}},{color:"info",variant:"subtle",class:{root:"bg-info/10 text-info ring ring-inset ring-info/25"}},{color:"warning",variant:"subtle",class:{root:"bg-warning/10 text-warning ring ring-inset ring-warning/25"}},{color:"error",variant:"subtle",class:{root:"bg-error/10 text-error ring ring-inset ring-error/25"}},{color:"neutral",variant:"solid",class:{root:"text-inverted bg-inverted"}},{color:"neutral",variant:"outline",class:{root:"text-highlighted bg-default ring ring-inset ring-default"}},{color:"neutral",variant:"soft",class:{root:"text-highlighted bg-elevated/50"}},{color:"neutral",variant:"subtle",class:{root:"text-highlighted bg-elevated/50 ring ring-inset ring-accented"}}],defaultVariants:{color:"primary",variant:"solid"}},U={__name:"UAlert",props:{as:{type:null,required:!1},title:{type:String,required:!1},description:{type:String,required:!1},icon:{type:null,required:!1},avatar:{type:Object,required:!1},color:{type:null,required:!1},variant:{type:null,required:!1},orientation:{type:null,required:!1,default:"vertical"},actions:{type:Array,required:!1},close:{type:[Boolean,Object],required:!1},closeIcon:{type:null,required:!1},class:{type:null,required:!1},ui:{type:Object,required:!1}},emits:["update:open"],setup(h,{emit:k}){const z=h,q=k,i=$(),t=S("alert",z),{t:_}=C(),f=V(),e=P(()=>F({extend:I,...f.ui?.alert||{}})({color:t.color,variant:t.variant,orientation:t.orientation,title:!!t.title||!!i.title}));return(n,y)=>(a(),l(r(O),{as:r(t).as,"data-orientation":r(t).orientation,"data-slot":"root",class:s(e.value.root({class:[r(t).ui?.root,r(t).class]}))},{default:j(()=>[c(n.$slots,"leading",{ui:e.value},()=>[r(t).avatar?(a(),l(B,d({key:0,size:r(t).ui?.avatarSize||e.value.avatarSize()},r(t).avatar,{"data-slot":"avatar",class:e.value.avatar({class:r(t).ui?.avatar})}),null,16,["size","class"])):r(t).icon?(a(),l(A,{key:1,name:r(t).icon,"data-slot":"icon",class:s(e.value.icon({class:r(t).ui?.icon}))},null,8,["name","class"])):o("",!0)]),N("div",{"data-slot":"wrapper",class:s(e.value.wrapper({class:r(t).ui?.wrapper}))},[r(t).title||i.title?(a(),u("div",{key:0,"data-slot":"title",class:s(e.value.title({class:r(t).ui?.title}))},[c(n.$slots,"title",{},()=>[m(x(r(t).title),1)])],2)):o("",!0),r(t).description||i.description?(a(),u("div",{key:1,"data-slot":"description",class:s(e.value.description({class:r(t).ui?.description}))},[c(n.$slots,"description",{},()=>[m(x(r(t).description),1)])],2)):o("",!0),r(t).orientation==="vertical"&&(r(t).actions?.length||i.actions)?(a(),u("div",{key:2,"data-slot":"actions",class:s(e.value.actions({class:r(t).ui?.actions}))},[c(n.$slots,"actions",{},()=>[(a(!0),u(b,null,w(r(t).actions,(g,v)=>(a(),l(p,d({key:v,size:"xs"},{ref_for:!0},g),null,16))),128))])],2)):o("",!0)],2),r(t).orientation==="horizontal"&&(r(t).actions?.length||i.actions)||r(t).close?(a(),u("div",{key:0,"data-slot":"actions",class:s(e.value.actions({class:r(t).ui?.actions,orientation:"horizontal"}))},[r(t).orientation==="horizontal"&&(r(t).actions?.length||i.actions)?c(n.$slots,"actions",{key:0},()=>[(a(!0),u(b,null,w(r(t).actions,(g,v)=>(a(),l(p,d({key:v,size:"xs"},{ref_for:!0},g),null,16))),128))]):o("",!0),c(n.$slots,"close",{ui:e.value},()=>[r(t).close?(a(),l(p,d({key:0,icon:r(t).closeIcon||r(f).ui.icons.close,color:"neutral",variant:"link","aria-label":r(_)("alert.close")},typeof r(t).close=="object"?r(t).close:{},{"data-slot":"close",class:e.value.close({class:r(t).ui?.close}),onClick:y[0]||(y[0]=g=>q("update:open",!1))}),null,16,["icon","aria-label","class"])):o("",!0)])],2)):o("",!0)]),_:3},8,["as","data-orientation","class"]))}};export{U as _};
1
+ import{a2 as $,a3 as S,a4 as C,a5 as V,o as a,e as l,f as j,U as c,b as r,aG as B,V as d,_ as A,i as s,l as o,g as N,c as u,k as m,t as x,F as b,z as w,j as p,W as O,v as P,a8 as F}from"./1QWBzxLM.js";const I={slots:{root:"relative overflow-hidden w-full rounded-lg p-4 flex gap-2.5",wrapper:"min-w-0 flex-1 flex flex-col",title:"text-sm font-medium",description:"text-sm opacity-90",icon:"shrink-0 size-5",avatar:"shrink-0",avatarSize:"2xl",actions:"flex flex-wrap gap-1.5 shrink-0",close:"p-0"},variants:{color:{primary:"",secondary:"",success:"",info:"",warning:"",error:"",neutral:""},variant:{solid:"",outline:"",soft:"",subtle:""},orientation:{horizontal:{root:"items-center",actions:"items-center"},vertical:{root:"items-start",actions:"items-start mt-2.5"}},title:{true:{description:"mt-1"}}},compoundVariants:[{color:"primary",variant:"solid",class:{root:"bg-primary text-inverted"}},{color:"secondary",variant:"solid",class:{root:"bg-secondary text-inverted"}},{color:"success",variant:"solid",class:{root:"bg-success text-inverted"}},{color:"info",variant:"solid",class:{root:"bg-info text-inverted"}},{color:"warning",variant:"solid",class:{root:"bg-warning text-inverted"}},{color:"error",variant:"solid",class:{root:"bg-error text-inverted"}},{color:"primary",variant:"outline",class:{root:"text-primary ring ring-inset ring-primary/25"}},{color:"secondary",variant:"outline",class:{root:"text-secondary ring ring-inset ring-secondary/25"}},{color:"success",variant:"outline",class:{root:"text-success ring ring-inset ring-success/25"}},{color:"info",variant:"outline",class:{root:"text-info ring ring-inset ring-info/25"}},{color:"warning",variant:"outline",class:{root:"text-warning ring ring-inset ring-warning/25"}},{color:"error",variant:"outline",class:{root:"text-error ring ring-inset ring-error/25"}},{color:"primary",variant:"soft",class:{root:"bg-primary/10 text-primary"}},{color:"secondary",variant:"soft",class:{root:"bg-secondary/10 text-secondary"}},{color:"success",variant:"soft",class:{root:"bg-success/10 text-success"}},{color:"info",variant:"soft",class:{root:"bg-info/10 text-info"}},{color:"warning",variant:"soft",class:{root:"bg-warning/10 text-warning"}},{color:"error",variant:"soft",class:{root:"bg-error/10 text-error"}},{color:"primary",variant:"subtle",class:{root:"bg-primary/10 text-primary ring ring-inset ring-primary/25"}},{color:"secondary",variant:"subtle",class:{root:"bg-secondary/10 text-secondary ring ring-inset ring-secondary/25"}},{color:"success",variant:"subtle",class:{root:"bg-success/10 text-success ring ring-inset ring-success/25"}},{color:"info",variant:"subtle",class:{root:"bg-info/10 text-info ring ring-inset ring-info/25"}},{color:"warning",variant:"subtle",class:{root:"bg-warning/10 text-warning ring ring-inset ring-warning/25"}},{color:"error",variant:"subtle",class:{root:"bg-error/10 text-error ring ring-inset ring-error/25"}},{color:"neutral",variant:"solid",class:{root:"text-inverted bg-inverted"}},{color:"neutral",variant:"outline",class:{root:"text-highlighted bg-default ring ring-inset ring-default"}},{color:"neutral",variant:"soft",class:{root:"text-highlighted bg-elevated/50"}},{color:"neutral",variant:"subtle",class:{root:"text-highlighted bg-elevated/50 ring ring-inset ring-accented"}}],defaultVariants:{color:"primary",variant:"solid"}},U={__name:"UAlert",props:{as:{type:null,required:!1},title:{type:String,required:!1},description:{type:String,required:!1},icon:{type:null,required:!1},avatar:{type:Object,required:!1},color:{type:null,required:!1},variant:{type:null,required:!1},orientation:{type:null,required:!1,default:"vertical"},actions:{type:Array,required:!1},close:{type:[Boolean,Object],required:!1},closeIcon:{type:null,required:!1},class:{type:null,required:!1},ui:{type:Object,required:!1}},emits:["update:open"],setup(h,{emit:k}){const z=h,q=k,i=$(),t=S("alert",z),{t:_}=C(),f=V(),e=P(()=>F({extend:I,...f.ui?.alert||{}})({color:t.color,variant:t.variant,orientation:t.orientation,title:!!t.title||!!i.title}));return(n,y)=>(a(),l(r(O),{as:r(t).as,"data-orientation":r(t).orientation,"data-slot":"root",class:s(e.value.root({class:[r(t).ui?.root,r(t).class]}))},{default:j(()=>[c(n.$slots,"leading",{ui:e.value},()=>[r(t).avatar?(a(),l(B,d({key:0,size:r(t).ui?.avatarSize||e.value.avatarSize()},r(t).avatar,{"data-slot":"avatar",class:e.value.avatar({class:r(t).ui?.avatar})}),null,16,["size","class"])):r(t).icon?(a(),l(A,{key:1,name:r(t).icon,"data-slot":"icon",class:s(e.value.icon({class:r(t).ui?.icon}))},null,8,["name","class"])):o("",!0)]),N("div",{"data-slot":"wrapper",class:s(e.value.wrapper({class:r(t).ui?.wrapper}))},[r(t).title||i.title?(a(),u("div",{key:0,"data-slot":"title",class:s(e.value.title({class:r(t).ui?.title}))},[c(n.$slots,"title",{},()=>[m(x(r(t).title),1)])],2)):o("",!0),r(t).description||i.description?(a(),u("div",{key:1,"data-slot":"description",class:s(e.value.description({class:r(t).ui?.description}))},[c(n.$slots,"description",{},()=>[m(x(r(t).description),1)])],2)):o("",!0),r(t).orientation==="vertical"&&(r(t).actions?.length||i.actions)?(a(),u("div",{key:2,"data-slot":"actions",class:s(e.value.actions({class:r(t).ui?.actions}))},[c(n.$slots,"actions",{},()=>[(a(!0),u(b,null,w(r(t).actions,(g,v)=>(a(),l(p,d({key:v,size:"xs"},{ref_for:!0},g),null,16))),128))])],2)):o("",!0)],2),r(t).orientation==="horizontal"&&(r(t).actions?.length||i.actions)||r(t).close?(a(),u("div",{key:0,"data-slot":"actions",class:s(e.value.actions({class:r(t).ui?.actions,orientation:"horizontal"}))},[r(t).orientation==="horizontal"&&(r(t).actions?.length||i.actions)?c(n.$slots,"actions",{key:0},()=>[(a(!0),u(b,null,w(r(t).actions,(g,v)=>(a(),l(p,d({key:v,size:"xs"},{ref_for:!0},g),null,16))),128))]):o("",!0),c(n.$slots,"close",{ui:e.value},()=>[r(t).close?(a(),l(p,d({key:0,icon:r(t).closeIcon||r(f).ui.icons.close,color:"neutral",variant:"link","aria-label":r(_)("alert.close")},typeof r(t).close=="object"?r(t).close:{},{"data-slot":"close",class:e.value.close({class:r(t).ui?.close}),onClick:y[0]||(y[0]=g=>q("update:open",!1))}),null,16,["icon","aria-label","class"])):o("",!0)])],2)):o("",!0)]),_:3},8,["as","data-orientation","class"]))}};export{U as _};
@@ -1 +1 @@
1
- import{ar as s}from"./BdQ7kfxJ.js";let a=null;function i(){const t=s("ai-status",()=>null);async function u(){t.value===null&&(a||(a=$fetch("/api/ai/status").catch(()=>({configured:!1}))),t.value=await a)}return u(),{aiStatus:t}}export{i as u};
1
+ import{ar as s}from"./1QWBzxLM.js";let a=null;function i(){const t=s("ai-status",()=>null);async function u(){t.value===null&&(a||(a=$fetch("/api/ai/status").catch(()=>({configured:!1}))),t.value=await a)}return u(),{aiStatus:t}}export{i as u};
@@ -1,2 +1,2 @@
1
- import{d as _,o as l,e as p,f as u,h as d,_ as f,i as g,b as a,v as o}from"./BdQ7kfxJ.js";import{_ as v}from"./C_eXufkv.js";import{g as x}from"./CrsaY0R_.js";const h=_({__name:"EnvManagedBadge",props:{envVars:{},size:{default:"sm"}},setup(r){const s=r,i=o(()=>{switch(s.size){case"xs":return"size-3";case"md":return"size-4";default:return"size-3.5"}}),c=o(()=>{if(!s.envVars?.length)return"Managed by environment variable";const e=s.envVars.map(n=>{const t=x(n).description;return t?`${n} — ${t}`:n});return e.length===1?`Set via ${e[0]}`:["Set via environment variables:",...e].join(`
1
+ import{d as _,o as l,e as p,f as u,h as d,_ as f,i as g,b as a,v as o}from"./1QWBzxLM.js";import{_ as v}from"./BnUQ3i5l.js";import{g as x}from"./B82vqOZe.js";const h=_({__name:"EnvManagedBadge",props:{envVars:{},size:{default:"sm"}},setup(r){const s=r,i=o(()=>{switch(s.size){case"xs":return"size-3";case"md":return"size-4";default:return"size-3.5"}}),c=o(()=>{if(!s.envVars?.length)return"Managed by environment variable";const e=s.envVars.map(n=>{const t=x(n).description;return t?`${n} — ${t}`:n});return e.length===1?`Set via ${e[0]}`:["Set via environment variables:",...e].join(`
2
2
  `)});return(e,n)=>{const t=f,m=v;return l(),p(m,{text:a(c),ui:{content:"whitespace-pre-line max-w-sm"}},{default:u(()=>[d(t,{name:"i-lucide-lock",class:g(["text-gray-400",a(i)])},null,8,["class"])]),_:1},8,["text"])}}}),$=Object.assign(h,{__name:"EnvManagedBadge"});export{$ as _};
@@ -0,0 +1,4 @@
1
+ import{_ as ra}from"./B-1zt4pp.js";import{aO as oa,d as oe,Y as Ve,X as Re,T as pe,o as i,c as y,h as s,f as r,U as M,b as e,V as X,D as Pe,W as he,e as k,l as _,F as re,v as K,ax as ia,aE as na,Z as ze,aP as qe,R as da,r as b,aQ as ua,aA as ca,a2 as pa,a3 as ma,a5 as fa,a6 as va,a7 as ya,aK as ba,aR as ga,g as d,i as E,k as x,t as V,z as je,ai as $e,a8 as ha,aF as be,w as _a,q as ka,O as wa,C as xa,E as Ca,ao as Aa,j as qa,m as $a,_ as Ua,I as Ia,x as ge,J as Va,B as Ra}from"./1QWBzxLM.js";import{_ as Pa}from"./DxBrlj7b.js";import{_ as za}from"./uspGXbik.js";import{_ as ja}from"./BuXJR5tn.js";import{_ as Sa}from"./bmAf49LT.js";import{_ as Ka}from"./B4lvHjBe.js";import{_ as Ea}from"./e-GZmCeP.js";import{_ as Da}from"./Cnm0d_7S.js";import{_ as Fa}from"./CtQMagSz.js";import{_ as Ba}from"./B82vqOZe.js";import{_ as Ga}from"./BF5qB58w.js";import{L as Ue}from"./Bl0xzETD.js";import{u as Se}from"./DpM8IgHL.js";import{V as Ke}from"./Bp1WeQ0_.js";import{u as Ee}from"./DBXXb0w8.js";import{R as Ma}from"./D_ZAGxCQ.js";import{_ as Ta}from"./UAmyrRCI.js";import{a as Oa,u as La}from"./CU_2YLhT.js";import{j as le}from"./D4mPjHHR.js";import{o as Na,s as ce,l as Ie,_ as Ha,u as Wa}from"./DGnQ69wW.js";import"./VBTxfbqU.js";import"./AbnDY6Zr.js";import"./CHz7LJIX.js";const Ya="radio.select";function Ja(S,A,u){oa(Ya,u,{originalEvent:S,value:A})}var Qa=oe({inheritAttrs:!1,__name:"Radio",props:{id:{type:String,required:!1},value:{type:null,required:!1},disabled:{type:Boolean,required:!1,default:!1},checked:{type:Boolean,required:!1,default:void 0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"button"},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:["update:checked","select"],setup(S,{emit:A}){const u=S,g=A,h=Ve(u,"checked",g,{passive:u.checked===void 0}),{value:l}=Re(u),{forwardRef:I,currentElement:C}=pe(),R=Se(C),w=Ee(),P=K(()=>u.id&&C.value?document.querySelector(`[for="${u.id}"]`)?.innerText??u.value:void 0);function q(p){u.disabled||Ja(p,u.value,z=>{g("select",z),!z?.defaultPrevented&&(h.value=!0,R.value&&z.stopPropagation())})}return(p,z)=>(i(),y(re,null,[s(e(he),X({id:p.id,ref:e(I),role:"radio",type:p.as==="button"?"button":void 0,as:p.as,"aria-checked":e(h)??!1,"aria-label":P.value,"as-child":p.asChild,disabled:p.disabled?"":void 0,"data-state":e(h)?"checked":"unchecked","data-disabled":p.disabled?"":void 0,value:e(l),required:p.required,name:p.name},{...e(w),...p.$attrs},{onClick:Pe(q,["stop"])}),{default:r(()=>[M(p.$slots,"default",{checked:e(h)})]),_:3},16,["id","type","as","aria-checked","aria-label","as-child","disabled","data-state","data-disabled","value","required","name"]),e(R)&&p.name?(i(),k(e(Ke),X({key:0,type:"radio",tabindex:"-1",value:e(l),checked:!!e(h),name:p.name,disabled:p.disabled,required:p.required},e(w)),null,16,["value","checked","name","disabled","required"])):_("v-if",!0)],64))}}),Xa=Qa;const[Za,et]=ze("RadioGroupRoot");var at=oe({__name:"RadioGroupRoot",props:{modelValue:{type:null,required:!1},defaultValue:{type:null,required:!1},disabled:{type:Boolean,required:!1,default:!1},orientation:{type:String,required:!1,default:void 0},dir:{type:String,required:!1},loop:{type:Boolean,required:!1,default:!0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1},name:{type:String,required:!1},required:{type:Boolean,required:!1,default:!1}},emits:["update:modelValue"],setup(S,{emit:A}){const u=S,g=A,{forwardRef:h,currentElement:l}=pe(),I=Ve(u,"modelValue",g,{defaultValue:u.defaultValue,passive:u.modelValue===void 0}),{disabled:C,loop:R,orientation:w,name:P,required:q,dir:p}=Re(u),z=ia(p),$=Se(l);return et({modelValue:I,changeModelValue:m=>{I.value=m},disabled:C,loop:R,orientation:w,name:P?.value,required:q}),(m,c)=>(i(),k(e(na),{"as-child":"",orientation:e(w),dir:e(z),loop:e(R)},{default:r(()=>[s(e(he),{ref:e(h),role:"radiogroup","data-disabled":e(C)?"":void 0,"as-child":m.asChild,as:m.as,"aria-orientation":e(w),"aria-required":e(q),dir:e(z)},{default:r(()=>[M(m.$slots,"default",{modelValue:e(I)}),e($)&&e(P)?(i(),k(e(Ke),{key:0,required:e(q),disabled:e(C),value:e(I),name:e(P)},null,8,["required","disabled","value","name"])):_("v-if",!0)]),_:3},8,["data-disabled","as-child","as","aria-orientation","aria-required","dir"])]),_:3},8,["orientation","dir","loop"]))}}),tt=at;const[st,lt]=ze("RadioGroupItem");var rt=oe({inheritAttrs:!1,__name:"RadioGroupItem",props:{id:{type:String,required:!1},value:{type:null,required:!1},disabled:{type:Boolean,required:!1,default:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"button"},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:["select"],setup(S,{emit:A}){const u=S,g=A,{forwardRef:h,currentElement:l}=pe(),I=Za(),C=K(()=>I.disabled.value||u.disabled),R=K(()=>I.required.value||u.required),w=K(()=>ua(I.modelValue?.value,u.value));lt({disabled:C,checked:w});const P=b(!1),q=["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"];qe("keydown",$=>{q.includes($.key)&&(P.value=!0)}),qe("keyup",()=>{P.value=!1});function p(){setTimeout(()=>{P.value&&l.value?.click()},0)}const z=Ee();return($,m)=>(i(),k(e(Ma),{checked:w.value,disabled:C.value,"as-child":"",focusable:!C.value,active:w.value},{default:r(()=>[s(Xa,X({...e(z),...$.$attrs,...u},{ref:e(h),checked:w.value,required:R.value,disabled:C.value,"onUpdate:checked":m[0]||(m[0]=c=>e(I).changeModelValue($.value)),onSelect:m[1]||(m[1]=c=>g("select",c)),onKeydown:m[2]||(m[2]=da(Pe(()=>{},["prevent"]),["enter"])),onFocus:p}),{default:r(()=>[M($.$slots,"default",{checked:w.value,required:R.value,disabled:C.value})]),_:3},16,["checked","required","disabled"])]),_:3},8,["checked","disabled","focusable","active"]))}}),ot=rt,it=oe({__name:"RadioGroupIndicator",props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"span"}},setup(S){const{forwardRef:A}=pe(),u=st();return(g,h)=>(i(),k(e(ca),{present:g.forceMount||e(u).checked.value},{default:r(()=>[s(e(he),X({ref:e(A),"data-state":e(u).checked.value?"checked":"unchecked","data-disabled":e(u).disabled.value?"":void 0,"as-child":g.asChild,as:g.as},g.$attrs),{default:r(()=>[M(g.$slots,"default")]),_:3},16,["data-state","data-disabled","as-child","as"])]),_:3},8,["present"]))}}),nt=it;const dt={slots:{root:"relative",fieldset:"flex gap-x-2",legend:"mb-1 block font-medium text-default",item:"flex items-start",container:"flex items-center",base:"rounded-full ring ring-inset ring-accented overflow-hidden focus-visible:outline-3",indicator:"flex items-center justify-center size-full after:bg-default after:rounded-full",wrapper:"w-full",label:"block font-medium text-default",description:"text-muted"},variants:{color:{primary:{base:"outline-primary/25 focus-visible:ring-primary",indicator:"bg-primary"},secondary:{base:"outline-secondary/25 focus-visible:ring-secondary",indicator:"bg-secondary"},success:{base:"outline-success/25 focus-visible:ring-success",indicator:"bg-success"},info:{base:"outline-info/25 focus-visible:ring-info",indicator:"bg-info"},warning:{base:"outline-warning/25 focus-visible:ring-warning",indicator:"bg-warning"},error:{base:"outline-error/25 focus-visible:ring-error",indicator:"bg-error"},neutral:{base:"outline-inverted/25 focus-visible:ring-inverted",indicator:"bg-inverted"}},variant:{list:{item:""},card:{item:"border border-muted rounded-lg"},table:{item:"border border-muted"}},orientation:{horizontal:{fieldset:"flex-row"},vertical:{fieldset:"flex-col"}},indicator:{start:{item:"flex-row",wrapper:"ms-2"},end:{item:"flex-row-reverse",wrapper:"me-2"},hidden:{base:"sr-only",wrapper:"text-center"}},size:{xs:{fieldset:"gap-y-0.5",legend:"text-xs",base:"size-3",item:"text-xs",container:"h-4",indicator:"after:size-1"},sm:{fieldset:"gap-y-0.5",legend:"text-xs",base:"size-3.5",item:"text-xs",container:"h-4",indicator:"after:size-1"},md:{fieldset:"gap-y-1",legend:"text-sm",base:"size-4",item:"text-sm",container:"h-5",indicator:"after:size-1.5"},lg:{fieldset:"gap-y-1",legend:"text-sm",base:"size-4.5",item:"text-sm",container:"h-5",indicator:"after:size-1.5"},xl:{fieldset:"gap-y-1.5",legend:"text-base",base:"size-5",item:"text-base",container:"h-6",indicator:"after:size-2"}},highlight:{true:""},disabled:{true:{item:"opacity-75",base:"cursor-not-allowed",label:"cursor-not-allowed",description:"cursor-not-allowed"}},required:{true:{legend:"after:content-['*'] after:ms-0.5 after:text-error"}}},compoundVariants:[{size:"xs",variant:["card","table"],class:{item:"p-2.5"}},{size:"sm",variant:["card","table"],class:{item:"p-3"}},{size:"md",variant:["card","table"],class:{item:"p-3.5"}},{size:"lg",variant:["card","table"],class:{item:"p-4"}},{size:"xl",variant:["card","table"],class:{item:"p-4.5"}},{orientation:"horizontal",variant:"table",class:{item:"first-of-type:rounded-s-lg last-of-type:rounded-e-lg",fieldset:"gap-0 -space-x-px"}},{orientation:"vertical",variant:"table",class:{item:"first-of-type:rounded-t-lg last-of-type:rounded-b-lg",fieldset:"gap-0 -space-y-px"}},{color:"primary",variant:"card",class:{item:"has-data-[state=checked]:border-primary"}},{color:"secondary",variant:"card",class:{item:"has-data-[state=checked]:border-secondary"}},{color:"success",variant:"card",class:{item:"has-data-[state=checked]:border-success"}},{color:"info",variant:"card",class:{item:"has-data-[state=checked]:border-info"}},{color:"warning",variant:"card",class:{item:"has-data-[state=checked]:border-warning"}},{color:"error",variant:"card",class:{item:"has-data-[state=checked]:border-error"}},{color:"neutral",variant:"card",class:{item:"has-data-[state=checked]:border-inverted"}},{color:"primary",variant:"table",class:{item:"has-data-[state=checked]:bg-primary/10 has-data-[state=checked]:border-primary/50 has-data-[state=checked]:z-[1]"}},{color:"secondary",variant:"table",class:{item:"has-data-[state=checked]:bg-secondary/10 has-data-[state=checked]:border-secondary/50 has-data-[state=checked]:z-[1]"}},{color:"success",variant:"table",class:{item:"has-data-[state=checked]:bg-success/10 has-data-[state=checked]:border-success/50 has-data-[state=checked]:z-[1]"}},{color:"info",variant:"table",class:{item:"has-data-[state=checked]:bg-info/10 has-data-[state=checked]:border-info/50 has-data-[state=checked]:z-[1]"}},{color:"warning",variant:"table",class:{item:"has-data-[state=checked]:bg-warning/10 has-data-[state=checked]:border-warning/50 has-data-[state=checked]:z-[1]"}},{color:"error",variant:"table",class:{item:"has-data-[state=checked]:bg-error/10 has-data-[state=checked]:border-error/50 has-data-[state=checked]:z-[1]"}},{color:"neutral",variant:"table",class:{item:"has-data-[state=checked]:bg-elevated has-data-[state=checked]:border-inverted/50 has-data-[state=checked]:z-[1]"}},{variant:["card","table"],disabled:!0,class:{item:"cursor-not-allowed"}},{color:"primary",highlight:!0,class:{base:"ring-primary"}},{color:"secondary",highlight:!0,class:{base:"ring-secondary"}},{color:"success",highlight:!0,class:{base:"ring-success"}},{color:"info",highlight:!0,class:{base:"ring-info"}},{color:"warning",highlight:!0,class:{base:"ring-warning"}},{color:"error",highlight:!0,class:{base:"ring-error"}},{color:"neutral",highlight:!0,class:{base:"ring-inverted"}}],defaultVariants:{size:"md",color:"primary",variant:"list",indicator:"start"}},ut={__name:"URadioGroup",props:{as:{type:null,required:!1},legend:{type:String,required:!1},valueKey:{type:null,required:!1,default:"value"},labelKey:{type:null,required:!1,default:"label"},descriptionKey:{type:null,required:!1,default:"description"},items:{type:null,required:!1},modelValue:{type:null,required:!1},defaultValue:{type:null,required:!1},size:{type:null,required:!1},variant:{type:null,required:!1},color:{type:null,required:!1},highlight:{type:Boolean,required:!1},orientation:{type:null,required:!1,default:"vertical"},indicator:{type:null,required:!1},class:{type:null,required:!1},ui:{type:Object,required:!1},disabled:{type:Boolean,required:!1},loop:{type:Boolean,required:!1},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:["change","update:modelValue"],setup(S,{emit:A}){const u=S,g=A,h=pa(),l=ma("radioGroup",u),I=fa(),C=va(ya(l,"as","loop","required"),g),{emitFormChange:R,emitFormInput:w,color:P,name:q,size:p,highlight:z,id:$,disabled:m,ariaAttrs:c}=ba(u,{bind:!1}),T=$.value??ga(),j=K(()=>ha({extend:dt,...I.ui?.radioGroup||{}})({size:p.value??l.size,color:P.value??l.color,highlight:z.value??l.highlight,disabled:m.value,required:l.required,orientation:l.orientation,variant:l.variant,indicator:l.indicator}));function me(f){if(f===null)return{id:`${T}:null`,value:void 0,label:void 0};if(typeof f=="string"||typeof f=="number"||typeof f=="bigint")return{id:`${T}:${f}`,value:String(f),label:String(f)};const G=be(f,l.valueKey),n=be(f,l.labelKey),O=be(f,l.descriptionKey);return{...f,value:G,label:n,description:O,id:`${T}:${G}`}}const fe=K(()=>l.items?l.items.map(me):[]);function B(f){const G=new Event("change",{target:{value:f}});g("change",G),R(),w()}return(f,G)=>(i(),k(e(tt),X({id:e(T)},e(C),{"model-value":e(l).modelValue,"default-value":e(l).defaultValue,orientation:e(l).orientation,name:e(q),disabled:e(m),"data-slot":"root",class:j.value.root({class:[e(l).ui?.root,e(l).class]}),"onUpdate:modelValue":B}),{default:r(()=>[d("fieldset",X({"data-slot":"fieldset",class:j.value.fieldset({class:e(l).ui?.fieldset})},e(c)),[e(l).legend||h.legend?(i(),y("legend",{key:0,"data-slot":"legend",class:E(j.value.legend({class:e(l).ui?.legend}))},[M(f.$slots,"legend",{},()=>[x(V(e(l).legend),1)])],2)):_("",!0),(i(!0),y(re,null,je(fe.value,n=>(i(),k($e(!e(l).variant||e(l).variant==="list"?"div":e(Ue)),{key:n.value,"data-slot":"item",class:E(j.value.item({class:[e(l).ui?.item,n.ui?.item,n.class],disabled:n.disabled||e(m)}))},{default:r(()=>[d("div",{"data-slot":"container",class:E(j.value.container({class:[e(l).ui?.container,n.ui?.container]}))},[s(e(ot),{id:n.id,value:n.value,disabled:n.disabled||e(m),"data-slot":"base",class:E(j.value.base({class:[e(l).ui?.base,n.ui?.base],disabled:n.disabled||e(m)}))},{default:r(()=>[s(e(nt),{"data-slot":"indicator",class:E(j.value.indicator({class:[e(l).ui?.indicator,n.ui?.indicator]}))},null,8,["class"])]),_:2},1032,["id","value","disabled","class"])],2),n.label||h.label||n.description||h.description?(i(),y("div",{key:0,"data-slot":"wrapper",class:E(j.value.wrapper({class:[e(l).ui?.wrapper,n.ui?.wrapper]}))},[n.label||h.label?(i(),k($e(!e(l).variant||e(l).variant==="list"?e(Ue):"p"),{key:0,for:n.id,"data-slot":"label",class:E(j.value.label({class:[e(l).ui?.label,n.ui?.label],disabled:n.disabled||e(m)}))},{default:r(()=>[M(f.$slots,"label",{item:n,modelValue:e(l).modelValue},()=>[x(V(n.label),1)])]),_:2},1032,["for","class"])):_("",!0),n.description||h.description?(i(),y("p",{key:1,"data-slot":"description",class:E(j.value.description({class:[e(l).ui?.description,n.ui?.description],disabled:n.disabled||e(m)}))},[M(f.$slots,"description",{item:n,modelValue:e(l).modelValue},()=>[x(V(n.description),1)])],2)):_("",!0)],2)):_("",!0)]),_:2},1032,["class"]))),128))],16)]),_:3},16,["id","model-value","default-value","orientation","name","disabled","class"]))}},ct={class:"space-y-6"},pt={class:"text-muted"},mt={key:0,class:"flex items-center gap-1 text-sm"},ft={key:1,class:"text-muted"},vt={class:"flex items-center gap-1 justify-end"},yt={class:"text-center py-12"},bt={class:"flex justify-center mb-4"},gt={class:"flex w-full justify-end gap-2"},ht={class:"inline-flex items-center gap-1"},_t={class:"space-y-4"},kt={key:0,class:"rounded-lg border border-primary/30 bg-primary/5 p-4 space-y-4"},wt={key:0,class:"space-y-4"},xt={class:"rounded-lg bg-elevated p-3 font-mono text-sm break-all select-all"},Ct={class:"flex gap-2"},At={key:1,class:"space-y-3"},qt={class:"flex gap-2"},$t={key:1,class:"space-y-2"},Ut={class:"flex-1 min-w-0"},It={class:"flex items-center gap-2"},Vt={class:"font-medium truncate"},Rt={class:"text-xs text-muted mt-1 flex flex-wrap gap-x-4"},Pt={class:"font-mono"},zt={key:0},jt={key:1,class:"italic"},St={key:2,class:"text-center text-muted py-6 text-sm"},Kt={class:"inline-flex items-center gap-1"},Et={class:"space-y-6"},Dt={key:0,class:"text-[var(--ui-text-muted)]"},Ft={key:1},us=oe({__name:"users",async setup(S){let A,u;const{data:g,refresh:h}=([A,u]=_a(()=>La("/api/users","$JTvQRs7G1d")),A=await A,u(),A),l=ka(),{copy:I}=Oa(),{authState:C}=wa(),R=Ra(),w=K(()=>g.value?.items||[]),P=K(()=>g.value?.authEnabled||!1),q=K(()=>R.public.authEnabled?C.value.user?.role==="administrator":!0),p=K(()=>C.value.user?.id??null),z=[{accessorKey:"username",header:le("Username")},{accessorKey:"name",header:le("Name")},{accessorKey:"email",header:le("Email")},{accessorKey:"role",header:le("Role")},{accessorKey:"createdAt",header:le("Created")},{accessorKey:"actions",header:""}],$=b(!1),m=Na({username:ce().min(3,"Username must be at least 3 characters"),password:Wa([ce().min(8,"Password must be at least 8 characters"),Ie("").transform(()=>{})]).optional(),role:Ha(["administrator","reporter","user"]),name:ce().optional(),email:ce().email().optional().or(Ie(""))}),c=Va({username:"",password:"",role:"user",name:"",email:""}),T=[{label:"Administrator",value:"administrator"},{label:"Reporter",value:"reporter"},{label:"User",value:"user"}];async function j(){try{const o={...c,password:c.password||void 0};await $fetch("/api/users",{method:"POST",body:o}),l.add({title:"User created",description:`User ${c.username} has been created successfully`,color:"success"}),$.value=!1,c.username="",c.password="",c.role="user",c.name="",c.email="",await h()}catch(o){const a=o&&typeof o=="object"&&"data"in o?o.data?.message:void 0;l.add({title:"Failed to create user",description:a||"An error occurred",color:"error"})}}async function me(o){f.value=o,B.value=!0}async function fe(){const o=f.value;if(o){B.value=!1,f.value=null;try{await $fetch(`/api/users/${o.id}`,{method:"DELETE"}),l.add({title:"User deleted",description:`User ${o.username} has been deleted`,color:"success"}),await h()}catch(a){const U=a&&typeof a=="object"&&"data"in a?a.data?.message:void 0;l.add({title:"Failed to delete user",description:U||"An error occurred",color:"error"})}}}const B=b(!1),f=b(null);function G(o){switch(o){case"administrator":return"primary";case"reporter":return"info";case"user":return"neutral";default:return"neutral"}}const n=b(null),O=b(!1),ie=b([]);async function De(o){n.value=o,O.value=!0,await _e(o.id)}async function _e(o){try{const a=await $fetch(`/api/users/${o}/api-keys`);ie.value=a.items}catch{ie.value=[]}}async function ke(){n.value&&await _e(n.value.id)}const L=b(!1),N=b(""),H=b(""),D=b(null),we=b("http://localhost:3000");xa(()=>{we.value=window.location.origin});const Fe=K(()=>`['@piwitests/reporter', {
2
+ serverUrl: '${we.value}',
3
+ apiKey: '${D.value??""}', // or set PIWI_API_KEY and use apiKey: process.env.PIWI_API_KEY
4
+ }]`);function Be(){N.value="",H.value="",D.value=null,L.value=!0}function xe(){L.value=!1,D.value=null}async function Ge(){if(n.value)try{const o={name:N.value};H.value&&(o.expiresAt=new Date(H.value).toISOString());const a=await $fetch(`/api/users/${n.value.id}/api-keys`,{method:"POST",body:o});D.value=a.key,await ke()}catch(o){const a=o&&typeof o=="object"&&"data"in o?o.data?.message:void 0;l.add({title:"Failed to create API key",description:a||"An error occurred",color:"error"})}}function Me(){I(D.value,{toast:"API key copied to clipboard"})}function Te(){D.value=null,L.value=!1}const Z=b(!1),ee=b(null);function Oe(o){ee.value=o,Z.value=!0}async function Le(){if(!n.value||!ee.value)return;const o=ee.value;Z.value=!1,ee.value=null;try{await $fetch(`/api/users/${n.value.id}/api-keys/${o.id}`,{method:"DELETE"}),l.add({title:"API key revoked",description:`Key "${o.name}" has been revoked`,color:"success"}),await ke()}catch(a){const U=a&&typeof a=="object"&&"data"in a?a.data?.message:void 0;l.add({title:"Failed to revoke API key",description:U||"An error occurred",color:"error"})}}function Ne(o){return R.public.authEnabled?q.value||p.value===o.id:!0}const ne=b(null),ae=b(!1),W=b(!1),Y=b([]),J=b([]);async function He(o){ne.value=o,ae.value=!0;try{const a=(await $fetch("/api/projects/menu")).items;J.value=a.map(U=>({...U,label:U.label||U.name}))}catch{J.value=[]}try{const a=await $fetch(`/api/users/${o.id}/projects`);W.value=a.global,Y.value=J.value.filter(U=>a.projectIds.includes(U.id))}catch{W.value=!1,Y.value=[]}}async function We(){const o=ne.value;if(o)try{await $fetch(`/api/users/${o.id}/projects`,{method:"PUT",body:{global:W.value,projectIds:Y.value.map(a=>a.id)}}),l.add({title:"Project access updated",description:`Access for ${o.username} has been updated`,color:"success"}),ae.value=!1}catch(a){const U=a&&typeof a=="object"&&"data"in a?a.data?.message:void 0;l.add({title:"Failed to update project access",description:U||"An error occurred",color:"error"})}}const ve=b(null);async function Ye(o){if(!o.email){l.add({title:"No email address",description:"Set an email address for this user first.",color:"error"});return}ve.value=o.id;try{await $fetch(`/api/users/${o.id}/invite`,{method:"POST"}),l.add({title:"Invite sent",description:`Invitation sent to ${o.email}`,color:"success"})}catch(a){const U=a&&typeof a=="object"&&"data"in a?a.data?.message:void 0;l.add({title:"Failed to send invite",description:U||"An error occurred",color:"error"})}finally{ve.value=null}}return(o,a)=>{const U=ra,v=qa,ye=Ua,Je=$a,de=Pa,Qe=za,Xe=ja,Ce=Sa,Q=Ia,F=Ka,Ze=Ea,ea=Da,te=Fa,se=Ca,Ae=Ba,aa=Ga,ta=ut,sa=Aa("UDivider"),la=Ta;return i(),y(re,null,[d("div",ct,[e(P)?_("",!0):(i(),k(U,{key:0,icon:"i-lucide-info",color:"primary",variant:"subtle",title:"Authentication is disabled",description:"Authentication is currently disabled. You can manage users here, but they will only be used when authentication is enabled via the PIWI_AUTH_ENABLED environment variable."})),e(w).length>0?(i(),k(Ce,{key:1,title:"Users",count:e(w).length,help:"settings.users"},{actions:r(()=>[e(q)?(i(),k(v,{key:0,label:"Add user",icon:"i-lucide-user-plus",size:"sm",onClick:a[0]||(a[0]=t=>$.value=!0)})):_("",!0)]),default:r(()=>[s(Xe,{"min-width":"44rem",bleed:!1},{default:r(()=>[s(Qe,{data:e(w),columns:z,sticky:"",class:"max-h-[32rem]"},{"username-cell":r(({row:t})=>[x(V(t.original.username),1)]),"name-cell":r(({row:t})=>[d("span",pt,V(t.original.name||"-"),1)]),"email-cell":r(({row:t})=>[t.original.email?(i(),y("span",mt,[x(V(t.original.email)+" ",1),t.original.emailVerified?(i(),k(ye,{key:0,name:"i-lucide-circle-check-big",class:"size-3.5 text-success-500",title:"Email verified"})):_("",!0)])):(i(),y("span",ft,"—"))]),"role-cell":r(({row:t})=>[s(Je,{color:G(t.original.role),variant:"subtle"},{default:r(()=>[x(V(t.original.role),1)]),_:2},1032,["color"])]),"createdAt-cell":r(({row:t})=>[s(de,{date:t.original.createdAt,"date-only":"",class:"text-sm text-muted"},null,8,["date"])]),"actions-cell":r(({row:t})=>[d("div",vt,[e(q)&&t.original.email&&!t.original.oauthProvider?(i(),k(v,{key:0,icon:"i-lucide-send",color:"neutral",variant:"ghost",size:"sm",title:"Send invite email","aria-label":"Send invite email",loading:e(ve)===t.original.id,onClick:ue=>Ye(t.original)},null,8,["loading","onClick"])):_("",!0),e(q)&&t.original.role!=="administrator"?(i(),k(v,{key:1,icon:"i-lucide-folder-lock",color:"neutral",variant:"ghost",size:"sm",title:"Project access","aria-label":"Project access",onClick:ue=>He(t.original)},null,8,["onClick"])):_("",!0),Ne(t.original)?(i(),k(v,{key:2,icon:"i-lucide-key",color:"neutral",variant:"ghost",size:"sm",title:"Manage API keys","aria-label":"Manage API keys",onClick:ue=>De(t.original)},null,8,["onClick"])):_("",!0),e(q)?(i(),k(v,{key:3,icon:"i-lucide-trash-2",color:"error",variant:"ghost",size:"sm",title:"Delete user","aria-label":"Delete user",onClick:ue=>me(t.original)},null,8,["onClick"])):_("",!0)])]),_:1},8,["data"])]),_:1})]),_:1},8,["count"])):(i(),k(Ce,{key:2,title:"Users",count:0,help:"settings.users"},{default:r(()=>[d("div",yt,[d("div",bt,[s(ye,{name:"i-lucide-users",class:"text-4xl text-muted"})]),a[21]||(a[21]=d("h3",{class:"text-lg font-semibold mb-2"},"No users yet",-1)),a[22]||(a[22]=d("p",{class:"text-muted mb-4"},"Create your first user to get started with authentication",-1)),e(q)?(i(),k(v,{key:0,label:"Add user",icon:"i-lucide-user-plus",onClick:a[1]||(a[1]=t=>$.value=!0)})):_("",!0)])]),_:1}))]),s(se,null,{default:r(()=>[s(te,{open:e($),title:"Add new user","onUpdate:open":a[8]||(a[8]=t=>$.value=t)},{body:r(()=>[s(ea,{schema:e(m),state:e(c),class:"space-y-5"},{default:r(()=>[s(F,{label:"Username",name:"username",required:""},{default:r(()=>[s(Q,{modelValue:e(c).username,"onUpdate:modelValue":a[2]||(a[2]=t=>e(c).username=t),placeholder:"Enter username",class:"w-full"},null,8,["modelValue"])]),_:1}),s(F,{label:"Password",name:"password",description:"Leave blank to let the user set their own password via invite email"},{default:r(()=>[s(Q,{modelValue:e(c).password,"onUpdate:modelValue":a[3]||(a[3]=t=>e(c).password=t),type:"password",placeholder:"Leave blank to send invite",class:"w-full"},null,8,["modelValue"])]),_:1}),s(F,{label:"Display name",name:"name"},{default:r(()=>[s(Q,{modelValue:e(c).name,"onUpdate:modelValue":a[4]||(a[4]=t=>e(c).name=t),placeholder:"Enter display name (optional)",class:"w-full"},null,8,["modelValue"])]),_:1}),s(F,{label:"Email",name:"email",description:"Optional — needed for invites and notifications"},{default:r(()=>[s(Q,{modelValue:e(c).email,"onUpdate:modelValue":a[5]||(a[5]=t=>e(c).email=t),type:"email",placeholder:"user@example.com (optional)",class:"w-full"},null,8,["modelValue"])]),_:1}),s(F,{label:"Role",name:"role",required:""},{default:r(()=>[s(Ze,{modelValue:e(c).role,"onUpdate:modelValue":a[6]||(a[6]=t=>e(c).role=t),items:T,class:"w-full"},null,8,["modelValue"])]),_:1})]),_:1},8,["schema","state"])]),footer:r(()=>[d("div",gt,[s(v,{type:"button",color:"neutral",variant:"ghost",label:"Cancel",onClick:a[7]||(a[7]=t=>$.value=!1)}),s(v,{type:"submit",label:"Create user",icon:"i-lucide-user-plus",onClick:j})])]),_:1},8,["open"])]),_:1}),s(se,null,{default:r(()=>[s(te,{open:e(O),title:`API keys – ${e(n)?.username}`,size:"xl","onUpdate:open":a[12]||(a[12]=t=>{O.value=t,t||xe()})},{title:r(()=>[d("span",ht,[x(" API keys – "+V(e(n)?.username)+" ",1),s(Ae,{topic:"settings.api-keys"})])]),body:r(()=>[d("div",_t,[a[29]||(a[29]=d("p",{class:"text-sm text-muted"},[x(" API keys allow the Playwright reporter (and other CI tools) to submit test results without a username/password login. Each key is shown "),d("strong",null,"only once"),x(" at creation time — store it in a CI secret immediately. ")],-1)),e(L)?(i(),y("div",kt,[e(D)?(i(),y("div",wt,[s(U,{icon:"i-lucide-triangle-alert",color:"warning",variant:"subtle",title:"Save your API key now",description:"This key will never be shown again. Copy it and store it in your CI secret manager immediately."}),d("div",xt,V(e(D)),1),d("div",Ct,[s(v,{label:"Copy to clipboard",icon:"i-lucide-clipboard",color:"primary",size:"sm",onClick:Me}),s(v,{label:"Done",variant:"ghost",size:"sm",onClick:Te})]),d("div",null,[a[23]||(a[23]=d("p",{class:"text-xs font-semibold uppercase tracking-wide text-muted mb-2"}," Use it in your reporter config ",-1)),s(aa,{code:e(Fe),lang:"typescript"},null,8,["code"])])])):(i(),y("div",At,[a[24]||(a[24]=d("h4",{class:"font-medium text-sm"},"Create new API key",-1)),s(F,{label:"Key name",name:"name",required:""},{default:r(()=>[s(Q,{modelValue:e(N),"onUpdate:modelValue":a[9]||(a[9]=t=>ge(N)?N.value=t:null),placeholder:"e.g. GitHub Actions CI",size:"sm"},null,8,["modelValue"])]),_:1}),s(F,{label:"Expires at (optional)",name:"expiresAt"},{default:r(()=>[s(Q,{modelValue:e(H),"onUpdate:modelValue":a[10]||(a[10]=t=>ge(H)?H.value=t:null),type:"date",size:"sm",min:new Date().toISOString().split("T")[0]},null,8,["modelValue","min"])]),_:1}),d("div",qt,[s(v,{label:"Generate key",icon:"i-lucide-key",size:"sm",disabled:!e(N).trim(),onClick:Ge},null,8,["disabled"]),s(v,{color:"neutral",variant:"ghost",label:"Cancel",size:"sm",onClick:xe})])]))])):_("",!0),e(ie).length>0?(i(),y("div",$t,[(i(!0),y(re,null,je(e(ie),t=>(i(),y("div",{key:t.id,class:"flex items-center justify-between rounded-lg border border-default px-4 py-3"},[d("div",Ut,[d("div",It,[s(ye,{name:"i-lucide-key",class:"text-muted shrink-0"}),d("span",Vt,V(t.name),1)]),d("div",Rt,[d("span",null,[a[25]||(a[25]=x("Prefix: ",-1)),d("code",Pt,"pd_"+V(t.keyPrefix)+"…",1)]),d("span",null,[a[26]||(a[26]=x("Created: ",-1)),s(de,{date:t.createdAt,"date-only":""},null,8,["date"])]),t.lastUsedAt?(i(),y("span",zt,[a[27]||(a[27]=x("Last used: ",-1)),s(de,{date:t.lastUsedAt,"date-only":""},null,8,["date"])])):(i(),y("span",jt,"Never used")),t.expiresAt?(i(),y("span",{key:2,class:E(new Date(t.expiresAt)<new Date?"text-error":"")},[a[28]||(a[28]=x(" Expires: ",-1)),s(de,{date:t.expiresAt,"date-only":""},null,8,["date"])],2)):_("",!0)])]),s(v,{icon:"i-lucide-trash-2",color:"error",variant:"ghost",size:"sm",title:"Revoke key",onClick:ue=>Oe(t)},null,8,["onClick"])]))),128))])):e(L)?_("",!0):(i(),y("div",St," No API keys yet. Create one to allow CI access. "))])]),footer:r(()=>[s(v,{color:"neutral",variant:"ghost",label:"Close",onClick:a[11]||(a[11]=t=>O.value=!1)}),e(L)?_("",!0):(i(),k(v,{key:0,label:"Create API key",icon:"i-lucide-plus",onClick:Be}))]),_:1},8,["open","title"])]),_:1}),s(se,null,{default:r(()=>[s(te,{open:e(B),title:"Delete user","onUpdate:open":a[14]||(a[14]=t=>B.value=t)},{body:r(()=>[d("p",null,[a[30]||(a[30]=x(" Are you sure you want to delete user ",-1)),d("strong",null,V(e(f)?.username),1),a[31]||(a[31]=x("? This action cannot be undone. ",-1))])]),footer:r(()=>[s(v,{color:"neutral",variant:"ghost",label:"Cancel",onClick:a[13]||(a[13]=t=>B.value=!1)}),s(v,{color:"error",label:"Delete user",icon:"i-lucide-trash-2",onClick:fe})]),_:1},8,["open"])]),_:1}),s(se,null,{default:r(()=>[s(te,{open:e(Z),title:"Revoke API key","onUpdate:open":a[16]||(a[16]=t=>Z.value=t)},{body:r(()=>[d("p",null,[a[32]||(a[32]=x(" Revoke API key ",-1)),d("strong",null,'"'+V(e(ee)?.name)+'"',1),a[33]||(a[33]=x("? Any CI pipeline using it will stop working immediately. ",-1))])]),footer:r(()=>[s(v,{color:"neutral",variant:"ghost",label:"Cancel",onClick:a[15]||(a[15]=t=>Z.value=!1)}),s(v,{color:"error",label:"Revoke",icon:"i-lucide-trash-2",onClick:Le})]),_:1},8,["open"])]),_:1}),s(se,null,{default:r(()=>[s(te,{open:e(ae),title:`Project access – ${e(ne)?.username}`,size:"xl","onUpdate:open":a[20]||(a[20]=t=>ae.value=t)},{title:r(()=>[d("span",Kt,[x(" Project access – "+V(e(ne)?.username)+" ",1),s(Ae,{topic:"project.members"})])]),body:r(()=>[d("div",Et,[a[34]||(a[34]=d("p",{class:"text-sm text-muted"}," Control which projects this user can access. Users without any project access will see no projects. ",-1)),s(ta,{"model-value":e(W)?"global":"specific",items:[{value:"global",label:"Global access",description:"Access to all projects (current and future)"},{value:"specific",label:"Specific projects",description:"Access only to selected projects"}],"onUpdate:modelValue":a[17]||(a[17]=t=>W.value=t==="global")},null,8,["model-value"]),e(W)?_("",!0):(i(),y(re,{key:0},[s(sa),s(F,{label:"Specific projects",description:`Select from ${e(J).length>0?e(J).length:"0"} available projects`},{default:r(()=>[s(la,{modelValue:e(Y),"onUpdate:modelValue":a[18]||(a[18]=t=>ge(Y)?Y.value=t:null),items:e(J),by:"id",multiple:"",searchable:"",class:"w-full",placeholder:"Search and select projects…"},{default:r(({modelValue:t})=>[t.length===0?(i(),y("span",Dt,"Select projects…")):(i(),y("span",Ft,V(t.length)+" project(s) selected",1))]),_:1},8,["modelValue","items"])]),_:1},8,["description"])],64))])]),footer:r(()=>[s(v,{color:"neutral",variant:"ghost",label:"Cancel",onClick:a[19]||(a[19]=t=>ae.value=!1)}),s(v,{label:"Save",icon:"i-lucide-check",onClick:We})]),_:1},8,["open","title"])]),_:1})],64)}}});export{us as default};
@@ -1 +1 @@
1
- import{a2 as $,a3 as z,a5 as S,aq as y,aW as j,r as w,aR as P,aX as V,a as B,o,e as C,f as b,g as q,i as s,b as t,c as u,h as N,U as n,k as c,t as f,l as m,W,v as h,a8 as F,N as g,bb as D,bc as K}from"./BdQ7kfxJ.js";import{L as O}from"./CxwnFFD0.js";const E={slots:{root:"",wrapper:"",labelWrapper:"flex content-center items-center justify-between gap-1",label:"block font-medium text-default",container:"relative",description:"text-muted",error:"mt-2 text-error",hint:"text-muted",help:"mt-2 text-muted"},variants:{size:{xs:{root:"text-xs"},sm:{root:"text-xs"},md:{root:"text-sm"},lg:{root:"text-sm"},xl:{root:"text-base"}},required:{true:{label:"after:content-['*'] after:ms-0.5 after:text-error"}},orientation:{vertical:{container:"mt-1"},horizontal:{root:"flex justify-between place-items-baseline gap-2"}}},defaultVariants:{size:"md"}},L=["id"],U=["id"],A=["id"],R=["id"],H={__name:"UFormField",props:{as:{type:null,required:!1},name:{type:String,required:!1},errorPattern:{type:null,required:!1},label:{type:String,required:!1},description:{type:String,required:!1},help:{type:String,required:!1},error:{type:[Boolean,String],required:!1,default:void 0},hint:{type:String,required:!1},size:{type:null,required:!1},required:{type:Boolean,required:!1},eagerValidation:{type:Boolean,required:!1},validateOnInputDelay:{type:Number,required:!1},orientation:{type:null,required:!1,default:"vertical"},class:{type:null,required:!1},ui:{type:Object,required:!1}},setup(x){const _=x,l=$(),e=z("formField",_),I=S(),a=h(()=>F({extend:E,...I.ui?.formField||{}})({size:e.size,required:e.required,orientation:e.orientation})),k=y(j,null),i=h(()=>e.error||k?.value?.find(r=>r.name===e.name||e.errorPattern&&r.name?.match(e.errorPattern))?.message),d=w(P()),p=d.value,v=y(V,void 0);return B(d,()=>{v&&e.name&&(v.value[e.name]={id:d.value,pattern:e.errorPattern})},{immediate:!0}),g(D,d),g(K,h(()=>({error:i.value,name:e.name,size:e.size,eagerValidation:e.eagerValidation,validateOnInputDelay:e.validateOnInputDelay,errorPattern:e.errorPattern,hint:e.hint,description:e.description,help:e.help,ariaId:p}))),(r,T)=>(o(),C(t(W),{as:t(e).as,"data-orientation":t(e).orientation,"data-slot":"root",class:s(a.value.root({class:[t(e).ui?.root,t(e).class]}))},{default:b(()=>[q("div",{"data-slot":"wrapper",class:s(a.value.wrapper({class:t(e).ui?.wrapper}))},[t(e).label||l.label?(o(),u("div",{key:0,"data-slot":"labelWrapper",class:s(a.value.labelWrapper({class:t(e).ui?.labelWrapper}))},[N(t(O),{for:d.value,"data-slot":"label",class:s(a.value.label({class:t(e).ui?.label}))},{default:b(()=>[n(r.$slots,"label",{label:t(e).label},()=>[c(f(t(e).label),1)])]),_:3},8,["for","class"]),t(e).hint||l.hint?(o(),u("span",{key:0,id:`${t(p)}-hint`,"data-slot":"hint",class:s(a.value.hint({class:t(e).ui?.hint}))},[n(r.$slots,"hint",{hint:t(e).hint},()=>[c(f(t(e).hint),1)])],10,L)):m("",!0)],2)):m("",!0),t(e).description||l.description?(o(),u("p",{key:1,id:`${t(p)}-description`,"data-slot":"description",class:s(a.value.description({class:t(e).ui?.description}))},[n(r.$slots,"description",{description:t(e).description},()=>[c(f(t(e).description),1)])],10,U)):m("",!0)],2),q("div",{class:s([(t(e).label||!!l.label||t(e).description||!!l.description)&&a.value.container({class:t(e).ui?.container})])},[n(r.$slots,"default",{error:i.value}),t(e).error!==!1&&(typeof i.value=="string"&&i.value||l.error)?(o(),u("div",{key:0,id:`${t(p)}-error`,"data-slot":"error",class:s(a.value.error({class:t(e).ui?.error}))},[n(r.$slots,"error",{error:i.value},()=>[c(f(i.value),1)])],10,A)):t(e).help||l.help?(o(),u("div",{key:1,id:`${t(p)}-help`,"data-slot":"help",class:s(a.value.help({class:t(e).ui?.help}))},[n(r.$slots,"help",{help:t(e).help},()=>[c(f(t(e).help),1)])],10,R)):m("",!0)],2)]),_:3},8,["as","data-orientation","class"]))}};export{H as _};
1
+ import{a2 as $,a3 as z,a5 as S,aq as y,aW as j,r as w,aR as P,aX as V,a as B,o,e as C,f as b,g as q,i as s,b as t,c as u,h as N,U as n,k as c,t as f,l as m,W,v as h,a8 as F,N as g,bb as D,bc as K}from"./1QWBzxLM.js";import{L as O}from"./Bl0xzETD.js";const E={slots:{root:"",wrapper:"",labelWrapper:"flex content-center items-center justify-between gap-1",label:"block font-medium text-default",container:"relative",description:"text-muted",error:"mt-2 text-error",hint:"text-muted",help:"mt-2 text-muted"},variants:{size:{xs:{root:"text-xs"},sm:{root:"text-xs"},md:{root:"text-sm"},lg:{root:"text-sm"},xl:{root:"text-base"}},required:{true:{label:"after:content-['*'] after:ms-0.5 after:text-error"}},orientation:{vertical:{container:"mt-1"},horizontal:{root:"flex justify-between place-items-baseline gap-2"}}},defaultVariants:{size:"md"}},L=["id"],U=["id"],A=["id"],R=["id"],H={__name:"UFormField",props:{as:{type:null,required:!1},name:{type:String,required:!1},errorPattern:{type:null,required:!1},label:{type:String,required:!1},description:{type:String,required:!1},help:{type:String,required:!1},error:{type:[Boolean,String],required:!1,default:void 0},hint:{type:String,required:!1},size:{type:null,required:!1},required:{type:Boolean,required:!1},eagerValidation:{type:Boolean,required:!1},validateOnInputDelay:{type:Number,required:!1},orientation:{type:null,required:!1,default:"vertical"},class:{type:null,required:!1},ui:{type:Object,required:!1}},setup(x){const _=x,l=$(),e=z("formField",_),I=S(),a=h(()=>F({extend:E,...I.ui?.formField||{}})({size:e.size,required:e.required,orientation:e.orientation})),k=y(j,null),i=h(()=>e.error||k?.value?.find(r=>r.name===e.name||e.errorPattern&&r.name?.match(e.errorPattern))?.message),d=w(P()),p=d.value,v=y(V,void 0);return B(d,()=>{v&&e.name&&(v.value[e.name]={id:d.value,pattern:e.errorPattern})},{immediate:!0}),g(D,d),g(K,h(()=>({error:i.value,name:e.name,size:e.size,eagerValidation:e.eagerValidation,validateOnInputDelay:e.validateOnInputDelay,errorPattern:e.errorPattern,hint:e.hint,description:e.description,help:e.help,ariaId:p}))),(r,T)=>(o(),C(t(W),{as:t(e).as,"data-orientation":t(e).orientation,"data-slot":"root",class:s(a.value.root({class:[t(e).ui?.root,t(e).class]}))},{default:b(()=>[q("div",{"data-slot":"wrapper",class:s(a.value.wrapper({class:t(e).ui?.wrapper}))},[t(e).label||l.label?(o(),u("div",{key:0,"data-slot":"labelWrapper",class:s(a.value.labelWrapper({class:t(e).ui?.labelWrapper}))},[N(t(O),{for:d.value,"data-slot":"label",class:s(a.value.label({class:t(e).ui?.label}))},{default:b(()=>[n(r.$slots,"label",{label:t(e).label},()=>[c(f(t(e).label),1)])]),_:3},8,["for","class"]),t(e).hint||l.hint?(o(),u("span",{key:0,id:`${t(p)}-hint`,"data-slot":"hint",class:s(a.value.hint({class:t(e).ui?.hint}))},[n(r.$slots,"hint",{hint:t(e).hint},()=>[c(f(t(e).hint),1)])],10,L)):m("",!0)],2)):m("",!0),t(e).description||l.description?(o(),u("p",{key:1,id:`${t(p)}-description`,"data-slot":"description",class:s(a.value.description({class:t(e).ui?.description}))},[n(r.$slots,"description",{description:t(e).description},()=>[c(f(t(e).description),1)])],10,U)):m("",!0)],2),q("div",{class:s([(t(e).label||!!l.label||t(e).description||!!l.description)&&a.value.container({class:t(e).ui?.container})])},[n(r.$slots,"default",{error:i.value}),t(e).error!==!1&&(typeof i.value=="string"&&i.value||l.error)?(o(),u("div",{key:0,id:`${t(p)}-error`,"data-slot":"error",class:s(a.value.error({class:t(e).ui?.error}))},[n(r.$slots,"error",{error:i.value},()=>[c(f(i.value),1)])],10,A)):t(e).help||l.help?(o(),u("div",{key:1,id:`${t(p)}-help`,"data-slot":"help",class:s(a.value.help({class:t(e).ui?.help}))},[n(r.$slots,"help",{help:t(e).help},()=>[c(f(t(e).help),1)])],10,R)):m("",!0)],2)]),_:3},8,["as","data-orientation","class"]))}};export{H as _};
@@ -0,0 +1 @@
1
+ import{_ as f}from"./BuMX-4RF.js";import{_ as b}from"./OMI0cmZ0.js";import{_ as h}from"./ChuJzPWz.js";import{_ as j,a as v}from"./BS91Og__.js";import{_ as $}from"./BM5C-Oec.js";import{d as x,u as w,w as y,s as C,e as P,f as a,v as B,o as N,g,h as e,b as o,r as k}from"./1QWBzxLM.js";import{u as D}from"./CU_2YLhT.js";import"./CiCUZGFZ.js";import"./e-GZmCeP.js";import"./DpM8IgHL.js";import"./DcOlL-oi.js";import"./Bx_lfKHl.js";import"./DVo_e_uj.js";import"./Dn_-RkxP.js";import"./B-1zt4pp.js";import"./DvYU87_a.js";import"./BnUQ3i5l.js";import"./Bc6Zr-Xn.js";import"./D4mPjHHR.js";import"./BFLa9ZEP.js";import"./DYdwHaco.js";import"./Dpwj_1H5.js";import"./BOA-I6S9.js";import"./Bp31ZRcA.js";import"./uspGXbik.js";import"./VBTxfbqU.js";import"./bmAf49LT.js";import"./B82vqOZe.js";import"./CHz7LJIX.js";import"./AbnDY6Zr.js";import"./B6j5Ornu.js";const R={class:"p-4"},lo=x({__name:"test-cases",async setup(T){let r,n;const i=w(),s=String(i.params.id),{data:t}=([r,n]=y(()=>D(`/api/projects/${s}`,"$GBv2haQFFX")),r=await r,n(),r),c=k(null);return C(B(()=>({title:`${t.value?.label||t.value?.name||"Project"} — Test cases — Piwi Dashboard`}))),(F,U)=>{const m=f,p=b,_=h,l=v,u=$,d=j;return N(),P(d,{id:"project-test-cases"},{header:a(()=>[e(l,null,{leading:a(()=>[e(m),e(p,{items:[{label:"Home",icon:"i-lucide-house",to:"/"},{label:"Projects",to:"/projects"},{label:o(t)?.label||o(t)?.name||"Project",to:`/projects/${o(s)}`},{label:"Test cases"}]},null,8,["items"])]),right:a(()=>[e(_,{actions:[{label:"Refresh",icon:"i-lucide-refresh-cw",onClick:()=>o(c)?.refresh()}]},null,8,["actions"])]),_:1})]),body:a(()=>[g("div",R,[e(u,{ref_key:"tableRef",ref:c,"project-id":o(s),"project-name":o(t)?.name,"sync-query":""},null,8,["project-id","project-name"])])]),_:1})}}});export{lo as default};
@@ -1 +1 @@
1
- import{r}from"./BdQ7kfxJ.js";function n(i){const o=`piwi-tree-view-${i}`,t=r(!1);try{const e=document.cookie.match(new RegExp(`(?:^|;\\s*)${o}=([^;]*)`));e&&(t.value=e[1]==="true")}catch{}function c(e){t.value=e,document.cookie=`${o}=${e}; path=/; max-age=31536000; sameSite=lax`}return{treeView:t,setTreeView:c}}export{n as u};
1
+ import{r}from"./1QWBzxLM.js";function n(i){const o=`piwi-tree-view-${i}`,t=r(!1);try{const e=document.cookie.match(new RegExp(`(?:^|;\\s*)${o}=([^;]*)`));e&&(t.value=e[1]==="true")}catch{}function c(e){t.value=e,document.cookie=`${o}=${e}; path=/; max-age=31536000; sameSite=lax`}return{treeView:t,setTreeView:c}}export{n as u};
@@ -1 +1 @@
1
- import{d as W,o as a,e as m,y as x,b as e,f as u,U as M,_ as v,l as s,v as n,k as A,G as L,x as D,h as C,c as _,t as p,g as h,F as N,z as k,r as w,j as U}from"./BdQ7kfxJ.js";import{H}from"./Bg63qh8W.js";import{a as G}from"./DTtizz85.js";const B="https://piwitests.dev";function X(t){return`${B}/${t.replace(/^\//,"")}`}const Y=W({__name:"DocLink",props:{to:{},noIcon:{type:Boolean}},setup(t){const i=t,E=n(()=>X(i.to));return(c,o)=>{const g=v,d=x;return a(),m(d,{to:e(E),target:"_blank",rel:"noopener noreferrer",class:"inline-flex items-center gap-1 text-primary hover:underline"},{default:u(()=>[M(c.$slots,"default",{},()=>[o[0]||(o[0]=A("Learn more",-1))]),t.noIcon?s("",!0):(a(),m(g,{key:0,name:"i-lucide-external-link",class:"w-3.5 h-3.5 shrink-0"}))]),_:3},8,["to"])}}}),V=Object.assign(Y,{__name:"DocLink"}),P={PIWI_SITE_URL:{description:"Public base URL of the instance (e.g. https://piwi.example.com). Used to build links in emails.",category:"general",type:"url",example:"https://piwi.example.com",notes:"When unset, links in emails point to http://localhost:3000 and OAuth callback URLs are inferred from the request host — set it when running behind a reverse proxy."},PIWI_SECRET_KEY:{description:"Master key for AES-256-GCM encryption of secrets stored in the database (AI API keys, webhook/SCM secrets). Strongly recommended in production.",category:"general",secret:!0,example:"a 64-char random hex string",notes:"Falls back to an insecure built-in development key (with a startup warning in production). Generate one with `node -e \"console.log(require('node:crypto').randomBytes(32).toString('hex'))\"`."},PIWI_BUILD_DIR:{description:"Overrides the Nuxt build output directory. Used by the test harness to isolate parallel builds.",category:"build",runtimeOnly:!0,type:"path"},PIWI_BUILD_SHA:{description:"Commit SHA baked into the build for provenance. Shown on Settings → About. Set as a build-time arg.",category:"build",runtimeOnly:!0},PIWI_DESKTOP_TOKEN:{description:"Per-install access token the desktop (Tauri) app injects to gate its local server. Set automatically by the desktop shell — not user-configurable. Absent on the server build.",category:"desktop",secret:!0,runtimeOnly:!0,since:"0.16.0"},PIWI_DATABASE_PATH:{description:"Path to the SQLite database file (used when PIWI_DATABASE_URL is not set).",category:"database",type:"path",default:".data/piwi.db",relevantWhen:{PIWI_DATABASE_URL:""}},PIWI_DATABASE_URL:{description:"PostgreSQL connection string. When set, PostgreSQL is used instead of SQLite and migrations run automatically on startup.",category:"database",secret:!0,example:"postgres://piwi:piwi@db:5432/piwi",docs:"database#postgresql"},PIWI_RETENTION_DAYS:{description:"Days of test-run history the nightly retention sweep keeps. Unset or 0 disables automatic run pruning (the default — pruning is opt-in).",category:"database",type:"number",min:0,docs:"storage#data-retention"},PIWI_RETENTION_NOTIFICATION_DAYS:{description:"Days to keep sent/failed notification outbox rows before the nightly sweep prunes them (default 30; 0 keeps them forever).",category:"database",type:"number",default:"30",min:0},PIWI_RETENTION_DIAGNOSIS_VERSIONS:{description:"AI-diagnosis history versions kept per diagnosis by the nightly sweep (default 20; 0 disables capping).",category:"database",type:"number",default:"20",min:0},PIWI_STORAGE_TYPE:{description:'Storage backend for test artifacts (HTML reports, traces, attachments): "local" or "s3".',category:"storage",type:"enum",enum:["local","s3"],default:"local",notes:"Only the exact value `s3` selects S3; any other value falls back to local storage."},PIWI_STORAGE_PATH:{description:'Directory for local file storage (when PIWI_STORAGE_TYPE is "local").',category:"storage",type:"path",default:".data/storage",relevantWhen:{PIWI_STORAGE_TYPE:"local"}},PIWI_S3_BUCKET:{description:'S3 bucket name for artifact storage (when PIWI_STORAGE_TYPE is "s3").',category:"storage",relevantWhen:{PIWI_STORAGE_TYPE:"s3"},requiredWhen:{PIWI_STORAGE_TYPE:"s3"},docs:"storage#s3-compatible-storage"},PIWI_S3_REGION:{description:'S3 bucket region (when PIWI_STORAGE_TYPE is "s3").',category:"storage",example:"us-east-1",relevantWhen:{PIWI_STORAGE_TYPE:"s3"},requiredWhen:{PIWI_STORAGE_TYPE:"s3"}},PIWI_S3_ACCESS_KEY_ID:{description:"S3 access key id with write access to the bucket.",category:"storage",secret:!0,relevantWhen:{PIWI_STORAGE_TYPE:"s3"},requiredWhen:{PIWI_STORAGE_TYPE:"s3"}},PIWI_S3_SECRET_ACCESS_KEY:{description:"S3 secret access key.",category:"storage",secret:!0,relevantWhen:{PIWI_STORAGE_TYPE:"s3"},requiredWhen:{PIWI_STORAGE_TYPE:"s3"}},PIWI_S3_ENDPOINT:{description:"Custom endpoint for S3-compatible services (MinIO, R2, Spaces).",category:"storage",type:"url",example:"https://minio.example.com",relevantWhen:{PIWI_STORAGE_TYPE:"s3"}},PIWI_S3_FORCE_PATH_STYLE:{description:"Use path-style addressing (required by some S3-compatible services).",category:"storage",type:"boolean",relevantWhen:{PIWI_STORAGE_TYPE:"s3"},notes:"Defaults to on when a custom endpoint is set, off otherwise; only the exact value `false` turns it off explicitly."},PIWI_AUTH_ENABLED:{description:'Set to "true" to enable role-based access control and API keys. Off by default.',category:"auth",type:"boolean",default:"false"},PIWI_AUTH_SECRET:{description:"Secret used to sign/encrypt session cookies. Required when PIWI_AUTH_ENABLED is true.",category:"auth",secret:!0,relevantWhen:{PIWI_AUTH_ENABLED:"true"},requiredWhen:{PIWI_AUTH_ENABLED:"true"},notes:"The server refuses to start when auth is enabled and this is unset."},PIWI_SHARE_LINKS_ENABLED:{description:'Set to "true" to allow minting read-only public share links for executions and failure clusters. Off by default; turning it off again immediately dead-ends every outstanding link without deleting anything.',category:"auth",type:"boolean",default:"false",since:"0.26.0"},PIWI_SHARE_LINK_MAX_TTL_DAYS:{description:"Longest allowed share-link lifetime, in days. The creation dialog offers expiries up to this; 0 lifts the cap and allows links with no expiry.",category:"auth",type:"number",default:"30",min:0,max:3650,relevantWhen:{PIWI_SHARE_LINKS_ENABLED:"true"},since:"0.26.0"},PIWI_TRUST_PROXY:{description:`Set to "true" when a reverse proxy sits in front of Piwi, so per-IP rate limits on the auth endpoints key on the client address your proxy appends to X-Forwarded-For instead of on the proxy's own address (which would pool every client into one bucket). Leave off when clients connect directly: the header is client-controlled then, and trusting it would let a caller choose its own bucket.`,category:"auth",type:"boolean",default:"false",since:"0.26.0"},PIWI_OAUTH_GOOGLE_CLIENT_ID:{description:"Google OAuth client id (optional single sign-on).",category:"oauth",relevantWhen:{PIWI_AUTH_ENABLED:"true"},requiredWhen:{PIWI_OAUTH_GOOGLE_CLIENT_SECRET:"*"},docs:"authentication#oauth-google-github"},PIWI_OAUTH_GOOGLE_CLIENT_SECRET:{description:"Google OAuth client secret.",category:"oauth",secret:!0,relevantWhen:{PIWI_AUTH_ENABLED:"true"},requiredWhen:{PIWI_OAUTH_GOOGLE_CLIENT_ID:"*"}},PIWI_OAUTH_GITHUB_CLIENT_ID:{description:"GitHub OAuth client id (optional single sign-on).",category:"oauth",relevantWhen:{PIWI_AUTH_ENABLED:"true"},requiredWhen:{PIWI_OAUTH_GITHUB_CLIENT_SECRET:"*"},docs:"authentication#oauth-google-github"},PIWI_OAUTH_GITHUB_CLIENT_SECRET:{description:"GitHub OAuth client secret.",category:"oauth",secret:!0,relevantWhen:{PIWI_AUTH_ENABLED:"true"},requiredWhen:{PIWI_OAUTH_GITHUB_CLIENT_ID:"*"}},PIWI_OAUTH_ALLOWED_DOMAINS:{description:"Comma-separated verified email domains allowed to sign in via OAuth (all providers).",category:"oauth",type:"list",example:"example.com,corp.example.com",relevantWhen:{PIWI_AUTH_ENABLED:"true"},notes:"Only verified emails in these domains are accepted. Empty means no domain restriction."},PIWI_OAUTH_GITHUB_ALLOWED_ORGS:{description:"Comma-separated GitHub org logins a user must belong to (requests read:org scope).",category:"oauth",type:"list",relevantWhen:{PIWI_OAUTH_GITHUB_CLIENT_ID:"*"}},PIWI_AI_PROVIDER:{description:'AI provider for failure diagnosis: "anthropic" or "openai" (OpenAI-compatible).',category:"ai",type:"enum",enum:["anthropic","openai"]},PIWI_AI_API_KEY:{description:"API key for the diagnosis provider. Takes precedence over the DB-stored key.",category:"ai",secret:!0,relevantWhen:{PIWI_AI_PROVIDER:"*"},requiredWhen:{PIWI_AI_PROVIDER:"anthropic"},notes:"Optional for OpenAI-compatible providers that need no key (e.g. a local model)."},PIWI_AI_MODEL:{description:"Diagnosis model name (default: claude-opus-4-8 for Anthropic).",category:"ai",example:"claude-opus-4-8",relevantWhen:{PIWI_AI_PROVIDER:"*"},requiredWhen:{PIWI_AI_PROVIDER:"openai"}},PIWI_AI_BASE_URL:{description:"Base URL for OpenAI-compatible providers (e.g. http://localhost:11434/v1).",category:"ai",type:"url",example:"http://localhost:11434/v1",relevantWhen:{PIWI_AI_PROVIDER:"*"},requiredWhen:{PIWI_AI_PROVIDER:"openai"}},PIWI_AI_AUTO_DIAGNOSE:{description:'Set to "true" to auto-diagnose new failure clusters when a run finishes.',category:"ai",type:"boolean",default:"false",relevantWhen:{PIWI_AI_PROVIDER:"*"}},PIWI_AI_AUTO_DIAGNOSE_MAX:{description:"Max clusters auto-diagnosed per finished run (budget cap; default 3).",category:"ai",type:"number",default:"3",min:1,relevantWhen:{PIWI_AI_AUTO_DIAGNOSE:"true"}},PIWI_AI_RESEARCH_PROVIDER:{description:"Provider for the optional research (pre-analysis) stage. Falls back to PIWI_AI_PROVIDER.",category:"ai",type:"enum",enum:["anthropic","openai"],relevantWhen:{PIWI_AI_RESEARCH_MODEL:"*"}},PIWI_AI_RESEARCH_MODEL:{description:"Cheaper/faster model for the research stage. Empty disables the two-stage pipeline.",category:"ai",relevantWhen:{PIWI_AI_PROVIDER:"*"}},PIWI_AI_RESEARCH_BASE_URL:{description:"Base URL for the research-stage provider. Falls back to PIWI_AI_BASE_URL.",category:"ai",type:"url",relevantWhen:{PIWI_AI_RESEARCH_MODEL:"*"}},PIWI_AI_RESEARCH_API_KEY:{description:"API key for the research-stage provider. Falls back to PIWI_AI_API_KEY.",category:"ai",secret:!0,relevantWhen:{PIWI_AI_RESEARCH_MODEL:"*"}},PIWI_AI_EMBEDDING_PROVIDER:{description:"Provider for embeddings (semantic failure clustering). Falls back to PIWI_AI_PROVIDER.",category:"ai",type:"enum",enum:["openai"],relevantWhen:{PIWI_AI_EMBEDDING_MODEL:"*"},notes:'Must resolve to an OpenAI-compatible provider — Anthropic has no embeddings API — so the fallback only helps when the main provider is "openai".'},PIWI_AI_EMBEDDING_MODEL:{description:"Embedding model name (e.g. text-embedding-3-small).",category:"ai",example:"text-embedding-3-small",relevantWhen:{PIWI_AI_PROVIDER:"*"},notes:"Empty disables semantic clustering (and the embedding fallbacks)."},PIWI_AI_EMBEDDING_BASE_URL:{description:"Base URL for the embedding provider. Falls back to PIWI_AI_BASE_URL.",category:"ai",type:"url",relevantWhen:{PIWI_AI_EMBEDDING_MODEL:"*"}},PIWI_AI_EMBEDDING_API_KEY:{description:"API key for the embedding provider. Falls back to PIWI_AI_API_KEY.",category:"ai",secret:!0,relevantWhen:{PIWI_AI_EMBEDDING_MODEL:"*"}},PIWI_AI_MAX_SAMPLE_ERROR_CHARS:{description:"Max characters of raw error text (per error block).",category:"ai-limits",type:"number",default:"10000",min:200,max:5e4},PIWI_AI_MAX_SCM_PATCH_BUDGET:{description:"Total characters of diff patches across changed files.",category:"ai-limits",type:"number",default:"15000",min:0,max:5e4},PIWI_AI_MAX_AFFECTED_TESTS:{description:"Max affected tests listed in the diagnosis context.",category:"ai-limits",type:"number",default:"30",min:1,max:200},PIWI_AI_MAX_STEPS:{description:"Max recent test steps included.",category:"ai-limits",type:"number",default:"50",min:1,max:200},PIWI_AI_MAX_CONSOLE_ENTRIES:{description:"Max console error/warning entries included.",category:"ai-limits",type:"number",default:"30",min:0,max:200},PIWI_AI_MAX_CONSOLE_ENTRY_CHARS:{description:"Max characters per console entry.",category:"ai-limits",type:"number",default:"1000",min:50,max:5e3},PIWI_AI_MAX_NETWORK_REQUESTS:{description:"Max failed network requests included.",category:"ai-limits",type:"number",default:"25",min:0,max:200},PIWI_AI_MAX_ARIA_SNAPSHOT_CHARS:{description:"Max characters of the page ARIA snapshot.",category:"ai-limits",type:"number",default:"12000",min:0,max:5e4},PIWI_AI_MAX_TEST_SOURCE_CHARS:{description:"Max characters of the test source snippet.",category:"ai-limits",type:"number",default:"8000",min:0,max:5e4},PIWI_AI_MAX_SOURCE_FILES:{description:"Max full source files fetched from SCM to ground patches (0 disables).",category:"ai-limits",type:"number",default:"4",min:0,max:20},PIWI_AI_MAX_SOURCE_FILE_CHARS:{description:"Max characters per fetched full source file.",category:"ai-limits",type:"number",default:"12000",min:0,max:5e4},PIWI_AI_MAX_SERVER_LOG_ENTRIES:{description:"Max backend server log entries (from X-Piwi-Logs header) included.",category:"ai-limits",type:"number",default:"50",min:0,max:200},PIWI_AI_MAX_SERVER_LOG_ENTRY_CHARS:{description:"Max characters per backend server log entry.",category:"ai-limits",type:"number",default:"1000",min:50,max:5e3},PIWI_AI_MAX_SERVER_TRACE_SPANS:{description:"Max backend server spans (from X-Piwi-Trace header) included in AI diagnosis (0 disables).",category:"ai-limits",type:"number",default:"40",min:0,max:500,since:"0.16.0"},PIWI_AI_MAX_STEP_INTENTS:{description:"Max AI-step intent mappings (natural-language prompt → compiled locator) included in a diagnosis (0 disables the section).",category:"ai-limits",type:"number",default:"20",min:0,max:100,since:"0.24.0"},PIWI_AI_STEP_MAX_SNAPSHOT_CHARS:{description:"Max characters of the page ARIA snapshot the reporter sends per AI-step authoring iteration.",category:"ai-steps",type:"number",default:"24000",min:0,max:1e5,since:"0.24.0"},PIWI_AI_STEP_MAX_OUTPUT_TOKENS:{description:"Max output tokens the model may return per AI-step authoring iteration. Reasoning models count hidden chain-of-thought against this, so raise it (up to 8192) when authoring with one.",category:"ai-steps",type:"number",default:"1024",min:256,max:8192,since:"0.24.0"},PIWI_AI_MAX_IMAGES:{description:"Max screenshots auto-included in the diagnosis context.",category:"ai-limits",type:"number",default:"5",min:0,max:20},PIWI_AI_MAX_PASSED_PEERS:{description:"Max peer tests in the same file listed when they passed.",category:"ai-limits",type:"number",default:"20",min:0,max:100},PIWI_AI_MAX_CONSOLE_WINDOW:{description:"Max console entries of any type in the window before failure.",category:"ai-limits",type:"number",default:"50",min:0,max:200},PIWI_AI_SLOW_REQUEST_MS:{description:"Network request duration (ms) threshold for flagging as slow.",category:"ai-limits",type:"number",default:"1500",min:100,max:3e4},PIWI_AI_MAX_TRACE_ACTIONS:{description:"Max actions extracted from trace ZIP for failing-action context (0 disables).",category:"ai-limits",type:"number",default:"10",min:0,max:50},PIWI_AI_TRACE_DOM_CHARS:{description:"Max characters for the trace-derived DOM/ARIA excerpt in failing-action context.",category:"ai-limits",type:"number",default:"6000",min:0,max:2e4},PIWI_AI_MAX_TRACE_STACK_FRAMES:{description:"Max call-stack frames (with source windows) from the trace call-stack section (0 disables).",category:"ai-limits",type:"number",default:"10",min:0,max:50},PIWI_AI_MAX_TRACE_NETWORK_REQUESTS:{description:"Max requests included from the trace network stream (0 disables).",category:"ai-limits",type:"number",default:"20",min:0,max:200},PIWI_AI_MAX_DOM_SNAPSHOT_CHARS:{description:"Max characters of the failure-time DOM snapshot rendered from the trace (0 disables).",category:"ai-limits",type:"number",default:"8000",min:0,max:5e4},PIWI_AI_IMAGE_MAX_EDGE:{description:"Screenshots are downscaled to at most this many pixels on the long edge before being sent.",category:"ai-limits",type:"number",default:"1920",min:512,max:8192},PIWI_INGEST_MAX_CONSOLE_ENTRIES:{description:"Max console entries stored per test execution.",category:"ingest",type:"number",default:"200",min:10,max:5e3},PIWI_IMPORT_MAX_BYTES:{description:"Max size of a single multipart upload (report upload or blob-report import), in bytes. Lower it to match a reverse proxy that rejects large bodies, so the import page rejects an oversized archive before uploading it.",category:"ingest",type:"number",default:String(500*1024*1024),min:1024*1024,max:5*1024*1024*1024,since:"0.19.0"},PIWI_EXPORT_MAX_INLINE_BYTES:{description:"Max size of a single evidence file embedded as a data: URI in an HTML export, in bytes. Larger files are left out of the single-file HTML (and listed as omitted); the ZIP export still carries them at full size.",category:"export",type:"number",default:String(8*1024*1024),min:64*1024,max:512*1024*1024,since:"0.19.0"},PIWI_EXPORT_MAX_BYTES:{description:"Max total size of one export, in bytes. Evidence is added largest-last until the budget is reached; the rest is listed as omitted. The archive is built in memory, so this also bounds what a single export costs the server.",category:"export",type:"number",default:String(500*1024*1024),min:1024*1024,max:4*1024*1024*1024,since:"0.19.0"},PIWI_EXPORT_MAX_CASES:{description:"Max member executions carrying full evidence in a failure-cluster export. Remaining affected tests are listed by name without their evidence.",category:"export",type:"number",default:"25",min:1,max:200,since:"0.19.0"},PIWI_INGEST_MAX_CONSOLE_ENTRY_CHARS:{description:"Max characters stored per console entry.",category:"ingest",type:"number",default:"2000",min:200,max:2e4},PIWI_INGEST_MAX_STEPS:{description:"Max test steps stored per execution.",category:"ingest",type:"number",default:"500",min:20,max:5e3},PIWI_INGEST_MAX_STEP_EVENTS:{description:"Max step events stored per execution.",category:"ingest",type:"number",default:"1000",min:20,max:1e4},PIWI_INGEST_MAX_ARIA_CHARS:{description:"Max characters of the ARIA snapshot stored per failing execution.",category:"ingest",type:"number",default:"100000",min:1e3,max:1e6},PIWI_INGEST_MAX_ERROR_CHARS:{description:"Max characters of error text stored per execution (head and tail are kept).",category:"ingest",type:"number",default:"20000",min:1e3,max:1e5},PIWI_INGEST_MAX_SAMPLE_ERROR_CHARS:{description:"Max characters of the sample error stored per failure cluster.",category:"ingest",type:"number",default:"50000",min:1e3,max:2e5},PIWI_INGEST_MAX_TEST_SOURCE_CHARS:{description:"Max characters of the test source snippet stored per failing execution.",category:"ingest",type:"number",default:"50000",min:1e3,max:2e5},PIWI_INGEST_MAX_SOURCE_FRAMES:{description:"Max source stack frames stored per failing execution.",category:"ingest",type:"number",default:"8",min:1,max:32},PIWI_INGEST_MAX_SOURCE_FRAME_CHARS:{description:"Max characters per stored source frame snippet.",category:"ingest",type:"number",default:"4000",min:500,max:2e4},PIWI_AUTO_MARKERS:{description:"Automatically create a timeline marker when a run’s environment, Playwright version, or reporter version changes from the previous run (default: enabled). Set to false to disable.",category:"markers",type:"boolean",default:"true",docs:"timeline-markers",notes:"Only the exact value `false` disables auto-markers."},PIWI_TEST_LOGS_DISABLED:{description:"Disable X-Piwi-Logs response header emission (default: auto-disabled in production, enabled in development).",category:"testing",type:"boolean",docs:"backend-logs",notes:"Unset: capture is on in development and off in production builds; `true` forces it off everywhere, `false` forces it on even in production."},PIWI_CLUSTER_SIMILARITY_THRESHOLD:{description:"Cosine similarity (0–1) above which two failure embeddings merge into one cluster.",category:"clustering",type:"number",default:"0.92",min:0,max:1,relevantWhen:{PIWI_AI_EMBEDDING_MODEL:"*"},notes:"Must be greater than 0 and at most 1; invalid values fall back to the default."},PIWI_CLUSTER_SUGGEST_THRESHOLD:{description:"Similarity at which a failure is suggested (not auto-merged) as related to a cluster.",category:"clustering",type:"number",default:"0.80",min:0,max:1,relevantWhen:{PIWI_AI_EMBEDDING_MODEL:"*"},notes:"Capped at the merge threshold."},PIWI_SMTP_HOST:{description:"SMTP server hostname for outbound email.",category:"smtp",example:"smtp.example.com"},PIWI_SMTP_PORT:{description:"SMTP port (default 587; 465 for implicit TLS).",category:"smtp",type:"number",default:"587",min:1,max:65535,relevantWhen:{PIWI_SMTP_HOST:"*"}},PIWI_SMTP_USER:{description:"SMTP username. Optional — only when the server requires authentication.",category:"smtp",relevantWhen:{PIWI_SMTP_HOST:"*"}},PIWI_SMTP_PASS:{description:"SMTP password. Optional — only when the server requires authentication. Never returned by the API.",category:"smtp",secret:!0,relevantWhen:{PIWI_SMTP_HOST:"*"}},PIWI_SMTP_FROM:{description:"From address for outbound email (e.g. noreply@example.com).",category:"smtp",example:"noreply@example.com",relevantWhen:{PIWI_SMTP_HOST:"*"},requiredWhen:{PIWI_SMTP_HOST:"*"}},PIWI_SMTP_FROM_NAME:{description:"Display name for the from address (optional).",category:"smtp",default:"Piwi Dashboard",relevantWhen:{PIWI_SMTP_HOST:"*"}},PIWI_SMTP_SECURE:{description:'Set to "true" for implicit TLS on port 465 (default false → STARTTLS/plain).',category:"smtp",type:"boolean",relevantWhen:{PIWI_SMTP_HOST:"*"},notes:"Defaults to on when the port is 465, off otherwise."},PIWI_WASTED_WAIT_PATTERNS:{description:"Glob patterns (comma or newline separated) defining which wait steps count as wasted time. Locks the UI when set.",category:"wasted-time",type:"list",default:"Wait for timeout*,*waitForTimeout*",notes:"Case-insensitive globs (`*` and `?`) matched against a wait step’s title or source location. Use `*` to count every wait."},PIWI_DEMO_MODE:{description:'Set to "true" to build the standalone client-side demo SPA (no server).',category:"demo",runtimeOnly:!0,type:"boolean"},PIWI_BASE_URL:{description:"Base URL the metadata test spec targets (defaults to http://localhost:3000).",category:"test",runtimeOnly:!0},PIWI_POSTGRES_TEST_URL:{description:"PostgreSQL connection string used by the Postgres test suite.",category:"test",runtimeOnly:!0,secret:!0},PIWI_S3_TEST_BUCKET:{description:"S3 bucket for the storage integration tests.",category:"test",runtimeOnly:!0},PIWI_S3_TEST_REGION:{description:"Region for the S3 storage integration tests.",category:"test",runtimeOnly:!0},PIWI_S3_TEST_ACCESS_KEY_ID:{description:"Access key id for the S3 storage integration tests.",category:"test",runtimeOnly:!0,secret:!0},PIWI_S3_TEST_SECRET_ACCESS_KEY:{description:"Secret access key for the S3 storage integration tests.",category:"test",runtimeOnly:!0,secret:!0},PIWI_S3_TEST_ENDPOINT:{description:"Custom endpoint for the S3 storage integration tests.",category:"test",runtimeOnly:!0},PIWI_MAILPIT_URL:{description:"Mailpit base URL; when set, the email/notification E2E tests run against it.",category:"test",runtimeOnly:!0},PIWI_MAILPIT_SMTP_PORT:{description:"SMTP port the email E2E tests send to (Mailpit).",category:"test",runtimeOnly:!0},PIWI_EMAIL_SERVER_URL:{description:"Base URL the email test spec targets.",category:"test",runtimeOnly:!0},PIWI_TEST_CLEANUP_ENABLED:{description:"Allow the E2E cleanup endpoint (`DELETE /api/tests/cleanup`) on a production build, which CI needs because it runs the suite against one. Never set it on a real deployment.",category:"test",runtimeOnly:!0,type:"boolean",since:"0.19.0"}};function T(t){return P[t]}function oe(t){return Object.keys(P).filter(i=>P[i].category===t)}const q={key:0,class:"font-medium mb-1"},F={class:"text-muted"},K={key:1,class:"mt-2 space-y-1"},$={class:"text-muted text-xs"},z={class:"flex flex-col gap-1.5"},Q=["title","onClick"],j={class:"block font-mono text-xs bg-elevated rounded px-1.5 py-0.5 select-all cursor-pointer group-hover:ring-1 ring-default"},Z={key:0,class:"block text-muted text-[11px] mt-0.5"},J={key:2,class:"mt-2 flex flex-col gap-1"},ee=W({__name:"HelpHint",props:{topic:{},title:{},text:{},doc:{},envVars:{},size:{}},setup(t){const i=t,{copy:E}=G(),c=n(()=>i.topic?H[i.topic]:null),o=n(()=>i.title??c.value?.title),g=n(()=>i.text??c.value?.text??""),d=n(()=>i.doc??c.value?.doc),I=n(()=>i.envVars??c.value?.envVars),y=w(!1),S=n(()=>o.value?`Help: ${o.value}`:"Help"),b=n(()=>({side:"bottom","aria-label":S.value}));return(te,l)=>{const R=U,f=V,O=L;return a(),m(O,{open:e(y),"onUpdate:open":l[0]||(l[0]=r=>D(y)?y.value=r:null),content:e(b),ui:{content:"max-w-xs p-3 text-sm"}},{content:u(()=>[e(o)?(a(),_("p",q,p(e(o)),1)):s("",!0),h("p",F,p(e(g)),1),e(I)?.length?(a(),_("div",K,[h("p",$,"Environment variable"+p(e(I).length>1?"s":"")+":",1),h("div",z,[(a(!0),_(N,null,k(e(I),r=>(a(),_("button",{key:r,type:"button",class:"group text-left",title:`Click to copy ${r}`,onClick:ae=>e(E)(r,{toast:`Copied ${r}`})},[h("code",j,p(r),1),e(T)(r).description?(a(),_("span",Z,p(e(T)(r).description),1)):s("",!0)],8,Q))),128))])])):s("",!0),e(d)||e(I)?.length?(a(),_("div",J,[e(d)?(a(),m(f,{key:0,to:e(d)},{default:u(()=>[...l[1]||(l[1]=[A("Learn more",-1)])]),_:1},8,["to"])):s("",!0),e(I)?.length?(a(),m(f,{key:1,to:"configuration"},{default:u(()=>[...l[2]||(l[2]=[A("Configuration reference",-1)])]),_:1})):s("",!0)])):s("",!0)]),default:u(()=>[C(R,{size:t.size??"xs",variant:"ghost",color:"neutral",icon:"i-lucide-circle-help","aria-label":e(S),title:"What is this?",class:"text-muted hover:text-default align-middle"},null,8,["size","aria-label"])]),_:1},8,["open","content"])}}}),se=Object.assign(ee,{__name:"HelpHint"});export{se as _,V as a,X as d,oe as e,T as g};
1
+ import{d as W,o as a,e as m,y as x,b as e,f as u,U as M,_ as v,l as s,v as n,k as A,G as L,x as D,h as C,c as _,t as p,g as h,F as N,z as k,r as w,j as U}from"./1QWBzxLM.js";import{H}from"./CHz7LJIX.js";import{a as G}from"./CU_2YLhT.js";const B="https://piwitests.dev";function X(t){return`${B}/${t.replace(/^\//,"")}`}const Y=W({__name:"DocLink",props:{to:{},noIcon:{type:Boolean}},setup(t){const i=t,E=n(()=>X(i.to));return(c,o)=>{const g=v,d=x;return a(),m(d,{to:e(E),target:"_blank",rel:"noopener noreferrer",class:"inline-flex items-center gap-1 text-primary hover:underline"},{default:u(()=>[M(c.$slots,"default",{},()=>[o[0]||(o[0]=A("Learn more",-1))]),t.noIcon?s("",!0):(a(),m(g,{key:0,name:"i-lucide-external-link",class:"w-3.5 h-3.5 shrink-0"}))]),_:3},8,["to"])}}}),V=Object.assign(Y,{__name:"DocLink"}),P={PIWI_SITE_URL:{description:"Public base URL of the instance (e.g. https://piwi.example.com). Used to build links in emails.",category:"general",type:"url",example:"https://piwi.example.com",notes:"When unset, links in emails point to http://localhost:3000 and OAuth callback URLs are inferred from the request host — set it when running behind a reverse proxy."},PIWI_SECRET_KEY:{description:"Master key for AES-256-GCM encryption of secrets stored in the database (AI API keys, webhook/SCM secrets). Strongly recommended in production.",category:"general",secret:!0,example:"a 64-char random hex string",notes:"Falls back to an insecure built-in development key (with a startup warning in production). Generate one with `node -e \"console.log(require('node:crypto').randomBytes(32).toString('hex'))\"`."},PIWI_BUILD_DIR:{description:"Overrides the Nuxt build output directory. Used by the test harness to isolate parallel builds.",category:"build",runtimeOnly:!0,type:"path"},PIWI_BUILD_SHA:{description:"Commit SHA baked into the build for provenance. Shown on Settings → About. Set as a build-time arg.",category:"build",runtimeOnly:!0},PIWI_DESKTOP_TOKEN:{description:"Per-install access token the desktop (Tauri) app injects to gate its local server. Set automatically by the desktop shell — not user-configurable. Absent on the server build.",category:"desktop",secret:!0,runtimeOnly:!0,since:"0.16.0"},PIWI_DATABASE_PATH:{description:"Path to the SQLite database file (used when PIWI_DATABASE_URL is not set).",category:"database",type:"path",default:".data/piwi.db",relevantWhen:{PIWI_DATABASE_URL:""}},PIWI_DATABASE_URL:{description:"PostgreSQL connection string. When set, PostgreSQL is used instead of SQLite and migrations run automatically on startup.",category:"database",secret:!0,example:"postgres://piwi:piwi@db:5432/piwi",docs:"database#postgresql"},PIWI_RETENTION_DAYS:{description:"Days of test-run history the nightly retention sweep keeps. Unset or 0 disables automatic run pruning (the default — pruning is opt-in).",category:"database",type:"number",min:0,docs:"storage#data-retention"},PIWI_RETENTION_NOTIFICATION_DAYS:{description:"Days to keep sent/failed notification outbox rows before the nightly sweep prunes them (default 30; 0 keeps them forever).",category:"database",type:"number",default:"30",min:0},PIWI_RETENTION_DIAGNOSIS_VERSIONS:{description:"AI-diagnosis history versions kept per diagnosis by the nightly sweep (default 20; 0 disables capping).",category:"database",type:"number",default:"20",min:0},PIWI_STORAGE_TYPE:{description:'Storage backend for test artifacts (HTML reports, traces, attachments): "local" or "s3".',category:"storage",type:"enum",enum:["local","s3"],default:"local",notes:"Only the exact value `s3` selects S3; any other value falls back to local storage."},PIWI_STORAGE_PATH:{description:'Directory for local file storage (when PIWI_STORAGE_TYPE is "local").',category:"storage",type:"path",default:".data/storage",relevantWhen:{PIWI_STORAGE_TYPE:"local"}},PIWI_S3_BUCKET:{description:'S3 bucket name for artifact storage (when PIWI_STORAGE_TYPE is "s3").',category:"storage",relevantWhen:{PIWI_STORAGE_TYPE:"s3"},requiredWhen:{PIWI_STORAGE_TYPE:"s3"},docs:"storage#s3-compatible-storage"},PIWI_S3_REGION:{description:'S3 bucket region (when PIWI_STORAGE_TYPE is "s3").',category:"storage",example:"us-east-1",relevantWhen:{PIWI_STORAGE_TYPE:"s3"},requiredWhen:{PIWI_STORAGE_TYPE:"s3"}},PIWI_S3_ACCESS_KEY_ID:{description:"S3 access key id with write access to the bucket.",category:"storage",secret:!0,relevantWhen:{PIWI_STORAGE_TYPE:"s3"},requiredWhen:{PIWI_STORAGE_TYPE:"s3"}},PIWI_S3_SECRET_ACCESS_KEY:{description:"S3 secret access key.",category:"storage",secret:!0,relevantWhen:{PIWI_STORAGE_TYPE:"s3"},requiredWhen:{PIWI_STORAGE_TYPE:"s3"}},PIWI_S3_ENDPOINT:{description:"Custom endpoint for S3-compatible services (MinIO, R2, Spaces).",category:"storage",type:"url",example:"https://minio.example.com",relevantWhen:{PIWI_STORAGE_TYPE:"s3"}},PIWI_S3_FORCE_PATH_STYLE:{description:"Use path-style addressing (required by some S3-compatible services).",category:"storage",type:"boolean",relevantWhen:{PIWI_STORAGE_TYPE:"s3"},notes:"Defaults to on when a custom endpoint is set, off otherwise; only the exact value `false` turns it off explicitly."},PIWI_AUTH_ENABLED:{description:'Set to "true" to enable role-based access control and API keys. Off by default.',category:"auth",type:"boolean",default:"false"},PIWI_AUTH_SECRET:{description:"Secret used to sign/encrypt session cookies. Required when PIWI_AUTH_ENABLED is true.",category:"auth",secret:!0,relevantWhen:{PIWI_AUTH_ENABLED:"true"},requiredWhen:{PIWI_AUTH_ENABLED:"true"},notes:"The server refuses to start when auth is enabled and this is unset."},PIWI_SHARE_LINKS_ENABLED:{description:'Set to "true" to allow minting read-only public share links for executions and failure clusters. Off by default; turning it off again immediately dead-ends every outstanding link without deleting anything.',category:"auth",type:"boolean",default:"false",since:"0.26.0"},PIWI_SHARE_LINK_MAX_TTL_DAYS:{description:"Longest allowed share-link lifetime, in days. The creation dialog offers expiries up to this; 0 lifts the cap and allows links with no expiry.",category:"auth",type:"number",default:"30",min:0,max:3650,relevantWhen:{PIWI_SHARE_LINKS_ENABLED:"true"},since:"0.26.0"},PIWI_TRUST_PROXY:{description:`Set to "true" when a reverse proxy sits in front of Piwi, so per-IP rate limits on the auth endpoints key on the client address your proxy appends to X-Forwarded-For instead of on the proxy's own address (which would pool every client into one bucket). Leave off when clients connect directly: the header is client-controlled then, and trusting it would let a caller choose its own bucket.`,category:"auth",type:"boolean",default:"false",since:"0.26.0"},PIWI_OAUTH_GOOGLE_CLIENT_ID:{description:"Google OAuth client id (optional single sign-on).",category:"oauth",relevantWhen:{PIWI_AUTH_ENABLED:"true"},requiredWhen:{PIWI_OAUTH_GOOGLE_CLIENT_SECRET:"*"},docs:"authentication#oauth-google-github"},PIWI_OAUTH_GOOGLE_CLIENT_SECRET:{description:"Google OAuth client secret.",category:"oauth",secret:!0,relevantWhen:{PIWI_AUTH_ENABLED:"true"},requiredWhen:{PIWI_OAUTH_GOOGLE_CLIENT_ID:"*"}},PIWI_OAUTH_GITHUB_CLIENT_ID:{description:"GitHub OAuth client id (optional single sign-on).",category:"oauth",relevantWhen:{PIWI_AUTH_ENABLED:"true"},requiredWhen:{PIWI_OAUTH_GITHUB_CLIENT_SECRET:"*"},docs:"authentication#oauth-google-github"},PIWI_OAUTH_GITHUB_CLIENT_SECRET:{description:"GitHub OAuth client secret.",category:"oauth",secret:!0,relevantWhen:{PIWI_AUTH_ENABLED:"true"},requiredWhen:{PIWI_OAUTH_GITHUB_CLIENT_ID:"*"}},PIWI_OAUTH_ALLOWED_DOMAINS:{description:"Comma-separated verified email domains allowed to sign in via OAuth (all providers).",category:"oauth",type:"list",example:"example.com,corp.example.com",relevantWhen:{PIWI_AUTH_ENABLED:"true"},notes:"Only verified emails in these domains are accepted. Empty means no domain restriction."},PIWI_OAUTH_GITHUB_ALLOWED_ORGS:{description:"Comma-separated GitHub org logins a user must belong to (requests read:org scope).",category:"oauth",type:"list",relevantWhen:{PIWI_OAUTH_GITHUB_CLIENT_ID:"*"}},PIWI_AI_PROVIDER:{description:'AI provider for failure diagnosis: "anthropic" or "openai" (OpenAI-compatible).',category:"ai",type:"enum",enum:["anthropic","openai"]},PIWI_AI_API_KEY:{description:"API key for the diagnosis provider. Takes precedence over the DB-stored key.",category:"ai",secret:!0,relevantWhen:{PIWI_AI_PROVIDER:"*"},requiredWhen:{PIWI_AI_PROVIDER:"anthropic"},notes:"Optional for OpenAI-compatible providers that need no key (e.g. a local model)."},PIWI_AI_MODEL:{description:"Diagnosis model name (default: claude-opus-4-8 for Anthropic).",category:"ai",example:"claude-opus-4-8",relevantWhen:{PIWI_AI_PROVIDER:"*"},requiredWhen:{PIWI_AI_PROVIDER:"openai"}},PIWI_AI_BASE_URL:{description:"Base URL for OpenAI-compatible providers (e.g. http://localhost:11434/v1).",category:"ai",type:"url",example:"http://localhost:11434/v1",relevantWhen:{PIWI_AI_PROVIDER:"*"},requiredWhen:{PIWI_AI_PROVIDER:"openai"}},PIWI_AI_AUTO_DIAGNOSE:{description:'Set to "true" to auto-diagnose new failure clusters when a run finishes.',category:"ai",type:"boolean",default:"false",relevantWhen:{PIWI_AI_PROVIDER:"*"}},PIWI_AI_AUTO_DIAGNOSE_MAX:{description:"Max clusters auto-diagnosed per finished run (budget cap; default 3).",category:"ai",type:"number",default:"3",min:1,relevantWhen:{PIWI_AI_AUTO_DIAGNOSE:"true"}},PIWI_AI_RESEARCH_PROVIDER:{description:"Provider for the optional research (pre-analysis) stage. Falls back to PIWI_AI_PROVIDER.",category:"ai",type:"enum",enum:["anthropic","openai"],relevantWhen:{PIWI_AI_RESEARCH_MODEL:"*"}},PIWI_AI_RESEARCH_MODEL:{description:"Cheaper/faster model for the research stage. Empty disables the two-stage pipeline.",category:"ai",relevantWhen:{PIWI_AI_PROVIDER:"*"}},PIWI_AI_RESEARCH_BASE_URL:{description:"Base URL for the research-stage provider. Falls back to PIWI_AI_BASE_URL.",category:"ai",type:"url",relevantWhen:{PIWI_AI_RESEARCH_MODEL:"*"}},PIWI_AI_RESEARCH_API_KEY:{description:"API key for the research-stage provider. Falls back to PIWI_AI_API_KEY.",category:"ai",secret:!0,relevantWhen:{PIWI_AI_RESEARCH_MODEL:"*"}},PIWI_AI_EMBEDDING_PROVIDER:{description:"Provider for embeddings (semantic failure clustering). Falls back to PIWI_AI_PROVIDER.",category:"ai",type:"enum",enum:["openai"],relevantWhen:{PIWI_AI_EMBEDDING_MODEL:"*"},notes:'Must resolve to an OpenAI-compatible provider — Anthropic has no embeddings API — so the fallback only helps when the main provider is "openai".'},PIWI_AI_EMBEDDING_MODEL:{description:"Embedding model name (e.g. text-embedding-3-small).",category:"ai",example:"text-embedding-3-small",relevantWhen:{PIWI_AI_PROVIDER:"*"},notes:"Empty disables semantic clustering (and the embedding fallbacks)."},PIWI_AI_EMBEDDING_BASE_URL:{description:"Base URL for the embedding provider. Falls back to PIWI_AI_BASE_URL.",category:"ai",type:"url",relevantWhen:{PIWI_AI_EMBEDDING_MODEL:"*"}},PIWI_AI_EMBEDDING_API_KEY:{description:"API key for the embedding provider. Falls back to PIWI_AI_API_KEY.",category:"ai",secret:!0,relevantWhen:{PIWI_AI_EMBEDDING_MODEL:"*"}},PIWI_AI_MAX_SAMPLE_ERROR_CHARS:{description:"Max characters of raw error text (per error block).",category:"ai-limits",type:"number",default:"10000",min:200,max:5e4},PIWI_AI_MAX_SCM_PATCH_BUDGET:{description:"Total characters of diff patches across changed files.",category:"ai-limits",type:"number",default:"15000",min:0,max:5e4},PIWI_AI_MAX_AFFECTED_TESTS:{description:"Max affected tests listed in the diagnosis context.",category:"ai-limits",type:"number",default:"30",min:1,max:200},PIWI_AI_MAX_STEPS:{description:"Max recent test steps included.",category:"ai-limits",type:"number",default:"50",min:1,max:200},PIWI_AI_MAX_CONSOLE_ENTRIES:{description:"Max console error/warning entries included.",category:"ai-limits",type:"number",default:"30",min:0,max:200},PIWI_AI_MAX_CONSOLE_ENTRY_CHARS:{description:"Max characters per console entry.",category:"ai-limits",type:"number",default:"1000",min:50,max:5e3},PIWI_AI_MAX_NETWORK_REQUESTS:{description:"Max failed network requests included.",category:"ai-limits",type:"number",default:"25",min:0,max:200},PIWI_AI_MAX_ARIA_SNAPSHOT_CHARS:{description:"Max characters of the page ARIA snapshot.",category:"ai-limits",type:"number",default:"12000",min:0,max:5e4},PIWI_AI_MAX_TEST_SOURCE_CHARS:{description:"Max characters of the test source snippet.",category:"ai-limits",type:"number",default:"8000",min:0,max:5e4},PIWI_AI_MAX_SOURCE_FILES:{description:"Max full source files fetched from SCM to ground patches (0 disables).",category:"ai-limits",type:"number",default:"4",min:0,max:20},PIWI_AI_MAX_SOURCE_FILE_CHARS:{description:"Max characters per fetched full source file.",category:"ai-limits",type:"number",default:"12000",min:0,max:5e4},PIWI_AI_MAX_SERVER_LOG_ENTRIES:{description:"Max backend server log entries (from X-Piwi-Logs header) included.",category:"ai-limits",type:"number",default:"50",min:0,max:200},PIWI_AI_MAX_SERVER_LOG_ENTRY_CHARS:{description:"Max characters per backend server log entry.",category:"ai-limits",type:"number",default:"1000",min:50,max:5e3},PIWI_AI_MAX_SERVER_TRACE_SPANS:{description:"Max backend server spans (from X-Piwi-Trace header) included in AI diagnosis (0 disables).",category:"ai-limits",type:"number",default:"40",min:0,max:500,since:"0.16.0"},PIWI_AI_MAX_STEP_INTENTS:{description:"Max AI-step intent mappings (natural-language prompt → compiled locator) included in a diagnosis (0 disables the section).",category:"ai-limits",type:"number",default:"20",min:0,max:100,since:"0.24.0"},PIWI_AI_STEP_MAX_SNAPSHOT_CHARS:{description:"Max characters of the page ARIA snapshot the reporter sends per AI-step authoring iteration.",category:"ai-steps",type:"number",default:"24000",min:0,max:1e5,since:"0.24.0"},PIWI_AI_STEP_MAX_OUTPUT_TOKENS:{description:"Max output tokens the model may return per AI-step authoring iteration. Reasoning models count hidden chain-of-thought against this, so raise it (up to 8192) when authoring with one.",category:"ai-steps",type:"number",default:"1024",min:256,max:8192,since:"0.24.0"},PIWI_AI_MAX_IMAGES:{description:"Max screenshots auto-included in the diagnosis context.",category:"ai-limits",type:"number",default:"5",min:0,max:20},PIWI_AI_MAX_PASSED_PEERS:{description:"Max peer tests in the same file listed when they passed.",category:"ai-limits",type:"number",default:"20",min:0,max:100},PIWI_AI_MAX_CONSOLE_WINDOW:{description:"Max console entries of any type in the window before failure.",category:"ai-limits",type:"number",default:"50",min:0,max:200},PIWI_AI_SLOW_REQUEST_MS:{description:"Network request duration (ms) threshold for flagging as slow.",category:"ai-limits",type:"number",default:"1500",min:100,max:3e4},PIWI_AI_MAX_TRACE_ACTIONS:{description:"Max actions extracted from trace ZIP for failing-action context (0 disables).",category:"ai-limits",type:"number",default:"10",min:0,max:50},PIWI_AI_TRACE_DOM_CHARS:{description:"Max characters for the trace-derived DOM/ARIA excerpt in failing-action context.",category:"ai-limits",type:"number",default:"6000",min:0,max:2e4},PIWI_AI_MAX_TRACE_STACK_FRAMES:{description:"Max call-stack frames (with source windows) from the trace call-stack section (0 disables).",category:"ai-limits",type:"number",default:"10",min:0,max:50},PIWI_AI_MAX_TRACE_NETWORK_REQUESTS:{description:"Max requests included from the trace network stream (0 disables).",category:"ai-limits",type:"number",default:"20",min:0,max:200},PIWI_AI_MAX_DOM_SNAPSHOT_CHARS:{description:"Max characters of the failure-time DOM snapshot rendered from the trace (0 disables).",category:"ai-limits",type:"number",default:"8000",min:0,max:5e4},PIWI_AI_IMAGE_MAX_EDGE:{description:"Screenshots are downscaled to at most this many pixels on the long edge before being sent.",category:"ai-limits",type:"number",default:"1920",min:512,max:8192},PIWI_INGEST_MAX_CONSOLE_ENTRIES:{description:"Max console entries stored per test execution.",category:"ingest",type:"number",default:"200",min:10,max:5e3},PIWI_IMPORT_MAX_BYTES:{description:"Max size of a single multipart upload (report upload or blob-report import), in bytes. Lower it to match a reverse proxy that rejects large bodies, so the import page rejects an oversized archive before uploading it.",category:"ingest",type:"number",default:String(500*1024*1024),min:1024*1024,max:5*1024*1024*1024,since:"0.19.0"},PIWI_EXPORT_MAX_INLINE_BYTES:{description:"Max size of a single evidence file embedded as a data: URI in an HTML export, in bytes. Larger files are left out of the single-file HTML (and listed as omitted); the ZIP export still carries them at full size.",category:"export",type:"number",default:String(8*1024*1024),min:64*1024,max:512*1024*1024,since:"0.19.0"},PIWI_EXPORT_MAX_BYTES:{description:"Max total size of one export, in bytes. Evidence is added largest-last until the budget is reached; the rest is listed as omitted. The archive is built in memory, so this also bounds what a single export costs the server.",category:"export",type:"number",default:String(500*1024*1024),min:1024*1024,max:4*1024*1024*1024,since:"0.19.0"},PIWI_EXPORT_MAX_CASES:{description:"Max member executions carrying full evidence in a failure-cluster export. Remaining affected tests are listed by name without their evidence.",category:"export",type:"number",default:"25",min:1,max:200,since:"0.19.0"},PIWI_INGEST_MAX_CONSOLE_ENTRY_CHARS:{description:"Max characters stored per console entry.",category:"ingest",type:"number",default:"2000",min:200,max:2e4},PIWI_INGEST_MAX_STEPS:{description:"Max test steps stored per execution.",category:"ingest",type:"number",default:"500",min:20,max:5e3},PIWI_INGEST_MAX_STEP_EVENTS:{description:"Max step events stored per execution.",category:"ingest",type:"number",default:"1000",min:20,max:1e4},PIWI_INGEST_MAX_ARIA_CHARS:{description:"Max characters of the ARIA snapshot stored per failing execution.",category:"ingest",type:"number",default:"100000",min:1e3,max:1e6},PIWI_INGEST_MAX_ERROR_CHARS:{description:"Max characters of error text stored per execution (head and tail are kept).",category:"ingest",type:"number",default:"20000",min:1e3,max:1e5},PIWI_INGEST_MAX_SAMPLE_ERROR_CHARS:{description:"Max characters of the sample error stored per failure cluster.",category:"ingest",type:"number",default:"50000",min:1e3,max:2e5},PIWI_INGEST_MAX_TEST_SOURCE_CHARS:{description:"Max characters of the test source snippet stored per failing execution.",category:"ingest",type:"number",default:"50000",min:1e3,max:2e5},PIWI_INGEST_MAX_SOURCE_FRAMES:{description:"Max source stack frames stored per failing execution.",category:"ingest",type:"number",default:"8",min:1,max:32},PIWI_INGEST_MAX_SOURCE_FRAME_CHARS:{description:"Max characters per stored source frame snippet.",category:"ingest",type:"number",default:"4000",min:500,max:2e4},PIWI_AUTO_MARKERS:{description:"Automatically create a timeline marker when a run’s environment, Playwright version, or reporter version changes from the previous run (default: enabled). Set to false to disable.",category:"markers",type:"boolean",default:"true",docs:"timeline-markers",notes:"Only the exact value `false` disables auto-markers."},PIWI_TEST_LOGS_DISABLED:{description:"Disable X-Piwi-Logs response header emission (default: auto-disabled in production, enabled in development).",category:"testing",type:"boolean",docs:"backend-logs",notes:"Unset: capture is on in development and off in production builds; `true` forces it off everywhere, `false` forces it on even in production."},PIWI_CLUSTER_SIMILARITY_THRESHOLD:{description:"Cosine similarity (0–1) above which two failure embeddings merge into one cluster.",category:"clustering",type:"number",default:"0.92",min:0,max:1,relevantWhen:{PIWI_AI_EMBEDDING_MODEL:"*"},notes:"Must be greater than 0 and at most 1; invalid values fall back to the default."},PIWI_CLUSTER_SUGGEST_THRESHOLD:{description:"Similarity at which a failure is suggested (not auto-merged) as related to a cluster.",category:"clustering",type:"number",default:"0.80",min:0,max:1,relevantWhen:{PIWI_AI_EMBEDDING_MODEL:"*"},notes:"Capped at the merge threshold."},PIWI_SMTP_HOST:{description:"SMTP server hostname for outbound email.",category:"smtp",example:"smtp.example.com"},PIWI_SMTP_PORT:{description:"SMTP port (default 587; 465 for implicit TLS).",category:"smtp",type:"number",default:"587",min:1,max:65535,relevantWhen:{PIWI_SMTP_HOST:"*"}},PIWI_SMTP_USER:{description:"SMTP username. Optional — only when the server requires authentication.",category:"smtp",relevantWhen:{PIWI_SMTP_HOST:"*"}},PIWI_SMTP_PASS:{description:"SMTP password. Optional — only when the server requires authentication. Never returned by the API.",category:"smtp",secret:!0,relevantWhen:{PIWI_SMTP_HOST:"*"}},PIWI_SMTP_FROM:{description:"From address for outbound email (e.g. noreply@example.com).",category:"smtp",example:"noreply@example.com",relevantWhen:{PIWI_SMTP_HOST:"*"},requiredWhen:{PIWI_SMTP_HOST:"*"}},PIWI_SMTP_FROM_NAME:{description:"Display name for the from address (optional).",category:"smtp",default:"Piwi Dashboard",relevantWhen:{PIWI_SMTP_HOST:"*"}},PIWI_SMTP_SECURE:{description:'Set to "true" for implicit TLS on port 465 (default false → STARTTLS/plain).',category:"smtp",type:"boolean",relevantWhen:{PIWI_SMTP_HOST:"*"},notes:"Defaults to on when the port is 465, off otherwise."},PIWI_WASTED_WAIT_PATTERNS:{description:"Glob patterns (comma or newline separated) defining which wait steps count as wasted time. Locks the UI when set.",category:"wasted-time",type:"list",default:"Wait for timeout*,*waitForTimeout*",notes:"Case-insensitive globs (`*` and `?`) matched against a wait step’s title or source location. Use `*` to count every wait."},PIWI_DEMO_MODE:{description:'Set to "true" to build the standalone client-side demo SPA (no server).',category:"demo",runtimeOnly:!0,type:"boolean"},PIWI_BASE_URL:{description:"Base URL the metadata test spec targets (defaults to http://localhost:3000).",category:"test",runtimeOnly:!0},PIWI_POSTGRES_TEST_URL:{description:"PostgreSQL connection string used by the Postgres test suite.",category:"test",runtimeOnly:!0,secret:!0},PIWI_S3_TEST_BUCKET:{description:"S3 bucket for the storage integration tests.",category:"test",runtimeOnly:!0},PIWI_S3_TEST_REGION:{description:"Region for the S3 storage integration tests.",category:"test",runtimeOnly:!0},PIWI_S3_TEST_ACCESS_KEY_ID:{description:"Access key id for the S3 storage integration tests.",category:"test",runtimeOnly:!0,secret:!0},PIWI_S3_TEST_SECRET_ACCESS_KEY:{description:"Secret access key for the S3 storage integration tests.",category:"test",runtimeOnly:!0,secret:!0},PIWI_S3_TEST_ENDPOINT:{description:"Custom endpoint for the S3 storage integration tests.",category:"test",runtimeOnly:!0},PIWI_MAILPIT_URL:{description:"Mailpit base URL; when set, the email/notification E2E tests run against it.",category:"test",runtimeOnly:!0},PIWI_MAILPIT_SMTP_PORT:{description:"SMTP port the email E2E tests send to (Mailpit).",category:"test",runtimeOnly:!0},PIWI_EMAIL_SERVER_URL:{description:"Base URL the email test spec targets.",category:"test",runtimeOnly:!0},PIWI_TEST_CLEANUP_ENABLED:{description:"Allow the E2E cleanup endpoint (`DELETE /api/tests/cleanup`) on a production build, which CI needs because it runs the suite against one. Never set it on a real deployment.",category:"test",runtimeOnly:!0,type:"boolean",since:"0.19.0"}};function T(t){return P[t]}function oe(t){return Object.keys(P).filter(i=>P[i].category===t)}const q={key:0,class:"font-medium mb-1"},F={class:"text-muted"},K={key:1,class:"mt-2 space-y-1"},$={class:"text-muted text-xs"},z={class:"flex flex-col gap-1.5"},Q=["title","onClick"],j={class:"block font-mono text-xs bg-elevated rounded px-1.5 py-0.5 select-all cursor-pointer group-hover:ring-1 ring-default"},Z={key:0,class:"block text-muted text-[11px] mt-0.5"},J={key:2,class:"mt-2 flex flex-col gap-1"},ee=W({__name:"HelpHint",props:{topic:{},title:{},text:{},doc:{},envVars:{},size:{}},setup(t){const i=t,{copy:E}=G(),c=n(()=>i.topic?H[i.topic]:null),o=n(()=>i.title??c.value?.title),g=n(()=>i.text??c.value?.text??""),d=n(()=>i.doc??c.value?.doc),I=n(()=>i.envVars??c.value?.envVars),y=w(!1),S=n(()=>o.value?`Help: ${o.value}`:"Help"),b=n(()=>({side:"bottom","aria-label":S.value}));return(te,l)=>{const R=U,f=V,O=L;return a(),m(O,{open:e(y),"onUpdate:open":l[0]||(l[0]=r=>D(y)?y.value=r:null),content:e(b),ui:{content:"max-w-xs p-3 text-sm"}},{content:u(()=>[e(o)?(a(),_("p",q,p(e(o)),1)):s("",!0),h("p",F,p(e(g)),1),e(I)?.length?(a(),_("div",K,[h("p",$,"Environment variable"+p(e(I).length>1?"s":"")+":",1),h("div",z,[(a(!0),_(N,null,k(e(I),r=>(a(),_("button",{key:r,type:"button",class:"group text-left",title:`Click to copy ${r}`,onClick:ae=>e(E)(r,{toast:`Copied ${r}`})},[h("code",j,p(r),1),e(T)(r).description?(a(),_("span",Z,p(e(T)(r).description),1)):s("",!0)],8,Q))),128))])])):s("",!0),e(d)||e(I)?.length?(a(),_("div",J,[e(d)?(a(),m(f,{key:0,to:e(d)},{default:u(()=>[...l[1]||(l[1]=[A("Learn more",-1)])]),_:1},8,["to"])):s("",!0),e(I)?.length?(a(),m(f,{key:1,to:"configuration"},{default:u(()=>[...l[2]||(l[2]=[A("Configuration reference",-1)])]),_:1})):s("",!0)])):s("",!0)]),default:u(()=>[C(R,{size:t.size??"xs",variant:"ghost",color:"neutral",icon:"i-lucide-circle-help","aria-label":e(S),title:"What is this?",class:"text-muted hover:text-default align-middle"},null,8,["size","aria-label"])]),_:1},8,["open","content"])}}}),se=Object.assign(ee,{__name:"HelpHint"});export{se as _,V as a,X as d,oe as e,T as g};