@polderlabs/bizar 10.4.3 → 10.4.4

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 (228) hide show
  1. package/bizar-dash/dist/assets/{ActivityFeed-DC0JiK49.js → ActivityFeed-RQeyFifx.js} +1 -1
  2. package/bizar-dash/dist/assets/{ActivityFeed-DC0JiK49.js.map → ActivityFeed-RQeyFifx.js.map} +1 -1
  3. package/bizar-dash/dist/assets/{ActivityView-ubEDAWMY.js → ActivityView-CibyssPM.js} +1 -1
  4. package/bizar-dash/dist/assets/{ActivityView-ubEDAWMY.js.map → ActivityView-CibyssPM.js.map} +1 -1
  5. package/bizar-dash/dist/assets/AdminView-BjczABeB.js +11 -0
  6. package/bizar-dash/dist/assets/AdminView-BjczABeB.js.map +1 -0
  7. package/bizar-dash/dist/assets/{AgentActivity-BLcqqkt2.js → AgentActivity-Bywt1twv.js} +1 -1
  8. package/bizar-dash/dist/assets/{AgentActivity-BLcqqkt2.js.map → AgentActivity-Bywt1twv.js.map} +1 -1
  9. package/bizar-dash/dist/assets/{AgentsView-CIQkZH8_.js → AgentsView-BnOjjM74.js} +4 -4
  10. package/bizar-dash/dist/assets/AgentsView-BnOjjM74.js.map +1 -0
  11. package/bizar-dash/dist/assets/{Alert-MwVEymjy.js → Alert-BZGk39mB.js} +1 -1
  12. package/bizar-dash/dist/assets/{Alert-MwVEymjy.js.map → Alert-BZGk39mB.js.map} +1 -1
  13. package/bizar-dash/dist/assets/{ArtifactsView-B-YUwZyb.js → ArtifactsView-CfYB1le1.js} +3 -3
  14. package/bizar-dash/dist/assets/ArtifactsView-CfYB1le1.js.map +1 -0
  15. package/bizar-dash/dist/assets/{AuthView-LaQuGo4u.js → AuthView-D4frSShw.js} +1 -1
  16. package/bizar-dash/dist/assets/{AuthView-LaQuGo4u.js.map → AuthView-D4frSShw.js.map} +1 -1
  17. package/bizar-dash/dist/assets/Avatar-BYg0rkPA.js +6 -0
  18. package/bizar-dash/dist/assets/Avatar-BYg0rkPA.js.map +1 -0
  19. package/bizar-dash/dist/assets/{BackgroundJobsView-CO3DEG8R.js → BackgroundJobsView-DEStvILz.js} +1 -1
  20. package/bizar-dash/dist/assets/{BackgroundJobsView-CO3DEG8R.js.map → BackgroundJobsView-DEStvILz.js.map} +1 -1
  21. package/bizar-dash/dist/assets/{BackupView-Cjf23ZWc.js → BackupView-B875KQa4.js} +1 -1
  22. package/bizar-dash/dist/assets/{BackupView-Cjf23ZWc.js.map → BackupView-B875KQa4.js.map} +1 -1
  23. package/bizar-dash/dist/assets/Banner-C8HEcT5l.js +1 -0
  24. package/bizar-dash/dist/assets/Banner-C8HEcT5l.js.map +1 -0
  25. package/bizar-dash/dist/assets/{Card-BmXiT4c6.js → Card-BtsmkhJa.js} +1 -1
  26. package/bizar-dash/dist/assets/{Card-BmXiT4c6.js.map → Card-BtsmkhJa.js.map} +1 -1
  27. package/bizar-dash/dist/assets/{ChatView-DXKFwvgp.js → ChatView-CkNS0SD8.js} +3 -3
  28. package/bizar-dash/dist/assets/{ChatView-DXKFwvgp.js.map → ChatView-CkNS0SD8.js.map} +1 -1
  29. package/bizar-dash/dist/assets/{Chip-Dei66BLx.js → Chip-XPOk0d_E.js} +1 -1
  30. package/bizar-dash/dist/assets/{Chip-Dei66BLx.js.map → Chip-XPOk0d_E.js.map} +1 -1
  31. package/bizar-dash/dist/assets/{ClaudeSessionsView-D-YNmzKi.js → ClaudeSessionsView-BprGo67K.js} +1 -1
  32. package/bizar-dash/dist/assets/{ClaudeSessionsView-D-YNmzKi.js.map → ClaudeSessionsView-BprGo67K.js.map} +1 -1
  33. package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js +1 -0
  34. package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js.map +1 -0
  35. package/bizar-dash/dist/assets/{ConfigView-BMBgifw5.js → ConfigView-BntUrW7s.js} +1 -1
  36. package/bizar-dash/dist/assets/{ConfigView-BMBgifw5.js.map → ConfigView-BntUrW7s.js.map} +1 -1
  37. package/bizar-dash/dist/assets/{DiagnosticsView-C0sdqhEl.js → DiagnosticsView-4x0Zu3yP.js} +1 -1
  38. package/bizar-dash/dist/assets/{DiagnosticsView-C0sdqhEl.js.map → DiagnosticsView-4x0Zu3yP.js.map} +1 -1
  39. package/bizar-dash/dist/assets/DialogsView-Xd02dVAX.js +6 -0
  40. package/bizar-dash/dist/assets/DialogsView-Xd02dVAX.js.map +1 -0
  41. package/bizar-dash/dist/assets/{DoctorView-CiFwRMW0.js → DoctorView-DepBdQGR.js} +2 -2
  42. package/bizar-dash/dist/assets/{DoctorView-CiFwRMW0.js.map → DoctorView-DepBdQGR.js.map} +1 -1
  43. package/bizar-dash/dist/assets/{EmptyState-CdDQmfEL.js → EmptyState-DjKtY1Qi.js} +1 -1
  44. package/bizar-dash/dist/assets/{EmptyState-CdDQmfEL.js.map → EmptyState-DjKtY1Qi.js.map} +1 -1
  45. package/bizar-dash/dist/assets/{EnvVarsView-CNO03NDJ.js → EnvVarsView-S4Pbm128.js} +3 -3
  46. package/bizar-dash/dist/assets/{EnvVarsView-CNO03NDJ.js.map → EnvVarsView-S4Pbm128.js.map} +1 -1
  47. package/bizar-dash/dist/assets/{ErrorState-BRvj8qZZ.js → ErrorState-CBJbEQ8B.js} +1 -1
  48. package/bizar-dash/dist/assets/{ErrorState-BRvj8qZZ.js.map → ErrorState-CBJbEQ8B.js.map} +1 -1
  49. package/bizar-dash/dist/assets/EvalView-BeAyMCD1.js +1 -0
  50. package/bizar-dash/dist/assets/{EvalView-lgUhlGJh.js.map → EvalView-BeAyMCD1.js.map} +1 -1
  51. package/bizar-dash/dist/assets/{GoalsView-DmkCCs9i.js → GoalsView-BZr8In4c.js} +1 -1
  52. package/bizar-dash/dist/assets/{GoalsView-DmkCCs9i.js.map → GoalsView-BZr8In4c.js.map} +1 -1
  53. package/bizar-dash/dist/assets/{Grid-BThCPJaV.js → Grid--WKvqu5h.js} +1 -1
  54. package/bizar-dash/dist/assets/{Grid-BThCPJaV.js.map → Grid--WKvqu5h.js.map} +1 -1
  55. package/bizar-dash/dist/assets/{HistoryView-Cn2cPiHZ.js → HistoryView-djEbzqtk.js} +1 -1
  56. package/bizar-dash/dist/assets/{HistoryView-Cn2cPiHZ.js.map → HistoryView-djEbzqtk.js.map} +1 -1
  57. package/bizar-dash/dist/assets/{Input-cAQOvR8U.js → Input-h_nSOtwm.js} +1 -1
  58. package/bizar-dash/dist/assets/{Input-cAQOvR8U.js.map → Input-h_nSOtwm.js.map} +1 -1
  59. package/bizar-dash/dist/assets/LibrariesView-Vez8CvNq.js +6 -0
  60. package/bizar-dash/dist/assets/{LibrariesView-Ca_PRjUm.js.map → LibrariesView-Vez8CvNq.js.map} +1 -1
  61. package/bizar-dash/dist/assets/{LightRAGView-CMk9wOae.js → LightRAGView-DvqzQoBp.js} +1 -1
  62. package/bizar-dash/dist/assets/{LightRAGView-CMk9wOae.js.map → LightRAGView-DvqzQoBp.js.map} +1 -1
  63. package/bizar-dash/dist/assets/{ListHeader-BLAeshe0.js → ListHeader-CM8QoIWG.js} +1 -1
  64. package/bizar-dash/dist/assets/{ListHeader-BLAeshe0.js.map → ListHeader-CM8QoIWG.js.map} +1 -1
  65. package/bizar-dash/dist/assets/{MemoryView-wo2Pu7xQ.js → MemoryView-DnL8E2vI.js} +1 -1
  66. package/bizar-dash/dist/assets/{MemoryView-wo2Pu7xQ.js.map → MemoryView-DnL8E2vI.js.map} +1 -1
  67. package/bizar-dash/dist/assets/MiscView-B2YQXhZ_.js +1 -0
  68. package/bizar-dash/dist/assets/MiscView-B2YQXhZ_.js.map +1 -0
  69. package/bizar-dash/dist/assets/{ModsView-CV_RxdzJ.js → ModsView-BVM3X5xc.js} +1 -1
  70. package/bizar-dash/dist/assets/{ModsView-CV_RxdzJ.js.map → ModsView-BVM3X5xc.js.map} +1 -1
  71. package/bizar-dash/dist/assets/NotificationsView-A-Xs8BL1.js +6 -0
  72. package/bizar-dash/dist/assets/NotificationsView-A-Xs8BL1.js.map +1 -0
  73. package/bizar-dash/dist/assets/ObsidianView-mI3qW9OP.js +1 -0
  74. package/bizar-dash/dist/assets/{ObsidianView-C-AvHfpT.js.map → ObsidianView-mI3qW9OP.js.map} +1 -1
  75. package/bizar-dash/dist/assets/OverviewView-By69Cr5H.js +1 -0
  76. package/bizar-dash/dist/assets/OverviewView-By69Cr5H.js.map +1 -0
  77. package/bizar-dash/dist/assets/{ProgressBar-ya2PCj8L.js → ProgressBar-BnaBqv-W.js} +1 -1
  78. package/bizar-dash/dist/assets/{ProgressBar-ya2PCj8L.js.map → ProgressBar-BnaBqv-W.js.map} +1 -1
  79. package/bizar-dash/dist/assets/{ProjectsView-N9zqFZ_O.js → ProjectsView-C81WTFka.js} +1 -1
  80. package/bizar-dash/dist/assets/{ProjectsView-N9zqFZ_O.js.map → ProjectsView-C81WTFka.js.map} +1 -1
  81. package/bizar-dash/dist/assets/{ProvidersView-BcL8jjwK.js → ProvidersView-2cn-TALE.js} +2 -2
  82. package/bizar-dash/dist/assets/{ProvidersView-BcL8jjwK.js.map → ProvidersView-2cn-TALE.js.map} +1 -1
  83. package/bizar-dash/dist/assets/{SchedulesView-8qxH3bg7.js → SchedulesView-o9AtIsH9.js} +1 -1
  84. package/bizar-dash/dist/assets/{SchedulesView-8qxH3bg7.js.map → SchedulesView-o9AtIsH9.js.map} +1 -1
  85. package/bizar-dash/dist/assets/{Select-D5AuVxxV.js → Select-CiGWEN8I.js} +1 -1
  86. package/bizar-dash/dist/assets/{Select-D5AuVxxV.js.map → Select-CiGWEN8I.js.map} +1 -1
  87. package/bizar-dash/dist/assets/{SettingsRow-BBALf9dA.js → SettingsRow-CflGJymA.js} +1 -1
  88. package/bizar-dash/dist/assets/{SettingsRow-BBALf9dA.js.map → SettingsRow-CflGJymA.js.map} +1 -1
  89. package/bizar-dash/dist/assets/{SettingsView-UD403neY.js → SettingsView-2HSFJPPK.js} +1 -1
  90. package/bizar-dash/dist/assets/{SettingsView-UD403neY.js.map → SettingsView-2HSFJPPK.js.map} +1 -1
  91. package/bizar-dash/dist/assets/{Sheet-CxXf6gvC.js → Sheet-B-CMP9-_.js} +1 -1
  92. package/bizar-dash/dist/assets/{Sheet-CxXf6gvC.js.map → Sheet-B-CMP9-_.js.map} +1 -1
  93. package/bizar-dash/dist/assets/{Slider-hvaVD_SW.js → Slider-Z4TP_CXY.js} +1 -1
  94. package/bizar-dash/dist/assets/{Slider-hvaVD_SW.js.map → Slider-Z4TP_CXY.js.map} +1 -1
  95. package/bizar-dash/dist/assets/{Sparkline-DqmQzdJH.js → Sparkline-cvkv2HbU.js} +1 -1
  96. package/bizar-dash/dist/assets/{Sparkline-DqmQzdJH.js.map → Sparkline-cvkv2HbU.js.map} +1 -1
  97. package/bizar-dash/dist/assets/{Switch-C-_zcNdl.js → Switch-jcYo4lmp.js} +1 -1
  98. package/bizar-dash/dist/assets/{Switch-C-_zcNdl.js.map → Switch-jcYo4lmp.js.map} +1 -1
  99. package/bizar-dash/dist/assets/{TasksView-DseftDlx.js → TasksView-CQaSFzWY.js} +2 -2
  100. package/bizar-dash/dist/assets/{TasksView-DseftDlx.js.map → TasksView-CQaSFzWY.js.map} +1 -1
  101. package/bizar-dash/dist/assets/{Textarea-CcQGSgSH.js → Textarea-xnAybFGd.js} +1 -1
  102. package/bizar-dash/dist/assets/{Textarea-CcQGSgSH.js.map → Textarea-xnAybFGd.js.map} +1 -1
  103. package/bizar-dash/dist/assets/UpdateView-BUAEcRCX.js +1 -0
  104. package/bizar-dash/dist/assets/UpdateView-BUAEcRCX.js.map +1 -0
  105. package/bizar-dash/dist/assets/{UsageView-P5_pQ68d.js → UsageView-DMFbBOfH.js} +1 -1
  106. package/bizar-dash/dist/assets/{UsageView-P5_pQ68d.js.map → UsageView-DMFbBOfH.js.map} +1 -1
  107. package/bizar-dash/dist/assets/{ViewHeader-BaCWNuVX.js → ViewHeader-C-t1U2cQ.js} +1 -1
  108. package/bizar-dash/dist/assets/{ViewHeader-BaCWNuVX.js.map → ViewHeader-C-t1U2cQ.js.map} +1 -1
  109. package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js +1 -0
  110. package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js.map +1 -0
  111. package/bizar-dash/dist/assets/{brain-D6tAeUDE.js → brain-DhAzcHUk.js} +1 -1
  112. package/bizar-dash/dist/assets/{brain-D6tAeUDE.js.map → brain-DhAzcHUk.js.map} +1 -1
  113. package/bizar-dash/dist/assets/{calendar-BrMJf3vl.js → calendar-B9Wbemh7.js} +1 -1
  114. package/bizar-dash/dist/assets/{calendar-BrMJf3vl.js.map → calendar-B9Wbemh7.js.map} +1 -1
  115. package/bizar-dash/dist/assets/{circle-fPTATiOs.js → circle-6NJF_Xl6.js} +1 -1
  116. package/bizar-dash/dist/assets/{circle-fPTATiOs.js.map → circle-6NJF_Xl6.js.map} +1 -1
  117. package/bizar-dash/dist/assets/{circle-alert-D7jn06kH.js → circle-alert-Dz8lGfCZ.js} +1 -1
  118. package/bizar-dash/dist/assets/{circle-alert-D7jn06kH.js.map → circle-alert-Dz8lGfCZ.js.map} +1 -1
  119. package/bizar-dash/dist/assets/{circle-check-DHs37Sot.js → circle-check-DFB50ojt.js} +1 -1
  120. package/bizar-dash/dist/assets/{circle-check-DHs37Sot.js.map → circle-check-DFB50ojt.js.map} +1 -1
  121. package/bizar-dash/dist/assets/{clock-E-G5aGua.js → clock-ClVA6-hQ.js} +1 -1
  122. package/bizar-dash/dist/assets/{clock-E-G5aGua.js.map → clock-ClVA6-hQ.js.map} +1 -1
  123. package/bizar-dash/dist/assets/{download-DBkNb6oI.js → download-BvJddD8D.js} +1 -1
  124. package/bizar-dash/dist/assets/{download-DBkNb6oI.js.map → download-BvJddD8D.js.map} +1 -1
  125. package/bizar-dash/dist/assets/{external-link-C4pHGbz2.js → external-link-DvL89gaZ.js} +1 -1
  126. package/bizar-dash/dist/assets/{external-link-C4pHGbz2.js.map → external-link-DvL89gaZ.js.map} +1 -1
  127. package/bizar-dash/dist/assets/{file-text-CEhDgLq2.js → file-text-BOroDtZE.js} +1 -1
  128. package/bizar-dash/dist/assets/{file-text-CEhDgLq2.js.map → file-text-BOroDtZE.js.map} +1 -1
  129. package/bizar-dash/dist/assets/{filter-CEYjeWFX.js → filter-DwPjMRQt.js} +1 -1
  130. package/bizar-dash/dist/assets/{filter-CEYjeWFX.js.map → filter-DwPjMRQt.js.map} +1 -1
  131. package/bizar-dash/dist/assets/{git-pull-request-Bo_wBZZw.js → git-pull-request-TDb1inux.js} +1 -1
  132. package/bizar-dash/dist/assets/{git-pull-request-Bo_wBZZw.js.map → git-pull-request-TDb1inux.js.map} +1 -1
  133. package/bizar-dash/dist/assets/{main-DDAMz_H5.css → main-B7D_IMTh.css} +1 -1
  134. package/bizar-dash/dist/assets/main-BURAlktW.js +277 -0
  135. package/bizar-dash/dist/assets/main-BURAlktW.js.map +1 -0
  136. package/bizar-dash/dist/assets/{network-BsfwrUA-.js → network-BcCoCzIY.js} +1 -1
  137. package/bizar-dash/dist/assets/{network-BsfwrUA-.js.map → network-BcCoCzIY.js.map} +1 -1
  138. package/bizar-dash/dist/assets/{pause-C8PN1_yO.js → pause-BllItT2_.js} +1 -1
  139. package/bizar-dash/dist/assets/{pause-C8PN1_yO.js.map → pause-BllItT2_.js.map} +1 -1
  140. package/bizar-dash/dist/assets/{pencil---XuvKlz.js → pencil-DAwM-CC3.js} +1 -1
  141. package/bizar-dash/dist/assets/{pencil---XuvKlz.js.map → pencil-DAwM-CC3.js.map} +1 -1
  142. package/bizar-dash/dist/assets/{play-fMLPTihK.js → play-mJh67AXo.js} +2 -2
  143. package/bizar-dash/dist/assets/{play-fMLPTihK.js.map → play-mJh67AXo.js.map} +1 -1
  144. package/bizar-dash/dist/assets/{plug-CG8al2Kq.js → plug-BjfntCMC.js} +1 -1
  145. package/bizar-dash/dist/assets/{plug-CG8al2Kq.js.map → plug-BjfntCMC.js.map} +1 -1
  146. package/bizar-dash/dist/assets/{plus-uA5Ecuch.js → plus-Cm6-fo14.js} +1 -1
  147. package/bizar-dash/dist/assets/{plus-uA5Ecuch.js.map → plus-Cm6-fo14.js.map} +1 -1
  148. package/bizar-dash/dist/assets/{power-DSUlNIuR.js → power-CXN9y2KV.js} +1 -1
  149. package/bizar-dash/dist/assets/{power-DSUlNIuR.js.map → power-CXN9y2KV.js.map} +1 -1
  150. package/bizar-dash/dist/assets/{power-off-1CAQsHHy.js → power-off-DUZqwMf9.js} +1 -1
  151. package/bizar-dash/dist/assets/{power-off-1CAQsHHy.js.map → power-off-DUZqwMf9.js.map} +1 -1
  152. package/bizar-dash/dist/assets/{refresh-ccw-BL7B0NO1.js → refresh-ccw-DA8_IB9l.js} +1 -1
  153. package/bizar-dash/dist/assets/{refresh-ccw-BL7B0NO1.js.map → refresh-ccw-DA8_IB9l.js.map} +1 -1
  154. package/bizar-dash/dist/assets/{refresh-cw-CR9BzJik.js → refresh-cw-DwlP59en.js} +1 -1
  155. package/bizar-dash/dist/assets/{refresh-cw-CR9BzJik.js.map → refresh-cw-DwlP59en.js.map} +1 -1
  156. package/bizar-dash/dist/assets/{rotate-ccw-BtnitLfb.js → rotate-ccw-DMTASfAn.js} +1 -1
  157. package/bizar-dash/dist/assets/{rotate-ccw-BtnitLfb.js.map → rotate-ccw-DMTASfAn.js.map} +1 -1
  158. package/bizar-dash/dist/assets/{rotate-cw-CHgXCO7O.js → rotate-cw-BDX5SE2s.js} +1 -1
  159. package/bizar-dash/dist/assets/{rotate-cw-CHgXCO7O.js.map → rotate-cw-BDX5SE2s.js.map} +1 -1
  160. package/bizar-dash/dist/assets/{save-RcZOXR0U.js → save-Y0jPK5D6.js} +1 -1
  161. package/bizar-dash/dist/assets/{save-RcZOXR0U.js.map → save-Y0jPK5D6.js.map} +1 -1
  162. package/bizar-dash/dist/assets/{send-Bg2X_ibk.js → send-C8wwPHhR.js} +2 -2
  163. package/bizar-dash/dist/assets/{send-Bg2X_ibk.js.map → send-C8wwPHhR.js.map} +1 -1
  164. package/bizar-dash/dist/assets/{shield-alert-Dm48D034.js → shield-alert-DEvq9UG0.js} +1 -1
  165. package/bizar-dash/dist/assets/{shield-alert-Dm48D034.js.map → shield-alert-DEvq9UG0.js.map} +1 -1
  166. package/bizar-dash/dist/assets/{trash-2-B885GY46.js → trash-2-D6qePV_q.js} +2 -2
  167. package/bizar-dash/dist/assets/{trash-2-B885GY46.js.map → trash-2-D6qePV_q.js.map} +1 -1
  168. package/bizar-dash/dist/assets/{trending-up-CqUBvVxw.js → trending-up-BZzo_1ic.js} +1 -1
  169. package/bizar-dash/dist/assets/{trending-up-CqUBvVxw.js.map → trending-up-BZzo_1ic.js.map} +1 -1
  170. package/bizar-dash/dist/assets/{triangle-alert-DLmUhymD.js → triangle-alert-B2oHbmoh.js} +1 -1
  171. package/bizar-dash/dist/assets/{triangle-alert-DLmUhymD.js.map → triangle-alert-B2oHbmoh.js.map} +1 -1
  172. package/bizar-dash/dist/assets/{upload-C-oafpyE.js → upload-Dy59aZn6.js} +1 -1
  173. package/bizar-dash/dist/assets/{upload-C-oafpyE.js.map → upload-Dy59aZn6.js.map} +1 -1
  174. package/bizar-dash/dist/assets/{zap-O_4Ys_hh.js → zap-DENVhJnO.js} +2 -2
  175. package/bizar-dash/dist/assets/{zap-O_4Ys_hh.js.map → zap-DENVhJnO.js.map} +1 -1
  176. package/bizar-dash/dist/index.html +2 -2
  177. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  178. package/bizar-dash/src/web/v8/App.tsx +25 -4
  179. package/bizar-dash/src/web/v8/shell/Sidebar.tsx +8 -5
  180. package/bizar-dash/src/web/v8/shell/Topbar.tsx +57 -1
  181. package/bizar-dash/src/web/v8/ui/styles/globals.css +14 -0
  182. package/bizar-dash/src/web/v8/ui/theme/ThemeToggle.tsx +11 -6
  183. package/bizar-dash/src/web/v8/views/Admin/AdminView.tsx +32 -5
  184. package/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +11 -4
  185. package/bizar-dash/src/web/v8/views/Artifacts/ArtifactsView.tsx +1 -1
  186. package/bizar-dash/src/web/v8/views/Clipboard/ClipboardView.tsx +1 -1
  187. package/bizar-dash/src/web/v8/views/Dialogs/DialogsView.tsx +1 -1
  188. package/bizar-dash/src/web/v8/views/Misc/MiscView.tsx +1 -1
  189. package/bizar-dash/src/web/v8/views/Notifications/NotificationsView.tsx +82 -13
  190. package/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +19 -0
  191. package/bizar-dash/src/web/v8/views/Voice/VoiceView.tsx +1 -1
  192. package/bizar-dash/tests/admin-run-grouping.test.mjs +42 -0
  193. package/bizar-dash/tests/agents-preview-truncate.test.mjs +35 -0
  194. package/bizar-dash/tests/empty-state-docs.test.mjs +55 -0
  195. package/bizar-dash/tests/focus-visible.test.mjs +30 -0
  196. package/bizar-dash/tests/notifications-dismiss-restore.test.mjs +85 -0
  197. package/bizar-dash/tests/palette-shortcut-hint.test.mjs +58 -0
  198. package/bizar-dash/tests/sidebar-distinct-icons.test.mjs +28 -0
  199. package/bizar-dash/tests/theme-toggle-icon.test.mjs +28 -0
  200. package/bizar-dash/tests/topbar-design-system.test.mjs +56 -0
  201. package/bizar-dash/vite.config.ts +8 -0
  202. package/package.json +1 -1
  203. package/packages/sdk/package.json +1 -1
  204. package/bizar-dash/dist/assets/AdminView-CI4zM2Qg.js +0 -11
  205. package/bizar-dash/dist/assets/AdminView-CI4zM2Qg.js.map +0 -1
  206. package/bizar-dash/dist/assets/AgentsView-CIQkZH8_.js.map +0 -1
  207. package/bizar-dash/dist/assets/ArtifactsView-B-YUwZyb.js.map +0 -1
  208. package/bizar-dash/dist/assets/Avatar-Dg4OF4RD.js +0 -6
  209. package/bizar-dash/dist/assets/Avatar-Dg4OF4RD.js.map +0 -1
  210. package/bizar-dash/dist/assets/ClipboardView-BA323V2J.js +0 -1
  211. package/bizar-dash/dist/assets/ClipboardView-BA323V2J.js.map +0 -1
  212. package/bizar-dash/dist/assets/DialogsView-DzTnyX8K.js +0 -6
  213. package/bizar-dash/dist/assets/DialogsView-DzTnyX8K.js.map +0 -1
  214. package/bizar-dash/dist/assets/EvalView-lgUhlGJh.js +0 -1
  215. package/bizar-dash/dist/assets/LibrariesView-Ca_PRjUm.js +0 -6
  216. package/bizar-dash/dist/assets/MiscView-fBT1TOXC.js +0 -1
  217. package/bizar-dash/dist/assets/MiscView-fBT1TOXC.js.map +0 -1
  218. package/bizar-dash/dist/assets/NotificationsView-BKAZLxM2.js +0 -6
  219. package/bizar-dash/dist/assets/NotificationsView-BKAZLxM2.js.map +0 -1
  220. package/bizar-dash/dist/assets/ObsidianView-C-AvHfpT.js +0 -1
  221. package/bizar-dash/dist/assets/OverviewView-CKYzZJe3.js +0 -1
  222. package/bizar-dash/dist/assets/OverviewView-CKYzZJe3.js.map +0 -1
  223. package/bizar-dash/dist/assets/UpdateView-B9Lh4svM.js +0 -6
  224. package/bizar-dash/dist/assets/UpdateView-B9Lh4svM.js.map +0 -1
  225. package/bizar-dash/dist/assets/VoiceView-BwR9gm5e.js +0 -1
  226. package/bizar-dash/dist/assets/VoiceView-BwR9gm5e.js.map +0 -1
  227. package/bizar-dash/dist/assets/main-BZMmD6a8.js +0 -249
  228. package/bizar-dash/dist/assets/main-BZMmD6a8.js.map +0 -1
@@ -1,6 +1,6 @@
1
- import{r as d,j as e}from"./cmdk-C3F6LD6N.js";import{c as C,u as m,S as i,I as c,d as x,h,H as z,B as E,J as T,G as w,i as R,F as I}from"./main-BZMmD6a8.js";import{V as b}from"./ViewHeader-BaCWNuVX.js";import{C as j,b as y}from"./Card-BmXiT4c6.js";import{E as N}from"./EmptyState-CdDQmfEL.js";import{E as B}from"./ErrorState-BRvj8qZZ.js";import{R as F}from"./refresh-cw-CR9BzJik.js";import{T as H}from"./triangle-alert-DLmUhymD.js";import{C as A}from"./circle-check-DHs37Sot.js";import"./Alert-MwVEymjy.js";import"./circle-alert-D7jn06kH.js";import"./refresh-ccw-BL7B0NO1.js";/**
1
+ import{r as d,j as e}from"./cmdk-C3F6LD6N.js";import{d as C,u as m,S as i,I as c,B as x,h,H as z,b as E,J as T,G as w,i as R,F as b}from"./main-BURAlktW.js";import{V as I}from"./ViewHeader-C-t1U2cQ.js";import{C as j,b as y}from"./Card-BtsmkhJa.js";import{E as N}from"./EmptyState-DjKtY1Qi.js";import{E as B}from"./ErrorState-CBJbEQ8B.js";import{R as F}from"./refresh-cw-DwlP59en.js";import{T as H}from"./triangle-alert-B2oHbmoh.js";import{C as A}from"./circle-check-DFB50ojt.js";import"./Alert-BZGk39mB.js";import"./circle-alert-Dz8lGfCZ.js";import"./refresh-ccw-DA8_IB9l.js";/**
2
2
  * @license lucide-react v0.460.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
5
5
  * See the LICENSE file in the root directory of this source tree.
6
- */const D=C("CircleX",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m15 9-6 6",key:"1uzhvr"}],["path",{d:"m9 9 6 6",key:"z0biqf"}]]),v={ok:A,warn:H,fail:D},O={ok:"success",warn:"warning",fail:"danger"};function M(){var p;const s=m("/api/doctor"),l=m("/api/doctor/health"),[k,u]=d.useState(null),[f,g]=d.useState(null);d.useEffect(()=>{const t=setInterval(()=>{l.refetch()},3e4);return()=>clearInterval(t)},[l]);const S=async t=>{u(t),g(null);try{await R("/api/doctor/check",{method:"POST",body:{checkName:t}}),s.refetch()}catch(r){g((r instanceof I,r.message))}finally{u(null)}},n=l.data??((p=s.data)==null?void 0:p.health),o=(()=>{var r;const t=(r=s.data)==null?void 0:r.checks;return t?[...t.system??[],...t.config??[],...t.services??[]].filter(a=>typeof a.name=="string"&&typeof a.status=="string"&&typeof a.message=="string"):[]})();return e.jsxs(i,{gap:5,"data-testid":"doctor-view",children:[e.jsx(b,{title:"Doctor",description:"System diagnostics. Health poll every 30s; click any check to re-run.",actions:e.jsxs(c,{gap:2,align:"center",children:[f!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:f}),e.jsxs(x,{variant:"ghost",onClick:()=>void s.refetch(),"data-testid":"doctor-refresh",children:[e.jsx(F,{size:14,"aria-hidden":!0})," Refresh"]})]})}),n?e.jsx(j,{variant:"elevated",children:e.jsx(y,{children:e.jsxs(c,{align:"center",gap:3,children:[(()=>{const t=v[n.status];return e.jsx(t,{size:20,"aria-hidden":!0})})(),e.jsxs(i,{gap:0,children:[e.jsxs("strong",{style:{fontSize:"var(--fs-14)"},children:["Health: ",n.status.toUpperCase()]}),e.jsx("span",{style:{color:"var(--fg-muted)",fontSize:"var(--fs-12)"},children:n.issues.length===0?"No issues detected.":`${n.issues.length} issue${n.issues.length===1?"":"s"}`})]})]})})}):e.jsx(h,{style:{height:64}}),s.loading&&o.length===0?e.jsxs(i,{gap:2,children:[e.jsx(h,{style:{height:64}}),e.jsx(h,{style:{height:64}})]}):s.error&&o.length===0?e.jsx(B,{block:!0,title:"Couldn't run doctor",description:"The diagnostic snapshot failed. Retry to refetch.",error:s.error,onRetry:()=>void s.refetch(),testid:"doctor-error"}):o.length===0?e.jsx(N,{icon:e.jsx(z,{size:32,"aria-hidden":!0}),title:"No checks yet",description:"The Doctor snapshot returned no checks."}):e.jsx(i,{gap:2,children:o.map(t=>{const r=v[t.status],a=k===t.name;return e.jsx(j,{variant:"default",children:e.jsx(y,{children:e.jsxs(c,{align:"center",justify:"between",gap:3,children:[e.jsxs(i,{gap:1,style:{flex:1,minWidth:0},children:[e.jsxs(c,{align:"center",gap:2,children:[e.jsx(r,{size:14,"aria-hidden":!0}),e.jsx("strong",{children:t.name}),e.jsx(E,{tone:O[t.status],children:t.status})]}),e.jsx("span",{style:{color:"var(--fg-muted)",fontSize:"var(--fs-12)"},children:t.message}),t.error&&e.jsx("span",{style:{color:"var(--danger)",fontSize:"var(--fs-12)",fontFamily:"var(--font-mono)"},children:t.error})]}),e.jsxs(x,{variant:"ghost",onClick:()=>void S(t.name),disabled:a,"data-testid":`doctor-run-${t.name}`,children:[a?e.jsx(T,{size:12,className:"animate-spin","aria-hidden":!0}):e.jsx(w,{size:12,"aria-hidden":!0}),a?"Running…":"Re-run"]})]})})},t.name)})})]})}export{M as DoctorView};
6
+ */const D=C("CircleX",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m15 9-6 6",key:"1uzhvr"}],["path",{d:"m9 9 6 6",key:"z0biqf"}]]),v={ok:A,warn:H,fail:D},O={ok:"success",warn:"warning",fail:"danger"};function M(){var p;const s=m("/api/doctor"),l=m("/api/doctor/health"),[k,u]=d.useState(null),[f,g]=d.useState(null);d.useEffect(()=>{const t=setInterval(()=>{l.refetch()},3e4);return()=>clearInterval(t)},[l]);const S=async t=>{u(t),g(null);try{await R("/api/doctor/check",{method:"POST",body:{checkName:t}}),s.refetch()}catch(r){g((r instanceof b,r.message))}finally{u(null)}},n=l.data??((p=s.data)==null?void 0:p.health),o=(()=>{var r;const t=(r=s.data)==null?void 0:r.checks;return t?[...t.system??[],...t.config??[],...t.services??[]].filter(a=>typeof a.name=="string"&&typeof a.status=="string"&&typeof a.message=="string"):[]})();return e.jsxs(i,{gap:5,"data-testid":"doctor-view",children:[e.jsx(I,{title:"Doctor",description:"System diagnostics. Health poll every 30s; click any check to re-run.",actions:e.jsxs(c,{gap:2,align:"center",children:[f!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:f}),e.jsxs(x,{variant:"ghost",onClick:()=>void s.refetch(),"data-testid":"doctor-refresh",children:[e.jsx(F,{size:14,"aria-hidden":!0})," Refresh"]})]})}),n?e.jsx(j,{variant:"elevated",children:e.jsx(y,{children:e.jsxs(c,{align:"center",gap:3,children:[(()=>{const t=v[n.status];return e.jsx(t,{size:20,"aria-hidden":!0})})(),e.jsxs(i,{gap:0,children:[e.jsxs("strong",{style:{fontSize:"var(--fs-14)"},children:["Health: ",n.status.toUpperCase()]}),e.jsx("span",{style:{color:"var(--fg-muted)",fontSize:"var(--fs-12)"},children:n.issues.length===0?"No issues detected.":`${n.issues.length} issue${n.issues.length===1?"":"s"}`})]})]})})}):e.jsx(h,{style:{height:64}}),s.loading&&o.length===0?e.jsxs(i,{gap:2,children:[e.jsx(h,{style:{height:64}}),e.jsx(h,{style:{height:64}})]}):s.error&&o.length===0?e.jsx(B,{block:!0,title:"Couldn't run doctor",description:"The diagnostic snapshot failed. Retry to refetch.",error:s.error,onRetry:()=>void s.refetch(),testid:"doctor-error"}):o.length===0?e.jsx(N,{icon:e.jsx(z,{size:32,"aria-hidden":!0}),title:"No checks yet",description:"The Doctor snapshot returned no checks."}):e.jsx(i,{gap:2,children:o.map(t=>{const r=v[t.status],a=k===t.name;return e.jsx(j,{variant:"default",children:e.jsx(y,{children:e.jsxs(c,{align:"center",justify:"between",gap:3,children:[e.jsxs(i,{gap:1,style:{flex:1,minWidth:0},children:[e.jsxs(c,{align:"center",gap:2,children:[e.jsx(r,{size:14,"aria-hidden":!0}),e.jsx("strong",{children:t.name}),e.jsx(E,{tone:O[t.status],children:t.status})]}),e.jsx("span",{style:{color:"var(--fg-muted)",fontSize:"var(--fs-12)"},children:t.message}),t.error&&e.jsx("span",{style:{color:"var(--danger)",fontSize:"var(--fs-12)",fontFamily:"var(--font-mono)"},children:t.error})]}),e.jsxs(x,{variant:"ghost",onClick:()=>void S(t.name),disabled:a,"data-testid":`doctor-run-${t.name}`,children:[a?e.jsx(T,{size:12,className:"animate-spin","aria-hidden":!0}):e.jsx(w,{size:12,"aria-hidden":!0}),a?"Running…":"Re-run"]})]})})},t.name)})})]})}export{M as DoctorView};
@@ -1 +1 @@
1
- {"version":3,"file":"DoctorView-CiFwRMW0.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/circle-x.js","../../src/web/v8/views/Doctor/DoctorView.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleX = createLucideIcon(\"CircleX\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m15 9-6 6\", key: \"1uzhvr\" }],\n [\"path\", { d: \"m9 9 6 6\", key: \"z0biqf\" }]\n]);\n\nexport { CircleX as default };\n//# sourceMappingURL=circle-x.js.map\n","import { useCallback, useEffect, useState } from 'react';\nimport { Stethoscope, RefreshCw, ShieldCheck, AlertTriangle, XCircle, CheckCircle2, Loader2 } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { ErrorState } from '../../ui/feedback/ErrorState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport type { LucideIcon } from 'lucide-react';\n\n/**\n * DoctorView — Sprint S35. Health rollup + per-check triggers.\n */\n\ntype Status = 'ok' | 'warn' | 'fail';\n\ninterface CheckResult {\n name: string;\n status: Status;\n message: string;\n error?: string;\n}\n\ninterface CheckGroup {\n name?: string;\n status?: Status;\n message?: string;\n error?: string;\n}\n\ninterface HealthRollup {\n status: Status;\n issues: Array<{ name: string; status: Status; message: string }>;\n}\n\ninterface DoctorSnapshot {\n health: HealthRollup;\n checks: { system?: CheckGroup[]; config?: CheckGroup[]; services?: CheckGroup[] };\n recentErrors?: unknown[];\n}\n\nconst STATUS_ICON: Record<Status, LucideIcon> = {\n ok: CheckCircle2,\n warn: AlertTriangle,\n fail: XCircle,\n};\n\nconst STATUS_TONE = {\n ok: 'success',\n warn: 'warning',\n fail: 'danger',\n} as const;\n\nexport function DoctorView(): JSX.Element {\n const snap = useFetch<DoctorSnapshot>('/api/doctor');\n const health = useFetch<HealthRollup>('/api/doctor/health');\n const [running, setRunning] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n // Re-poll health every 30s for a live rollup.\n useEffect(() => {\n const id = setInterval(() => { void health.refetch(); }, 30_000);\n return () => clearInterval(id);\n }, [health]);\n\n const runCheck = async (name: string): Promise<void> => {\n setRunning(name);\n setError(null);\n try {\n await fetchJson('/api/doctor/check', { method: 'POST', body: { checkName: name } });\n void snap.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setRunning(null);\n }\n };\n\n const rollup = health.data ?? snap.data?.health;\n const checks: CheckResult[] = (() => {\n const g = snap.data?.checks;\n if (!g) return [];\n return [...(g.system ?? []), ...(g.config ?? []), ...(g.services ?? [])]\n .filter((c): c is CheckResult =>\n typeof c.name === 'string' && typeof c.status === 'string' && typeof c.message === 'string'\n );\n })();\n\n return (\n <Stack gap={5} data-testid=\"doctor-view\">\n <ViewHeader\n title=\"Doctor\"\n description=\"System diagnostics. Health poll every 30s; click any check to re-run.\"\n actions={\n <Inline gap={2} align=\"center\">\n {error !== null && <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>}\n <Button variant=\"ghost\" onClick={() => void snap.refetch()} data-testid=\"doctor-refresh\">\n <RefreshCw size={14} aria-hidden /> Refresh\n </Button>\n </Inline>\n }\n />\n\n {rollup ? (\n <Card variant=\"elevated\">\n <CardBody>\n <Inline align=\"center\" gap={3}>\n {(() => {\n const Icon = STATUS_ICON[rollup.status];\n return <Icon size={20} aria-hidden />;\n })()}\n <Stack gap={0}>\n <strong style={{ fontSize: 'var(--fs-14)' }}>Health: {rollup.status.toUpperCase()}</strong>\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>\n {rollup.issues.length === 0 ? 'No issues detected.' : `${rollup.issues.length} issue${rollup.issues.length === 1 ? '' : 's'}`}\n </span>\n </Stack>\n </Inline>\n </CardBody>\n </Card>\n ) : (\n <Skeleton style={{ height: 64 }} />\n )}\n\n {snap.loading && checks.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 64 }} />\n <Skeleton style={{ height: 64 }} />\n </Stack>\n ) : snap.error && checks.length === 0 ? (\n <ErrorState\n block\n title=\"Couldn't run doctor\"\n description=\"The diagnostic snapshot failed. Retry to refetch.\"\n error={snap.error}\n onRetry={() => void snap.refetch()}\n testid=\"doctor-error\"\n />\n ) : checks.length === 0 ? (\n <EmptyState\n icon={<Stethoscope size={32} aria-hidden />}\n title=\"No checks yet\"\n description=\"The Doctor snapshot returned no checks.\"\n />\n ) : (\n <Stack gap={2}>\n {checks.map((c) => {\n const Icon = STATUS_ICON[c.status];\n const busy = running === c.name;\n return (\n <Card key={c.name} variant=\"default\">\n <CardBody>\n <Inline align=\"center\" justify=\"between\" gap={3}>\n <Stack gap={1} style={{ flex: 1, minWidth: 0 }}>\n <Inline align=\"center\" gap={2}>\n <Icon size={14} aria-hidden />\n <strong>{c.name}</strong>\n <Badge tone={STATUS_TONE[c.status]}>{c.status}</Badge>\n </Inline>\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>{c.message}</span>\n {c.error && <span style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)', fontFamily: 'var(--font-mono)' }}>{c.error}</span>}\n </Stack>\n <Button variant=\"ghost\" onClick={() => void runCheck(c.name)} disabled={busy} data-testid={`doctor-run-${c.name}`}>\n {busy ? <Loader2 size={12} className=\"animate-spin\" aria-hidden /> : <ShieldCheck size={12} aria-hidden />}\n {busy ? 'Running…' : 'Re-run'}\n </Button>\n </Inline>\n </CardBody>\n </Card>\n );\n })}\n </Stack>\n )}\n </Stack>\n );\n}"],"names":["CircleX","createLucideIcon","STATUS_ICON","CheckCircle2","AlertTriangle","XCircle","STATUS_TONE","DoctorView","snap","useFetch","health","running","setRunning","useState","error","setError","useEffect","id","runCheck","name","fetchJson","err","FetchError","rollup","_a","checks","g","c","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCw","Card","CardBody","Icon","Skeleton","ErrorState","EmptyState","Stethoscope","busy","Badge","Loader2","ShieldCheck"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"DoctorView-DepBdQGR.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/circle-x.js","../../src/web/v8/views/Doctor/DoctorView.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleX = createLucideIcon(\"CircleX\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m15 9-6 6\", key: \"1uzhvr\" }],\n [\"path\", { d: \"m9 9 6 6\", key: \"z0biqf\" }]\n]);\n\nexport { CircleX as default };\n//# sourceMappingURL=circle-x.js.map\n","import { useCallback, useEffect, useState } from 'react';\nimport { Stethoscope, RefreshCw, ShieldCheck, AlertTriangle, XCircle, CheckCircle2, Loader2 } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { ErrorState } from '../../ui/feedback/ErrorState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport type { LucideIcon } from 'lucide-react';\n\n/**\n * DoctorView — Sprint S35. Health rollup + per-check triggers.\n */\n\ntype Status = 'ok' | 'warn' | 'fail';\n\ninterface CheckResult {\n name: string;\n status: Status;\n message: string;\n error?: string;\n}\n\ninterface CheckGroup {\n name?: string;\n status?: Status;\n message?: string;\n error?: string;\n}\n\ninterface HealthRollup {\n status: Status;\n issues: Array<{ name: string; status: Status; message: string }>;\n}\n\ninterface DoctorSnapshot {\n health: HealthRollup;\n checks: { system?: CheckGroup[]; config?: CheckGroup[]; services?: CheckGroup[] };\n recentErrors?: unknown[];\n}\n\nconst STATUS_ICON: Record<Status, LucideIcon> = {\n ok: CheckCircle2,\n warn: AlertTriangle,\n fail: XCircle,\n};\n\nconst STATUS_TONE = {\n ok: 'success',\n warn: 'warning',\n fail: 'danger',\n} as const;\n\nexport function DoctorView(): JSX.Element {\n const snap = useFetch<DoctorSnapshot>('/api/doctor');\n const health = useFetch<HealthRollup>('/api/doctor/health');\n const [running, setRunning] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n // Re-poll health every 30s for a live rollup.\n useEffect(() => {\n const id = setInterval(() => { void health.refetch(); }, 30_000);\n return () => clearInterval(id);\n }, [health]);\n\n const runCheck = async (name: string): Promise<void> => {\n setRunning(name);\n setError(null);\n try {\n await fetchJson('/api/doctor/check', { method: 'POST', body: { checkName: name } });\n void snap.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setRunning(null);\n }\n };\n\n const rollup = health.data ?? snap.data?.health;\n const checks: CheckResult[] = (() => {\n const g = snap.data?.checks;\n if (!g) return [];\n return [...(g.system ?? []), ...(g.config ?? []), ...(g.services ?? [])]\n .filter((c): c is CheckResult =>\n typeof c.name === 'string' && typeof c.status === 'string' && typeof c.message === 'string'\n );\n })();\n\n return (\n <Stack gap={5} data-testid=\"doctor-view\">\n <ViewHeader\n title=\"Doctor\"\n description=\"System diagnostics. Health poll every 30s; click any check to re-run.\"\n actions={\n <Inline gap={2} align=\"center\">\n {error !== null && <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>}\n <Button variant=\"ghost\" onClick={() => void snap.refetch()} data-testid=\"doctor-refresh\">\n <RefreshCw size={14} aria-hidden /> Refresh\n </Button>\n </Inline>\n }\n />\n\n {rollup ? (\n <Card variant=\"elevated\">\n <CardBody>\n <Inline align=\"center\" gap={3}>\n {(() => {\n const Icon = STATUS_ICON[rollup.status];\n return <Icon size={20} aria-hidden />;\n })()}\n <Stack gap={0}>\n <strong style={{ fontSize: 'var(--fs-14)' }}>Health: {rollup.status.toUpperCase()}</strong>\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>\n {rollup.issues.length === 0 ? 'No issues detected.' : `${rollup.issues.length} issue${rollup.issues.length === 1 ? '' : 's'}`}\n </span>\n </Stack>\n </Inline>\n </CardBody>\n </Card>\n ) : (\n <Skeleton style={{ height: 64 }} />\n )}\n\n {snap.loading && checks.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 64 }} />\n <Skeleton style={{ height: 64 }} />\n </Stack>\n ) : snap.error && checks.length === 0 ? (\n <ErrorState\n block\n title=\"Couldn't run doctor\"\n description=\"The diagnostic snapshot failed. Retry to refetch.\"\n error={snap.error}\n onRetry={() => void snap.refetch()}\n testid=\"doctor-error\"\n />\n ) : checks.length === 0 ? (\n <EmptyState\n icon={<Stethoscope size={32} aria-hidden />}\n title=\"No checks yet\"\n description=\"The Doctor snapshot returned no checks.\"\n />\n ) : (\n <Stack gap={2}>\n {checks.map((c) => {\n const Icon = STATUS_ICON[c.status];\n const busy = running === c.name;\n return (\n <Card key={c.name} variant=\"default\">\n <CardBody>\n <Inline align=\"center\" justify=\"between\" gap={3}>\n <Stack gap={1} style={{ flex: 1, minWidth: 0 }}>\n <Inline align=\"center\" gap={2}>\n <Icon size={14} aria-hidden />\n <strong>{c.name}</strong>\n <Badge tone={STATUS_TONE[c.status]}>{c.status}</Badge>\n </Inline>\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>{c.message}</span>\n {c.error && <span style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)', fontFamily: 'var(--font-mono)' }}>{c.error}</span>}\n </Stack>\n <Button variant=\"ghost\" onClick={() => void runCheck(c.name)} disabled={busy} data-testid={`doctor-run-${c.name}`}>\n {busy ? <Loader2 size={12} className=\"animate-spin\" aria-hidden /> : <ShieldCheck size={12} aria-hidden />}\n {busy ? 'Running…' : 'Re-run'}\n </Button>\n </Inline>\n </CardBody>\n </Card>\n );\n })}\n </Stack>\n )}\n </Stack>\n );\n}"],"names":["CircleX","createLucideIcon","STATUS_ICON","CheckCircle2","AlertTriangle","XCircle","STATUS_TONE","DoctorView","snap","useFetch","health","running","setRunning","useState","error","setError","useEffect","id","runCheck","name","fetchJson","err","FetchError","rollup","_a","checks","g","c","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCw","Card","CardBody","Icon","Skeleton","ErrorState","EmptyState","Stethoscope","busy","Badge","Loader2","ShieldCheck"],"mappings":"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","x_google_ignoreList":[0]}
@@ -1 +1 @@
1
- import{r as l,j as e}from"./cmdk-C3F6LD6N.js";import{g as d}from"./main-BZMmD6a8.js";const m=l.forwardRef(function(r,a){const{icon:t,title:n,description:s,action:i,className:o,...c}=r;return e.jsxs("div",{ref:a,className:d("v8-empty-state",o),style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:"var(--space-3)",padding:"var(--space-12) var(--space-6)",textAlign:"center",color:"var(--fg-muted)"},...c,children:[t!==void 0&&e.jsx("div",{style:{color:"var(--fg-subtle)",display:"inline-flex"},children:t}),e.jsx("div",{style:{fontSize:"var(--fs-16)",fontWeight:600,color:"var(--fg)"},children:n}),s!==void 0&&e.jsx("div",{style:{fontSize:"var(--fs-13)",maxWidth:480},children:s}),i!==void 0&&e.jsx("div",{style:{marginTop:"var(--space-2)"},children:i})]})});export{m as E};
1
+ import{r as l,j as e}from"./cmdk-C3F6LD6N.js";import{g as d}from"./main-BURAlktW.js";const m=l.forwardRef(function(r,a){const{icon:t,title:n,description:s,action:i,className:o,...c}=r;return e.jsxs("div",{ref:a,className:d("v8-empty-state",o),style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:"var(--space-3)",padding:"var(--space-12) var(--space-6)",textAlign:"center",color:"var(--fg-muted)"},...c,children:[t!==void 0&&e.jsx("div",{style:{color:"var(--fg-subtle)",display:"inline-flex"},children:t}),e.jsx("div",{style:{fontSize:"var(--fs-16)",fontWeight:600,color:"var(--fg)"},children:n}),s!==void 0&&e.jsx("div",{style:{fontSize:"var(--fs-13)",maxWidth:480},children:s}),i!==void 0&&e.jsx("div",{style:{marginTop:"var(--space-2)"},children:i})]})});export{m as E};
@@ -1 +1 @@
1
- {"version":3,"file":"EmptyState-CdDQmfEL.js","sources":["../../src/web/v8/ui/feedback/EmptyState.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cx } from '../utils/cx.js';\n\n/**\n * EmptyState — placeholder for empty lists / zero-data views.\n *\n * Use when a view has no rows. Never use a spinner; the data is\n * genuinely empty.\n */\nexport interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n icon?: ReactNode;\n title: ReactNode;\n description?: ReactNode;\n action?: ReactNode;\n}\n\nexport const EmptyState = forwardRef<HTMLDivElement, EmptyStateProps>(function EmptyState(\n props,\n ref,\n) {\n const { icon, title, description, action, className, ...rest } = props;\n return (\n <div\n ref={ref}\n className={cx('v8-empty-state', className)}\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 'var(--space-3)',\n padding: 'var(--space-12) var(--space-6)',\n textAlign: 'center',\n color: 'var(--fg-muted)',\n }}\n {...rest}\n >\n {icon !== undefined && (\n <div style={{ color: 'var(--fg-subtle)', display: 'inline-flex' }}>{icon}</div>\n )}\n <div style={{ fontSize: 'var(--fs-16)', fontWeight: 600, color: 'var(--fg)' }}>{title}</div>\n {description !== undefined && (\n <div style={{ fontSize: 'var(--fs-13)', maxWidth: 480 }}>{description}</div>\n )}\n {action !== undefined && <div style={{ marginTop: 'var(--space-2)' }}>{action}</div>}\n </div>\n );\n});"],"names":["EmptyState","forwardRef","props","ref","icon","title","description","action","className","rest","jsxs","cx","jsx"],"mappings":"qFAgBO,MAAMA,EAAaC,EAAAA,WAA4C,SACpEC,EACAC,EACA,CACA,KAAM,CAAE,KAAAC,EAAM,MAAAC,EAAO,YAAAC,EAAa,OAAAC,EAAQ,UAAAC,EAAW,GAAGC,GAASP,EACjE,OACEQ,EAAAA,KAAC,MAAA,CACC,IAAAP,EACA,UAAWQ,EAAG,iBAAkBH,CAAS,EACzC,MAAO,CACL,QAAS,OACT,cAAe,SACf,WAAY,SACZ,eAAgB,SAChB,IAAK,iBACL,QAAS,iCACT,UAAW,SACX,MAAO,iBAAA,EAER,GAAGC,EAEH,SAAA,CAAAL,IAAS,QACRQ,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,MAAO,mBAAoB,QAAS,aAAA,EAAkB,SAAAR,CAAA,CAAK,EAE3EQ,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,SAAU,eAAgB,WAAY,IAAK,MAAO,WAAA,EAAgB,SAAAP,CAAA,CAAM,EACrFC,IAAgB,QACfM,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,SAAU,eAAgB,SAAU,GAAA,EAAQ,SAAAN,CAAA,CAAY,EAEvEC,IAAW,QAAaK,MAAC,MAAA,CAAI,MAAO,CAAE,UAAW,gBAAA,EAAqB,SAAAL,CAAA,CAAO,CAAA,CAAA,CAAA,CAGpF,CAAC"}
1
+ {"version":3,"file":"EmptyState-DjKtY1Qi.js","sources":["../../src/web/v8/ui/feedback/EmptyState.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cx } from '../utils/cx.js';\n\n/**\n * EmptyState — placeholder for empty lists / zero-data views.\n *\n * Use when a view has no rows. Never use a spinner; the data is\n * genuinely empty.\n */\nexport interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n icon?: ReactNode;\n title: ReactNode;\n description?: ReactNode;\n action?: ReactNode;\n}\n\nexport const EmptyState = forwardRef<HTMLDivElement, EmptyStateProps>(function EmptyState(\n props,\n ref,\n) {\n const { icon, title, description, action, className, ...rest } = props;\n return (\n <div\n ref={ref}\n className={cx('v8-empty-state', className)}\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 'var(--space-3)',\n padding: 'var(--space-12) var(--space-6)',\n textAlign: 'center',\n color: 'var(--fg-muted)',\n }}\n {...rest}\n >\n {icon !== undefined && (\n <div style={{ color: 'var(--fg-subtle)', display: 'inline-flex' }}>{icon}</div>\n )}\n <div style={{ fontSize: 'var(--fs-16)', fontWeight: 600, color: 'var(--fg)' }}>{title}</div>\n {description !== undefined && (\n <div style={{ fontSize: 'var(--fs-13)', maxWidth: 480 }}>{description}</div>\n )}\n {action !== undefined && <div style={{ marginTop: 'var(--space-2)' }}>{action}</div>}\n </div>\n );\n});"],"names":["EmptyState","forwardRef","props","ref","icon","title","description","action","className","rest","jsxs","cx","jsx"],"mappings":"qFAgBO,MAAMA,EAAaC,EAAAA,WAA4C,SACpEC,EACAC,EACA,CACA,KAAM,CAAE,KAAAC,EAAM,MAAAC,EAAO,YAAAC,EAAa,OAAAC,EAAQ,UAAAC,EAAW,GAAGC,GAASP,EACjE,OACEQ,EAAAA,KAAC,MAAA,CACC,IAAAP,EACA,UAAWQ,EAAG,iBAAkBH,CAAS,EACzC,MAAO,CACL,QAAS,OACT,cAAe,SACf,WAAY,SACZ,eAAgB,SAChB,IAAK,iBACL,QAAS,iCACT,UAAW,SACX,MAAO,iBAAA,EAER,GAAGC,EAEH,SAAA,CAAAL,IAAS,QACRQ,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,MAAO,mBAAoB,QAAS,aAAA,EAAkB,SAAAR,CAAA,CAAK,EAE3EQ,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,SAAU,eAAgB,WAAY,IAAK,MAAO,WAAA,EAAgB,SAAAP,CAAA,CAAM,EACrFC,IAAgB,QACfM,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,SAAU,eAAgB,SAAU,GAAA,EAAQ,SAAAN,CAAA,CAAY,EAEvEC,IAAW,QAAaK,MAAC,MAAA,CAAI,MAAO,CAAE,UAAW,gBAAA,EAAqB,SAAAL,CAAA,CAAO,CAAA,CAAA,CAAA,CAGpF,CAAC"}
@@ -1,8 +1,8 @@
1
- import{r as s,j as e}from"./cmdk-C3F6LD6N.js";import{c as O,u as V,S as p,I as f,d as n,h as I,V as P,N as D,i as y,F as k}from"./main-BZMmD6a8.js";import{V as Z}from"./ViewHeader-BaCWNuVX.js";import{L as M}from"./ListHeader-BLAeshe0.js";import{C as N,b as _}from"./Card-BmXiT4c6.js";import{I as A}from"./Input-cAQOvR8U.js";import{S as w,a as E,b as T}from"./Sheet-CxXf6gvC.js";import{E as L}from"./EmptyState-CdDQmfEL.js";import{D as U}from"./download-DBkNb6oI.js";import{R as q}from"./refresh-ccw-BL7B0NO1.js";import{P as H}from"./plus-uA5Ecuch.js";import{P as K}from"./pencil---XuvKlz.js";import{T as J}from"./trash-2-B885GY46.js";/**
1
+ import{r as s,j as e}from"./cmdk-C3F6LD6N.js";import{d as O,u as V,S as p,I as f,B as n,h as I,V as P,N as D,i as y,F as k}from"./main-BURAlktW.js";import{V as Z}from"./ViewHeader-C-t1U2cQ.js";import{L as M}from"./ListHeader-CM8QoIWG.js";import{C as N,b as _}from"./Card-BtsmkhJa.js";import{I as A}from"./Input-h_nSOtwm.js";import{S as w,a as E,b as R}from"./Sheet-B-CMP9-_.js";import{E as L}from"./EmptyState-DjKtY1Qi.js";import{D as U}from"./download-BvJddD8D.js";import{R as q}from"./refresh-ccw-DA8_IB9l.js";import{P as H}from"./plus-Cm6-fo14.js";import{P as K}from"./pencil-DAwM-CC3.js";import{T as J}from"./trash-2-D6qePV_q.js";/**
2
2
  * @license lucide-react v0.460.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
5
5
  * See the LICENSE file in the root directory of this source tree.
6
- */const W=O("FileUp",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M12 12v6",key:"3ahymv"}],["path",{d:"m15 15-3-3-3 3",key:"15xj92"}]]);function ce(){const d=V("/api/env-vars"),[g,c]=s.useState(!1),[v,r]=s.useState(null),[m,i]=s.useState(!1),[u,l]=s.useState(null),[x,h]=s.useState(null),[b,C]=s.useState(null),[o,$]=s.useState(null),S=s.useMemo(()=>d.data??[],[d.data]),j=s.useCallback(()=>{d.refetch()},[d]),B=async a=>{C(a),h(null);try{const t=await y(`/api/env-vars/${encodeURIComponent(a)}/test`,{method:"POST"});$({name:a,ok:t.ok!==!1,message:t.message??(t.ok!==!1?"OK":"Failed")})}catch(t){const z=(t instanceof k,t.message);$({name:a,ok:!1,message:z})}finally{C(null)}},F=async a=>{h(null);try{await y(`/api/env-vars/${a}`,{method:"DELETE"}),l(null),j()}catch(t){h((t instanceof k,t.message))}};return e.jsxs(p,{gap:4,"data-testid":"env-vars-view",children:[e.jsx(Z,{title:"Env vars",description:"Runtime environment variables for the dashboard. Stored in ~/.config/bizar/env.json (mode 0600).",actions:e.jsxs(f,{align:"center",gap:2,children:[x!==null&&e.jsx("span",{role:"alert","data-testid":"env-vars-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:x}),e.jsxs(n,{variant:"ghost",onClick:()=>{window.open("/api/env-vars/export","_blank")},"data-testid":"env-vars-export",children:[e.jsx(U,{size:14,"aria-hidden":!0})," Export"]}),e.jsxs(n,{variant:"ghost",onClick:()=>i(!0),"data-testid":"env-vars-bulk-import",children:[e.jsx(W,{size:14,"aria-hidden":!0})," Bulk import"]}),e.jsxs(n,{variant:"ghost",onClick:()=>void j(),"data-testid":"env-vars-refresh",children:[e.jsx(q,{size:14,"aria-hidden":!0})," Refresh"]}),e.jsxs(n,{variant:"primary",onClick:()=>c(!0),"data-testid":"env-vars-add",children:[e.jsx(H,{size:14,"aria-hidden":!0})," Add"]})]})}),e.jsx(M,{title:"Variables",count:S.length,testid:"env-vars-list-header"}),e.jsx(N,{variant:"default",children:e.jsx(_,{children:d.loading&&S.length===0?e.jsxs(p,{gap:2,children:[e.jsx(I,{style:{height:36}}),e.jsx(I,{style:{height:36}})]}):S.length===0?e.jsx(L,{icon:e.jsx(P,{size:28,"aria-hidden":!0}),title:"No env vars",description:"Add one or bulk-import a .env file."}):e.jsx(p,{gap:1,children:S.map(a=>{const t=u===a.name;return e.jsxs("div",{"data-testid":`env-var-row-${a.name}`,style:{padding:"var(--space-2)",borderRadius:"var(--radius-sm)",border:"1px solid var(--border)",background:"var(--surface-0)"},children:[e.jsxs(f,{align:"center",justify:"between",gap:2,children:[e.jsxs(p,{gap:0,style:{minWidth:0},children:[e.jsx("code",{style:{fontSize:"var(--fs-12)"},children:a.name}),e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:a.value}),a.source&&e.jsxs("span",{style:{fontSize:"var(--fs-11)",color:"var(--fg-subtle)"},children:["source: ",a.source," ",a.createdAt?`· ${a.createdAt}`:""]})]}),e.jsxs(f,{gap:1,children:[e.jsx(n,{variant:"ghost",onClick:()=>void B(a.name),disabled:b===a.name,"data-testid":`env-var-test-${a.name}`,"aria-label":`Test ${a.name}`,children:e.jsx(D,{size:14,"aria-hidden":!0})}),e.jsx(n,{variant:"ghost",onClick:()=>r(a.name),"data-testid":`env-var-edit-${a.name}`,"aria-label":`Edit ${a.name}`,children:e.jsx(K,{size:14,"aria-hidden":!0})}),e.jsx(n,{variant:"ghost",onClick:()=>l(z=>z===a.name?null:a.name),"data-testid":`env-var-delete-${a.name}`,"aria-label":`Delete ${a.name}`,children:e.jsx(J,{size:14,"aria-hidden":!0})})]})]}),t&&e.jsxs(f,{gap:1,style:{marginTop:"var(--space-1)"},children:[e.jsx(n,{variant:"danger",onClick:()=>void F(a.name),"data-testid":`env-var-confirm-delete-${a.name}`,children:"Confirm delete"}),e.jsx(n,{variant:"ghost",onClick:()=>l(null),"data-testid":`env-var-cancel-delete-${a.name}`,children:"Cancel"})]}),o!==null&&o.name===a.name&&e.jsxs("div",{"data-testid":`env-var-test-result-${a.name}`,style:{marginTop:"var(--space-1)",fontSize:"var(--fs-11)",color:o.ok?"var(--success)":"var(--danger)",fontFamily:"var(--font-mono)"},children:["test: ",o.message]})]},a.name)})})})}),e.jsx(w,{open:g,onOpenChange:c,children:e.jsx(E,{side:"right",title:"Add env var",description:"Must match /^BIZAR_[A-Z0-9_]+$/.",children:e.jsx(R,{mode:"add",onSubmit:async(a,t)=>{await y("/api/env-vars",{method:"POST",body:{name:a,value:t}}),c(!1),j()},onCancel:()=>c(!1)})})}),e.jsx(w,{open:v!==null,onOpenChange:a=>{a||r(null)},children:e.jsx(E,{side:"right",title:"Edit env var",description:v??"",children:v!==null&&e.jsx(R,{mode:"edit",initialName:v,onSubmit:async(a,t)=>{await y(`/api/env-vars/${a}`,{method:"PUT",body:{value:t}}),r(null),j()},onCancel:()=>r(null)})})}),e.jsx(w,{open:m,onOpenChange:i,children:e.jsx(E,{side:"right",title:"Bulk import",description:"Paste KEY=value lines (one per line, # comments ignored).",children:e.jsx(Y,{onSubmit:async a=>{await y("/api/env-vars/bulk-import",{method:"POST",body:{envContent:a}}),i(!1),j()},onCancel:()=>i(!1)})})})]})}function R({mode:d,initialName:g,onSubmit:c,onCancel:v}){const[r,m]=s.useState(g??""),[i,u]=s.useState(""),[l,x]=s.useState(!1),[h,b]=s.useState(null),C=async()=>{if(!(!r.trim()||!i||l)){x(!0),b(null);try{await c(r.trim(),i)}catch(o){b((o instanceof k,o.message))}finally{x(!1)}}};return e.jsxs(p,{gap:3,style:{padding:"var(--space-4)"},children:[e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Name"}),e.jsx(A,{value:r,readOnly:d==="edit","data-testid":"env-var-form-name",onChange:o=>m(o.target.value)})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Value"}),e.jsx(A,{type:"password",value:i,"data-testid":"env-var-form-value",onChange:o=>u(o.target.value)})]}),h!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:h}),e.jsxs(f,{justify:"end",gap:2,children:[e.jsx(T,{asChild:!0,children:e.jsx(n,{variant:"ghost",onClick:v,"data-testid":"env-var-form-cancel",children:"Cancel"})}),e.jsx(n,{variant:"primary",onClick:()=>void C(),disabled:l||!r.trim()||!i,"data-testid":"env-var-form-submit",children:d==="add"?"Add":"Save"})]})]})}function Y({onSubmit:d,onCancel:g}){const[c,v]=s.useState(""),[r,m]=s.useState(!1),[i,u]=s.useState(null);return e.jsxs(p,{gap:3,style:{padding:"var(--space-4)"},children:[e.jsx("textarea",{value:c,placeholder:`BIZAR_FOO=bar
6
+ */const W=O("FileUp",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M12 12v6",key:"3ahymv"}],["path",{d:"m15 15-3-3-3 3",key:"15xj92"}]]);function ce(){const d=V("/api/env-vars"),[g,c]=s.useState(!1),[v,r]=s.useState(null),[m,i]=s.useState(!1),[u,l]=s.useState(null),[x,h]=s.useState(null),[b,C]=s.useState(null),[o,$]=s.useState(null),S=s.useMemo(()=>d.data??[],[d.data]),j=s.useCallback(()=>{d.refetch()},[d]),T=async a=>{C(a),h(null);try{const t=await y(`/api/env-vars/${encodeURIComponent(a)}/test`,{method:"POST"});$({name:a,ok:t.ok!==!1,message:t.message??(t.ok!==!1?"OK":"Failed")})}catch(t){const z=(t instanceof k,t.message);$({name:a,ok:!1,message:z})}finally{C(null)}},F=async a=>{h(null);try{await y(`/api/env-vars/${a}`,{method:"DELETE"}),l(null),j()}catch(t){h((t instanceof k,t.message))}};return e.jsxs(p,{gap:4,"data-testid":"env-vars-view",children:[e.jsx(Z,{title:"Env vars",description:"Runtime environment variables for the dashboard. Stored in ~/.config/bizar/env.json (mode 0600).",actions:e.jsxs(f,{align:"center",gap:2,children:[x!==null&&e.jsx("span",{role:"alert","data-testid":"env-vars-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:x}),e.jsxs(n,{variant:"ghost",onClick:()=>{window.open("/api/env-vars/export","_blank")},"data-testid":"env-vars-export",children:[e.jsx(U,{size:14,"aria-hidden":!0})," Export"]}),e.jsxs(n,{variant:"ghost",onClick:()=>i(!0),"data-testid":"env-vars-bulk-import",children:[e.jsx(W,{size:14,"aria-hidden":!0})," Bulk import"]}),e.jsxs(n,{variant:"ghost",onClick:()=>void j(),"data-testid":"env-vars-refresh",children:[e.jsx(q,{size:14,"aria-hidden":!0})," Refresh"]}),e.jsxs(n,{variant:"primary",onClick:()=>c(!0),"data-testid":"env-vars-add",children:[e.jsx(H,{size:14,"aria-hidden":!0})," Add"]})]})}),e.jsx(M,{title:"Variables",count:S.length,testid:"env-vars-list-header"}),e.jsx(N,{variant:"default",children:e.jsx(_,{children:d.loading&&S.length===0?e.jsxs(p,{gap:2,children:[e.jsx(I,{style:{height:36}}),e.jsx(I,{style:{height:36}})]}):S.length===0?e.jsx(L,{icon:e.jsx(P,{size:28,"aria-hidden":!0}),title:"No env vars",description:"Add one or bulk-import a .env file."}):e.jsx(p,{gap:1,children:S.map(a=>{const t=u===a.name;return e.jsxs("div",{"data-testid":`env-var-row-${a.name}`,style:{padding:"var(--space-2)",borderRadius:"var(--radius-sm)",border:"1px solid var(--border)",background:"var(--surface-0)"},children:[e.jsxs(f,{align:"center",justify:"between",gap:2,children:[e.jsxs(p,{gap:0,style:{minWidth:0},children:[e.jsx("code",{style:{fontSize:"var(--fs-12)"},children:a.name}),e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:a.value}),a.source&&e.jsxs("span",{style:{fontSize:"var(--fs-11)",color:"var(--fg-subtle)"},children:["source: ",a.source," ",a.createdAt?`· ${a.createdAt}`:""]})]}),e.jsxs(f,{gap:1,children:[e.jsx(n,{variant:"ghost",onClick:()=>void T(a.name),disabled:b===a.name,"data-testid":`env-var-test-${a.name}`,"aria-label":`Test ${a.name}`,children:e.jsx(D,{size:14,"aria-hidden":!0})}),e.jsx(n,{variant:"ghost",onClick:()=>r(a.name),"data-testid":`env-var-edit-${a.name}`,"aria-label":`Edit ${a.name}`,children:e.jsx(K,{size:14,"aria-hidden":!0})}),e.jsx(n,{variant:"ghost",onClick:()=>l(z=>z===a.name?null:a.name),"data-testid":`env-var-delete-${a.name}`,"aria-label":`Delete ${a.name}`,children:e.jsx(J,{size:14,"aria-hidden":!0})})]})]}),t&&e.jsxs(f,{gap:1,style:{marginTop:"var(--space-1)"},children:[e.jsx(n,{variant:"danger",onClick:()=>void F(a.name),"data-testid":`env-var-confirm-delete-${a.name}`,children:"Confirm delete"}),e.jsx(n,{variant:"ghost",onClick:()=>l(null),"data-testid":`env-var-cancel-delete-${a.name}`,children:"Cancel"})]}),o!==null&&o.name===a.name&&e.jsxs("div",{"data-testid":`env-var-test-result-${a.name}`,style:{marginTop:"var(--space-1)",fontSize:"var(--fs-11)",color:o.ok?"var(--success)":"var(--danger)",fontFamily:"var(--font-mono)"},children:["test: ",o.message]})]},a.name)})})})}),e.jsx(w,{open:g,onOpenChange:c,children:e.jsx(E,{side:"right",title:"Add env var",description:"Must match /^BIZAR_[A-Z0-9_]+$/.",children:e.jsx(B,{mode:"add",onSubmit:async(a,t)=>{await y("/api/env-vars",{method:"POST",body:{name:a,value:t}}),c(!1),j()},onCancel:()=>c(!1)})})}),e.jsx(w,{open:v!==null,onOpenChange:a=>{a||r(null)},children:e.jsx(E,{side:"right",title:"Edit env var",description:v??"",children:v!==null&&e.jsx(B,{mode:"edit",initialName:v,onSubmit:async(a,t)=>{await y(`/api/env-vars/${a}`,{method:"PUT",body:{value:t}}),r(null),j()},onCancel:()=>r(null)})})}),e.jsx(w,{open:m,onOpenChange:i,children:e.jsx(E,{side:"right",title:"Bulk import",description:"Paste KEY=value lines (one per line, # comments ignored).",children:e.jsx(Y,{onSubmit:async a=>{await y("/api/env-vars/bulk-import",{method:"POST",body:{envContent:a}}),i(!1),j()},onCancel:()=>i(!1)})})})]})}function B({mode:d,initialName:g,onSubmit:c,onCancel:v}){const[r,m]=s.useState(g??""),[i,u]=s.useState(""),[l,x]=s.useState(!1),[h,b]=s.useState(null),C=async()=>{if(!(!r.trim()||!i||l)){x(!0),b(null);try{await c(r.trim(),i)}catch(o){b((o instanceof k,o.message))}finally{x(!1)}}};return e.jsxs(p,{gap:3,style:{padding:"var(--space-4)"},children:[e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Name"}),e.jsx(A,{value:r,readOnly:d==="edit","data-testid":"env-var-form-name",onChange:o=>m(o.target.value)})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Value"}),e.jsx(A,{type:"password",value:i,"data-testid":"env-var-form-value",onChange:o=>u(o.target.value)})]}),h!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:h}),e.jsxs(f,{justify:"end",gap:2,children:[e.jsx(R,{asChild:!0,children:e.jsx(n,{variant:"ghost",onClick:v,"data-testid":"env-var-form-cancel",children:"Cancel"})}),e.jsx(n,{variant:"primary",onClick:()=>void C(),disabled:l||!r.trim()||!i,"data-testid":"env-var-form-submit",children:d==="add"?"Add":"Save"})]})]})}function Y({onSubmit:d,onCancel:g}){const[c,v]=s.useState(""),[r,m]=s.useState(!1),[i,u]=s.useState(null);return e.jsxs(p,{gap:3,style:{padding:"var(--space-4)"},children:[e.jsx("textarea",{value:c,placeholder:`BIZAR_FOO=bar
7
7
  BIZAR_BAZ=qux
8
- # comment`,rows:12,"data-testid":"env-vars-bulk-input",onChange:l=>v(l.target.value),style:{background:"var(--surface-0)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"var(--space-2)",color:"var(--fg)",fontFamily:"var(--font-mono)",fontSize:"var(--fs-12)",resize:"vertical"}}),i!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:i}),e.jsxs(f,{justify:"end",gap:2,children:[e.jsx(T,{asChild:!0,children:e.jsx(n,{variant:"ghost",onClick:g,children:"Cancel"})}),e.jsx(n,{variant:"primary",onClick:async()=>{m(!0),u(null);try{await d(c)}catch(l){u((l instanceof k,l.message))}finally{m(!1)}},disabled:r||c.trim()==="","data-testid":"env-vars-bulk-submit",children:r?"Importing…":"Import"})]})]})}export{ce as EnvVarsView};
8
+ # comment`,rows:12,"data-testid":"env-vars-bulk-input",onChange:l=>v(l.target.value),style:{background:"var(--surface-0)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"var(--space-2)",color:"var(--fg)",fontFamily:"var(--font-mono)",fontSize:"var(--fs-12)",resize:"vertical"}}),i!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:i}),e.jsxs(f,{justify:"end",gap:2,children:[e.jsx(R,{asChild:!0,children:e.jsx(n,{variant:"ghost",onClick:g,children:"Cancel"})}),e.jsx(n,{variant:"primary",onClick:async()=>{m(!0),u(null);try{await d(c)}catch(l){u((l instanceof k,l.message))}finally{m(!1)}},disabled:r||c.trim()==="","data-testid":"env-vars-bulk-submit",children:r?"Importing…":"Import"})]})]})}export{ce as EnvVarsView};
@@ -1 +1 @@
1
- {"version":3,"file":"EnvVarsView-CNO03NDJ.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/file-up.js","../../src/web/v8/views/EnvVars/EnvVarsView.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FileUp = createLucideIcon(\"FileUp\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"M12 12v6\", key: \"3ahymv\" }],\n [\"path\", { d: \"m15 15-3-3-3 3\", key: \"15xj92\" }]\n]);\n\nexport { FileUp as default };\n//# sourceMappingURL=file-up.js.map\n","/**\n * v8/views/EnvVars/EnvVarsView.tsx — Sprint S41, v9.3.0.\n *\n * List of env vars (masked values) with: per-row edit (Sheet),\n * per-row delete (inline confirm), Add Sheet, Bulk Import Sheet,\n * and Export trigger. Backed by /api/env-vars + /api/env-vars/grouped\n * + /api/env-vars/export + /api/env-vars/bulk-import.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { Download, FileUp, FlaskConical, Pencil, Plus, RefreshCcw, Trash2, Variable } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { ListHeader } from '../../ui/data/ListHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface EnvRow {\n name: string;\n value: string;\n createdAt?: string;\n source?: string;\n}\n\nexport function EnvVarsView(): JSX.Element {\n const payload = useFetch<EnvRow[]>('/api/env-vars');\n const [adding, setAdding] = useState<boolean>(false);\n const [editing, setEditing] = useState<string | null>(null);\n const [bulkImporting, setBulkImporting] = useState<boolean>(false);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [testing, setTesting] = useState<string | null>(null);\n const [testResult, setTestResult] = useState<{ name: string; ok: boolean; message: string } | null>(null);\n\n const rows = useMemo<EnvRow[]>(() => payload.data ?? [], [payload.data]);\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const runTest = async (name: string): Promise<void> => {\n setTesting(name);\n setError(null);\n try {\n const res = await fetchJson<{ ok?: boolean; status?: string; message?: string }>(`/api/env-vars/${encodeURIComponent(name)}/test`, { method: 'POST' });\n setTestResult({ name, ok: res.ok !== false, message: res.message ?? (res.ok !== false ? 'OK' : 'Failed') });\n } catch (err) {\n const msg = err instanceof FetchError ? err.message : (err as Error).message;\n setTestResult({ name, ok: false, message: msg });\n } finally {\n setTesting(null);\n }\n };\n\n const drop = async (name: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/env-vars/${name}`, { method: 'DELETE' });\n setConfirmDelete(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <Stack gap={4} data-testid=\"env-vars-view\">\n <ViewHeader\n title=\"Env vars\"\n description=\"Runtime environment variables for the dashboard. Stored in ~/.config/bizar/env.json (mode 0600).\"\n actions={\n <Inline align=\"center\" gap={2}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"env-vars-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => { window.open('/api/env-vars/export', '_blank'); }} data-testid=\"env-vars-export\">\n <Download size={14} aria-hidden /> Export\n </Button>\n <Button variant=\"ghost\" onClick={() => setBulkImporting(true)} data-testid=\"env-vars-bulk-import\">\n <FileUp size={14} aria-hidden /> Bulk import\n </Button>\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"env-vars-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setAdding(true)} data-testid=\"env-vars-add\">\n <Plus size={14} aria-hidden /> Add\n </Button>\n </Inline>\n }\n />\n <ListHeader title=\"Variables\" count={rows.length} testid=\"env-vars-list-header\" />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && rows.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 36 }} />\n <Skeleton style={{ height: 36 }} />\n </Stack>\n ) : rows.length === 0 ? (\n <EmptyState\n icon={<Variable size={28} aria-hidden />}\n title=\"No env vars\"\n description=\"Add one or bulk-import a .env file.\"\n />\n ) : (\n <Stack gap={1}>\n {rows.map((r) => {\n const isConfirming = confirmDelete === r.name;\n return (\n <div\n key={r.name}\n data-testid={`env-var-row-${r.name}`}\n style={{\n padding: 'var(--space-2)',\n borderRadius: 'var(--radius-sm)',\n border: '1px solid var(--border)',\n background: 'var(--surface-0)',\n }}\n >\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Stack gap={0} style={{ minWidth: 0 }}>\n <code style={{ fontSize: 'var(--fs-12)' }}>{r.name}</code>\n <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{r.value}</code>\n {r.source && (\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>\n source: {r.source} {r.createdAt ? `· ${r.createdAt}` : ''}\n </span>\n )}\n </Stack>\n <Inline gap={1}>\n <Button\n variant=\"ghost\"\n onClick={() => void runTest(r.name)}\n disabled={testing === r.name}\n data-testid={`env-var-test-${r.name}`}\n aria-label={`Test ${r.name}`}\n >\n <FlaskConical size={14} aria-hidden />\n </Button>\n <Button variant=\"ghost\" onClick={() => setEditing(r.name)} data-testid={`env-var-edit-${r.name}`} aria-label={`Edit ${r.name}`}>\n <Pencil size={14} aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmDelete((cur) => (cur === r.name ? null : r.name))}\n data-testid={`env-var-delete-${r.name}`}\n aria-label={`Delete ${r.name}`}\n >\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"danger\" onClick={() => void drop(r.name)} data-testid={`env-var-confirm-delete-${r.name}`}>\n Confirm delete\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)} data-testid={`env-var-cancel-delete-${r.name}`}>\n Cancel\n </Button>\n </Inline>\n )}\n {testResult !== null && testResult.name === r.name && (\n <div\n data-testid={`env-var-test-result-${r.name}`}\n style={{\n marginTop: 'var(--space-1)',\n fontSize: 'var(--fs-11)',\n color: testResult.ok ? 'var(--success)' : 'var(--danger)',\n fontFamily: 'var(--font-mono)',\n }}\n >\n test: {testResult.message}\n </div>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n <Sheet open={adding} onOpenChange={setAdding}>\n <SheetContent side=\"right\" title=\"Add env var\" description=\"Must match /^BIZAR_[A-Z0-9_]+$/.\">\n <AddEditForm\n mode=\"add\"\n onSubmit={async (name, value) => {\n await fetchJson('/api/env-vars', { method: 'POST', body: { name, value } });\n setAdding(false);\n refresh();\n }}\n onCancel={() => setAdding(false)}\n />\n </SheetContent>\n </Sheet>\n\n <Sheet open={editing !== null} onOpenChange={(open) => { if (!open) setEditing(null); }}>\n <SheetContent side=\"right\" title=\"Edit env var\" description={editing ?? ''}>\n {editing !== null && (\n <AddEditForm\n mode=\"edit\"\n initialName={editing}\n onSubmit={async (name, value) => {\n await fetchJson(`/api/env-vars/${name}`, { method: 'PUT', body: { value } });\n setEditing(null);\n refresh();\n }}\n onCancel={() => setEditing(null)}\n />\n )}\n </SheetContent>\n </Sheet>\n\n <Sheet open={bulkImporting} onOpenChange={setBulkImporting}>\n <SheetContent side=\"right\" title=\"Bulk import\" description=\"Paste KEY=value lines (one per line, # comments ignored).\">\n <BulkImportForm\n onSubmit={async (envContent) => {\n await fetchJson('/api/env-vars/bulk-import', {\n method: 'POST',\n body: { envContent },\n });\n setBulkImporting(false);\n refresh();\n }}\n onCancel={() => setBulkImporting(false)}\n />\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n\nfunction AddEditForm({\n mode,\n initialName,\n onSubmit,\n onCancel,\n}: {\n mode: 'add' | 'edit';\n initialName?: string;\n onSubmit: (name: string, value: string) => Promise<void>;\n onCancel: () => void;\n}): JSX.Element {\n const [name, setName] = useState<string>(initialName ?? '');\n const [value, setValue] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const submit = async (): Promise<void> => {\n if (!name.trim() || !value || busy) return;\n setBusy(true);\n setError(null);\n try {\n await onSubmit(name.trim(), value);\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Name</span>\n <Input\n value={name}\n readOnly={mode === 'edit'}\n data-testid=\"env-var-form-name\"\n onChange={(e) => setName((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Value</span>\n <Input\n type=\"password\"\n value={value}\n data-testid=\"env-var-form-value\"\n onChange={(e) => setValue((e.target as HTMLInputElement).value)}\n />\n </label>\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" onClick={onCancel} data-testid=\"env-var-form-cancel\">Cancel</Button>\n </SheetClose>\n <Button\n variant=\"primary\"\n onClick={() => void submit()}\n disabled={busy || !name.trim() || !value}\n data-testid=\"env-var-form-submit\"\n >\n {mode === 'add' ? 'Add' : 'Save'}\n </Button>\n </Inline>\n </Stack>\n );\n}\n\nfunction BulkImportForm({\n onSubmit,\n onCancel,\n}: {\n onSubmit: (envContent: string) => Promise<void>;\n onCancel: () => void;\n}): JSX.Element {\n const [content, setContent] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <textarea\n value={content}\n placeholder={'BIZAR_FOO=bar\\nBIZAR_BAZ=qux\\n# comment'}\n rows={12}\n data-testid=\"env-vars-bulk-input\"\n onChange={(e) => setContent((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-mono)',\n fontSize: 'var(--fs-12)',\n resize: 'vertical',\n }}\n />\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" onClick={onCancel}>Cancel</Button>\n </SheetClose>\n <Button\n variant=\"primary\"\n onClick={async () => {\n setBusy(true);\n setError(null);\n try { await onSubmit(content); }\n catch (err) { setError(err instanceof FetchError ? err.message : (err as Error).message); }\n finally { setBusy(false); }\n }}\n disabled={busy || content.trim() === ''}\n data-testid=\"env-vars-bulk-submit\"\n >\n {busy ? 'Importing…' : 'Import'}\n </Button>\n </Inline>\n </Stack>\n );\n}"],"names":["FileUp","createLucideIcon","EnvVarsView","payload","useFetch","adding","setAdding","useState","editing","setEditing","bulkImporting","setBulkImporting","confirmDelete","setConfirmDelete","error","setError","testing","setTesting","testResult","setTestResult","rows","useMemo","refresh","useCallback","runTest","name","res","fetchJson","err","msg","FetchError","drop","jsxs","Stack","jsx","ViewHeader","Inline","Button","Download","RefreshCcw","Plus","ListHeader","Card","CardBody","Skeleton","EmptyState","Variable","r","isConfirming","FlaskConical","Pencil","cur","Trash2","Sheet","SheetContent","AddEditForm","value","open","BulkImportForm","envContent","mode","initialName","onSubmit","onCancel","setName","setValue","busy","setBusy","submit","Input","e","SheetClose","content","setContent"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"EnvVarsView-S4Pbm128.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/file-up.js","../../src/web/v8/views/EnvVars/EnvVarsView.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FileUp = createLucideIcon(\"FileUp\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"M12 12v6\", key: \"3ahymv\" }],\n [\"path\", { d: \"m15 15-3-3-3 3\", key: \"15xj92\" }]\n]);\n\nexport { FileUp as default };\n//# sourceMappingURL=file-up.js.map\n","/**\n * v8/views/EnvVars/EnvVarsView.tsx — Sprint S41, v9.3.0.\n *\n * List of env vars (masked values) with: per-row edit (Sheet),\n * per-row delete (inline confirm), Add Sheet, Bulk Import Sheet,\n * and Export trigger. Backed by /api/env-vars + /api/env-vars/grouped\n * + /api/env-vars/export + /api/env-vars/bulk-import.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { Download, FileUp, FlaskConical, Pencil, Plus, RefreshCcw, Trash2, Variable } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { ListHeader } from '../../ui/data/ListHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface EnvRow {\n name: string;\n value: string;\n createdAt?: string;\n source?: string;\n}\n\nexport function EnvVarsView(): JSX.Element {\n const payload = useFetch<EnvRow[]>('/api/env-vars');\n const [adding, setAdding] = useState<boolean>(false);\n const [editing, setEditing] = useState<string | null>(null);\n const [bulkImporting, setBulkImporting] = useState<boolean>(false);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [testing, setTesting] = useState<string | null>(null);\n const [testResult, setTestResult] = useState<{ name: string; ok: boolean; message: string } | null>(null);\n\n const rows = useMemo<EnvRow[]>(() => payload.data ?? [], [payload.data]);\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const runTest = async (name: string): Promise<void> => {\n setTesting(name);\n setError(null);\n try {\n const res = await fetchJson<{ ok?: boolean; status?: string; message?: string }>(`/api/env-vars/${encodeURIComponent(name)}/test`, { method: 'POST' });\n setTestResult({ name, ok: res.ok !== false, message: res.message ?? (res.ok !== false ? 'OK' : 'Failed') });\n } catch (err) {\n const msg = err instanceof FetchError ? err.message : (err as Error).message;\n setTestResult({ name, ok: false, message: msg });\n } finally {\n setTesting(null);\n }\n };\n\n const drop = async (name: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/env-vars/${name}`, { method: 'DELETE' });\n setConfirmDelete(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <Stack gap={4} data-testid=\"env-vars-view\">\n <ViewHeader\n title=\"Env vars\"\n description=\"Runtime environment variables for the dashboard. Stored in ~/.config/bizar/env.json (mode 0600).\"\n actions={\n <Inline align=\"center\" gap={2}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"env-vars-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => { window.open('/api/env-vars/export', '_blank'); }} data-testid=\"env-vars-export\">\n <Download size={14} aria-hidden /> Export\n </Button>\n <Button variant=\"ghost\" onClick={() => setBulkImporting(true)} data-testid=\"env-vars-bulk-import\">\n <FileUp size={14} aria-hidden /> Bulk import\n </Button>\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"env-vars-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setAdding(true)} data-testid=\"env-vars-add\">\n <Plus size={14} aria-hidden /> Add\n </Button>\n </Inline>\n }\n />\n <ListHeader title=\"Variables\" count={rows.length} testid=\"env-vars-list-header\" />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && rows.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 36 }} />\n <Skeleton style={{ height: 36 }} />\n </Stack>\n ) : rows.length === 0 ? (\n <EmptyState\n icon={<Variable size={28} aria-hidden />}\n title=\"No env vars\"\n description=\"Add one or bulk-import a .env file.\"\n />\n ) : (\n <Stack gap={1}>\n {rows.map((r) => {\n const isConfirming = confirmDelete === r.name;\n return (\n <div\n key={r.name}\n data-testid={`env-var-row-${r.name}`}\n style={{\n padding: 'var(--space-2)',\n borderRadius: 'var(--radius-sm)',\n border: '1px solid var(--border)',\n background: 'var(--surface-0)',\n }}\n >\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Stack gap={0} style={{ minWidth: 0 }}>\n <code style={{ fontSize: 'var(--fs-12)' }}>{r.name}</code>\n <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{r.value}</code>\n {r.source && (\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>\n source: {r.source} {r.createdAt ? `· ${r.createdAt}` : ''}\n </span>\n )}\n </Stack>\n <Inline gap={1}>\n <Button\n variant=\"ghost\"\n onClick={() => void runTest(r.name)}\n disabled={testing === r.name}\n data-testid={`env-var-test-${r.name}`}\n aria-label={`Test ${r.name}`}\n >\n <FlaskConical size={14} aria-hidden />\n </Button>\n <Button variant=\"ghost\" onClick={() => setEditing(r.name)} data-testid={`env-var-edit-${r.name}`} aria-label={`Edit ${r.name}`}>\n <Pencil size={14} aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmDelete((cur) => (cur === r.name ? null : r.name))}\n data-testid={`env-var-delete-${r.name}`}\n aria-label={`Delete ${r.name}`}\n >\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"danger\" onClick={() => void drop(r.name)} data-testid={`env-var-confirm-delete-${r.name}`}>\n Confirm delete\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)} data-testid={`env-var-cancel-delete-${r.name}`}>\n Cancel\n </Button>\n </Inline>\n )}\n {testResult !== null && testResult.name === r.name && (\n <div\n data-testid={`env-var-test-result-${r.name}`}\n style={{\n marginTop: 'var(--space-1)',\n fontSize: 'var(--fs-11)',\n color: testResult.ok ? 'var(--success)' : 'var(--danger)',\n fontFamily: 'var(--font-mono)',\n }}\n >\n test: {testResult.message}\n </div>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n <Sheet open={adding} onOpenChange={setAdding}>\n <SheetContent side=\"right\" title=\"Add env var\" description=\"Must match /^BIZAR_[A-Z0-9_]+$/.\">\n <AddEditForm\n mode=\"add\"\n onSubmit={async (name, value) => {\n await fetchJson('/api/env-vars', { method: 'POST', body: { name, value } });\n setAdding(false);\n refresh();\n }}\n onCancel={() => setAdding(false)}\n />\n </SheetContent>\n </Sheet>\n\n <Sheet open={editing !== null} onOpenChange={(open) => { if (!open) setEditing(null); }}>\n <SheetContent side=\"right\" title=\"Edit env var\" description={editing ?? ''}>\n {editing !== null && (\n <AddEditForm\n mode=\"edit\"\n initialName={editing}\n onSubmit={async (name, value) => {\n await fetchJson(`/api/env-vars/${name}`, { method: 'PUT', body: { value } });\n setEditing(null);\n refresh();\n }}\n onCancel={() => setEditing(null)}\n />\n )}\n </SheetContent>\n </Sheet>\n\n <Sheet open={bulkImporting} onOpenChange={setBulkImporting}>\n <SheetContent side=\"right\" title=\"Bulk import\" description=\"Paste KEY=value lines (one per line, # comments ignored).\">\n <BulkImportForm\n onSubmit={async (envContent) => {\n await fetchJson('/api/env-vars/bulk-import', {\n method: 'POST',\n body: { envContent },\n });\n setBulkImporting(false);\n refresh();\n }}\n onCancel={() => setBulkImporting(false)}\n />\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n\nfunction AddEditForm({\n mode,\n initialName,\n onSubmit,\n onCancel,\n}: {\n mode: 'add' | 'edit';\n initialName?: string;\n onSubmit: (name: string, value: string) => Promise<void>;\n onCancel: () => void;\n}): JSX.Element {\n const [name, setName] = useState<string>(initialName ?? '');\n const [value, setValue] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const submit = async (): Promise<void> => {\n if (!name.trim() || !value || busy) return;\n setBusy(true);\n setError(null);\n try {\n await onSubmit(name.trim(), value);\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Name</span>\n <Input\n value={name}\n readOnly={mode === 'edit'}\n data-testid=\"env-var-form-name\"\n onChange={(e) => setName((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Value</span>\n <Input\n type=\"password\"\n value={value}\n data-testid=\"env-var-form-value\"\n onChange={(e) => setValue((e.target as HTMLInputElement).value)}\n />\n </label>\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" onClick={onCancel} data-testid=\"env-var-form-cancel\">Cancel</Button>\n </SheetClose>\n <Button\n variant=\"primary\"\n onClick={() => void submit()}\n disabled={busy || !name.trim() || !value}\n data-testid=\"env-var-form-submit\"\n >\n {mode === 'add' ? 'Add' : 'Save'}\n </Button>\n </Inline>\n </Stack>\n );\n}\n\nfunction BulkImportForm({\n onSubmit,\n onCancel,\n}: {\n onSubmit: (envContent: string) => Promise<void>;\n onCancel: () => void;\n}): JSX.Element {\n const [content, setContent] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <textarea\n value={content}\n placeholder={'BIZAR_FOO=bar\\nBIZAR_BAZ=qux\\n# comment'}\n rows={12}\n data-testid=\"env-vars-bulk-input\"\n onChange={(e) => setContent((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-mono)',\n fontSize: 'var(--fs-12)',\n resize: 'vertical',\n }}\n />\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" onClick={onCancel}>Cancel</Button>\n </SheetClose>\n <Button\n variant=\"primary\"\n onClick={async () => {\n setBusy(true);\n setError(null);\n try { await onSubmit(content); }\n catch (err) { setError(err instanceof FetchError ? err.message : (err as Error).message); }\n finally { setBusy(false); }\n }}\n disabled={busy || content.trim() === ''}\n data-testid=\"env-vars-bulk-submit\"\n >\n {busy ? 'Importing…' : 'Import'}\n </Button>\n </Inline>\n </Stack>\n );\n}"],"names":["FileUp","createLucideIcon","EnvVarsView","payload","useFetch","adding","setAdding","useState","editing","setEditing","bulkImporting","setBulkImporting","confirmDelete","setConfirmDelete","error","setError","testing","setTesting","testResult","setTestResult","rows","useMemo","refresh","useCallback","runTest","name","res","fetchJson","err","msg","FetchError","drop","jsxs","Stack","jsx","ViewHeader","Inline","Button","Download","RefreshCcw","Plus","ListHeader","Card","CardBody","Skeleton","EmptyState","Variable","r","isConfirming","FlaskConical","Pencil","cur","Trash2","Sheet","SheetContent","AddEditForm","value","open","BulkImportForm","envContent","mode","initialName","onSubmit","onCancel","setName","setValue","busy","setBusy","submit","Input","e","SheetClose","content","setContent"],"mappings":"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","x_google_ignoreList":[0]}
@@ -1 +1 @@
1
- import{r as h,j as e}from"./cmdk-C3F6LD6N.js";import{A as y}from"./Alert-MwVEymjy.js";import{d as f}from"./main-BZMmD6a8.js";import{C as j}from"./circle-alert-D7jn06kH.js";import{R as v}from"./refresh-ccw-BL7B0NO1.js";function u(t){return t==null?"":typeof t=="string"?t:t.message}const b=h.forwardRef(function(m,n){const{title:o="Something went wrong",description:s,error:x,onRetry:r,retryLabel:a="Retry",block:p=!1,silent:g=!1,testid:d,className:l,...c}=m,i=g?"":u(x);return p?e.jsxs("div",{ref:n,"data-testid":d??"error-state",className:l,style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:"var(--space-3)",padding:"var(--space-12) var(--space-6)",textAlign:"center",color:"var(--fg-muted)"},...c,children:[e.jsx("div",{style:{color:"var(--danger)",display:"inline-flex"},children:e.jsx(j,{size:28,"aria-hidden":!0})}),e.jsx("div",{style:{fontSize:"var(--fs-16)",fontWeight:600,color:"var(--fg)"},children:o}),s!==void 0&&e.jsx("div",{style:{fontSize:"var(--fs-13)",maxWidth:480},children:s}),i!==""&&e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-subtle)"},children:i}),r!==void 0&&e.jsxs(f,{variant:"primary",onClick:r,"data-testid":"error-state-retry",children:[e.jsx(v,{size:14,"aria-hidden":!0})," ",a]})]}):e.jsx("div",{ref:n,"data-testid":d??"error-state",className:l,...c,children:e.jsxs(y,{tone:"danger",title:o,action:r!==void 0?e.jsxs(f,{variant:"ghost",onClick:r,"data-testid":"error-state-retry","aria-label":a,children:[e.jsx(v,{size:14,"aria-hidden":!0})," ",a]}):void 0,children:[s,i!==""&&e.jsx("div",{style:{marginTop:"var(--space-1)",fontFamily:"var(--font-mono)",fontSize:"var(--fs-12)"},children:i})]})})});export{b as E};
1
+ import{r as h,j as e}from"./cmdk-C3F6LD6N.js";import{A as y}from"./Alert-BZGk39mB.js";import{B as f}from"./main-BURAlktW.js";import{C as j}from"./circle-alert-Dz8lGfCZ.js";import{R as v}from"./refresh-ccw-DA8_IB9l.js";function u(t){return t==null?"":typeof t=="string"?t:t.message}const b=h.forwardRef(function(m,n){const{title:o="Something went wrong",description:s,error:x,onRetry:r,retryLabel:a="Retry",block:p=!1,silent:g=!1,testid:d,className:l,...c}=m,i=g?"":u(x);return p?e.jsxs("div",{ref:n,"data-testid":d??"error-state",className:l,style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:"var(--space-3)",padding:"var(--space-12) var(--space-6)",textAlign:"center",color:"var(--fg-muted)"},...c,children:[e.jsx("div",{style:{color:"var(--danger)",display:"inline-flex"},children:e.jsx(j,{size:28,"aria-hidden":!0})}),e.jsx("div",{style:{fontSize:"var(--fs-16)",fontWeight:600,color:"var(--fg)"},children:o}),s!==void 0&&e.jsx("div",{style:{fontSize:"var(--fs-13)",maxWidth:480},children:s}),i!==""&&e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-subtle)"},children:i}),r!==void 0&&e.jsxs(f,{variant:"primary",onClick:r,"data-testid":"error-state-retry",children:[e.jsx(v,{size:14,"aria-hidden":!0})," ",a]})]}):e.jsx("div",{ref:n,"data-testid":d??"error-state",className:l,...c,children:e.jsxs(y,{tone:"danger",title:o,action:r!==void 0?e.jsxs(f,{variant:"ghost",onClick:r,"data-testid":"error-state-retry","aria-label":a,children:[e.jsx(v,{size:14,"aria-hidden":!0})," ",a]}):void 0,children:[s,i!==""&&e.jsx("div",{style:{marginTop:"var(--space-1)",fontFamily:"var(--font-mono)",fontSize:"var(--fs-12)"},children:i})]})})});export{b as E};
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorState-BRvj8qZZ.js","sources":["../../src/web/v8/ui/feedback/ErrorState.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { AlertCircle, RefreshCcw } from 'lucide-react';\nimport { Alert } from './Alert.js';\nimport { Button } from '../controls/Button.js';\n\n/**\n * ErrorState — surfaced error with optional retry CTA.\n *\n * Use when a view's primary fetch failed and we want to recover,\n * not when the fetch succeeded with zero rows (use EmptyState).\n *\n * Two layout modes:\n * - inline (default): Alert-tone=danger banner with optional retry button\n * - block: centered icon + title + description + retry (mirrors EmptyState)\n *\n * `error` is the raw error (Error | string | null). When non-null,\n * the message is rendered below the title. Use the `silent` flag to\n * omit the message (e.g. when the parent already shows it).\n */\nexport interface ErrorStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n title?: ReactNode;\n description?: ReactNode;\n error?: Error | string | null;\n onRetry?: () => void;\n retryLabel?: string;\n /** Use the centered block layout instead of the inline Alert. */\n block?: boolean;\n /** Hide the error message (parent surfaces it elsewhere). */\n silent?: boolean;\n testid?: string;\n}\n\nfunction errMessage(error: Error | string | null | undefined): string {\n if (error === null || error === undefined) return '';\n return typeof error === 'string' ? error : error.message;\n}\n\nexport const ErrorState = forwardRef<HTMLDivElement, ErrorStateProps>(function ErrorState(\n props,\n ref,\n) {\n const {\n title = 'Something went wrong',\n description,\n error,\n onRetry,\n retryLabel = 'Retry',\n block = false,\n silent = false,\n testid,\n className,\n ...rest\n } = props;\n\n const message = silent ? '' : errMessage(error);\n\n if (block) {\n return (\n <div\n ref={ref}\n data-testid={testid ?? 'error-state'}\n className={className}\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 'var(--space-3)',\n padding: 'var(--space-12) var(--space-6)',\n textAlign: 'center',\n color: 'var(--fg-muted)',\n }}\n {...rest}\n >\n <div style={{ color: 'var(--danger)', display: 'inline-flex' }}>\n <AlertCircle size={28} aria-hidden />\n </div>\n <div style={{ fontSize: 'var(--fs-16)', fontWeight: 600, color: 'var(--fg)' }}>{title}</div>\n {description !== undefined && (\n <div style={{ fontSize: 'var(--fs-13)', maxWidth: 480 }}>{description}</div>\n )}\n {message !== '' && (\n <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-subtle)' }}>{message}</code>\n )}\n {onRetry !== undefined && (\n <Button variant=\"primary\" onClick={onRetry} data-testid=\"error-state-retry\">\n <RefreshCcw size={14} aria-hidden /> {retryLabel}\n </Button>\n )}\n </div>\n );\n }\n\n return (\n <div ref={ref} data-testid={testid ?? 'error-state'} className={className} {...rest}>\n <Alert\n tone=\"danger\"\n title={title}\n action={\n onRetry !== undefined ? (\n <Button variant=\"ghost\" onClick={onRetry} data-testid=\"error-state-retry\" aria-label={retryLabel}>\n <RefreshCcw size={14} aria-hidden /> {retryLabel}\n </Button>\n ) : undefined\n }\n >\n {description}\n {message !== '' && (\n <div style={{ marginTop: 'var(--space-1)', fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)' }}>\n {message}\n </div>\n )}\n </Alert>\n </div>\n );\n});"],"names":["errMessage","error","ErrorState","forwardRef","props","ref","title","description","onRetry","retryLabel","block","silent","testid","className","rest","message","jsxs","jsx","AlertCircle","Button","RefreshCcw","Alert"],"mappings":"0NAgCA,SAASA,EAAWC,EAAkD,CACpE,OAAIA,GAAU,KAAoC,GAC3C,OAAOA,GAAU,SAAWA,EAAQA,EAAM,OACnD,CAEO,MAAMC,EAAaC,EAAAA,WAA4C,SACpEC,EACAC,EACA,CACA,KAAM,CACJ,MAAAC,EAAQ,uBACR,YAAAC,EACA,MAAAN,EACA,QAAAO,EACA,WAAAC,EAAa,QACb,MAAAC,EAAQ,GACR,OAAAC,EAAS,GACT,OAAAC,EACA,UAAAC,EACA,GAAGC,CAAA,EACDV,EAEEW,EAAUJ,EAAS,GAAKX,EAAWC,CAAK,EAE9C,OAAIS,EAEAM,EAAAA,KAAC,MAAA,CACC,IAAAX,EACA,cAAaO,GAAU,cACvB,UAAAC,EACA,MAAO,CACL,QAAS,OACT,cAAe,SACf,WAAY,SACZ,eAAgB,SAChB,IAAK,iBACL,QAAS,iCACT,UAAW,SACX,MAAO,iBAAA,EAER,GAAGC,EAEJ,SAAA,CAAAG,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,MAAO,gBAAiB,QAAS,aAAA,EAC7C,SAAAA,EAAAA,IAACC,EAAA,CAAY,KAAM,GAAI,cAAW,GAAC,EACrC,EACAD,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,SAAU,eAAgB,WAAY,IAAK,MAAO,WAAA,EAAgB,SAAAX,CAAA,CAAM,EACrFC,IAAgB,QACfU,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,SAAU,eAAgB,SAAU,GAAA,EAAQ,SAAAV,CAAA,CAAY,EAEvEQ,IAAY,IACXE,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,kBAAA,EAAuB,SAAAF,CAAA,CAAQ,EAEhFP,IAAY,QACXQ,OAACG,EAAA,CAAO,QAAQ,UAAU,QAASX,EAAS,cAAY,oBACtD,SAAA,CAAAS,EAAAA,IAACG,EAAA,CAAW,KAAM,GAAI,cAAW,GAAC,EAAE,IAAEX,CAAA,CAAA,CACxC,CAAA,CAAA,CAAA,EAONQ,MAAC,OAAI,IAAAZ,EAAU,cAAaO,GAAU,cAAe,UAAAC,EAAuB,GAAGC,EAC7E,SAAAE,EAAAA,KAACK,EAAA,CACC,KAAK,SACL,MAAAf,EACA,OACEE,IAAY,OACVQ,EAAAA,KAACG,EAAA,CAAO,QAAQ,QAAQ,QAASX,EAAS,cAAY,oBAAoB,aAAYC,EACpF,SAAA,CAAAQ,EAAAA,IAACG,EAAA,CAAW,KAAM,GAAI,cAAW,GAAC,EAAE,IAAEX,CAAA,CAAA,CACxC,EACE,OAGL,SAAA,CAAAF,EACAQ,IAAY,IACXE,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,UAAW,iBAAkB,WAAY,mBAAoB,SAAU,cAAA,EAClF,SAAAF,CAAA,CACH,CAAA,CAAA,CAAA,EAGN,CAEJ,CAAC"}
1
+ {"version":3,"file":"ErrorState-CBJbEQ8B.js","sources":["../../src/web/v8/ui/feedback/ErrorState.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { AlertCircle, RefreshCcw } from 'lucide-react';\nimport { Alert } from './Alert.js';\nimport { Button } from '../controls/Button.js';\n\n/**\n * ErrorState — surfaced error with optional retry CTA.\n *\n * Use when a view's primary fetch failed and we want to recover,\n * not when the fetch succeeded with zero rows (use EmptyState).\n *\n * Two layout modes:\n * - inline (default): Alert-tone=danger banner with optional retry button\n * - block: centered icon + title + description + retry (mirrors EmptyState)\n *\n * `error` is the raw error (Error | string | null). When non-null,\n * the message is rendered below the title. Use the `silent` flag to\n * omit the message (e.g. when the parent already shows it).\n */\nexport interface ErrorStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n title?: ReactNode;\n description?: ReactNode;\n error?: Error | string | null;\n onRetry?: () => void;\n retryLabel?: string;\n /** Use the centered block layout instead of the inline Alert. */\n block?: boolean;\n /** Hide the error message (parent surfaces it elsewhere). */\n silent?: boolean;\n testid?: string;\n}\n\nfunction errMessage(error: Error | string | null | undefined): string {\n if (error === null || error === undefined) return '';\n return typeof error === 'string' ? error : error.message;\n}\n\nexport const ErrorState = forwardRef<HTMLDivElement, ErrorStateProps>(function ErrorState(\n props,\n ref,\n) {\n const {\n title = 'Something went wrong',\n description,\n error,\n onRetry,\n retryLabel = 'Retry',\n block = false,\n silent = false,\n testid,\n className,\n ...rest\n } = props;\n\n const message = silent ? '' : errMessage(error);\n\n if (block) {\n return (\n <div\n ref={ref}\n data-testid={testid ?? 'error-state'}\n className={className}\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 'var(--space-3)',\n padding: 'var(--space-12) var(--space-6)',\n textAlign: 'center',\n color: 'var(--fg-muted)',\n }}\n {...rest}\n >\n <div style={{ color: 'var(--danger)', display: 'inline-flex' }}>\n <AlertCircle size={28} aria-hidden />\n </div>\n <div style={{ fontSize: 'var(--fs-16)', fontWeight: 600, color: 'var(--fg)' }}>{title}</div>\n {description !== undefined && (\n <div style={{ fontSize: 'var(--fs-13)', maxWidth: 480 }}>{description}</div>\n )}\n {message !== '' && (\n <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-subtle)' }}>{message}</code>\n )}\n {onRetry !== undefined && (\n <Button variant=\"primary\" onClick={onRetry} data-testid=\"error-state-retry\">\n <RefreshCcw size={14} aria-hidden /> {retryLabel}\n </Button>\n )}\n </div>\n );\n }\n\n return (\n <div ref={ref} data-testid={testid ?? 'error-state'} className={className} {...rest}>\n <Alert\n tone=\"danger\"\n title={title}\n action={\n onRetry !== undefined ? (\n <Button variant=\"ghost\" onClick={onRetry} data-testid=\"error-state-retry\" aria-label={retryLabel}>\n <RefreshCcw size={14} aria-hidden /> {retryLabel}\n </Button>\n ) : undefined\n }\n >\n {description}\n {message !== '' && (\n <div style={{ marginTop: 'var(--space-1)', fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)' }}>\n {message}\n </div>\n )}\n </Alert>\n </div>\n );\n});"],"names":["errMessage","error","ErrorState","forwardRef","props","ref","title","description","onRetry","retryLabel","block","silent","testid","className","rest","message","jsxs","jsx","AlertCircle","Button","RefreshCcw","Alert"],"mappings":"0NAgCA,SAASA,EAAWC,EAAkD,CACpE,OAAIA,GAAU,KAAoC,GAC3C,OAAOA,GAAU,SAAWA,EAAQA,EAAM,OACnD,CAEO,MAAMC,EAAaC,EAAAA,WAA4C,SACpEC,EACAC,EACA,CACA,KAAM,CACJ,MAAAC,EAAQ,uBACR,YAAAC,EACA,MAAAN,EACA,QAAAO,EACA,WAAAC,EAAa,QACb,MAAAC,EAAQ,GACR,OAAAC,EAAS,GACT,OAAAC,EACA,UAAAC,EACA,GAAGC,CAAA,EACDV,EAEEW,EAAUJ,EAAS,GAAKX,EAAWC,CAAK,EAE9C,OAAIS,EAEAM,EAAAA,KAAC,MAAA,CACC,IAAAX,EACA,cAAaO,GAAU,cACvB,UAAAC,EACA,MAAO,CACL,QAAS,OACT,cAAe,SACf,WAAY,SACZ,eAAgB,SAChB,IAAK,iBACL,QAAS,iCACT,UAAW,SACX,MAAO,iBAAA,EAER,GAAGC,EAEJ,SAAA,CAAAG,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,MAAO,gBAAiB,QAAS,aAAA,EAC7C,SAAAA,EAAAA,IAACC,EAAA,CAAY,KAAM,GAAI,cAAW,GAAC,EACrC,EACAD,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,SAAU,eAAgB,WAAY,IAAK,MAAO,WAAA,EAAgB,SAAAX,CAAA,CAAM,EACrFC,IAAgB,QACfU,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,SAAU,eAAgB,SAAU,GAAA,EAAQ,SAAAV,CAAA,CAAY,EAEvEQ,IAAY,IACXE,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,kBAAA,EAAuB,SAAAF,CAAA,CAAQ,EAEhFP,IAAY,QACXQ,OAACG,EAAA,CAAO,QAAQ,UAAU,QAASX,EAAS,cAAY,oBACtD,SAAA,CAAAS,EAAAA,IAACG,EAAA,CAAW,KAAM,GAAI,cAAW,GAAC,EAAE,IAAEX,CAAA,CAAA,CACxC,CAAA,CAAA,CAAA,EAONQ,MAAC,OAAI,IAAAZ,EAAU,cAAaO,GAAU,cAAe,UAAAC,EAAuB,GAAGC,EAC7E,SAAAE,EAAAA,KAACK,EAAA,CACC,KAAK,SACL,MAAAf,EACA,OACEE,IAAY,OACVQ,EAAAA,KAACG,EAAA,CAAO,QAAQ,QAAQ,QAASX,EAAS,cAAY,oBAAoB,aAAYC,EACpF,SAAA,CAAAQ,EAAAA,IAACG,EAAA,CAAW,KAAM,GAAI,cAAW,GAAC,EAAE,IAAEX,CAAA,CAAA,CACxC,EACE,OAGL,SAAA,CAAAF,EACAQ,IAAY,IACXE,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,UAAW,iBAAkB,WAAY,mBAAoB,SAAU,cAAA,EAClF,SAAAF,CAAA,CACH,CAAA,CAAA,CAAA,EAGN,CAEJ,CAAC"}
@@ -0,0 +1 @@
1
+ import{r,j as e}from"./cmdk-C3F6LD6N.js";import{u as P,S as i,I as s,B as d,J as N,h as T,N as q,b as f,i as j,F as y}from"./main-BURAlktW.js";import{V as I}from"./ViewHeader-C-t1U2cQ.js";import{C as R,b as $}from"./Card-BtsmkhJa.js";import{E as M}from"./EmptyState-DjKtY1Qi.js";import{P as V}from"./play-mJh67AXo.js";import{R as J}from"./refresh-cw-DwlP59en.js";import{C as O}from"./calendar-B9Wbemh7.js";import{P as H}from"./plus-Cm6-fo14.js";import{T as U}from"./trash-2-D6qePV_q.js";function W(t){return t==="done"?"success":t==="failed"?"danger":t==="running"?"info":t==="queued"?"warning":"neutral"}function G(t){return!t||t<=0?"—":t<1e3?`${t}ms`:t<6e4?`${(t/1e3).toFixed(1)}s`:`${Math.floor(t/6e4)}m ${Math.round(t%6e4/1e3)}s`}function ne(){var E,F;const t=P("/api/eval/runs?limit=20"),g=P("/api/eval/schedules"),[o,b]=r.useState(!1),[v,A]=r.useState("default"),[C,l]=r.useState(null),[z,m]=r.useState(!1),[n,c]=r.useState({name:"",cron:"",suitePath:"default"}),[w,k]=r.useState(!1);r.useEffect(()=>{var a;if((a=t.data)!=null&&a.runs&&t.data.runs.some(h=>h.status==="running"||h.status==="queued")){const h=setTimeout(()=>{t.refetch()},5e3);return()=>clearTimeout(h)}},[t]);const L=async()=>{b(!0),l(null);try{await j("/api/eval/run",{method:"POST",body:{suite:v}}),t.refetch()}catch(a){l((a instanceof y,a.message))}finally{b(!1)}},p=((E=t.data)==null?void 0:E.runs)??[],B=async()=>{if(!(!n.name.trim()||!n.cron.trim())){k(!0),l(null);try{await j("/api/eval/schedules",{method:"POST",body:n}),m(!1),c({name:"",cron:"",suitePath:"default"}),g.refetch()}catch(a){l((a instanceof y,a.message))}finally{k(!1)}}},D=async a=>{l(null);try{await j(`/api/eval/schedules/${encodeURIComponent(a)}`,{method:"DELETE"}),g.refetch()}catch(u){l((u instanceof y,u.message))}},x=((F=g.data)==null?void 0:F.schedules)??[];return e.jsxs(i,{gap:5,"data-testid":"eval-view",children:[e.jsx(I,{title:"Eval framework",description:"Run evaluation suites against the agent model. Suites live under fixtures/.",actions:e.jsxs(s,{gap:2,align:"center",children:[C!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:C}),e.jsx("input",{value:v,onChange:a=>A(a.target.value),placeholder:"suite name",disabled:o,"data-testid":"eval-suite-input",style:{padding:"6px 10px",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)",background:"var(--surface-0)",color:"var(--fg)",fontSize:"var(--fs-13)",fontFamily:"var(--font-mono)"}}),e.jsxs(d,{variant:"primary",onClick:()=>void L(),disabled:o||!v.trim(),"data-testid":"eval-launch",children:[o?e.jsx(N,{size:14,className:"animate-spin","aria-hidden":!0}):e.jsx(V,{size:14,"aria-hidden":!0}),o?"Launching…":"Run suite"]}),e.jsxs(d,{variant:"ghost",onClick:()=>void t.refetch(),"data-testid":"eval-refresh",children:[e.jsx(J,{size:14,"aria-hidden":!0})," Refresh"]})]})}),t.loading&&p.length===0?e.jsxs(i,{gap:2,children:[e.jsx(T,{style:{height:80}}),e.jsx(T,{style:{height:80}})]}):p.length===0?e.jsx(M,{icon:e.jsx(q,{size:32,"aria-hidden":!0}),title:"No eval runs yet",description:"Launch a suite to begin measuring agent quality."}):e.jsx(i,{gap:2,children:p.map(a=>e.jsx(R,{variant:"default",children:e.jsx($,{children:e.jsxs(s,{align:"center",justify:"between",gap:3,children:[e.jsxs(i,{gap:1,style:{flex:1,minWidth:0},children:[e.jsxs(s,{align:"center",gap:2,children:[e.jsx("strong",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--fs-13)"},children:a.id}),e.jsx(f,{tone:W(a.status),children:a.status??"unknown"}),a.suite&&e.jsx(f,{tone:"neutral",children:a.suite})]}),e.jsxs(s,{align:"center",gap:3,style:{color:"var(--fg-muted)",fontSize:"var(--fs-12)"},children:[e.jsx("span",{children:a.startedAt?new Date(a.startedAt).toLocaleString():""}),e.jsx("span",{children:G(a.durationMs)})]})]}),e.jsxs(i,{align:"end",gap:0,children:[e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--fs-14)"},children:[e.jsx("strong",{style:{color:"var(--success)"},children:a.passed??0})," pass"," / ",e.jsx("strong",{style:{color:"var(--danger)"},children:a.failed??0})," fail"]}),e.jsxs("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:[a.total??0," total"]})]})]})})},a.id))}),e.jsx(R,{variant:"elevated",children:e.jsxs($,{children:[e.jsxs(s,{align:"center",justify:"between",gap:2,children:[e.jsxs(s,{align:"center",gap:2,children:[e.jsx(O,{size:16,"aria-hidden":!0}),e.jsx("strong",{style:{fontSize:"var(--fs-14)"},children:"Schedules"}),e.jsx(f,{tone:"neutral",children:x.length})]}),!z&&e.jsxs(d,{variant:"primary",onClick:()=>m(!0),"data-testid":"eval-schedule-add",children:[e.jsx(H,{size:14,"aria-hidden":!0})," Add schedule"]})]}),z&&e.jsxs(i,{gap:2,style:{marginTop:"var(--space-3)"},"data-testid":"eval-schedule-form",children:[e.jsxs(s,{gap:2,align:"center",children:[e.jsx("input",{value:n.name,onChange:a=>c({...n,name:a.target.value}),placeholder:"name","data-testid":"eval-schedule-form-name",style:S}),e.jsx("input",{value:n.cron,onChange:a=>c({...n,cron:a.target.value}),placeholder:"cron (e.g. 0 9 * * *)","data-testid":"eval-schedule-form-cron",style:S}),e.jsx("input",{value:n.suitePath,onChange:a=>c({...n,suitePath:a.target.value}),placeholder:"suite path","data-testid":"eval-schedule-form-suite",style:S})]}),e.jsxs(s,{gap:2,children:[e.jsx(d,{variant:"primary",onClick:()=>void B(),disabled:w,"data-testid":"eval-schedule-form-submit",children:w?"Saving…":"Save"}),e.jsx(d,{variant:"ghost",onClick:()=>m(!1),"data-testid":"eval-schedule-form-cancel",children:"Cancel"})]})]}),x.length===0?e.jsx("div",{style:{marginTop:"var(--space-2)",fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"No schedules yet. Add one to run suites on a cron."}):e.jsx(i,{gap:2,style:{marginTop:"var(--space-3)"},children:x.map(a=>e.jsxs(s,{align:"center",justify:"between",gap:2,"data-testid":`eval-schedule-row-${a.id}`,children:[e.jsxs(s,{align:"center",gap:2,children:[e.jsx("strong",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--fs-13)"},children:a.name}),e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:a.cron}),a.suitePath&&e.jsx(f,{tone:"neutral",children:a.suitePath})]}),e.jsx(d,{variant:"ghost",onClick:()=>void D(a.id),"data-testid":`eval-schedule-delete-${a.id}`,"aria-label":`Delete schedule ${a.name}`,children:e.jsx(U,{size:14,"aria-hidden":!0})})]},a.id))})]})})]})}const S={padding:"6px 10px",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)",background:"var(--surface-0)",color:"var(--fg)",fontSize:"var(--fs-13)",fontFamily:"var(--font-mono)"};export{ne as EvalView};
@@ -1 +1 @@
1
- {"version":3,"file":"EvalView-lgUhlGJh.js","sources":["../../src/web/v8/views/Eval/EvalView.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { Calendar, FlaskConical, Play, Plus, RefreshCw, Trash2, Loader2 } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\n/**\n * EvalView — Sprint S35. Eval runs list + launch new suite.\n */\n\ntype Tone = 'neutral' | 'success' | 'warning' | 'danger' | 'info';\n\ninterface EvalRun {\n id: string;\n suite?: string;\n status?: 'queued' | 'running' | 'done' | 'failed';\n passed?: number;\n failed?: number;\n total?: number;\n startedAt?: string;\n durationMs?: number;\n}\n\ninterface EvalSchedule {\n id: string;\n name: string;\n cron: string;\n suitePath?: string;\n enabled?: boolean;\n}\n\nfunction statusTone(s: EvalRun['status'] | undefined): Tone {\n if (s === 'done') return 'success';\n if (s === 'failed') return 'danger';\n if (s === 'running') return 'info';\n if (s === 'queued') return 'warning';\n return 'neutral';\n}\n\nfunction fmtDuration(ms: number | undefined): string {\n if (!ms || ms <= 0) return '—';\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;\n return `${Math.floor(ms / 60_000)}m ${Math.round((ms % 60_000) / 1000)}s`;\n}\n\nexport function EvalView(): JSX.Element {\n const runs = useFetch<{ runs: EvalRun[] }>('/api/eval/runs?limit=20');\n const schedules = useFetch<{ schedules: EvalSchedule[] }>('/api/eval/schedules');\n const [launching, setLaunching] = useState(false);\n const [suite, setSuite] = useState('default');\n const [error, setError] = useState<string | null>(null);\n const [addingSchedule, setAddingSchedule] = useState(false);\n const [scheduleForm, setScheduleForm] = useState({ name: '', cron: '', suitePath: 'default' });\n const [busySchedule, setBusySchedule] = useState(false);\n\n useEffect(() => {\n if (runs.data?.runs) {\n const hasActive = runs.data.runs.some((r) => r.status === 'running' || r.status === 'queued');\n if (hasActive) {\n const id = setTimeout(() => { void runs.refetch(); }, 5_000);\n return () => clearTimeout(id);\n }\n }\n }, [runs]);\n\n const launch = async (): Promise<void> => {\n setLaunching(true);\n setError(null);\n try {\n await fetchJson('/api/eval/run', { method: 'POST', body: { suite } });\n void runs.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setLaunching(false);\n }\n };\n\n const list = runs.data?.runs ?? [];\n\n const addSchedule = async (): Promise<void> => {\n if (!scheduleForm.name.trim() || !scheduleForm.cron.trim()) return;\n setBusySchedule(true);\n setError(null);\n try {\n await fetchJson<{ ok?: boolean }>('/api/eval/schedules', { method: 'POST', body: scheduleForm });\n setAddingSchedule(false);\n setScheduleForm({ name: '', cron: '', suitePath: 'default' });\n void schedules.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusySchedule(false);\n }\n };\n\n const deleteSchedule = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/eval/schedules/${encodeURIComponent(id)}`, { method: 'DELETE' });\n void schedules.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const scheduleList = schedules.data?.schedules ?? [];\n\n return (\n <Stack gap={5} data-testid=\"eval-view\">\n <ViewHeader\n title=\"Eval framework\"\n description=\"Run evaluation suites against the agent model. Suites live under fixtures/.\"\n actions={\n <Inline gap={2} align=\"center\">\n {error !== null && <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>}\n <input\n value={suite}\n onChange={(e) => setSuite(e.target.value)}\n placeholder=\"suite name\"\n disabled={launching}\n data-testid=\"eval-suite-input\"\n style={{\n padding: '6px 10px',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n background: 'var(--surface-0)',\n color: 'var(--fg)',\n fontSize: 'var(--fs-13)',\n fontFamily: 'var(--font-mono)',\n }}\n />\n <Button variant=\"primary\" onClick={() => void launch()} disabled={launching || !suite.trim()} data-testid=\"eval-launch\">\n {launching ? <Loader2 size={14} className=\"animate-spin\" aria-hidden /> : <Play size={14} aria-hidden />}\n {launching ? 'Launching…' : 'Run suite'}\n </Button>\n <Button variant=\"ghost\" onClick={() => void runs.refetch()} data-testid=\"eval-refresh\">\n <RefreshCw size={14} aria-hidden /> Refresh\n </Button>\n </Inline>\n }\n />\n\n {runs.loading && list.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 80 }} />\n <Skeleton style={{ height: 80 }} />\n </Stack>\n ) : list.length === 0 ? (\n <EmptyState\n icon={<FlaskConical size={32} aria-hidden />}\n title=\"No eval runs yet\"\n description=\"Launch a suite to begin measuring agent quality.\"\n />\n ) : (\n <Stack gap={2}>\n {list.map((r) => (\n <Card key={r.id} variant=\"default\">\n <CardBody>\n <Inline align=\"center\" justify=\"between\" gap={3}>\n <Stack gap={1} style={{ flex: 1, minWidth: 0 }}>\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-13)' }}>{r.id}</strong>\n <Badge tone={statusTone(r.status)}>{r.status ?? 'unknown'}</Badge>\n {r.suite && <Badge tone=\"neutral\">{r.suite}</Badge>}\n </Inline>\n <Inline align=\"center\" gap={3} style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>\n <span>{r.startedAt ? new Date(r.startedAt).toLocaleString() : ''}</span>\n <span>{fmtDuration(r.durationMs)}</span>\n </Inline>\n </Stack>\n <Stack align=\"end\" gap={0}>\n <span style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-14)' }}>\n <strong style={{ color: 'var(--success)' }}>{r.passed ?? 0}</strong> pass\n {' / '}\n <strong style={{ color: 'var(--danger)' }}>{r.failed ?? 0}</strong> fail\n </span>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{(r.total ?? 0)} total</span>\n </Stack>\n </Inline>\n </CardBody>\n </Card>\n ))}\n </Stack>\n )}\n\n <Card variant=\"elevated\">\n <CardBody>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Inline align=\"center\" gap={2}>\n <Calendar size={16} aria-hidden />\n <strong style={{ fontSize: 'var(--fs-14)' }}>Schedules</strong>\n <Badge tone=\"neutral\">{scheduleList.length}</Badge>\n </Inline>\n {!addingSchedule && (\n <Button variant=\"primary\" onClick={() => setAddingSchedule(true)} data-testid=\"eval-schedule-add\">\n <Plus size={14} aria-hidden /> Add schedule\n </Button>\n )}\n </Inline>\n\n {addingSchedule && (\n <Stack gap={2} style={{ marginTop: 'var(--space-3)' }} data-testid=\"eval-schedule-form\">\n <Inline gap={2} align=\"center\">\n <input\n value={scheduleForm.name}\n onChange={(e) => setScheduleForm({ ...scheduleForm, name: e.target.value })}\n placeholder=\"name\"\n data-testid=\"eval-schedule-form-name\"\n style={inputStyle}\n />\n <input\n value={scheduleForm.cron}\n onChange={(e) => setScheduleForm({ ...scheduleForm, cron: e.target.value })}\n placeholder=\"cron (e.g. 0 9 * * *)\"\n data-testid=\"eval-schedule-form-cron\"\n style={inputStyle}\n />\n <input\n value={scheduleForm.suitePath}\n onChange={(e) => setScheduleForm({ ...scheduleForm, suitePath: e.target.value })}\n placeholder=\"suite path\"\n data-testid=\"eval-schedule-form-suite\"\n style={inputStyle}\n />\n </Inline>\n <Inline gap={2}>\n <Button variant=\"primary\" onClick={() => void addSchedule()} disabled={busySchedule} data-testid=\"eval-schedule-form-submit\">\n {busySchedule ? 'Saving…' : 'Save'}\n </Button>\n <Button variant=\"ghost\" onClick={() => setAddingSchedule(false)} data-testid=\"eval-schedule-form-cancel\">Cancel</Button>\n </Inline>\n </Stack>\n )}\n\n {scheduleList.length === 0 ? (\n <div style={{ marginTop: 'var(--space-2)', fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n No schedules yet. Add one to run suites on a cron.\n </div>\n ) : (\n <Stack gap={2} style={{ marginTop: 'var(--space-3)' }}>\n {scheduleList.map((s) => (\n <Inline key={s.id} align=\"center\" justify=\"between\" gap={2} data-testid={`eval-schedule-row-${s.id}`}>\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-13)' }}>{s.name}</strong>\n <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{s.cron}</code>\n {s.suitePath && <Badge tone=\"neutral\">{s.suitePath}</Badge>}\n </Inline>\n <Button variant=\"ghost\" onClick={() => void deleteSchedule(s.id)} data-testid={`eval-schedule-delete-${s.id}`} aria-label={`Delete schedule ${s.name}`}>\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n ))}\n </Stack>\n )}\n </CardBody>\n </Card>\n </Stack>\n );\n}\n\nconst inputStyle = {\n padding: '6px 10px',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n background: 'var(--surface-0)',\n color: 'var(--fg)',\n fontSize: 'var(--fs-13)',\n fontFamily: 'var(--font-mono)',\n} as const;"],"names":["statusTone","s","fmtDuration","ms","EvalView","runs","useFetch","schedules","launching","setLaunching","useState","suite","setSuite","error","setError","addingSchedule","setAddingSchedule","scheduleForm","setScheduleForm","busySchedule","setBusySchedule","useEffect","_a","r","id","launch","fetchJson","err","FetchError","list","addSchedule","deleteSchedule","scheduleList","_b","jsxs","Stack","jsx","ViewHeader","Inline","e","Button","Loader2","Play","RefreshCw","Skeleton","EmptyState","FlaskConical","Card","CardBody","Badge","Calendar","Plus","inputStyle","Trash2"],"mappings":"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"}
1
+ {"version":3,"file":"EvalView-BeAyMCD1.js","sources":["../../src/web/v8/views/Eval/EvalView.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { Calendar, FlaskConical, Play, Plus, RefreshCw, Trash2, Loader2 } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\n/**\n * EvalView — Sprint S35. Eval runs list + launch new suite.\n */\n\ntype Tone = 'neutral' | 'success' | 'warning' | 'danger' | 'info';\n\ninterface EvalRun {\n id: string;\n suite?: string;\n status?: 'queued' | 'running' | 'done' | 'failed';\n passed?: number;\n failed?: number;\n total?: number;\n startedAt?: string;\n durationMs?: number;\n}\n\ninterface EvalSchedule {\n id: string;\n name: string;\n cron: string;\n suitePath?: string;\n enabled?: boolean;\n}\n\nfunction statusTone(s: EvalRun['status'] | undefined): Tone {\n if (s === 'done') return 'success';\n if (s === 'failed') return 'danger';\n if (s === 'running') return 'info';\n if (s === 'queued') return 'warning';\n return 'neutral';\n}\n\nfunction fmtDuration(ms: number | undefined): string {\n if (!ms || ms <= 0) return '—';\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;\n return `${Math.floor(ms / 60_000)}m ${Math.round((ms % 60_000) / 1000)}s`;\n}\n\nexport function EvalView(): JSX.Element {\n const runs = useFetch<{ runs: EvalRun[] }>('/api/eval/runs?limit=20');\n const schedules = useFetch<{ schedules: EvalSchedule[] }>('/api/eval/schedules');\n const [launching, setLaunching] = useState(false);\n const [suite, setSuite] = useState('default');\n const [error, setError] = useState<string | null>(null);\n const [addingSchedule, setAddingSchedule] = useState(false);\n const [scheduleForm, setScheduleForm] = useState({ name: '', cron: '', suitePath: 'default' });\n const [busySchedule, setBusySchedule] = useState(false);\n\n useEffect(() => {\n if (runs.data?.runs) {\n const hasActive = runs.data.runs.some((r) => r.status === 'running' || r.status === 'queued');\n if (hasActive) {\n const id = setTimeout(() => { void runs.refetch(); }, 5_000);\n return () => clearTimeout(id);\n }\n }\n }, [runs]);\n\n const launch = async (): Promise<void> => {\n setLaunching(true);\n setError(null);\n try {\n await fetchJson('/api/eval/run', { method: 'POST', body: { suite } });\n void runs.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setLaunching(false);\n }\n };\n\n const list = runs.data?.runs ?? [];\n\n const addSchedule = async (): Promise<void> => {\n if (!scheduleForm.name.trim() || !scheduleForm.cron.trim()) return;\n setBusySchedule(true);\n setError(null);\n try {\n await fetchJson<{ ok?: boolean }>('/api/eval/schedules', { method: 'POST', body: scheduleForm });\n setAddingSchedule(false);\n setScheduleForm({ name: '', cron: '', suitePath: 'default' });\n void schedules.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusySchedule(false);\n }\n };\n\n const deleteSchedule = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/eval/schedules/${encodeURIComponent(id)}`, { method: 'DELETE' });\n void schedules.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const scheduleList = schedules.data?.schedules ?? [];\n\n return (\n <Stack gap={5} data-testid=\"eval-view\">\n <ViewHeader\n title=\"Eval framework\"\n description=\"Run evaluation suites against the agent model. Suites live under fixtures/.\"\n actions={\n <Inline gap={2} align=\"center\">\n {error !== null && <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>}\n <input\n value={suite}\n onChange={(e) => setSuite(e.target.value)}\n placeholder=\"suite name\"\n disabled={launching}\n data-testid=\"eval-suite-input\"\n style={{\n padding: '6px 10px',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n background: 'var(--surface-0)',\n color: 'var(--fg)',\n fontSize: 'var(--fs-13)',\n fontFamily: 'var(--font-mono)',\n }}\n />\n <Button variant=\"primary\" onClick={() => void launch()} disabled={launching || !suite.trim()} data-testid=\"eval-launch\">\n {launching ? <Loader2 size={14} className=\"animate-spin\" aria-hidden /> : <Play size={14} aria-hidden />}\n {launching ? 'Launching…' : 'Run suite'}\n </Button>\n <Button variant=\"ghost\" onClick={() => void runs.refetch()} data-testid=\"eval-refresh\">\n <RefreshCw size={14} aria-hidden /> Refresh\n </Button>\n </Inline>\n }\n />\n\n {runs.loading && list.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 80 }} />\n <Skeleton style={{ height: 80 }} />\n </Stack>\n ) : list.length === 0 ? (\n <EmptyState\n icon={<FlaskConical size={32} aria-hidden />}\n title=\"No eval runs yet\"\n description=\"Launch a suite to begin measuring agent quality.\"\n />\n ) : (\n <Stack gap={2}>\n {list.map((r) => (\n <Card key={r.id} variant=\"default\">\n <CardBody>\n <Inline align=\"center\" justify=\"between\" gap={3}>\n <Stack gap={1} style={{ flex: 1, minWidth: 0 }}>\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-13)' }}>{r.id}</strong>\n <Badge tone={statusTone(r.status)}>{r.status ?? 'unknown'}</Badge>\n {r.suite && <Badge tone=\"neutral\">{r.suite}</Badge>}\n </Inline>\n <Inline align=\"center\" gap={3} style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>\n <span>{r.startedAt ? new Date(r.startedAt).toLocaleString() : ''}</span>\n <span>{fmtDuration(r.durationMs)}</span>\n </Inline>\n </Stack>\n <Stack align=\"end\" gap={0}>\n <span style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-14)' }}>\n <strong style={{ color: 'var(--success)' }}>{r.passed ?? 0}</strong> pass\n {' / '}\n <strong style={{ color: 'var(--danger)' }}>{r.failed ?? 0}</strong> fail\n </span>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{(r.total ?? 0)} total</span>\n </Stack>\n </Inline>\n </CardBody>\n </Card>\n ))}\n </Stack>\n )}\n\n <Card variant=\"elevated\">\n <CardBody>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Inline align=\"center\" gap={2}>\n <Calendar size={16} aria-hidden />\n <strong style={{ fontSize: 'var(--fs-14)' }}>Schedules</strong>\n <Badge tone=\"neutral\">{scheduleList.length}</Badge>\n </Inline>\n {!addingSchedule && (\n <Button variant=\"primary\" onClick={() => setAddingSchedule(true)} data-testid=\"eval-schedule-add\">\n <Plus size={14} aria-hidden /> Add schedule\n </Button>\n )}\n </Inline>\n\n {addingSchedule && (\n <Stack gap={2} style={{ marginTop: 'var(--space-3)' }} data-testid=\"eval-schedule-form\">\n <Inline gap={2} align=\"center\">\n <input\n value={scheduleForm.name}\n onChange={(e) => setScheduleForm({ ...scheduleForm, name: e.target.value })}\n placeholder=\"name\"\n data-testid=\"eval-schedule-form-name\"\n style={inputStyle}\n />\n <input\n value={scheduleForm.cron}\n onChange={(e) => setScheduleForm({ ...scheduleForm, cron: e.target.value })}\n placeholder=\"cron (e.g. 0 9 * * *)\"\n data-testid=\"eval-schedule-form-cron\"\n style={inputStyle}\n />\n <input\n value={scheduleForm.suitePath}\n onChange={(e) => setScheduleForm({ ...scheduleForm, suitePath: e.target.value })}\n placeholder=\"suite path\"\n data-testid=\"eval-schedule-form-suite\"\n style={inputStyle}\n />\n </Inline>\n <Inline gap={2}>\n <Button variant=\"primary\" onClick={() => void addSchedule()} disabled={busySchedule} data-testid=\"eval-schedule-form-submit\">\n {busySchedule ? 'Saving…' : 'Save'}\n </Button>\n <Button variant=\"ghost\" onClick={() => setAddingSchedule(false)} data-testid=\"eval-schedule-form-cancel\">Cancel</Button>\n </Inline>\n </Stack>\n )}\n\n {scheduleList.length === 0 ? (\n <div style={{ marginTop: 'var(--space-2)', fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n No schedules yet. Add one to run suites on a cron.\n </div>\n ) : (\n <Stack gap={2} style={{ marginTop: 'var(--space-3)' }}>\n {scheduleList.map((s) => (\n <Inline key={s.id} align=\"center\" justify=\"between\" gap={2} data-testid={`eval-schedule-row-${s.id}`}>\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-13)' }}>{s.name}</strong>\n <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{s.cron}</code>\n {s.suitePath && <Badge tone=\"neutral\">{s.suitePath}</Badge>}\n </Inline>\n <Button variant=\"ghost\" onClick={() => void deleteSchedule(s.id)} data-testid={`eval-schedule-delete-${s.id}`} aria-label={`Delete schedule ${s.name}`}>\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n ))}\n </Stack>\n )}\n </CardBody>\n </Card>\n </Stack>\n );\n}\n\nconst inputStyle = {\n padding: '6px 10px',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n background: 'var(--surface-0)',\n color: 'var(--fg)',\n fontSize: 'var(--fs-13)',\n fontFamily: 'var(--font-mono)',\n} as const;"],"names":["statusTone","s","fmtDuration","ms","EvalView","runs","useFetch","schedules","launching","setLaunching","useState","suite","setSuite","error","setError","addingSchedule","setAddingSchedule","scheduleForm","setScheduleForm","busySchedule","setBusySchedule","useEffect","_a","r","id","launch","fetchJson","err","FetchError","list","addSchedule","deleteSchedule","scheduleList","_b","jsxs","Stack","jsx","ViewHeader","Inline","e","Button","Loader2","Play","RefreshCw","Skeleton","EmptyState","FlaskConical","Card","CardBody","Badge","Calendar","Plus","inputStyle","Trash2"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import{j as e,r}from"./cmdk-C3F6LD6N.js";import{B as F,g as q,S as f,I as C,d as b,h as K,i as R,u as Q,a as V}from"./main-BZMmD6a8.js";import{G as X}from"./Grid-BThCPJaV.js";import{C as Y}from"./Chip-Dei66BLx.js";import{C as Z,V as ee}from"./ViewHeader-BaCWNuVX.js";import{P as te}from"./ProgressBar-ya2PCj8L.js";import{C as se}from"./calendar-BrMJf3vl.js";import{S as _,a as M}from"./Sheet-CxXf6gvC.js";import{I as P}from"./Input-cAQOvR8U.js";import{S as ae,a as le,b as re,c as ne}from"./Select-D5AuVxxV.js";import{E as ie}from"./external-link-C4pHGbz2.js";import{T as W}from"./trash-2-B885GY46.js";import{P as H}from"./plus-uA5Ecuch.js";import{C as oe,b as de}from"./Card-BmXiT4c6.js";import{E as ce}from"./ErrorState-BRvj8qZZ.js";import{L as ue}from"./ListHeader-BLAeshe0.js";import{T as ge}from"./Textarea-CcQGSgSH.js";import"./index-CR0TeJmc.js";import"./index-B1OIS316.js";import"./Alert-MwVEymjy.js";import"./circle-alert-D7jn06kH.js";import"./triangle-alert-DLmUhymD.js";import"./circle-check-DHs37Sot.js";import"./refresh-ccw-BL7B0NO1.js";const fe={"on-track":"On track","at-risk":"At risk","off-track":"Off track",done:"Done"},he={"on-track":"success","at-risk":"warning","off-track":"danger",done:"neutral"};function pe(i){const{title:l,description:u,status:p,progress:D,due:g,ownerName:m,ownerAvatarUrl:h,keyResultsDone:w,keyResultsTotal:I,badges:E,onOpen:z,className:j}=i;return e.jsxs("button",{type:"button",onClick:z,className:q("v8-goal-card",`v8-goal-card--${p}`,j),style:{display:"flex",flexDirection:"column",gap:"var(--space-3)",width:"100%",padding:"var(--space-4)",background:"var(--surface-1)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",textAlign:"left",cursor:"pointer",font:"inherit",color:"inherit",transition:"border-color var(--motion-fast) var(--ease-out), background var(--motion-fast) var(--ease-out)"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",gap:"var(--space-2)"},children:[e.jsxs("div",{style:{flex:1,minWidth:0},children:[e.jsx("div",{style:{fontSize:"var(--fs-14)",fontWeight:600,color:"var(--fg)",lineHeight:"var(--lh-snug)"},children:l}),u!==void 0&&e.jsx("div",{style:{fontSize:"var(--fs-13)",color:"var(--fg-muted)",marginTop:4,display:"-webkit-box",WebkitLineClamp:2,WebkitBoxOrient:"vertical",overflow:"hidden"},children:u})]}),e.jsx(F,{tone:he[p],dot:!0,children:fe[p]})]}),e.jsxs("div",{children:[e.jsx(te,{value:D,tone:p==="on-track"?"success":p==="at-risk"?"warning":p==="off-track"?"danger":"accent"}),e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",marginTop:6,fontSize:"var(--fs-12)",color:"var(--fg-muted)",fontVariantNumeric:"tabular-nums"},children:[e.jsxs("span",{children:[Math.round(D*100),"% complete"]}),w!==void 0&&I!==void 0&&e.jsxs("span",{children:[w," / ",I," key results"]})]})]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:"var(--space-2)",fontSize:"var(--fs-12)",color:"var(--fg-subtle)"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"var(--space-3)"},children:[g!==void 0&&e.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:4},children:[e.jsx(se,{size:12,"aria-hidden":"true"}),g]}),m!==void 0&&e.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:6},children:[e.jsx("span",{"aria-hidden":"true",style:{width:16,height:16,borderRadius:"var(--radius-pill)",background:h!==void 0?`url(${h}) center/cover`:"var(--accent)",display:"inline-block"}}),m]})]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"var(--space-2)"},children:[E,e.jsx(Z,{size:14,"aria-hidden":"true",style:{color:"var(--fg-subtle)"}})]})]}),e.jsx("style",{children:`
1
+ import{j as e,r}from"./cmdk-C3F6LD6N.js";import{b as F,g as q,S as f,I as C,B as b,h as K,i as R,u as Q,a as V}from"./main-BURAlktW.js";import{G as X}from"./Grid--WKvqu5h.js";import{C as Y}from"./Chip-XPOk0d_E.js";import{C as Z,V as ee}from"./ViewHeader-C-t1U2cQ.js";import{P as te}from"./ProgressBar-BnaBqv-W.js";import{C as se}from"./calendar-B9Wbemh7.js";import{S as _,a as M}from"./Sheet-B-CMP9-_.js";import{I as P}from"./Input-h_nSOtwm.js";import{S as ae,a as le,b as re,c as ne}from"./Select-CiGWEN8I.js";import{E as ie}from"./external-link-DvL89gaZ.js";import{T as W}from"./trash-2-D6qePV_q.js";import{P as H}from"./plus-Cm6-fo14.js";import{C as oe,b as de}from"./Card-BtsmkhJa.js";import{E as ce}from"./ErrorState-CBJbEQ8B.js";import{L as ue}from"./ListHeader-CM8QoIWG.js";import{T as ge}from"./Textarea-xnAybFGd.js";import"./index-CR0TeJmc.js";import"./index-B1OIS316.js";import"./Alert-BZGk39mB.js";import"./circle-alert-Dz8lGfCZ.js";import"./triangle-alert-B2oHbmoh.js";import"./circle-check-DFB50ojt.js";import"./refresh-ccw-DA8_IB9l.js";const fe={"on-track":"On track","at-risk":"At risk","off-track":"Off track",done:"Done"},he={"on-track":"success","at-risk":"warning","off-track":"danger",done:"neutral"};function pe(i){const{title:l,description:u,status:p,progress:D,due:g,ownerName:m,ownerAvatarUrl:h,keyResultsDone:w,keyResultsTotal:I,badges:E,onOpen:z,className:j}=i;return e.jsxs("button",{type:"button",onClick:z,className:q("v8-goal-card",`v8-goal-card--${p}`,j),style:{display:"flex",flexDirection:"column",gap:"var(--space-3)",width:"100%",padding:"var(--space-4)",background:"var(--surface-1)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",textAlign:"left",cursor:"pointer",font:"inherit",color:"inherit",transition:"border-color var(--motion-fast) var(--ease-out), background var(--motion-fast) var(--ease-out)"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",gap:"var(--space-2)"},children:[e.jsxs("div",{style:{flex:1,minWidth:0},children:[e.jsx("div",{style:{fontSize:"var(--fs-14)",fontWeight:600,color:"var(--fg)",lineHeight:"var(--lh-snug)"},children:l}),u!==void 0&&e.jsx("div",{style:{fontSize:"var(--fs-13)",color:"var(--fg-muted)",marginTop:4,display:"-webkit-box",WebkitLineClamp:2,WebkitBoxOrient:"vertical",overflow:"hidden"},children:u})]}),e.jsx(F,{tone:he[p],dot:!0,children:fe[p]})]}),e.jsxs("div",{children:[e.jsx(te,{value:D,tone:p==="on-track"?"success":p==="at-risk"?"warning":p==="off-track"?"danger":"accent"}),e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",marginTop:6,fontSize:"var(--fs-12)",color:"var(--fg-muted)",fontVariantNumeric:"tabular-nums"},children:[e.jsxs("span",{children:[Math.round(D*100),"% complete"]}),w!==void 0&&I!==void 0&&e.jsxs("span",{children:[w," / ",I," key results"]})]})]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:"var(--space-2)",fontSize:"var(--fs-12)",color:"var(--fg-subtle)"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"var(--space-3)"},children:[g!==void 0&&e.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:4},children:[e.jsx(se,{size:12,"aria-hidden":"true"}),g]}),m!==void 0&&e.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:6},children:[e.jsx("span",{"aria-hidden":"true",style:{width:16,height:16,borderRadius:"var(--radius-pill)",background:h!==void 0?`url(${h}) center/cover`:"var(--accent)",display:"inline-block"}}),m]})]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"var(--space-2)"},children:[E,e.jsx(Z,{size:14,"aria-hidden":"true",style:{color:"var(--fg-subtle)"}})]})]}),e.jsx("style",{children:`
2
2
  .v8-goal-card:hover {
3
3
  border-color: var(--accent);
4
4
  background: var(--surface-2);