@polderlabs/bizar 10.4.4 → 10.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/bizar-dash/dist/assets/{ActivityFeed-RQeyFifx.js → ActivityFeed-Bw4Cai7r.js} +1 -1
  2. package/bizar-dash/dist/assets/{ActivityFeed-RQeyFifx.js.map → ActivityFeed-Bw4Cai7r.js.map} +1 -1
  3. package/bizar-dash/dist/assets/{ActivityView-CibyssPM.js → ActivityView-BC0QQ_j9.js} +1 -1
  4. package/bizar-dash/dist/assets/{ActivityView-CibyssPM.js.map → ActivityView-BC0QQ_j9.js.map} +1 -1
  5. package/bizar-dash/dist/assets/{AdminView-BjczABeB.js → AdminView-CLTNKFL4.js} +1 -1
  6. package/bizar-dash/dist/assets/{AdminView-BjczABeB.js.map → AdminView-CLTNKFL4.js.map} +1 -1
  7. package/bizar-dash/dist/assets/{AgentActivity-Bywt1twv.js → AgentActivity-DBWDByjk.js} +1 -1
  8. package/bizar-dash/dist/assets/{AgentActivity-Bywt1twv.js.map → AgentActivity-DBWDByjk.js.map} +1 -1
  9. package/bizar-dash/dist/assets/{AgentsView-BnOjjM74.js → AgentsView-DD6bCIbA.js} +1 -1
  10. package/bizar-dash/dist/assets/{AgentsView-BnOjjM74.js.map → AgentsView-DD6bCIbA.js.map} +1 -1
  11. package/bizar-dash/dist/assets/{Alert-BZGk39mB.js → Alert-pzFISNtS.js} +1 -1
  12. package/bizar-dash/dist/assets/{Alert-BZGk39mB.js.map → Alert-pzFISNtS.js.map} +1 -1
  13. package/bizar-dash/dist/assets/ArtifactsView-BVU5lfo7.js +21 -0
  14. package/bizar-dash/dist/assets/ArtifactsView-BVU5lfo7.js.map +1 -0
  15. package/bizar-dash/dist/assets/{AuthView-D4frSShw.js → AuthView-BZ-bPIOM.js} +2 -2
  16. package/bizar-dash/dist/assets/AuthView-BZ-bPIOM.js.map +1 -0
  17. package/bizar-dash/dist/assets/{Avatar-BYg0rkPA.js → Avatar-CRW81ewE.js} +1 -1
  18. package/bizar-dash/dist/assets/{Avatar-BYg0rkPA.js.map → Avatar-CRW81ewE.js.map} +1 -1
  19. package/bizar-dash/dist/assets/BackgroundJobsView-w8OZtXyI.js +1 -0
  20. package/bizar-dash/dist/assets/BackgroundJobsView-w8OZtXyI.js.map +1 -0
  21. package/bizar-dash/dist/assets/{BackupView-B875KQa4.js → BackupView-u_O3j0TG.js} +1 -1
  22. package/bizar-dash/dist/assets/{BackupView-B875KQa4.js.map → BackupView-u_O3j0TG.js.map} +1 -1
  23. package/bizar-dash/dist/assets/{Banner-C8HEcT5l.js → Banner-Du-3l05O.js} +1 -1
  24. package/bizar-dash/dist/assets/{Banner-C8HEcT5l.js.map → Banner-Du-3l05O.js.map} +1 -1
  25. package/bizar-dash/dist/assets/{Card-BtsmkhJa.js → Card-Clkvh43Q.js} +1 -1
  26. package/bizar-dash/dist/assets/{Card-BtsmkhJa.js.map → Card-Clkvh43Q.js.map} +1 -1
  27. package/bizar-dash/dist/assets/{ChatView-CkNS0SD8.js → ChatView-BTjb3mIh.js} +1 -1
  28. package/bizar-dash/dist/assets/{ChatView-CkNS0SD8.js.map → ChatView-BTjb3mIh.js.map} +1 -1
  29. package/bizar-dash/dist/assets/{Chip-XPOk0d_E.js → Chip-B7ovcm01.js} +1 -1
  30. package/bizar-dash/dist/assets/{Chip-XPOk0d_E.js.map → Chip-B7ovcm01.js.map} +1 -1
  31. package/bizar-dash/dist/assets/ClaudeSessionsView-BoZS5ldi.js +1 -0
  32. package/bizar-dash/dist/assets/ClaudeSessionsView-BoZS5ldi.js.map +1 -0
  33. package/bizar-dash/dist/assets/ClipboardView-Cb6XgYZI.js +1 -0
  34. package/bizar-dash/dist/assets/{ClipboardView-CPlTU5VG.js.map → ClipboardView-Cb6XgYZI.js.map} +1 -1
  35. package/bizar-dash/dist/assets/{ConfigView-BntUrW7s.js → ConfigView-DfTJk1uL.js} +1 -1
  36. package/bizar-dash/dist/assets/{ConfigView-BntUrW7s.js.map → ConfigView-DfTJk1uL.js.map} +1 -1
  37. package/bizar-dash/dist/assets/{DiagnosticsView-4x0Zu3yP.js → DiagnosticsView-D5Wy9xlJ.js} +1 -1
  38. package/bizar-dash/dist/assets/{DiagnosticsView-4x0Zu3yP.js.map → DiagnosticsView-D5Wy9xlJ.js.map} +1 -1
  39. package/bizar-dash/dist/assets/{DialogsView-Xd02dVAX.js → DialogsView-HVyfrXpq.js} +1 -1
  40. package/bizar-dash/dist/assets/{DialogsView-Xd02dVAX.js.map → DialogsView-HVyfrXpq.js.map} +1 -1
  41. package/bizar-dash/dist/assets/{DoctorView-DepBdQGR.js → DoctorView-Dm94WI2z.js} +2 -2
  42. package/bizar-dash/dist/assets/{DoctorView-DepBdQGR.js.map → DoctorView-Dm94WI2z.js.map} +1 -1
  43. package/bizar-dash/dist/assets/{EmptyState-DjKtY1Qi.js → EmptyState-ccT__JZG.js} +1 -1
  44. package/bizar-dash/dist/assets/{EmptyState-DjKtY1Qi.js.map → EmptyState-ccT__JZG.js.map} +1 -1
  45. package/bizar-dash/dist/assets/{EnvVarsView-S4Pbm128.js → EnvVarsView-BhcIuJ6V.js} +2 -2
  46. package/bizar-dash/dist/assets/{EnvVarsView-S4Pbm128.js.map → EnvVarsView-BhcIuJ6V.js.map} +1 -1
  47. package/bizar-dash/dist/assets/{ErrorState-CBJbEQ8B.js → ErrorState-BSqf65ka.js} +1 -1
  48. package/bizar-dash/dist/assets/{ErrorState-CBJbEQ8B.js.map → ErrorState-BSqf65ka.js.map} +1 -1
  49. package/bizar-dash/dist/assets/{EvalView-BeAyMCD1.js → EvalView-2cbWVBUA.js} +1 -1
  50. package/bizar-dash/dist/assets/{EvalView-BeAyMCD1.js.map → EvalView-2cbWVBUA.js.map} +1 -1
  51. package/bizar-dash/dist/assets/{GoalsView-BZr8In4c.js → GoalsView-C3QG5p7T.js} +1 -1
  52. package/bizar-dash/dist/assets/{GoalsView-BZr8In4c.js.map → GoalsView-C3QG5p7T.js.map} +1 -1
  53. package/bizar-dash/dist/assets/{Grid--WKvqu5h.js → Grid-Bojq8Sg7.js} +1 -1
  54. package/bizar-dash/dist/assets/{Grid--WKvqu5h.js.map → Grid-Bojq8Sg7.js.map} +1 -1
  55. package/bizar-dash/dist/assets/{HistoryView-djEbzqtk.js → HistoryView-Bum2TMMw.js} +1 -1
  56. package/bizar-dash/dist/assets/{HistoryView-djEbzqtk.js.map → HistoryView-Bum2TMMw.js.map} +1 -1
  57. package/bizar-dash/dist/assets/{Input-h_nSOtwm.js → Input-DV-vdaV8.js} +1 -1
  58. package/bizar-dash/dist/assets/{Input-h_nSOtwm.js.map → Input-DV-vdaV8.js.map} +1 -1
  59. package/bizar-dash/dist/assets/{LibrariesView-Vez8CvNq.js → LibrariesView-DH2E2uNb.js} +1 -1
  60. package/bizar-dash/dist/assets/{LibrariesView-Vez8CvNq.js.map → LibrariesView-DH2E2uNb.js.map} +1 -1
  61. package/bizar-dash/dist/assets/LightRAGView-BFCcj7Tl.js +6 -0
  62. package/bizar-dash/dist/assets/LightRAGView-BFCcj7Tl.js.map +1 -0
  63. package/bizar-dash/dist/assets/{ListHeader-CM8QoIWG.js → ListHeader-CCD_nIHb.js} +1 -1
  64. package/bizar-dash/dist/assets/{ListHeader-CM8QoIWG.js.map → ListHeader-CCD_nIHb.js.map} +1 -1
  65. package/bizar-dash/dist/assets/{MemoryView-DnL8E2vI.js → MemoryView-Cr-obIQY.js} +1 -1
  66. package/bizar-dash/dist/assets/{MemoryView-DnL8E2vI.js.map → MemoryView-Cr-obIQY.js.map} +1 -1
  67. package/bizar-dash/dist/assets/{MiscView-B2YQXhZ_.js → MiscView-CDUQpYuV.js} +1 -1
  68. package/bizar-dash/dist/assets/{MiscView-B2YQXhZ_.js.map → MiscView-CDUQpYuV.js.map} +1 -1
  69. package/bizar-dash/dist/assets/{ModsView-BVM3X5xc.js → ModsView-B6OR-a4B.js} +2 -2
  70. package/bizar-dash/dist/assets/{ModsView-BVM3X5xc.js.map → ModsView-B6OR-a4B.js.map} +1 -1
  71. package/bizar-dash/dist/assets/{NotificationsView-A-Xs8BL1.js → NotificationsView-CIqtY6D0.js} +1 -1
  72. package/bizar-dash/dist/assets/{NotificationsView-A-Xs8BL1.js.map → NotificationsView-CIqtY6D0.js.map} +1 -1
  73. package/bizar-dash/dist/assets/{ObsidianView-mI3qW9OP.js → ObsidianView-Nahah8QC.js} +1 -1
  74. package/bizar-dash/dist/assets/{ObsidianView-mI3qW9OP.js.map → ObsidianView-Nahah8QC.js.map} +1 -1
  75. package/bizar-dash/dist/assets/{OverviewView-By69Cr5H.js → OverviewView-B6L_wa4M.js} +1 -1
  76. package/bizar-dash/dist/assets/{OverviewView-By69Cr5H.js.map → OverviewView-B6L_wa4M.js.map} +1 -1
  77. package/bizar-dash/dist/assets/{ProgressBar-BnaBqv-W.js → ProgressBar-KC4VXsl_.js} +1 -1
  78. package/bizar-dash/dist/assets/{ProgressBar-BnaBqv-W.js.map → ProgressBar-KC4VXsl_.js.map} +1 -1
  79. package/bizar-dash/dist/assets/{ProjectsView-C81WTFka.js → ProjectsView-DgxWiqHb.js} +1 -1
  80. package/bizar-dash/dist/assets/{ProjectsView-C81WTFka.js.map → ProjectsView-DgxWiqHb.js.map} +1 -1
  81. package/bizar-dash/dist/assets/{ProvidersView-2cn-TALE.js → ProvidersView-BOqN9omv.js} +1 -1
  82. package/bizar-dash/dist/assets/{ProvidersView-2cn-TALE.js.map → ProvidersView-BOqN9omv.js.map} +1 -1
  83. package/bizar-dash/dist/assets/SchedulesView-yMaG3Dtd.js +1 -0
  84. package/bizar-dash/dist/assets/SchedulesView-yMaG3Dtd.js.map +1 -0
  85. package/bizar-dash/dist/assets/{Select-CiGWEN8I.js → Select-Bf_P0S6H.js} +1 -1
  86. package/bizar-dash/dist/assets/{Select-CiGWEN8I.js.map → Select-Bf_P0S6H.js.map} +1 -1
  87. package/bizar-dash/dist/assets/{SettingsRow-CflGJymA.js → SettingsRow-CJb-F94Y.js} +1 -1
  88. package/bizar-dash/dist/assets/{SettingsRow-CflGJymA.js.map → SettingsRow-CJb-F94Y.js.map} +1 -1
  89. package/bizar-dash/dist/assets/{SettingsView-2HSFJPPK.js → SettingsView-BvOGcgMS.js} +2 -2
  90. package/bizar-dash/dist/assets/SettingsView-BvOGcgMS.js.map +1 -0
  91. package/bizar-dash/dist/assets/{Sheet-B-CMP9-_.js → Sheet-BwMVGN-8.js} +1 -1
  92. package/bizar-dash/dist/assets/{Sheet-B-CMP9-_.js.map → Sheet-BwMVGN-8.js.map} +1 -1
  93. package/bizar-dash/dist/assets/{Slider-Z4TP_CXY.js → Slider-AjjzqI-5.js} +1 -1
  94. package/bizar-dash/dist/assets/{Slider-Z4TP_CXY.js.map → Slider-AjjzqI-5.js.map} +1 -1
  95. package/bizar-dash/dist/assets/{Sparkline-cvkv2HbU.js → Sparkline-Z4y0YUZS.js} +1 -1
  96. package/bizar-dash/dist/assets/{Sparkline-cvkv2HbU.js.map → Sparkline-Z4y0YUZS.js.map} +1 -1
  97. package/bizar-dash/dist/assets/{Switch-jcYo4lmp.js → Switch-B79a2t-G.js} +1 -1
  98. package/bizar-dash/dist/assets/{Switch-jcYo4lmp.js.map → Switch-B79a2t-G.js.map} +1 -1
  99. package/bizar-dash/dist/assets/{TasksView-CQaSFzWY.js → TasksView-G-s_pwwr.js} +1 -1
  100. package/bizar-dash/dist/assets/{TasksView-CQaSFzWY.js.map → TasksView-G-s_pwwr.js.map} +1 -1
  101. package/bizar-dash/dist/assets/{Textarea-xnAybFGd.js → Textarea-BfXGMXQ7.js} +1 -1
  102. package/bizar-dash/dist/assets/{Textarea-xnAybFGd.js.map → Textarea-BfXGMXQ7.js.map} +1 -1
  103. package/bizar-dash/dist/assets/{UpdateView-BUAEcRCX.js → UpdateView-BKx3u9X8.js} +1 -1
  104. package/bizar-dash/dist/assets/{UpdateView-BUAEcRCX.js.map → UpdateView-BKx3u9X8.js.map} +1 -1
  105. package/bizar-dash/dist/assets/{UsageView-DMFbBOfH.js → UsageView-M01G6bZQ.js} +1 -1
  106. package/bizar-dash/dist/assets/{UsageView-DMFbBOfH.js.map → UsageView-M01G6bZQ.js.map} +1 -1
  107. package/bizar-dash/dist/assets/{ViewHeader-C-t1U2cQ.js → ViewHeader-BsnaspKw.js} +1 -1
  108. package/bizar-dash/dist/assets/{ViewHeader-C-t1U2cQ.js.map → ViewHeader-BsnaspKw.js.map} +1 -1
  109. package/bizar-dash/dist/assets/VoiceView-rWE8vziD.js +1 -0
  110. package/bizar-dash/dist/assets/{VoiceView-aoPVT6LJ.js.map → VoiceView-rWE8vziD.js.map} +1 -1
  111. package/bizar-dash/dist/assets/{brain-DhAzcHUk.js → brain-D7k5s8vH.js} +1 -1
  112. package/bizar-dash/dist/assets/{brain-DhAzcHUk.js.map → brain-D7k5s8vH.js.map} +1 -1
  113. package/bizar-dash/dist/assets/{calendar-B9Wbemh7.js → calendar-CAZoDd-l.js} +1 -1
  114. package/bizar-dash/dist/assets/{calendar-B9Wbemh7.js.map → calendar-CAZoDd-l.js.map} +1 -1
  115. package/bizar-dash/dist/assets/{circle-6NJF_Xl6.js → circle-D99cZJBr.js} +1 -1
  116. package/bizar-dash/dist/assets/{circle-6NJF_Xl6.js.map → circle-D99cZJBr.js.map} +1 -1
  117. package/bizar-dash/dist/assets/{circle-alert-Dz8lGfCZ.js → circle-alert-QQTU4Quz.js} +1 -1
  118. package/bizar-dash/dist/assets/{circle-alert-Dz8lGfCZ.js.map → circle-alert-QQTU4Quz.js.map} +1 -1
  119. package/bizar-dash/dist/assets/{circle-check-DFB50ojt.js → circle-check-BMbe7Kkr.js} +1 -1
  120. package/bizar-dash/dist/assets/{circle-check-DFB50ojt.js.map → circle-check-BMbe7Kkr.js.map} +1 -1
  121. package/bizar-dash/dist/assets/{clock-ClVA6-hQ.js → clock-OtT5mvF3.js} +1 -1
  122. package/bizar-dash/dist/assets/{clock-ClVA6-hQ.js.map → clock-OtT5mvF3.js.map} +1 -1
  123. package/bizar-dash/dist/assets/{download-BvJddD8D.js → download-B-mPX5P_.js} +1 -1
  124. package/bizar-dash/dist/assets/{download-BvJddD8D.js.map → download-B-mPX5P_.js.map} +1 -1
  125. package/bizar-dash/dist/assets/{external-link-DvL89gaZ.js → external-link-DPDQM1YO.js} +1 -1
  126. package/bizar-dash/dist/assets/{external-link-DvL89gaZ.js.map → external-link-DPDQM1YO.js.map} +1 -1
  127. package/bizar-dash/dist/assets/{file-text-BOroDtZE.js → file-text-BsCrv5aP.js} +1 -1
  128. package/bizar-dash/dist/assets/{file-text-BOroDtZE.js.map → file-text-BsCrv5aP.js.map} +1 -1
  129. package/bizar-dash/dist/assets/{filter-DwPjMRQt.js → filter-Do63x17E.js} +1 -1
  130. package/bizar-dash/dist/assets/{filter-DwPjMRQt.js.map → filter-Do63x17E.js.map} +1 -1
  131. package/bizar-dash/dist/assets/{git-pull-request-TDb1inux.js → git-pull-request-CpRAmERC.js} +1 -1
  132. package/bizar-dash/dist/assets/{git-pull-request-TDb1inux.js.map → git-pull-request-CpRAmERC.js.map} +1 -1
  133. package/bizar-dash/dist/assets/main-BRmJZcHt.js +277 -0
  134. package/bizar-dash/dist/assets/main-BRmJZcHt.js.map +1 -0
  135. package/bizar-dash/dist/assets/main-D0TY0myE.css +1 -0
  136. package/bizar-dash/dist/assets/{network-BcCoCzIY.js → network-DJnHwHX3.js} +1 -1
  137. package/bizar-dash/dist/assets/{network-BcCoCzIY.js.map → network-DJnHwHX3.js.map} +1 -1
  138. package/bizar-dash/dist/assets/{pause-BllItT2_.js → pause-HitDUnk_.js} +1 -1
  139. package/bizar-dash/dist/assets/{pause-BllItT2_.js.map → pause-HitDUnk_.js.map} +1 -1
  140. package/bizar-dash/dist/assets/{pencil-DAwM-CC3.js → pencil-Dkks7eIC.js} +1 -1
  141. package/bizar-dash/dist/assets/{pencil-DAwM-CC3.js.map → pencil-Dkks7eIC.js.map} +1 -1
  142. package/bizar-dash/dist/assets/{play-mJh67AXo.js → play-blqh0msT.js} +1 -1
  143. package/bizar-dash/dist/assets/{play-mJh67AXo.js.map → play-blqh0msT.js.map} +1 -1
  144. package/bizar-dash/dist/assets/{plug-BjfntCMC.js → plug-DVvSSe40.js} +1 -1
  145. package/bizar-dash/dist/assets/{plug-BjfntCMC.js.map → plug-DVvSSe40.js.map} +1 -1
  146. package/bizar-dash/dist/assets/{plus-Cm6-fo14.js → plus-Cps-8lcG.js} +1 -1
  147. package/bizar-dash/dist/assets/{plus-Cm6-fo14.js.map → plus-Cps-8lcG.js.map} +1 -1
  148. package/bizar-dash/dist/assets/{power-CXN9y2KV.js → power-DEX4_Xoa.js} +1 -1
  149. package/bizar-dash/dist/assets/{power-CXN9y2KV.js.map → power-DEX4_Xoa.js.map} +1 -1
  150. package/bizar-dash/dist/assets/{power-off-DUZqwMf9.js → power-off-upZ4xjaG.js} +1 -1
  151. package/bizar-dash/dist/assets/{power-off-DUZqwMf9.js.map → power-off-upZ4xjaG.js.map} +1 -1
  152. package/bizar-dash/dist/assets/{refresh-ccw-DA8_IB9l.js → refresh-ccw-DN_zCB1h.js} +1 -1
  153. package/bizar-dash/dist/assets/{refresh-ccw-DA8_IB9l.js.map → refresh-ccw-DN_zCB1h.js.map} +1 -1
  154. package/bizar-dash/dist/assets/{refresh-cw-DwlP59en.js → refresh-cw-KGm5eQgv.js} +1 -1
  155. package/bizar-dash/dist/assets/{refresh-cw-DwlP59en.js.map → refresh-cw-KGm5eQgv.js.map} +1 -1
  156. package/bizar-dash/dist/assets/{rotate-ccw-DMTASfAn.js → rotate-ccw-D5fkDRgk.js} +1 -1
  157. package/bizar-dash/dist/assets/{rotate-ccw-DMTASfAn.js.map → rotate-ccw-D5fkDRgk.js.map} +1 -1
  158. package/bizar-dash/dist/assets/{rotate-cw-BDX5SE2s.js → rotate-cw-CClSVUaX.js} +1 -1
  159. package/bizar-dash/dist/assets/{rotate-cw-BDX5SE2s.js.map → rotate-cw-CClSVUaX.js.map} +1 -1
  160. package/bizar-dash/dist/assets/{save-Y0jPK5D6.js → save-BY4ViPku.js} +1 -1
  161. package/bizar-dash/dist/assets/{save-Y0jPK5D6.js.map → save-BY4ViPku.js.map} +1 -1
  162. package/bizar-dash/dist/assets/{send-C8wwPHhR.js → send-CaOL1yQD.js} +1 -1
  163. package/bizar-dash/dist/assets/{send-C8wwPHhR.js.map → send-CaOL1yQD.js.map} +1 -1
  164. package/bizar-dash/dist/assets/{shield-alert-DEvq9UG0.js → shield-alert-DA9K6uZO.js} +1 -1
  165. package/bizar-dash/dist/assets/{shield-alert-DEvq9UG0.js.map → shield-alert-DA9K6uZO.js.map} +1 -1
  166. package/bizar-dash/dist/assets/{trash-2-D6qePV_q.js → trash-2-B_Y6HrfN.js} +1 -1
  167. package/bizar-dash/dist/assets/{trash-2-D6qePV_q.js.map → trash-2-B_Y6HrfN.js.map} +1 -1
  168. package/bizar-dash/dist/assets/{trending-up-BZzo_1ic.js → trending-up-qKTUQKIT.js} +1 -1
  169. package/bizar-dash/dist/assets/{trending-up-BZzo_1ic.js.map → trending-up-qKTUQKIT.js.map} +1 -1
  170. package/bizar-dash/dist/assets/{triangle-alert-B2oHbmoh.js → triangle-alert-BeY8LAv6.js} +1 -1
  171. package/bizar-dash/dist/assets/{triangle-alert-B2oHbmoh.js.map → triangle-alert-BeY8LAv6.js.map} +1 -1
  172. package/bizar-dash/dist/assets/{upload-Dy59aZn6.js → upload-BZCtmqIh.js} +1 -1
  173. package/bizar-dash/dist/assets/{upload-Dy59aZn6.js.map → upload-BZCtmqIh.js.map} +1 -1
  174. package/bizar-dash/dist/assets/{zap-DENVhJnO.js → zap-Bz1Z8y1Q.js} +1 -1
  175. package/bizar-dash/dist/assets/{zap-DENVhJnO.js.map → zap-Bz1Z8y1Q.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/server/agent-bus.mjs +485 -0
  179. package/bizar-dash/src/server/api.mjs +6 -0
  180. package/bizar-dash/src/server/loop-runtime.mjs +429 -0
  181. package/bizar-dash/src/server/routes/agent-bus.mjs +185 -0
  182. package/bizar-dash/src/server/routes/loops.mjs +138 -0
  183. package/bizar-dash/src/server/task-splitter.mjs +241 -0
  184. package/bizar-dash/src/web/v8/shell/Sidebar.tsx +41 -31
  185. package/bizar-dash/src/web/v8/shell/Topbar.tsx +63 -23
  186. package/bizar-dash/src/web/v8/ui/feedback/NotificationsPopover.tsx +3 -0
  187. package/bizar-dash/src/web/v8/ui/feedback/useFocusTrap.ts +58 -0
  188. package/bizar-dash/src/web/v8/ui/navigation/CommandPalette.tsx +1 -0
  189. package/bizar-dash/src/web/v8/ui/styles/tokens.css +21 -0
  190. package/bizar-dash/src/web/v8/views/Artifacts/ClaudeArtifactView.tsx +1 -1
  191. package/bizar-dash/src/web/v8/views/Auth/AuthView.tsx +10 -6
  192. package/bizar-dash/src/web/v8/views/BackgroundJobs/BackgroundJobsView.tsx +38 -13
  193. package/bizar-dash/src/web/v8/views/ClaudeSessions/ClaudeSessionDetail.tsx +16 -5
  194. package/bizar-dash/src/web/v8/views/LightRAG/LightRAGView.tsx +23 -2
  195. package/bizar-dash/src/web/v8/views/Schedules/SchedulesView.tsx +48 -13
  196. package/bizar-dash/src/web/v8/views/Settings/SettingsView.tsx +3 -3
  197. package/bizar-dash/tests/agent-bus.test.mjs +289 -0
  198. package/bizar-dash/tests/auth-inputs-labels.test.mjs +45 -0
  199. package/bizar-dash/tests/background-jobs-action-labels.test.mjs +41 -0
  200. package/bizar-dash/tests/background-jobs-states.test.mjs +80 -0
  201. package/bizar-dash/tests/banner-tones.test.mjs +50 -0
  202. package/bizar-dash/tests/callout-tokens.test.mjs +30 -0
  203. package/bizar-dash/tests/claude-session-detail-states.test.mjs +67 -0
  204. package/bizar-dash/tests/components/BackgroundJobsSkeleton.test.tsx +38 -0
  205. package/bizar-dash/tests/density-tokens.test.mjs +46 -0
  206. package/bizar-dash/tests/doctor-route-shape.test.mjs +67 -0
  207. package/bizar-dash/tests/errorstate-retry.test.mjs +42 -0
  208. package/bizar-dash/tests/lightrag-skeleton.test.mjs +31 -0
  209. package/bizar-dash/tests/lightrag-states.test.mjs +60 -0
  210. package/bizar-dash/tests/loop-runtime.test.mjs +312 -0
  211. package/bizar-dash/tests/loops-agent-bus-routes.test.mjs +293 -0
  212. package/bizar-dash/tests/modal-focus-trap.test.mjs +114 -0
  213. package/bizar-dash/tests/orphan-tests-audit.test.mjs +80 -0
  214. package/bizar-dash/tests/palette-keyboard-nav.test.mjs +123 -0
  215. package/bizar-dash/tests/schedules-skeleton.test.mjs +25 -0
  216. package/bizar-dash/tests/schedules-states.test.mjs +67 -0
  217. package/bizar-dash/tests/sidebar-collapse-animation.test.mjs +37 -0
  218. package/bizar-dash/tests/sidebar-section-styles.test.mjs +55 -0
  219. package/bizar-dash/tests/skeleton-height.test.mjs +47 -0
  220. package/bizar-dash/tests/space-tokens.test.mjs +36 -0
  221. package/bizar-dash/tests/stattile-loading.test.mjs +28 -0
  222. package/bizar-dash/tests/task-splitter.test.mjs +268 -0
  223. package/bizar-dash/tests/topbar-popover-styles.test.mjs +53 -0
  224. package/bizar-dash/tests/update-channels.test.mjs +67 -0
  225. package/package.json +1 -1
  226. package/packages/sdk/${HOME}/.bizar_home/memory/projects/sdk/sessions/2026-07-16-e16c2f59.md +14 -0
  227. package/packages/sdk/.bizar/learning/instincts.jsonl +5 -0
  228. package/packages/sdk/package.json +1 -1
  229. package/scripts/loop-log.txt +29 -0
  230. package/scripts/loop-tasks.md +79 -0
  231. package/scripts/overnight-loop.mjs +60 -0
  232. package/bizar-dash/dist/assets/ArtifactsView-CfYB1le1.js +0 -21
  233. package/bizar-dash/dist/assets/ArtifactsView-CfYB1le1.js.map +0 -1
  234. package/bizar-dash/dist/assets/AuthView-D4frSShw.js.map +0 -1
  235. package/bizar-dash/dist/assets/BackgroundJobsView-DEStvILz.js +0 -1
  236. package/bizar-dash/dist/assets/BackgroundJobsView-DEStvILz.js.map +0 -1
  237. package/bizar-dash/dist/assets/ClaudeSessionsView-BprGo67K.js +0 -1
  238. package/bizar-dash/dist/assets/ClaudeSessionsView-BprGo67K.js.map +0 -1
  239. package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js +0 -1
  240. package/bizar-dash/dist/assets/LightRAGView-DvqzQoBp.js +0 -6
  241. package/bizar-dash/dist/assets/LightRAGView-DvqzQoBp.js.map +0 -1
  242. package/bizar-dash/dist/assets/SchedulesView-o9AtIsH9.js +0 -1
  243. package/bizar-dash/dist/assets/SchedulesView-o9AtIsH9.js.map +0 -1
  244. package/bizar-dash/dist/assets/SettingsView-2HSFJPPK.js.map +0 -1
  245. package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js +0 -1
  246. package/bizar-dash/dist/assets/main-B7D_IMTh.css +0 -1
  247. package/bizar-dash/dist/assets/main-BURAlktW.js +0 -277
  248. package/bizar-dash/dist/assets/main-BURAlktW.js.map +0 -1
  249. package/bizar-dash/tests/chat-session-create.test.mjs +0 -391
  250. package/bizar-dash/tests/chat-session-stream.test.mjs +0 -308
  251. package/bizar-dash/tests/cline-runner.test.mjs +0 -172
  252. package/bizar-dash/tests/cline-sessions-detail.test.mjs +0 -434
@@ -1 +1 @@
1
- import{r as t,j as e}from"./cmdk-C3F6LD6N.js";import{S as v,I as o,k as I,j as w,Q as L,u as y,B as c,h as S,i as z,F as k}from"./main-BURAlktW.js";import{V as D}from"./ViewHeader-C-t1U2cQ.js";import{C as b,b as C}from"./Card-BtsmkhJa.js";import{I as P}from"./Input-h_nSOtwm.js";import{E}from"./EmptyState-DjKtY1Qi.js";import{P as R}from"./plug-BjfntCMC.js";import{R as M}from"./refresh-ccw-DA8_IB9l.js";import{S as $}from"./save-Y0jPK5D6.js";import{P as T}from"./plus-Cm6-fo14.js";import{P as A}from"./pencil-DAwM-CC3.js";import{T as B}from"./trash-2-D6qePV_q.js";const F=[{id:"runtime",label:"Runtime config",icon:I},{id:"providers",label:"Providers",icon:w},{id:"mcps",label:"MCPs",icon:R},{id:"system-llm",label:"System LLM",icon:L}];function se(){const[s,n]=t.useState("runtime");return e.jsxs(v,{gap:4,"data-testid":"config-view",children:[e.jsx(D,{title:"Config",description:"Runtime config + providers + MCPs + system LLM."}),e.jsx(o,{gap:1,role:"tablist",children:F.map(r=>e.jsxs("button",{type:"button",role:"tab","aria-selected":s===r.id,onClick:()=>n(r.id),"data-testid":`config-tab-${r.id}`,style:{padding:"var(--space-2) var(--space-3)",borderRadius:"var(--radius-md)",border:"1px solid var(--border)",background:s===r.id?"color-mix(in oklch, var(--accent) 14%, transparent)":"var(--surface-0)",color:s===r.id?"var(--accent)":"var(--fg-muted)",fontSize:"var(--fs-12)",cursor:"pointer"},children:[e.jsx(r.icon,{size:14,"aria-hidden":!0,style:{verticalAlign:"middle",marginRight:6}}),r.label]},r.id))}),s==="runtime"&&e.jsx(N,{}),s==="providers"&&e.jsx(V,{}),s==="mcps"&&e.jsx(U,{}),s==="system-llm"&&e.jsx(H,{})]})}function N(){var h;const s=y("/api/config"),[n,r]=t.useState(""),[i,m]=t.useState(!1),[x,l]=t.useState(!1),[f,u]=t.useState(null);t.useEffect(()=>{var a;((a=s.data)==null?void 0:a.raw)!==void 0&&r(s.data.raw)},[(h=s.data)==null?void 0:h.raw]);const j=t.useCallback(()=>{s.refetch()},[s]),g=async()=>{m(!0),u(null),l(!1);try{await z("/api/config",{method:"PUT",body:n}),l(!0),j()}catch(a){u((a instanceof k,a.message))}finally{m(!1)}};return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsxs(o,{align:"center",justify:"between",gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"Runtime config"}),e.jsxs(o,{gap:1,children:[e.jsxs(c,{variant:"ghost",onClick:j,"data-testid":"config-runtime-reload",children:[e.jsx(M,{size:14,"aria-hidden":!0})," Reload"]}),e.jsxs(c,{variant:"primary",onClick:()=>void g(),disabled:i,"data-testid":"config-runtime-save",children:[e.jsx($,{size:14,"aria-hidden":!0})," ",i?"Saving…":"Save"]})]})]}),s.loading&&s.data===null?e.jsx(S,{style:{height:240}}):e.jsx("textarea",{value:n,rows:16,"data-testid":"config-runtime-raw",onChange:a=>r(a.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"}}),x&&e.jsx("span",{"data-testid":"config-runtime-saved",style:{color:"var(--success)",fontSize:"var(--fs-12)"},children:"Saved"}),f!==null&&e.jsx("span",{role:"alert","data-testid":"config-runtime-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:f})]})})})}function V(){const s=y("/api/config/providers"),[n,r]=t.useState(!1),[i,m]=t.useState(null),[x,l]=t.useState(null),[f,u]=t.useState(null),j=t.useCallback(()=>{s.refetch()},[s]),g=t.useMemo(()=>{var a;return((a=s.data)==null?void 0:a.providers)??[]},[s.data]),h=async a=>{u(null);try{await z(`/api/config/providers/${a}`,{method:"DELETE"}),l(null),j()}catch(p){u((p instanceof k,p.message))}};return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsxs(o,{align:"center",justify:"between",gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"Providers"}),e.jsxs(o,{gap:1,children:[f!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:f}),e.jsxs(c,{variant:"primary",onClick:()=>r(!0),"data-testid":"config-providers-add",children:[e.jsx(T,{size:14,"aria-hidden":!0})," Add"]})]})]}),s.loading&&g.length===0?e.jsx(S,{style:{height:100}}):g.length===0?e.jsx(E,{icon:e.jsx(w,{size:28,"aria-hidden":!0}),title:"No providers",description:"Add one or use Auto-add with key."}):e.jsx(v,{gap:1,children:g.map(a=>{const p=x===a.id;return e.jsxs("div",{"data-testid":`config-provider-row-${a.id}`,style:{padding:"var(--space-2)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)"},children:[e.jsxs(o,{align:"center",justify:"between",gap:2,children:[e.jsxs(o,{align:"center",gap:2,children:[e.jsx("strong",{children:a.name||a.id}),a.groupId&&e.jsxs("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:["group=",a.groupId]})]}),e.jsxs(o,{gap:1,children:[e.jsx(c,{variant:"ghost",onClick:()=>m(a.id),"data-testid":`config-provider-edit-${a.id}`,"aria-label":`Edit ${a.id}`,children:e.jsx(A,{size:14,"aria-hidden":!0})}),e.jsx(c,{variant:"ghost",onClick:()=>l(d=>d===a.id?null:a.id),"data-testid":`config-provider-delete-${a.id}`,"aria-label":`Delete ${a.id}`,children:e.jsx(B,{size:14,"aria-hidden":!0})})]})]}),p&&e.jsxs(o,{gap:1,style:{marginTop:"var(--space-1)"},children:[e.jsx(c,{variant:"danger",onClick:()=>void h(a.id),"data-testid":`config-provider-confirm-delete-${a.id}`,children:"Confirm delete"}),e.jsx(c,{variant:"ghost",onClick:()=>l(null),children:"Cancel"})]})]},a.id)})})]})})})}function U(){const s=y("/api/config/mcps"),n=t.useMemo(()=>{var i;return((i=s.data)==null?void 0:i.mcps)??[]},[s.data]),r=t.useCallback(()=>{s.refetch()},[s]);return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsx(o,{align:"center",justify:"between",gap:2,children:e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"MCP servers"})}),s.loading&&n.length===0?e.jsx(S,{style:{height:60}}):n.length===0?e.jsx(E,{icon:e.jsx(R,{size:28,"aria-hidden":!0}),title:"No MCPs",description:"Add one via /api/config/mcps."}):e.jsx(v,{gap:1,children:n.map(i=>e.jsxs("div",{"data-testid":`config-mcp-row-${i.id}`,style:{padding:"var(--space-2)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)",display:"flex",justifyContent:"space-between"},children:[e.jsx("strong",{children:i.name||i.id}),i.command&&e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:i.command})]},i.id))}),e.jsxs(c,{variant:"ghost",onClick:r,"data-testid":"config-mcps-refresh",children:[e.jsx(M,{size:14,"aria-hidden":!0})," Refresh"]})]})})})}function H(){const s=y("/api/llm/system-llm"),[n,r]=t.useState(!1),[i,m]=t.useState(""),[x,l]=t.useState(""),[f,u]=t.useState(!1),[j,g]=t.useState(!1),[h,a]=t.useState(null);t.useEffect(()=>{s.data&&(r(s.data.enabled),m(s.data.provider??""),l(s.data.model??""))},[s.data]);const p=async()=>{u(!0),a(null),g(!1);try{await z("/api/llm/system-llm",{method:"PUT",body:{enabled:n,provider:i,model:x}}),g(!0),s.refetch()}catch(d){a((d instanceof k,d.message))}finally{u(!1)}};return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"System LLM"}),s.loading&&s.data===null?e.jsx(S,{style:{height:100}}):e.jsxs(v,{gap:2,children:[e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:"var(--space-2)"},children:[e.jsx("input",{type:"checkbox",checked:n,"data-testid":"config-system-llm-enabled",onChange:d=>r(d.target.checked)}),e.jsx("span",{style:{fontSize:"var(--fs-13)"},children:"Enabled"})]}),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:"Provider"}),e.jsx(P,{value:i,"data-testid":"config-system-llm-provider",onChange:d=>m(d.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:"Model"}),e.jsx(P,{value:x,"data-testid":"config-system-llm-model",onChange:d=>l(d.target.value)})]}),e.jsx(o,{justify:"end",gap:2,children:e.jsxs(c,{variant:"primary",onClick:()=>void p(),disabled:f,"data-testid":"config-system-llm-save",children:[e.jsx($,{size:14,"aria-hidden":!0})," ",f?"Saving…":"Save"]})}),j&&e.jsx("span",{"data-testid":"config-system-llm-saved",style:{color:"var(--success)",fontSize:"var(--fs-12)"},children:"Saved"}),h!==null&&e.jsx("span",{role:"alert","data-testid":"config-system-llm-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:h})]})]})})})}export{se as ConfigView};
1
+ import{r as t,j as e}from"./cmdk-C3F6LD6N.js";import{S as v,I as o,k as I,j as w,U as L,u as y,B as c,h as S,i as z,F as k}from"./main-BRmJZcHt.js";import{V as D}from"./ViewHeader-BsnaspKw.js";import{C as b,b as C}from"./Card-Clkvh43Q.js";import{I as P}from"./Input-DV-vdaV8.js";import{E}from"./EmptyState-ccT__JZG.js";import{P as R}from"./plug-DVvSSe40.js";import{R as M}from"./refresh-ccw-DN_zCB1h.js";import{S as $}from"./save-BY4ViPku.js";import{P as T}from"./plus-Cps-8lcG.js";import{P as A}from"./pencil-Dkks7eIC.js";import{T as B}from"./trash-2-B_Y6HrfN.js";const F=[{id:"runtime",label:"Runtime config",icon:I},{id:"providers",label:"Providers",icon:w},{id:"mcps",label:"MCPs",icon:R},{id:"system-llm",label:"System LLM",icon:L}];function se(){const[s,n]=t.useState("runtime");return e.jsxs(v,{gap:4,"data-testid":"config-view",children:[e.jsx(D,{title:"Config",description:"Runtime config + providers + MCPs + system LLM."}),e.jsx(o,{gap:1,role:"tablist",children:F.map(r=>e.jsxs("button",{type:"button",role:"tab","aria-selected":s===r.id,onClick:()=>n(r.id),"data-testid":`config-tab-${r.id}`,style:{padding:"var(--space-2) var(--space-3)",borderRadius:"var(--radius-md)",border:"1px solid var(--border)",background:s===r.id?"color-mix(in oklch, var(--accent) 14%, transparent)":"var(--surface-0)",color:s===r.id?"var(--accent)":"var(--fg-muted)",fontSize:"var(--fs-12)",cursor:"pointer"},children:[e.jsx(r.icon,{size:14,"aria-hidden":!0,style:{verticalAlign:"middle",marginRight:6}}),r.label]},r.id))}),s==="runtime"&&e.jsx(N,{}),s==="providers"&&e.jsx(U,{}),s==="mcps"&&e.jsx(V,{}),s==="system-llm"&&e.jsx(H,{})]})}function N(){var h;const s=y("/api/config"),[n,r]=t.useState(""),[i,m]=t.useState(!1),[x,l]=t.useState(!1),[f,u]=t.useState(null);t.useEffect(()=>{var a;((a=s.data)==null?void 0:a.raw)!==void 0&&r(s.data.raw)},[(h=s.data)==null?void 0:h.raw]);const j=t.useCallback(()=>{s.refetch()},[s]),g=async()=>{m(!0),u(null),l(!1);try{await z("/api/config",{method:"PUT",body:n}),l(!0),j()}catch(a){u((a instanceof k,a.message))}finally{m(!1)}};return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsxs(o,{align:"center",justify:"between",gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"Runtime config"}),e.jsxs(o,{gap:1,children:[e.jsxs(c,{variant:"ghost",onClick:j,"data-testid":"config-runtime-reload",children:[e.jsx(M,{size:14,"aria-hidden":!0})," Reload"]}),e.jsxs(c,{variant:"primary",onClick:()=>void g(),disabled:i,"data-testid":"config-runtime-save",children:[e.jsx($,{size:14,"aria-hidden":!0})," ",i?"Saving…":"Save"]})]})]}),s.loading&&s.data===null?e.jsx(S,{style:{height:240}}):e.jsx("textarea",{value:n,rows:16,"data-testid":"config-runtime-raw",onChange:a=>r(a.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"}}),x&&e.jsx("span",{"data-testid":"config-runtime-saved",style:{color:"var(--success)",fontSize:"var(--fs-12)"},children:"Saved"}),f!==null&&e.jsx("span",{role:"alert","data-testid":"config-runtime-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:f})]})})})}function U(){const s=y("/api/config/providers"),[n,r]=t.useState(!1),[i,m]=t.useState(null),[x,l]=t.useState(null),[f,u]=t.useState(null),j=t.useCallback(()=>{s.refetch()},[s]),g=t.useMemo(()=>{var a;return((a=s.data)==null?void 0:a.providers)??[]},[s.data]),h=async a=>{u(null);try{await z(`/api/config/providers/${a}`,{method:"DELETE"}),l(null),j()}catch(p){u((p instanceof k,p.message))}};return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsxs(o,{align:"center",justify:"between",gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"Providers"}),e.jsxs(o,{gap:1,children:[f!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:f}),e.jsxs(c,{variant:"primary",onClick:()=>r(!0),"data-testid":"config-providers-add",children:[e.jsx(T,{size:14,"aria-hidden":!0})," Add"]})]})]}),s.loading&&g.length===0?e.jsx(S,{style:{height:100}}):g.length===0?e.jsx(E,{icon:e.jsx(w,{size:28,"aria-hidden":!0}),title:"No providers",description:"Add one or use Auto-add with key."}):e.jsx(v,{gap:1,children:g.map(a=>{const p=x===a.id;return e.jsxs("div",{"data-testid":`config-provider-row-${a.id}`,style:{padding:"var(--space-2)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)"},children:[e.jsxs(o,{align:"center",justify:"between",gap:2,children:[e.jsxs(o,{align:"center",gap:2,children:[e.jsx("strong",{children:a.name||a.id}),a.groupId&&e.jsxs("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:["group=",a.groupId]})]}),e.jsxs(o,{gap:1,children:[e.jsx(c,{variant:"ghost",onClick:()=>m(a.id),"data-testid":`config-provider-edit-${a.id}`,"aria-label":`Edit ${a.id}`,children:e.jsx(A,{size:14,"aria-hidden":!0})}),e.jsx(c,{variant:"ghost",onClick:()=>l(d=>d===a.id?null:a.id),"data-testid":`config-provider-delete-${a.id}`,"aria-label":`Delete ${a.id}`,children:e.jsx(B,{size:14,"aria-hidden":!0})})]})]}),p&&e.jsxs(o,{gap:1,style:{marginTop:"var(--space-1)"},children:[e.jsx(c,{variant:"danger",onClick:()=>void h(a.id),"data-testid":`config-provider-confirm-delete-${a.id}`,children:"Confirm delete"}),e.jsx(c,{variant:"ghost",onClick:()=>l(null),children:"Cancel"})]})]},a.id)})})]})})})}function V(){const s=y("/api/config/mcps"),n=t.useMemo(()=>{var i;return((i=s.data)==null?void 0:i.mcps)??[]},[s.data]),r=t.useCallback(()=>{s.refetch()},[s]);return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsx(o,{align:"center",justify:"between",gap:2,children:e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"MCP servers"})}),s.loading&&n.length===0?e.jsx(S,{style:{height:60}}):n.length===0?e.jsx(E,{icon:e.jsx(R,{size:28,"aria-hidden":!0}),title:"No MCPs",description:"Add one via /api/config/mcps."}):e.jsx(v,{gap:1,children:n.map(i=>e.jsxs("div",{"data-testid":`config-mcp-row-${i.id}`,style:{padding:"var(--space-2)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)",display:"flex",justifyContent:"space-between"},children:[e.jsx("strong",{children:i.name||i.id}),i.command&&e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:i.command})]},i.id))}),e.jsxs(c,{variant:"ghost",onClick:r,"data-testid":"config-mcps-refresh",children:[e.jsx(M,{size:14,"aria-hidden":!0})," Refresh"]})]})})})}function H(){const s=y("/api/llm/system-llm"),[n,r]=t.useState(!1),[i,m]=t.useState(""),[x,l]=t.useState(""),[f,u]=t.useState(!1),[j,g]=t.useState(!1),[h,a]=t.useState(null);t.useEffect(()=>{s.data&&(r(s.data.enabled),m(s.data.provider??""),l(s.data.model??""))},[s.data]);const p=async()=>{u(!0),a(null),g(!1);try{await z("/api/llm/system-llm",{method:"PUT",body:{enabled:n,provider:i,model:x}}),g(!0),s.refetch()}catch(d){a((d instanceof k,d.message))}finally{u(!1)}};return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"System LLM"}),s.loading&&s.data===null?e.jsx(S,{style:{height:100}}):e.jsxs(v,{gap:2,children:[e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:"var(--space-2)"},children:[e.jsx("input",{type:"checkbox",checked:n,"data-testid":"config-system-llm-enabled",onChange:d=>r(d.target.checked)}),e.jsx("span",{style:{fontSize:"var(--fs-13)"},children:"Enabled"})]}),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:"Provider"}),e.jsx(P,{value:i,"data-testid":"config-system-llm-provider",onChange:d=>m(d.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:"Model"}),e.jsx(P,{value:x,"data-testid":"config-system-llm-model",onChange:d=>l(d.target.value)})]}),e.jsx(o,{justify:"end",gap:2,children:e.jsxs(c,{variant:"primary",onClick:()=>void p(),disabled:f,"data-testid":"config-system-llm-save",children:[e.jsx($,{size:14,"aria-hidden":!0})," ",f?"Saving…":"Save"]})}),j&&e.jsx("span",{"data-testid":"config-system-llm-saved",style:{color:"var(--success)",fontSize:"var(--fs-12)"},children:"Saved"}),h!==null&&e.jsx("span",{role:"alert","data-testid":"config-system-llm-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:h})]})]})})})}export{se as ConfigView};
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigView-BntUrW7s.js","sources":["../../src/web/v8/views/Config/ConfigView.tsx"],"sourcesContent":["/**\n * v8/views/Config/ConfigView.tsx — Sprint S41, v9.3.0.\n *\n * Three sub-sections:\n * - Runtime config: read-only viewer + Reload + Save (PUT\n * /api/config with the edited raw JSON).\n * - Providers: full CRUD via /api/config/providers + the\n * \"add with key\" auto endpoint.\n * - MCPs: full CRUD via /api/config/mcps.\n * - System LLM: read/write the cline.json#systemLlm block via\n * /api/llm/system-llm.\n *\n * Inline confirm for delete. Sheet form for Add / Edit.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Plus, Pencil, Trash2, RefreshCcw, Save, ServerCog, Cpu, Plug, Settings as SettingsIcon } from 'lucide-react';\nimport type { LucideIcon } 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 { 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 Provider {\n id: string;\n name?: string;\n groupId?: string;\n}\n\ninterface Mcp {\n id: string;\n name?: string;\n command?: string;\n}\n\ninterface SystemLlm {\n enabled: boolean;\n provider: string | null;\n model: string | null;\n}\n\ninterface RuntimeConfig {\n path: string;\n data: unknown;\n raw: string;\n exists: boolean;\n}\n\ntype SectionId = 'runtime' | 'providers' | 'mcps' | 'system-llm';\n\nconst SECTIONS: Array<{ id: SectionId; label: string; icon: LucideIcon }> = [\n { id: 'runtime', label: 'Runtime config', icon: SettingsIcon },\n { id: 'providers', label: 'Providers', icon: Cpu },\n { id: 'mcps', label: 'MCPs', icon: Plug },\n { id: 'system-llm', label: 'System LLM', icon: ServerCog },\n];\n\nexport function ConfigView(): JSX.Element {\n const [section, setSection] = useState<SectionId>('runtime');\n return (\n <Stack gap={4} data-testid=\"config-view\">\n <ViewHeader\n title=\"Config\"\n description=\"Runtime config + providers + MCPs + system LLM.\"\n />\n <Inline gap={1} role=\"tablist\">\n {SECTIONS.map((s) => (\n <button\n key={s.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={section === s.id}\n onClick={() => setSection(s.id)}\n data-testid={`config-tab-${s.id}`}\n style={{\n padding: 'var(--space-2) var(--space-3)',\n borderRadius: 'var(--radius-md)',\n border: '1px solid var(--border)',\n background: section === s.id ? 'color-mix(in oklch, var(--accent) 14%, transparent)' : 'var(--surface-0)',\n color: section === s.id ? 'var(--accent)' : 'var(--fg-muted)',\n fontSize: 'var(--fs-12)',\n cursor: 'pointer',\n }}\n >\n <s.icon size={14} aria-hidden style={{ verticalAlign: 'middle', marginRight: 6 }} />\n {s.label}\n </button>\n ))}\n </Inline>\n {section === 'runtime' && <RuntimeConfigPanel />}\n {section === 'providers' && <ProvidersPanel />}\n {section === 'mcps' && <McpsPanel />}\n {section === 'system-llm' && <SystemLlmPanel />}\n </Stack>\n );\n}\n\nfunction RuntimeConfigPanel(): JSX.Element {\n const payload = useFetch<RuntimeConfig>('/api/config');\n const [draft, setDraft] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [saved, setSaved] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (payload.data?.raw !== undefined) setDraft(payload.data.raw);\n }, [payload.data?.raw]);\n\n const reload = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const save = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n setSaved(false);\n try {\n await fetchJson('/api/config', { method: 'PUT', body: draft });\n setSaved(true);\n reload();\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 <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Runtime config</strong>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={reload} data-testid=\"config-runtime-reload\">\n <RefreshCcw size={14} aria-hidden /> Reload\n </Button>\n <Button variant=\"primary\" onClick={() => void save()} disabled={busy} data-testid=\"config-runtime-save\">\n <Save size={14} aria-hidden /> {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n </Inline>\n {payload.loading && payload.data === null ? (\n <Skeleton style={{ height: 240 }} />\n ) : (\n <textarea\n value={draft}\n rows={16}\n data-testid=\"config-runtime-raw\"\n onChange={(e) => setDraft((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 )}\n {saved && <span data-testid=\"config-runtime-saved\" style={{ color: 'var(--success)', fontSize: 'var(--fs-12)' }}>Saved</span>}\n {error !== null && (\n <span role=\"alert\" data-testid=\"config-runtime-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction ProvidersPanel(): JSX.Element {\n const payload = useFetch<{ providers: Provider[] }>('/api/config/providers');\n const [adding, setAdding] = useState<boolean>(false);\n const [editing, setEditing] = useState<string | null>(null);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n const providers = useMemo(() => payload.data?.providers ?? [], [payload.data]);\n\n const drop = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/config/providers/${id}`, { 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 <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Providers</strong>\n <Inline gap={1}>\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Button variant=\"primary\" onClick={() => setAdding(true)} data-testid=\"config-providers-add\">\n <Plus size={14} aria-hidden /> Add\n </Button>\n </Inline>\n </Inline>\n {payload.loading && providers.length === 0 ? (\n <Skeleton style={{ height: 100 }} />\n ) : providers.length === 0 ? (\n <EmptyState icon={<Cpu size={28} aria-hidden />} title=\"No providers\" description=\"Add one or use Auto-add with key.\" />\n ) : (\n <Stack gap={1}>\n {providers.map((p) => {\n const isConfirming = confirmDelete === p.id;\n return (\n <div key={p.id} data-testid={`config-provider-row-${p.id}`} style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)' }}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Inline align=\"center\" gap={2}>\n <strong>{p.name || p.id}</strong>\n {p.groupId && <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>group={p.groupId}</span>}\n </Inline>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={() => setEditing(p.id)} data-testid={`config-provider-edit-${p.id}`} aria-label={`Edit ${p.id}`}>\n <Pencil size={14} aria-hidden />\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete((cur) => (cur === p.id ? null : p.id))} data-testid={`config-provider-delete-${p.id}`} aria-label={`Delete ${p.id}`}>\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(p.id)} data-testid={`config-provider-confirm-delete-${p.id}`}>Confirm delete</Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)}>Cancel</Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction McpsPanel(): JSX.Element {\n const payload = useFetch<{ mcps: Mcp[] }>('/api/config/mcps');\n const mcps = useMemo(() => payload.data?.mcps ?? [], [payload.data]);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>MCP servers</strong>\n </Inline>\n {payload.loading && mcps.length === 0 ? (\n <Skeleton style={{ height: 60 }} />\n ) : mcps.length === 0 ? (\n <EmptyState icon={<Plug size={28} aria-hidden />} title=\"No MCPs\" description=\"Add one via /api/config/mcps.\" />\n ) : (\n <Stack gap={1}>\n {mcps.map((m) => (\n <div key={m.id} data-testid={`config-mcp-row-${m.id}`} style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)', display: 'flex', justifyContent: 'space-between' }}>\n <strong>{m.name || m.id}</strong>\n {m.command && <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{m.command}</code>}\n </div>\n ))}\n </Stack>\n )}\n <Button variant=\"ghost\" onClick={refresh} data-testid=\"config-mcps-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction SystemLlmPanel(): JSX.Element {\n const payload = useFetch<SystemLlm>('/api/llm/system-llm');\n const [enabled, setEnabled] = useState<boolean>(false);\n const [provider, setProvider] = useState<string>('');\n const [model, setModel] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [saved, setSaved] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (payload.data) {\n setEnabled(payload.data.enabled);\n setProvider(payload.data.provider ?? '');\n setModel(payload.data.model ?? '');\n }\n }, [payload.data]);\n\n const save = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n setSaved(false);\n try {\n await fetchJson('/api/llm/system-llm', {\n method: 'PUT',\n body: { enabled, provider, model },\n });\n setSaved(true);\n void payload.refetch();\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 <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>System LLM</strong>\n {payload.loading && payload.data === null ? (\n <Skeleton style={{ height: 100 }} />\n ) : (\n <Stack gap={2}>\n <label style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-2)' }}>\n <input\n type=\"checkbox\"\n checked={enabled}\n data-testid=\"config-system-llm-enabled\"\n onChange={(e) => setEnabled((e.target as HTMLInputElement).checked)}\n />\n <span style={{ fontSize: 'var(--fs-13)' }}>Enabled</span>\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Provider</span>\n <Input value={provider} data-testid=\"config-system-llm-provider\" onChange={(e) => setProvider((e.target as HTMLInputElement).value)} />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Model</span>\n <Input value={model} data-testid=\"config-system-llm-model\" onChange={(e) => setModel((e.target as HTMLInputElement).value)} />\n </label>\n <Inline justify=\"end\" gap={2}>\n <Button variant=\"primary\" onClick={() => void save()} disabled={busy} data-testid=\"config-system-llm-save\">\n <Save size={14} aria-hidden /> {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n {saved && <span data-testid=\"config-system-llm-saved\" style={{ color: 'var(--success)', fontSize: 'var(--fs-12)' }}>Saved</span>}\n {error !== null && (\n <span role=\"alert\" data-testid=\"config-system-llm-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}"],"names":["SECTIONS","SettingsIcon","Cpu","Plug","ServerCog","ConfigView","section","setSection","useState","jsxs","Stack","jsx","ViewHeader","Inline","s","RuntimeConfigPanel","ProvidersPanel","McpsPanel","SystemLlmPanel","payload","useFetch","draft","setDraft","busy","setBusy","saved","setSaved","error","setError","useEffect","_a","reload","useCallback","save","fetchJson","err","FetchError","Card","CardBody","Button","RefreshCcw","Save","Skeleton","e","adding","setAdding","editing","setEditing","confirmDelete","setConfirmDelete","refresh","providers","useMemo","drop","id","Plus","EmptyState","p","isConfirming","Pencil","cur","Trash2","mcps","m","enabled","setEnabled","provider","setProvider","model","setModel","Input"],"mappings":"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"}
1
+ {"version":3,"file":"ConfigView-DfTJk1uL.js","sources":["../../src/web/v8/views/Config/ConfigView.tsx"],"sourcesContent":["/**\n * v8/views/Config/ConfigView.tsx — Sprint S41, v9.3.0.\n *\n * Three sub-sections:\n * - Runtime config: read-only viewer + Reload + Save (PUT\n * /api/config with the edited raw JSON).\n * - Providers: full CRUD via /api/config/providers + the\n * \"add with key\" auto endpoint.\n * - MCPs: full CRUD via /api/config/mcps.\n * - System LLM: read/write the cline.json#systemLlm block via\n * /api/llm/system-llm.\n *\n * Inline confirm for delete. Sheet form for Add / Edit.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Plus, Pencil, Trash2, RefreshCcw, Save, ServerCog, Cpu, Plug, Settings as SettingsIcon } from 'lucide-react';\nimport type { LucideIcon } 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 { 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 Provider {\n id: string;\n name?: string;\n groupId?: string;\n}\n\ninterface Mcp {\n id: string;\n name?: string;\n command?: string;\n}\n\ninterface SystemLlm {\n enabled: boolean;\n provider: string | null;\n model: string | null;\n}\n\ninterface RuntimeConfig {\n path: string;\n data: unknown;\n raw: string;\n exists: boolean;\n}\n\ntype SectionId = 'runtime' | 'providers' | 'mcps' | 'system-llm';\n\nconst SECTIONS: Array<{ id: SectionId; label: string; icon: LucideIcon }> = [\n { id: 'runtime', label: 'Runtime config', icon: SettingsIcon },\n { id: 'providers', label: 'Providers', icon: Cpu },\n { id: 'mcps', label: 'MCPs', icon: Plug },\n { id: 'system-llm', label: 'System LLM', icon: ServerCog },\n];\n\nexport function ConfigView(): JSX.Element {\n const [section, setSection] = useState<SectionId>('runtime');\n return (\n <Stack gap={4} data-testid=\"config-view\">\n <ViewHeader\n title=\"Config\"\n description=\"Runtime config + providers + MCPs + system LLM.\"\n />\n <Inline gap={1} role=\"tablist\">\n {SECTIONS.map((s) => (\n <button\n key={s.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={section === s.id}\n onClick={() => setSection(s.id)}\n data-testid={`config-tab-${s.id}`}\n style={{\n padding: 'var(--space-2) var(--space-3)',\n borderRadius: 'var(--radius-md)',\n border: '1px solid var(--border)',\n background: section === s.id ? 'color-mix(in oklch, var(--accent) 14%, transparent)' : 'var(--surface-0)',\n color: section === s.id ? 'var(--accent)' : 'var(--fg-muted)',\n fontSize: 'var(--fs-12)',\n cursor: 'pointer',\n }}\n >\n <s.icon size={14} aria-hidden style={{ verticalAlign: 'middle', marginRight: 6 }} />\n {s.label}\n </button>\n ))}\n </Inline>\n {section === 'runtime' && <RuntimeConfigPanel />}\n {section === 'providers' && <ProvidersPanel />}\n {section === 'mcps' && <McpsPanel />}\n {section === 'system-llm' && <SystemLlmPanel />}\n </Stack>\n );\n}\n\nfunction RuntimeConfigPanel(): JSX.Element {\n const payload = useFetch<RuntimeConfig>('/api/config');\n const [draft, setDraft] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [saved, setSaved] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (payload.data?.raw !== undefined) setDraft(payload.data.raw);\n }, [payload.data?.raw]);\n\n const reload = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const save = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n setSaved(false);\n try {\n await fetchJson('/api/config', { method: 'PUT', body: draft });\n setSaved(true);\n reload();\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 <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Runtime config</strong>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={reload} data-testid=\"config-runtime-reload\">\n <RefreshCcw size={14} aria-hidden /> Reload\n </Button>\n <Button variant=\"primary\" onClick={() => void save()} disabled={busy} data-testid=\"config-runtime-save\">\n <Save size={14} aria-hidden /> {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n </Inline>\n {payload.loading && payload.data === null ? (\n <Skeleton style={{ height: 240 }} />\n ) : (\n <textarea\n value={draft}\n rows={16}\n data-testid=\"config-runtime-raw\"\n onChange={(e) => setDraft((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 )}\n {saved && <span data-testid=\"config-runtime-saved\" style={{ color: 'var(--success)', fontSize: 'var(--fs-12)' }}>Saved</span>}\n {error !== null && (\n <span role=\"alert\" data-testid=\"config-runtime-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction ProvidersPanel(): JSX.Element {\n const payload = useFetch<{ providers: Provider[] }>('/api/config/providers');\n const [adding, setAdding] = useState<boolean>(false);\n const [editing, setEditing] = useState<string | null>(null);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n const providers = useMemo(() => payload.data?.providers ?? [], [payload.data]);\n\n const drop = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/config/providers/${id}`, { 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 <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Providers</strong>\n <Inline gap={1}>\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Button variant=\"primary\" onClick={() => setAdding(true)} data-testid=\"config-providers-add\">\n <Plus size={14} aria-hidden /> Add\n </Button>\n </Inline>\n </Inline>\n {payload.loading && providers.length === 0 ? (\n <Skeleton style={{ height: 100 }} />\n ) : providers.length === 0 ? (\n <EmptyState icon={<Cpu size={28} aria-hidden />} title=\"No providers\" description=\"Add one or use Auto-add with key.\" />\n ) : (\n <Stack gap={1}>\n {providers.map((p) => {\n const isConfirming = confirmDelete === p.id;\n return (\n <div key={p.id} data-testid={`config-provider-row-${p.id}`} style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)' }}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Inline align=\"center\" gap={2}>\n <strong>{p.name || p.id}</strong>\n {p.groupId && <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>group={p.groupId}</span>}\n </Inline>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={() => setEditing(p.id)} data-testid={`config-provider-edit-${p.id}`} aria-label={`Edit ${p.id}`}>\n <Pencil size={14} aria-hidden />\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete((cur) => (cur === p.id ? null : p.id))} data-testid={`config-provider-delete-${p.id}`} aria-label={`Delete ${p.id}`}>\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(p.id)} data-testid={`config-provider-confirm-delete-${p.id}`}>Confirm delete</Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)}>Cancel</Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction McpsPanel(): JSX.Element {\n const payload = useFetch<{ mcps: Mcp[] }>('/api/config/mcps');\n const mcps = useMemo(() => payload.data?.mcps ?? [], [payload.data]);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>MCP servers</strong>\n </Inline>\n {payload.loading && mcps.length === 0 ? (\n <Skeleton style={{ height: 60 }} />\n ) : mcps.length === 0 ? (\n <EmptyState icon={<Plug size={28} aria-hidden />} title=\"No MCPs\" description=\"Add one via /api/config/mcps.\" />\n ) : (\n <Stack gap={1}>\n {mcps.map((m) => (\n <div key={m.id} data-testid={`config-mcp-row-${m.id}`} style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)', display: 'flex', justifyContent: 'space-between' }}>\n <strong>{m.name || m.id}</strong>\n {m.command && <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{m.command}</code>}\n </div>\n ))}\n </Stack>\n )}\n <Button variant=\"ghost\" onClick={refresh} data-testid=\"config-mcps-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction SystemLlmPanel(): JSX.Element {\n const payload = useFetch<SystemLlm>('/api/llm/system-llm');\n const [enabled, setEnabled] = useState<boolean>(false);\n const [provider, setProvider] = useState<string>('');\n const [model, setModel] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [saved, setSaved] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (payload.data) {\n setEnabled(payload.data.enabled);\n setProvider(payload.data.provider ?? '');\n setModel(payload.data.model ?? '');\n }\n }, [payload.data]);\n\n const save = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n setSaved(false);\n try {\n await fetchJson('/api/llm/system-llm', {\n method: 'PUT',\n body: { enabled, provider, model },\n });\n setSaved(true);\n void payload.refetch();\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 <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>System LLM</strong>\n {payload.loading && payload.data === null ? (\n <Skeleton style={{ height: 100 }} />\n ) : (\n <Stack gap={2}>\n <label style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-2)' }}>\n <input\n type=\"checkbox\"\n checked={enabled}\n data-testid=\"config-system-llm-enabled\"\n onChange={(e) => setEnabled((e.target as HTMLInputElement).checked)}\n />\n <span style={{ fontSize: 'var(--fs-13)' }}>Enabled</span>\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Provider</span>\n <Input value={provider} data-testid=\"config-system-llm-provider\" onChange={(e) => setProvider((e.target as HTMLInputElement).value)} />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Model</span>\n <Input value={model} data-testid=\"config-system-llm-model\" onChange={(e) => setModel((e.target as HTMLInputElement).value)} />\n </label>\n <Inline justify=\"end\" gap={2}>\n <Button variant=\"primary\" onClick={() => void save()} disabled={busy} data-testid=\"config-system-llm-save\">\n <Save size={14} aria-hidden /> {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n {saved && <span data-testid=\"config-system-llm-saved\" style={{ color: 'var(--success)', fontSize: 'var(--fs-12)' }}>Saved</span>}\n {error !== null && (\n <span role=\"alert\" data-testid=\"config-system-llm-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}"],"names":["SECTIONS","SettingsIcon","Cpu","Plug","ServerCog","ConfigView","section","setSection","useState","jsxs","Stack","jsx","ViewHeader","Inline","s","RuntimeConfigPanel","ProvidersPanel","McpsPanel","SystemLlmPanel","payload","useFetch","draft","setDraft","busy","setBusy","saved","setSaved","error","setError","useEffect","_a","reload","useCallback","save","fetchJson","err","FetchError","Card","CardBody","Button","RefreshCcw","Save","Skeleton","e","adding","setAdding","editing","setEditing","confirmDelete","setConfirmDelete","refresh","providers","useMemo","drop","id","Plus","EmptyState","p","isConfirming","Pencil","cur","Trash2","mcps","m","enabled","setEnabled","provider","setProvider","model","setModel","Input"],"mappings":"qjBAyDA,MAAMA,EAAsE,CAC1E,CAAE,GAAI,UAAW,MAAO,iBAAkB,KAAMC,CAAA,EAChD,CAAE,GAAI,YAAa,MAAO,YAAa,KAAMC,CAAA,EAC7C,CAAE,GAAI,OAAQ,MAAO,OAAQ,KAAMC,CAAA,EACnC,CAAE,GAAI,aAAc,MAAO,aAAc,KAAMC,CAAA,CACjD,EAEO,SAASC,IAA0B,CACxC,KAAM,CAACC,EAASC,CAAU,EAAIC,EAAAA,SAAoB,SAAS,EAC3D,OACEC,EAAAA,KAACC,EAAA,CAAM,IAAK,EAAG,cAAY,cACzB,SAAA,CAAAC,EAAAA,IAACC,EAAA,CACC,MAAM,SACN,YAAY,iDAAA,CAAA,EAEdD,EAAAA,IAACE,GAAO,IAAK,EAAG,KAAK,UAClB,SAAAb,EAAS,IAAKc,GACbL,EAAAA,KAAC,SAAA,CAEC,KAAK,SACL,KAAK,MACL,gBAAeH,IAAYQ,EAAE,GAC7B,QAAS,IAAMP,EAAWO,EAAE,EAAE,EAC9B,cAAa,cAAcA,EAAE,EAAE,GAC/B,MAAO,CACL,QAAS,gCACT,aAAc,mBACd,OAAQ,0BACR,WAAYR,IAAYQ,EAAE,GAAK,sDAAwD,mBACvF,MAAOR,IAAYQ,EAAE,GAAK,gBAAkB,kBAC5C,SAAU,eACV,OAAQ,SAAA,EAGV,SAAA,CAAAH,EAAAA,IAACG,EAAE,KAAF,CAAO,KAAM,GAAI,cAAW,GAAC,MAAO,CAAE,cAAe,SAAU,YAAa,EAAE,CAAG,EACjFA,EAAE,KAAA,CAAA,EAjBEA,EAAE,EAAA,CAmBV,EACH,EACCR,IAAY,WAAaK,MAACI,EAAA,CAAA,CAAmB,EAC7CT,IAAY,aAAeK,MAACK,EAAA,CAAA,CAAe,EAC3CV,IAAY,QAAUK,MAACM,EAAA,CAAA,CAAU,EACjCX,IAAY,cAAgBK,MAACO,EAAA,CAAA,CAAe,CAAA,EAC/C,CAEJ,CAEA,SAASH,GAAkC,OACzC,MAAMI,EAAUC,EAAwB,aAAa,EAC/C,CAACC,EAAOC,CAAQ,EAAId,EAAAA,SAAiB,EAAE,EACvC,CAACe,EAAMC,CAAO,EAAIhB,EAAAA,SAAkB,EAAK,EACzC,CAACiB,EAAOC,CAAQ,EAAIlB,EAAAA,SAAkB,EAAK,EAC3C,CAACmB,EAAOC,CAAQ,EAAIpB,EAAAA,SAAwB,IAAI,EAEtDqB,EAAAA,UAAU,IAAM,SACVC,EAAAX,EAAQ,OAAR,YAAAW,EAAc,OAAQ,QAAWR,EAASH,EAAQ,KAAK,GAAG,CAChE,EAAG,EAACW,EAAAX,EAAQ,OAAR,YAAAW,EAAc,GAAG,CAAC,EAEtB,MAAMC,EAASC,EAAAA,YAAY,IAAM,CAAOb,EAAQ,QAAA,CAAW,EAAG,CAACA,CAAO,CAAC,EAEjEc,EAAO,SAA2B,CACtCT,EAAQ,EAAI,EACZI,EAAS,IAAI,EACbF,EAAS,EAAK,EACd,GAAI,CACF,MAAMQ,EAAU,cAAe,CAAE,OAAQ,MAAO,KAAMb,EAAO,EAC7DK,EAAS,EAAI,EACbK,EAAA,CACF,OAASI,EAAK,CACZP,GAASO,aAAeC,EAAaD,EAAI,QAAgC,CAC3E,QAAA,CACEX,EAAQ,EAAK,CACf,CACF,EAEA,OACEb,EAAAA,IAAC0B,GAAK,QAAQ,UACZ,eAACC,EAAA,CACC,SAAA7B,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAD,OAACI,GAAO,MAAM,SAAS,QAAQ,UAAU,IAAK,EAC5C,SAAA,CAAAF,MAAC,UAAO,MAAO,CAAE,SAAU,cAAA,EAAkB,SAAA,iBAAc,EAC3DF,EAAAA,KAACI,EAAA,CAAO,IAAK,EACX,SAAA,CAAAJ,OAAC8B,GAAO,QAAQ,QAAQ,QAASR,EAAQ,cAAY,wBACnD,SAAA,CAAApB,EAAAA,IAAC6B,EAAA,CAAW,KAAM,GAAI,cAAW,GAAC,EAAE,SAAA,EACtC,EACA/B,EAAAA,KAAC8B,EAAA,CAAO,QAAQ,UAAU,QAAS,IAAM,KAAKN,EAAA,EAAQ,SAAUV,EAAM,cAAY,sBAChF,SAAA,CAAAZ,EAAAA,IAAC8B,EAAA,CAAK,KAAM,GAAI,cAAW,GAAC,EAAE,IAAElB,EAAO,UAAY,MAAA,CAAA,CACrD,CAAA,CAAA,CACF,CAAA,EACF,EACCJ,EAAQ,SAAWA,EAAQ,OAAS,KACnCR,EAAAA,IAAC+B,EAAA,CAAS,MAAO,CAAE,OAAQ,GAAA,CAAI,CAAG,EAElC/B,EAAAA,IAAC,WAAA,CACC,MAAOU,EACP,KAAM,GACN,cAAY,qBACZ,SAAWsB,GAAMrB,EAAUqB,EAAE,OAA+B,KAAK,EACjE,MAAO,CACL,WAAY,mBACZ,OAAQ,0BACR,aAAc,mBACd,QAAS,iBACT,MAAO,YACP,WAAY,mBACZ,SAAU,eACV,OAAQ,UAAA,CACV,CAAA,EAGHlB,GAASd,EAAAA,IAAC,OAAA,CAAK,cAAY,uBAAuB,MAAO,CAAE,MAAO,iBAAkB,SAAU,cAAA,EAAkB,SAAA,OAAA,CAAK,EACrHgB,IAAU,MACThB,MAAC,OAAA,CAAK,KAAK,QAAQ,cAAY,uBAAuB,MAAO,CAAE,MAAO,gBAAiB,SAAU,cAAA,EAAmB,SAAAgB,CAAA,CAAM,CAAA,CAAA,CAE9H,EACF,EACF,CAEJ,CAEA,SAASX,GAA8B,CACrC,MAAMG,EAAUC,EAAoC,uBAAuB,EACrE,CAACwB,EAAQC,CAAS,EAAIrC,EAAAA,SAAkB,EAAK,EAC7C,CAACsC,EAASC,CAAU,EAAIvC,EAAAA,SAAwB,IAAI,EACpD,CAACwC,EAAeC,CAAgB,EAAIzC,EAAAA,SAAwB,IAAI,EAChE,CAACmB,EAAOC,CAAQ,EAAIpB,EAAAA,SAAwB,IAAI,EAChD0C,EAAUlB,EAAAA,YAAY,IAAM,CAAOb,EAAQ,QAAA,CAAW,EAAG,CAACA,CAAO,CAAC,EAClEgC,EAAYC,UAAQ,IAAA,OAAM,QAAAtB,EAAAX,EAAQ,OAAR,YAAAW,EAAc,YAAa,IAAI,CAACX,EAAQ,IAAI,CAAC,EAEvEkC,EAAO,MAAOC,GAA8B,CAChD1B,EAAS,IAAI,EACb,GAAI,CACF,MAAMM,EAAU,yBAAyBoB,CAAE,GAAI,CAAE,OAAQ,SAAU,EACnEL,EAAiB,IAAI,EACrBC,EAAA,CACF,OAASf,EAAK,CACZP,GAASO,aAAeC,EAAaD,EAAI,QAAgC,CAC3E,CACF,EAEA,OACExB,EAAAA,IAAC0B,GAAK,QAAQ,UACZ,eAACC,EAAA,CACC,SAAA7B,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAD,OAACI,GAAO,MAAM,SAAS,QAAQ,UAAU,IAAK,EAC5C,SAAA,CAAAF,MAAC,UAAO,MAAO,CAAE,SAAU,cAAA,EAAkB,SAAA,YAAS,EACtDF,EAAAA,KAACI,EAAA,CAAO,IAAK,EACV,SAAA,CAAAc,IAAU,MACThB,EAAAA,IAAC,OAAA,CAAK,KAAK,QAAQ,MAAO,CAAE,MAAO,gBAAiB,SAAU,cAAA,EAAmB,SAAAgB,EAAM,EAEzFlB,EAAAA,KAAC8B,EAAA,CAAO,QAAQ,UAAU,QAAS,IAAMM,EAAU,EAAI,EAAG,cAAY,uBACpE,SAAA,CAAAlC,EAAAA,IAAC4C,EAAA,CAAK,KAAM,GAAI,cAAW,GAAC,EAAE,MAAA,CAAA,CAChC,CAAA,CAAA,CACF,CAAA,EACF,EACCpC,EAAQ,SAAWgC,EAAU,SAAW,QACtCT,EAAA,CAAS,MAAO,CAAE,OAAQ,IAAI,CAAG,EAChCS,EAAU,SAAW,QACtBK,EAAA,CAAW,KAAM7C,EAAAA,IAACT,EAAA,CAAI,KAAM,GAAI,cAAW,EAAA,CAAC,EAAI,MAAM,eAAe,YAAY,mCAAA,CAAoC,QAErHQ,EAAA,CAAM,IAAK,EACT,SAAAyC,EAAU,IAAKM,GAAM,CACpB,MAAMC,EAAeV,IAAkBS,EAAE,GACzC,OACEhD,EAAAA,KAAC,MAAA,CAAe,cAAa,uBAAuBgD,EAAE,EAAE,GAAI,MAAO,CAAE,QAAS,iBAAkB,OAAQ,0BAA2B,aAAc,oBAC/I,SAAA,CAAAhD,OAACI,GAAO,MAAM,SAAS,QAAQ,UAAU,IAAK,EAC5C,SAAA,CAAAJ,EAAAA,KAACI,EAAA,CAAO,MAAM,SAAS,IAAK,EAC1B,SAAA,CAAAF,EAAAA,IAAC,SAAA,CAAQ,SAAA8C,EAAE,MAAQA,EAAE,GAAG,EACvBA,EAAE,SAAWhD,OAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,CAAA,SAAOgD,EAAE,OAAA,CAAA,CAAQ,CAAA,EACtG,EACAhD,EAAAA,KAACI,EAAA,CAAO,IAAK,EACX,SAAA,CAAAF,EAAAA,IAAC4B,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAMQ,EAAWU,EAAE,EAAE,EAAG,cAAa,wBAAwBA,EAAE,EAAE,GAAI,aAAY,QAAQA,EAAE,EAAE,GAC5H,SAAA9C,EAAAA,IAACgD,EAAA,CAAO,KAAM,GAAI,cAAW,EAAA,CAAC,CAAA,CAChC,EACAhD,EAAAA,IAAC4B,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAMU,EAAkBW,GAASA,IAAQH,EAAE,GAAK,KAAOA,EAAE,EAAG,EAAG,cAAa,0BAA0BA,EAAE,EAAE,GAAI,aAAY,UAAUA,EAAE,EAAE,GACvK,SAAA9C,EAAAA,IAACkD,EAAA,CAAO,KAAM,GAAI,cAAW,GAAC,CAAA,CAChC,CAAA,CAAA,CACF,CAAA,EACF,EACCH,UACE7C,EAAA,CAAO,IAAK,EAAG,MAAO,CAAE,UAAW,gBAAA,EAClC,SAAA,CAAAF,EAAAA,IAAC4B,EAAA,CAAO,QAAQ,SAAS,QAAS,IAAM,KAAKc,EAAKI,EAAE,EAAE,EAAG,cAAa,kCAAkCA,EAAE,EAAE,GAAI,SAAA,iBAAc,EAC9H9C,EAAAA,IAAC4B,GAAO,QAAQ,QAAQ,QAAS,IAAMU,EAAiB,IAAI,EAAG,SAAA,QAAA,CAAM,CAAA,CAAA,CACvE,CAAA,CAAA,EAnBMQ,EAAE,EAqBZ,CAEJ,CAAC,CAAA,CACH,CAAA,CAAA,CAEJ,EACF,EACF,CAEJ,CAEA,SAASxC,GAAyB,CAChC,MAAME,EAAUC,EAA0B,kBAAkB,EACtD0C,EAAOV,UAAQ,IAAA,OAAM,QAAAtB,EAAAX,EAAQ,OAAR,YAAAW,EAAc,OAAQ,IAAI,CAACX,EAAQ,IAAI,CAAC,EAC7D+B,EAAUlB,EAAAA,YAAY,IAAM,CAAOb,EAAQ,QAAA,CAAW,EAAG,CAACA,CAAO,CAAC,EACxE,OACER,EAAAA,IAAC0B,GAAK,QAAQ,UACZ,eAACC,EAAA,CACC,SAAA7B,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAC,MAACE,EAAA,CAAO,MAAM,SAAS,QAAQ,UAAU,IAAK,EAC5C,SAAAF,EAAAA,IAAC,SAAA,CAAO,MAAO,CAAE,SAAU,cAAA,EAAkB,uBAAW,EAC1D,EACCQ,EAAQ,SAAW2C,EAAK,SAAW,EAClCnD,EAAAA,IAAC+B,EAAA,CAAS,MAAO,CAAE,OAAQ,EAAA,CAAG,CAAG,EAC/BoB,EAAK,SAAW,EAClBnD,EAAAA,IAAC6C,EAAA,CAAW,KAAM7C,EAAAA,IAACR,EAAA,CAAK,KAAM,GAAI,cAAW,EAAA,CAAC,EAAI,MAAM,UAAU,YAAY,gCAAgC,EAE9GQ,EAAAA,IAACD,EAAA,CAAM,IAAK,EACT,SAAAoD,EAAK,IAAKC,GACTtD,EAAAA,KAAC,MAAA,CAAe,cAAa,kBAAkBsD,EAAE,EAAE,GAAI,MAAO,CAAE,QAAS,iBAAkB,OAAQ,0BAA2B,aAAc,mBAAoB,QAAS,OAAQ,eAAgB,eAAA,EAC/L,SAAA,CAAApD,EAAAA,IAAC,SAAA,CAAQ,SAAAoD,EAAE,MAAQA,EAAE,GAAG,EACvBA,EAAE,SAAWpD,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAsB,SAAAoD,EAAE,OAAA,CAAQ,CAAA,CAAA,EAFtFA,EAAE,EAGZ,CACD,EACH,SAEDxB,EAAA,CAAO,QAAQ,QAAQ,QAASW,EAAS,cAAY,sBACpD,SAAA,CAAAvC,EAAAA,IAAC6B,EAAA,CAAW,KAAM,GAAI,cAAW,GAAC,EAAE,UAAA,CAAA,CACtC,CAAA,CAAA,CACF,EACF,EACF,CAEJ,CAEA,SAAStB,GAA8B,CACrC,MAAMC,EAAUC,EAAoB,qBAAqB,EACnD,CAAC4C,EAASC,CAAU,EAAIzD,EAAAA,SAAkB,EAAK,EAC/C,CAAC0D,EAAUC,CAAW,EAAI3D,EAAAA,SAAiB,EAAE,EAC7C,CAAC4D,EAAOC,CAAQ,EAAI7D,EAAAA,SAAiB,EAAE,EACvC,CAACe,EAAMC,CAAO,EAAIhB,EAAAA,SAAkB,EAAK,EACzC,CAACiB,EAAOC,CAAQ,EAAIlB,EAAAA,SAAkB,EAAK,EAC3C,CAACmB,EAAOC,CAAQ,EAAIpB,EAAAA,SAAwB,IAAI,EAEtDqB,EAAAA,UAAU,IAAM,CACVV,EAAQ,OACV8C,EAAW9C,EAAQ,KAAK,OAAO,EAC/BgD,EAAYhD,EAAQ,KAAK,UAAY,EAAE,EACvCkD,EAASlD,EAAQ,KAAK,OAAS,EAAE,EAErC,EAAG,CAACA,EAAQ,IAAI,CAAC,EAEjB,MAAMc,EAAO,SAA2B,CACtCT,EAAQ,EAAI,EACZI,EAAS,IAAI,EACbF,EAAS,EAAK,EACd,GAAI,CACF,MAAMQ,EAAU,sBAAuB,CACrC,OAAQ,MACR,KAAM,CAAE,QAAA8B,EAAS,SAAAE,EAAU,MAAAE,CAAA,CAAM,CAClC,EACD1C,EAAS,EAAI,EACRP,EAAQ,QAAA,CACf,OAASgB,EAAK,CACZP,GAASO,aAAeC,EAAaD,EAAI,QAAgC,CAC3E,QAAA,CACEX,EAAQ,EAAK,CACf,CACF,EAEA,OACEb,EAAAA,IAAC0B,GAAK,QAAQ,UACZ,eAACC,EAAA,CACC,SAAA7B,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAC,MAAC,UAAO,MAAO,CAAE,SAAU,cAAA,EAAkB,SAAA,aAAU,EACtDQ,EAAQ,SAAWA,EAAQ,OAAS,WAClCuB,EAAA,CAAS,MAAO,CAAE,OAAQ,IAAI,CAAG,EAElCjC,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAD,EAAAA,KAAC,QAAA,CAAM,MAAO,CAAE,QAAS,OAAQ,WAAY,SAAU,IAAK,gBAAA,EAC1D,SAAA,CAAAE,EAAAA,IAAC,QAAA,CACC,KAAK,WACL,QAASqD,EACT,cAAY,4BACZ,SAAWrB,GAAMsB,EAAYtB,EAAE,OAA4B,OAAO,CAAA,CAAA,QAEnE,OAAA,CAAK,MAAO,CAAE,SAAU,cAAA,EAAkB,SAAA,SAAA,CAAO,CAAA,EACpD,EACAlC,EAAAA,KAAC,QAAA,CAAM,MAAO,CAAE,QAAS,OAAQ,cAAe,SAAU,IAAK,gBAAA,EAC7D,SAAA,CAAAE,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,UAAA,CAAQ,EAC7EA,EAAAA,IAAC2D,EAAA,CAAM,MAAOJ,EAAU,cAAY,6BAA6B,SAAWvB,GAAMwB,EAAaxB,EAAE,OAA4B,KAAK,CAAA,CAAG,CAAA,EACvI,EACAlC,EAAAA,KAAC,QAAA,CAAM,MAAO,CAAE,QAAS,OAAQ,cAAe,SAAU,IAAK,gBAAA,EAC7D,SAAA,CAAAE,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,OAAA,CAAK,EAC1EA,EAAAA,IAAC2D,EAAA,CAAM,MAAOF,EAAO,cAAY,0BAA0B,SAAWzB,GAAM0B,EAAU1B,EAAE,OAA4B,KAAK,CAAA,CAAG,CAAA,EAC9H,QACC9B,EAAA,CAAO,QAAQ,MAAM,IAAK,EACzB,gBAAC0B,EAAA,CAAO,QAAQ,UAAU,QAAS,IAAM,KAAKN,EAAA,EAAQ,SAAUV,EAAM,cAAY,yBAChF,SAAA,CAAAZ,EAAAA,IAAC8B,EAAA,CAAK,KAAM,GAAI,cAAW,GAAC,EAAE,IAAElB,EAAO,UAAY,MAAA,CAAA,CACrD,CAAA,CACF,EACCE,GAASd,EAAAA,IAAC,OAAA,CAAK,cAAY,0BAA0B,MAAO,CAAE,MAAO,iBAAkB,SAAU,cAAA,EAAkB,SAAA,OAAA,CAAK,EACxHgB,IAAU,MACThB,MAAC,OAAA,CAAK,KAAK,QAAQ,cAAY,0BAA0B,MAAO,CAAE,MAAO,gBAAiB,SAAU,cAAA,EAAmB,SAAAgB,CAAA,CAAM,CAAA,CAAA,CAEjI,CAAA,CAAA,CAEJ,EACF,EACF,CAEJ"}
@@ -1,2 +1,2 @@
1
- import{r as $,j as e}from"./cmdk-C3F6LD6N.js";import{u as k,S as a,B as F,I as d,A as b,b as I,h as V}from"./main-BURAlktW.js";import{G as C}from"./Grid--WKvqu5h.js";import{V as A}from"./ViewHeader-C-t1U2cQ.js";import{C as n,b as i}from"./Card-BtsmkhJa.js";import{R}from"./refresh-cw-DwlP59en.js";import{F as D}from"./file-text-BOroDtZE.js";function E(r){if(!r||r<=0)return"—";const s=Math.floor(r/86400),l=Math.floor(r%86400/3600),o=Math.floor(r%3600/60);return s>0?`${s}d ${l}h`:l>0?`${l}h ${o}m`:`${o}m`}function N(){var g,x,j,m,u,p,v,y,S,z,w;const r=k("/api/diagnostics"),s=k("/api/diagnostics/logs?tail=200");$.useEffect(()=>{const t=setInterval(()=>{s.refetch()},1e4);return()=>clearInterval(t)},[s]);const l=(g=r.data)==null?void 0:g.uptime,o=((x=r.data)==null?void 0:x.checks)??[],h=((j=r.data)==null?void 0:j.counts)??{},c=((m=s.data)==null?void 0:m.lines)??[],f=((u=s.data)==null?void 0:u.file)??null;return e.jsxs(a,{gap:5,"data-testid":"diagnostics-view",children:[e.jsx(A,{title:"Diagnostics",description:"Live system snapshot + active log tail. Auto-refresh every 10s.",actions:e.jsxs(F,{variant:"ghost",onClick:()=>{r.refetch(),s.refetch()},"data-testid":"diagnostics-refresh",children:[e.jsx(R,{size:14,"aria-hidden":!0})," Refresh"]})}),e.jsxs(C,{cols:3,children:[e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Status"}),e.jsxs(d,{align:"center",gap:2,children:[e.jsx(b,{size:14,"aria-hidden":!0}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:r.loading?"…":r.error?"error":(v=(p=r.data)==null?void 0:p.service)!=null&&v.running?(((S=(y=r.data)==null?void 0:y.errors)==null?void 0:S.length)??0)>0?"warn":"ok":"stopped"})]})]})})}),e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Uptime"}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:r.loading?"…":E(l)})]})})}),e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Version"}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:r.loading?"…":((z=r.data)==null?void 0:z.version)??"—"})]})})})]}),r.error&&e.jsx(n,{variant:"default",style:{borderColor:"var(--danger)"},children:e.jsx(i,{children:e.jsxs(a,{gap:2,children:[e.jsxs(d,{align:"center",gap:2,children:[e.jsx(b,{size:14,"aria-hidden":!0,style:{color:"var(--danger)"}}),e.jsx("strong",{style:{color:"var(--danger)"},children:"Diagnostics fetch failed"})]}),e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:r.error.message??String(r.error)}),e.jsxs(F,{variant:"secondary",size:"sm",onClick:()=>{r.refetch()},children:[e.jsx(R,{size:12,"aria-hidden":!0})," Retry"]})]})})}),Object.keys(h).length>0&&e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:2,children:[e.jsx("strong",{children:"Counts"}),e.jsx(C,{cols:4,children:Object.entries(h).map(([t,B])=>e.jsxs(a,{gap:0,children:[e.jsx("span",{style:{fontSize:"var(--fs-11)",color:"var(--fg-muted)",textTransform:"uppercase",letterSpacing:"0.04em"},children:t}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--fs-13)"},children:String(B??"—")})]},t))})]})})}),o.length>0&&e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:2,children:[e.jsxs("strong",{children:["Checks (",o.length,")"]}),e.jsx(d,{gap:1,wrap:!0,children:o.map(t=>e.jsx(I,{tone:t.status==="ok"?"success":t.status==="warn"?"warning":"danger",children:t.name},t.name))})]})})}),e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:2,children:[e.jsxs(d,{align:"center",justify:"between",children:[e.jsxs(d,{align:"center",gap:2,children:[e.jsx(D,{size:14,"aria-hidden":!0}),e.jsx("strong",{children:"Log tail"}),f&&e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)",fontFamily:"var(--font-mono)"},children:f})]}),e.jsxs("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:[c.length," / ",((w=s.data)==null?void 0:w.total)??0," lines"]})]}),s.loading&&c.length===0?e.jsx(V,{style:{height:240}}):c.length===0?e.jsx("span",{style:{color:"var(--fg-muted)",fontSize:"var(--fs-12)"},children:"No log lines yet."}):e.jsx("pre",{"data-testid":"diagnostics-log-tail",style:{maxHeight:320,overflowY:"auto",padding:"var(--space-3)",background:"var(--surface-1)",borderRadius:"var(--radius-sm)",fontSize:"var(--fs-12)",fontFamily:"var(--font-mono)",margin:0,whiteSpace:"pre-wrap",wordBreak:"break-all"},children:c.join(`
1
+ import{r as $,j as e}from"./cmdk-C3F6LD6N.js";import{u as k,S as a,B as F,I as d,A as b,b as I,h as V}from"./main-BRmJZcHt.js";import{G as C}from"./Grid-Bojq8Sg7.js";import{V as A}from"./ViewHeader-BsnaspKw.js";import{C as n,b as i}from"./Card-Clkvh43Q.js";import{R}from"./refresh-cw-KGm5eQgv.js";import{F as D}from"./file-text-BsCrv5aP.js";function E(r){if(!r||r<=0)return"—";const s=Math.floor(r/86400),l=Math.floor(r%86400/3600),o=Math.floor(r%3600/60);return s>0?`${s}d ${l}h`:l>0?`${l}h ${o}m`:`${o}m`}function N(){var g,x,j,m,u,p,v,y,S,z,w;const r=k("/api/diagnostics"),s=k("/api/diagnostics/logs?tail=200");$.useEffect(()=>{const t=setInterval(()=>{s.refetch()},1e4);return()=>clearInterval(t)},[s]);const l=(g=r.data)==null?void 0:g.uptime,o=((x=r.data)==null?void 0:x.checks)??[],h=((j=r.data)==null?void 0:j.counts)??{},c=((m=s.data)==null?void 0:m.lines)??[],f=((u=s.data)==null?void 0:u.file)??null;return e.jsxs(a,{gap:5,"data-testid":"diagnostics-view",children:[e.jsx(A,{title:"Diagnostics",description:"Live system snapshot + active log tail. Auto-refresh every 10s.",actions:e.jsxs(F,{variant:"ghost",onClick:()=>{r.refetch(),s.refetch()},"data-testid":"diagnostics-refresh",children:[e.jsx(R,{size:14,"aria-hidden":!0})," Refresh"]})}),e.jsxs(C,{cols:3,children:[e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Status"}),e.jsxs(d,{align:"center",gap:2,children:[e.jsx(b,{size:14,"aria-hidden":!0}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:r.loading?"…":r.error?"error":(v=(p=r.data)==null?void 0:p.service)!=null&&v.running?(((S=(y=r.data)==null?void 0:y.errors)==null?void 0:S.length)??0)>0?"warn":"ok":"stopped"})]})]})})}),e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Uptime"}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:r.loading?"…":E(l)})]})})}),e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Version"}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:r.loading?"…":((z=r.data)==null?void 0:z.version)??"—"})]})})})]}),r.error&&e.jsx(n,{variant:"default",style:{borderColor:"var(--danger)"},children:e.jsx(i,{children:e.jsxs(a,{gap:2,children:[e.jsxs(d,{align:"center",gap:2,children:[e.jsx(b,{size:14,"aria-hidden":!0,style:{color:"var(--danger)"}}),e.jsx("strong",{style:{color:"var(--danger)"},children:"Diagnostics fetch failed"})]}),e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:r.error.message??String(r.error)}),e.jsxs(F,{variant:"secondary",size:"sm",onClick:()=>{r.refetch()},children:[e.jsx(R,{size:12,"aria-hidden":!0})," Retry"]})]})})}),Object.keys(h).length>0&&e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:2,children:[e.jsx("strong",{children:"Counts"}),e.jsx(C,{cols:4,children:Object.entries(h).map(([t,B])=>e.jsxs(a,{gap:0,children:[e.jsx("span",{style:{fontSize:"var(--fs-11)",color:"var(--fg-muted)",textTransform:"uppercase",letterSpacing:"0.04em"},children:t}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--fs-13)"},children:String(B??"—")})]},t))})]})})}),o.length>0&&e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:2,children:[e.jsxs("strong",{children:["Checks (",o.length,")"]}),e.jsx(d,{gap:1,wrap:!0,children:o.map(t=>e.jsx(I,{tone:t.status==="ok"?"success":t.status==="warn"?"warning":"danger",children:t.name},t.name))})]})})}),e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:2,children:[e.jsxs(d,{align:"center",justify:"between",children:[e.jsxs(d,{align:"center",gap:2,children:[e.jsx(D,{size:14,"aria-hidden":!0}),e.jsx("strong",{children:"Log tail"}),f&&e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)",fontFamily:"var(--font-mono)"},children:f})]}),e.jsxs("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:[c.length," / ",((w=s.data)==null?void 0:w.total)??0," lines"]})]}),s.loading&&c.length===0?e.jsx(V,{style:{height:240}}):c.length===0?e.jsx("span",{style:{color:"var(--fg-muted)",fontSize:"var(--fs-12)"},children:"No log lines yet."}):e.jsx("pre",{"data-testid":"diagnostics-log-tail",style:{maxHeight:320,overflowY:"auto",padding:"var(--space-3)",background:"var(--surface-1)",borderRadius:"var(--radius-sm)",fontSize:"var(--fs-12)",fontFamily:"var(--font-mono)",margin:0,whiteSpace:"pre-wrap",wordBreak:"break-all"},children:c.join(`
2
2
  `)})]})})})]})}export{N as DiagnosticsView};
@@ -1 +1 @@
1
- {"version":3,"file":"DiagnosticsView-4x0Zu3yP.js","sources":["../../src/web/v8/views/Diagnostics/DiagnosticsView.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { Activity, RefreshCw, FileText } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { Grid } from '../../ui/primitives/Grid.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 { useFetch } from '../../data/useFetch.js';\n\n/**\n * DiagnosticsView — Sprint S35. System snapshot + active log tail.\n */\n\ninterface DiagnosticsHealth {\n status: string;\n checks?: Array<{ name: string; status: string; message?: string }>;\n}\n\ninterface DiagnosticsSnapshot {\n version?: string;\n uptime?: number;\n memory?: { rss?: number; heapUsed?: number; heapTotal?: number };\n checks?: Array<{ name: string; status: string; message?: string }>;\n counts?: Record<string, number | string | null>;\n errors?: Array<{ line: string; ts: string | null }>;\n service?: { running?: boolean; pid?: number };\n}\n\ninterface LogsResponse {\n lines: string[];\n file: string | null;\n total: number;\n}\n\nfunction fmtUptime(secs: number | undefined): string {\n if (!secs || secs <= 0) return '—';\n const days = Math.floor(secs / 86400);\n const hours = Math.floor((secs % 86400) / 3600);\n const mins = Math.floor((secs % 3600) / 60);\n if (days > 0) return `${days}d ${hours}h`;\n if (hours > 0) return `${hours}h ${mins}m`;\n return `${mins}m`;\n}\n\nexport function DiagnosticsView(): JSX.Element {\n const snap = useFetch<DiagnosticsSnapshot>('/api/diagnostics');\n const logs = useFetch<LogsResponse>('/api/diagnostics/logs?tail=200');\n\n // Auto-refresh logs every 10s while page is open.\n useEffect(() => {\n const id = setInterval(() => { void logs.refetch(); }, 10_000);\n return () => clearInterval(id);\n }, [logs]);\n\n const uptime = snap.data?.uptime;\n const checks = snap.data?.checks ?? [];\n const counts = snap.data?.counts ?? {};\n const lines = logs.data?.lines ?? [];\n const logFile = logs.data?.file ?? null;\n\n return (\n <Stack gap={5} data-testid=\"diagnostics-view\">\n <ViewHeader\n title=\"Diagnostics\"\n description=\"Live system snapshot + active log tail. Auto-refresh every 10s.\"\n actions={\n <Button variant=\"ghost\" onClick={() => { void snap.refetch(); void logs.refetch(); }} data-testid=\"diagnostics-refresh\">\n <RefreshCw size={14} aria-hidden /> Refresh\n </Button>\n }\n />\n\n <Grid cols={3}>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Status</span>\n <Inline align=\"center\" gap={2}>\n <Activity size={14} aria-hidden />\n <strong style={{ fontFamily: 'var(--font-mono)' }}>\n {snap.loading ? '…' : (\n snap.error ? 'error' :\n !snap.data?.service?.running ? 'stopped' :\n (snap.data?.errors?.length ?? 0) > 0 ? 'warn' : 'ok'\n )}\n </strong>\n </Inline>\n </Stack>\n </CardBody>\n </Card>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Uptime</span>\n <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.loading ? '…' : fmtUptime(uptime)}</strong>\n </Stack>\n </CardBody>\n </Card>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Version</span>\n <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.loading ? '…' : (snap.data?.version ?? '—')}</strong>\n </Stack>\n </CardBody>\n </Card>\n </Grid>\n\n {snap.error && (\n <Card variant=\"default\" style={{ borderColor: 'var(--danger)' }}>\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" gap={2}>\n <Activity size={14} aria-hidden style={{ color: 'var(--danger)' }} />\n <strong style={{ color: 'var(--danger)' }}>Diagnostics fetch failed</strong>\n </Inline>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{snap.error.message ?? String(snap.error)}</span>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => { void snap.refetch(); }}>\n <RefreshCw size={12} aria-hidden /> Retry\n </Button>\n </Stack>\n </CardBody>\n </Card>\n )}\n\n {Object.keys(counts).length > 0 && (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong>Counts</strong>\n <Grid cols={4}>\n {Object.entries(counts).map(([k, v]) => (\n <Stack key={k} gap={0}>\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>{k}</span>\n <strong style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-13)' }}>{String(v ?? '—')}</strong>\n </Stack>\n ))}\n </Grid>\n </Stack>\n </CardBody>\n </Card>\n )}\n\n {checks.length > 0 && (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong>Checks ({checks.length})</strong>\n <Inline gap={1} wrap={true}>\n {checks.map((c) => (\n <Badge key={c.name} tone={c.status === 'ok' ? 'success' : c.status === 'warn' ? 'warning' : 'danger'}>\n {c.name}\n </Badge>\n ))}\n </Inline>\n </Stack>\n </CardBody>\n </Card>\n )}\n\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\">\n <Inline align=\"center\" gap={2}>\n <FileText size={14} aria-hidden />\n <strong>Log tail</strong>\n {logFile && <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', fontFamily: 'var(--font-mono)' }}>{logFile}</code>}\n </Inline>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{lines.length} / {logs.data?.total ?? 0} lines</span>\n </Inline>\n {logs.loading && lines.length === 0 ? (\n <Skeleton style={{ height: 240 }} />\n ) : lines.length === 0 ? (\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>No log lines yet.</span>\n ) : (\n <pre\n data-testid=\"diagnostics-log-tail\"\n style={{\n maxHeight: 320,\n overflowY: 'auto',\n padding: 'var(--space-3)',\n background: 'var(--surface-1)',\n borderRadius: 'var(--radius-sm)',\n fontSize: 'var(--fs-12)',\n fontFamily: 'var(--font-mono)',\n margin: 0,\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-all',\n }}\n >\n {lines.join('\\n')}\n </pre>\n )}\n </Stack>\n </CardBody>\n </Card>\n </Stack>\n );\n}"],"names":["fmtUptime","secs","days","hours","mins","DiagnosticsView","snap","useFetch","logs","useEffect","id","uptime","_a","checks","_b","counts","_c","lines","_d","logFile","_e","jsxs","Stack","jsx","ViewHeader","Button","RefreshCw","Grid","Card","CardBody","Inline","Activity","_g","_f","_i","_h","_j","k","v","c","Badge","FileText","_k","Skeleton"],"mappings":"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"}
1
+ {"version":3,"file":"DiagnosticsView-D5Wy9xlJ.js","sources":["../../src/web/v8/views/Diagnostics/DiagnosticsView.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { Activity, RefreshCw, FileText } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { Grid } from '../../ui/primitives/Grid.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 { useFetch } from '../../data/useFetch.js';\n\n/**\n * DiagnosticsView — Sprint S35. System snapshot + active log tail.\n */\n\ninterface DiagnosticsHealth {\n status: string;\n checks?: Array<{ name: string; status: string; message?: string }>;\n}\n\ninterface DiagnosticsSnapshot {\n version?: string;\n uptime?: number;\n memory?: { rss?: number; heapUsed?: number; heapTotal?: number };\n checks?: Array<{ name: string; status: string; message?: string }>;\n counts?: Record<string, number | string | null>;\n errors?: Array<{ line: string; ts: string | null }>;\n service?: { running?: boolean; pid?: number };\n}\n\ninterface LogsResponse {\n lines: string[];\n file: string | null;\n total: number;\n}\n\nfunction fmtUptime(secs: number | undefined): string {\n if (!secs || secs <= 0) return '—';\n const days = Math.floor(secs / 86400);\n const hours = Math.floor((secs % 86400) / 3600);\n const mins = Math.floor((secs % 3600) / 60);\n if (days > 0) return `${days}d ${hours}h`;\n if (hours > 0) return `${hours}h ${mins}m`;\n return `${mins}m`;\n}\n\nexport function DiagnosticsView(): JSX.Element {\n const snap = useFetch<DiagnosticsSnapshot>('/api/diagnostics');\n const logs = useFetch<LogsResponse>('/api/diagnostics/logs?tail=200');\n\n // Auto-refresh logs every 10s while page is open.\n useEffect(() => {\n const id = setInterval(() => { void logs.refetch(); }, 10_000);\n return () => clearInterval(id);\n }, [logs]);\n\n const uptime = snap.data?.uptime;\n const checks = snap.data?.checks ?? [];\n const counts = snap.data?.counts ?? {};\n const lines = logs.data?.lines ?? [];\n const logFile = logs.data?.file ?? null;\n\n return (\n <Stack gap={5} data-testid=\"diagnostics-view\">\n <ViewHeader\n title=\"Diagnostics\"\n description=\"Live system snapshot + active log tail. Auto-refresh every 10s.\"\n actions={\n <Button variant=\"ghost\" onClick={() => { void snap.refetch(); void logs.refetch(); }} data-testid=\"diagnostics-refresh\">\n <RefreshCw size={14} aria-hidden /> Refresh\n </Button>\n }\n />\n\n <Grid cols={3}>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Status</span>\n <Inline align=\"center\" gap={2}>\n <Activity size={14} aria-hidden />\n <strong style={{ fontFamily: 'var(--font-mono)' }}>\n {snap.loading ? '…' : (\n snap.error ? 'error' :\n !snap.data?.service?.running ? 'stopped' :\n (snap.data?.errors?.length ?? 0) > 0 ? 'warn' : 'ok'\n )}\n </strong>\n </Inline>\n </Stack>\n </CardBody>\n </Card>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Uptime</span>\n <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.loading ? '…' : fmtUptime(uptime)}</strong>\n </Stack>\n </CardBody>\n </Card>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Version</span>\n <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.loading ? '…' : (snap.data?.version ?? '—')}</strong>\n </Stack>\n </CardBody>\n </Card>\n </Grid>\n\n {snap.error && (\n <Card variant=\"default\" style={{ borderColor: 'var(--danger)' }}>\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" gap={2}>\n <Activity size={14} aria-hidden style={{ color: 'var(--danger)' }} />\n <strong style={{ color: 'var(--danger)' }}>Diagnostics fetch failed</strong>\n </Inline>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{snap.error.message ?? String(snap.error)}</span>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => { void snap.refetch(); }}>\n <RefreshCw size={12} aria-hidden /> Retry\n </Button>\n </Stack>\n </CardBody>\n </Card>\n )}\n\n {Object.keys(counts).length > 0 && (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong>Counts</strong>\n <Grid cols={4}>\n {Object.entries(counts).map(([k, v]) => (\n <Stack key={k} gap={0}>\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>{k}</span>\n <strong style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-13)' }}>{String(v ?? '—')}</strong>\n </Stack>\n ))}\n </Grid>\n </Stack>\n </CardBody>\n </Card>\n )}\n\n {checks.length > 0 && (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong>Checks ({checks.length})</strong>\n <Inline gap={1} wrap={true}>\n {checks.map((c) => (\n <Badge key={c.name} tone={c.status === 'ok' ? 'success' : c.status === 'warn' ? 'warning' : 'danger'}>\n {c.name}\n </Badge>\n ))}\n </Inline>\n </Stack>\n </CardBody>\n </Card>\n )}\n\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\">\n <Inline align=\"center\" gap={2}>\n <FileText size={14} aria-hidden />\n <strong>Log tail</strong>\n {logFile && <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', fontFamily: 'var(--font-mono)' }}>{logFile}</code>}\n </Inline>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{lines.length} / {logs.data?.total ?? 0} lines</span>\n </Inline>\n {logs.loading && lines.length === 0 ? (\n <Skeleton style={{ height: 240 }} />\n ) : lines.length === 0 ? (\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>No log lines yet.</span>\n ) : (\n <pre\n data-testid=\"diagnostics-log-tail\"\n style={{\n maxHeight: 320,\n overflowY: 'auto',\n padding: 'var(--space-3)',\n background: 'var(--surface-1)',\n borderRadius: 'var(--radius-sm)',\n fontSize: 'var(--fs-12)',\n fontFamily: 'var(--font-mono)',\n margin: 0,\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-all',\n }}\n >\n {lines.join('\\n')}\n </pre>\n )}\n </Stack>\n </CardBody>\n </Card>\n </Stack>\n );\n}"],"names":["fmtUptime","secs","days","hours","mins","DiagnosticsView","snap","useFetch","logs","useEffect","id","uptime","_a","checks","_b","counts","_c","lines","_d","logFile","_e","jsxs","Stack","jsx","ViewHeader","Button","RefreshCw","Grid","Card","CardBody","Inline","Activity","_g","_f","_i","_h","_j","k","v","c","Badge","FileText","_k","Skeleton"],"mappings":"qVAqCA,SAASA,EAAUC,EAAkC,CACnD,GAAI,CAACA,GAAQA,GAAQ,EAAG,MAAO,IAC/B,MAAMC,EAAO,KAAK,MAAMD,EAAO,KAAK,EAC9BE,EAAQ,KAAK,MAAOF,EAAO,MAAS,IAAI,EACxCG,EAAO,KAAK,MAAOH,EAAO,KAAQ,EAAE,EAC1C,OAAIC,EAAO,EAAU,GAAGA,CAAI,KAAKC,CAAK,IAClCA,EAAQ,EAAU,GAAGA,CAAK,KAAKC,CAAI,IAChC,GAAGA,CAAI,GAChB,CAEO,SAASC,GAA+B,2BAC7C,MAAMC,EAAOC,EAA8B,kBAAkB,EACvDC,EAAOD,EAAuB,gCAAgC,EAGpEE,EAAAA,UAAU,IAAM,CACd,MAAMC,EAAK,YAAY,IAAM,CAAOF,EAAK,QAAA,CAAW,EAAG,GAAM,EAC7D,MAAO,IAAM,cAAcE,CAAE,CAC/B,EAAG,CAACF,CAAI,CAAC,EAET,MAAMG,GAASC,EAAAN,EAAK,OAAL,YAAAM,EAAW,OACpBC,IAASC,EAAAR,EAAK,OAAL,YAAAQ,EAAW,SAAU,CAAA,EAC9BC,IAASC,EAAAV,EAAK,OAAL,YAAAU,EAAW,SAAU,CAAA,EAC9BC,IAAQC,EAAAV,EAAK,OAAL,YAAAU,EAAW,QAAS,CAAA,EAC5BC,IAAUC,EAAAZ,EAAK,OAAL,YAAAY,EAAW,OAAQ,KAEnC,OACEC,EAAAA,KAACC,EAAA,CAAM,IAAK,EAAG,cAAY,mBACzB,SAAA,CAAAC,EAAAA,IAACC,EAAA,CACC,MAAM,cACN,YAAY,kEACZ,QACEH,EAAAA,KAACI,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAM,CAAOnB,EAAK,QAAA,EAAgBE,EAAK,QAAA,CAAW,EAAG,cAAY,sBAChG,SAAA,CAAAe,EAAAA,IAACG,EAAA,CAAU,KAAM,GAAI,cAAW,GAAC,EAAE,UAAA,CAAA,CACrC,CAAA,CAAA,EAIJL,EAAAA,KAACM,EAAA,CAAK,KAAM,EACV,SAAA,CAAAJ,EAAAA,IAACK,EAAA,CAAK,QAAQ,UACZ,SAAAL,EAAAA,IAACM,GACC,SAAAR,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,QAAA,CAAM,EAC3EF,EAAAA,KAACS,EAAA,CAAO,MAAM,SAAS,IAAK,EAC1B,SAAA,CAAAP,EAAAA,IAACQ,EAAA,CAAS,KAAM,GAAI,cAAW,GAAC,EAChCR,EAAAA,IAAC,SAAA,CAAO,MAAO,CAAE,WAAY,kBAAA,EAC1B,SAAAjB,EAAK,QAAU,IACdA,EAAK,MAAQ,SACZ0B,GAAAC,EAAA3B,EAAK,OAAL,YAAA2B,EAAW,UAAX,MAAAD,EAAoB,WACpBE,GAAAC,EAAA7B,EAAK,OAAL,YAAA6B,EAAW,SAAX,YAAAD,EAAmB,SAAU,GAAK,EAAI,OAAS,KADjB,SACiB,CAEpD,CAAA,CAAA,CACF,CAAA,CAAA,CACF,EACF,EACF,EACAX,EAAAA,IAACK,GAAK,QAAQ,UACZ,eAACC,EAAA,CACC,SAAAR,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,QAAA,CAAM,EAC3EA,EAAAA,IAAC,SAAA,CAAO,MAAO,CAAE,WAAY,kBAAA,EAAuB,SAAAjB,EAAK,QAAU,IAAMN,EAAUW,CAAM,CAAA,CAAE,CAAA,CAAA,CAC7F,EACF,EACF,EACAY,EAAAA,IAACK,GAAK,QAAQ,UACZ,eAACC,EAAA,CACC,SAAAR,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,SAAA,CAAO,EAC5EA,EAAAA,IAAC,SAAA,CAAO,MAAO,CAAE,WAAY,kBAAA,EAAuB,SAAAjB,EAAK,QAAU,MAAO8B,EAAA9B,EAAK,OAAL,YAAA8B,EAAW,UAAW,GAAA,CAAK,CAAA,CAAA,CACvG,EACF,CAAA,CACF,CAAA,EACF,EAEC9B,EAAK,OACJiB,EAAAA,IAACK,EAAA,CAAK,QAAQ,UAAU,MAAO,CAAE,YAAa,eAAA,EAC5C,SAAAL,EAAAA,IAACM,EAAA,CACC,SAAAR,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAD,EAAAA,KAACS,EAAA,CAAO,MAAM,SAAS,IAAK,EAC1B,SAAA,CAAAP,EAAAA,IAACQ,EAAA,CAAS,KAAM,GAAI,cAAW,GAAC,MAAO,CAAE,MAAO,eAAA,CAAgB,CAAG,QAClE,SAAA,CAAO,MAAO,CAAE,MAAO,eAAA,EAAmB,SAAA,0BAAA,CAAwB,CAAA,EACrE,EACAR,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAsB,WAAK,MAAM,SAAW,OAAOjB,EAAK,KAAK,EAAE,SAC9GmB,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS,IAAM,CAAOnB,EAAK,QAAA,CAAW,EAC1E,SAAA,CAAAiB,EAAAA,IAACG,EAAA,CAAU,KAAM,GAAI,cAAW,GAAC,EAAE,QAAA,CAAA,CACrC,CAAA,CAAA,CACF,EACF,EACF,EAGD,OAAO,KAAKX,CAAM,EAAE,OAAS,GAC5BQ,EAAAA,IAACK,EAAA,CAAK,QAAQ,UACZ,SAAAL,EAAAA,IAACM,EAAA,CACC,SAAAR,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAC,EAAAA,IAAC,UAAO,SAAA,QAAA,CAAM,QACbI,EAAA,CAAK,KAAM,EACT,SAAA,OAAO,QAAQZ,CAAM,EAAE,IAAI,CAAC,CAACsB,EAAGC,CAAC,IAChCjB,EAAAA,KAACC,EAAA,CAAc,IAAK,EAClB,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,kBAAmB,cAAe,YAAa,cAAe,QAAA,EAAa,SAAAc,EAAE,EAC7Hd,EAAAA,IAAC,SAAA,CAAO,MAAO,CAAE,WAAY,mBAAoB,SAAU,cAAA,EAAmB,SAAA,OAAOe,GAAK,GAAG,CAAA,CAAE,CAAA,CAAA,EAFrFD,CAGZ,CACD,CAAA,CACH,CAAA,CAAA,CACF,EACF,EACF,EAGDxB,EAAO,OAAS,GACfU,EAAAA,IAACK,EAAA,CAAK,QAAQ,UACZ,SAAAL,EAAAA,IAACM,EAAA,CACC,SAAAR,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAD,OAAC,SAAA,CAAO,SAAA,CAAA,WAASR,EAAO,OAAO,GAAA,EAAC,EAChCU,EAAAA,IAACO,EAAA,CAAO,IAAK,EAAG,KAAM,GACnB,SAAAjB,EAAO,IAAK0B,GACXhB,EAAAA,IAACiB,EAAA,CAAmB,KAAMD,EAAE,SAAW,KAAO,UAAYA,EAAE,SAAW,OAAS,UAAY,SACzF,SAAAA,EAAE,IAAA,EADOA,EAAE,IAEd,CACD,CAAA,CACH,CAAA,CAAA,CACF,EACF,EACF,EAGFhB,EAAAA,IAACK,GAAK,QAAQ,UACZ,eAACC,EAAA,CACC,SAAAR,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAD,EAAAA,KAACS,EAAA,CAAO,MAAM,SAAS,QAAQ,UAC7B,SAAA,CAAAT,EAAAA,KAACS,EAAA,CAAO,MAAM,SAAS,IAAK,EAC1B,SAAA,CAAAP,EAAAA,IAACkB,EAAA,CAAS,KAAM,GAAI,cAAW,GAAC,EAChClB,EAAAA,IAAC,UAAO,SAAA,UAAA,CAAQ,EACfJ,GAAWI,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,kBAAmB,WAAY,kBAAA,EAAuB,SAAAJ,CAAA,CAAQ,CAAA,EAC5H,EACAE,OAAC,QAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,mBAAsB,SAAA,CAAAJ,EAAM,OAAO,QAAIyB,EAAAlC,EAAK,OAAL,YAAAkC,EAAW,QAAS,EAAE,QAAA,CAAA,CAAM,CAAA,EACrH,EACClC,EAAK,SAAWS,EAAM,SAAW,EAChCM,EAAAA,IAACoB,EAAA,CAAS,MAAO,CAAE,OAAQ,GAAA,CAAI,CAAG,EAChC1B,EAAM,SAAW,EACnBM,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,MAAO,kBAAmB,SAAU,cAAA,EAAkB,SAAA,mBAAA,CAAiB,EAEtFA,EAAAA,IAAC,MAAA,CACC,cAAY,uBACZ,MAAO,CACL,UAAW,IACX,UAAW,OACX,QAAS,iBACT,WAAY,mBACZ,aAAc,mBACd,SAAU,eACV,WAAY,mBACZ,OAAQ,EACR,WAAY,WACZ,UAAW,WAAA,EAGZ,SAAAN,EAAM,KAAK;AAAA,CAAI,CAAA,CAAA,CAClB,CAAA,CAEJ,EACF,CAAA,CACF,CAAA,EACF,CAEJ"}
@@ -1,4 +1,4 @@
1
- import{r as c,j as e}from"./cmdk-C3F6LD6N.js";import{d as k,u as b,a as C,S as h,I as d,B as r,h as m,M as S,l as $,X as w,i as f,F as x}from"./main-BURAlktW.js";import{V as z}from"./ViewHeader-C-t1U2cQ.js";import{L as E}from"./ListHeader-CM8QoIWG.js";import{C as D,b as R}from"./Card-BtsmkhJa.js";import{E as T}from"./EmptyState-DjKtY1Qi.js";import{E as F}from"./ErrorState-CBJbEQ8B.js";import{R as q}from"./refresh-ccw-DA8_IB9l.js";import{T as j}from"./trash-2-D6qePV_q.js";import"./Alert-BZGk39mB.js";import"./circle-alert-Dz8lGfCZ.js";import"./triangle-alert-B2oHbmoh.js";import"./circle-check-DFB50ojt.js";/**
1
+ import{r as c,j as e}from"./cmdk-C3F6LD6N.js";import{d as k,u as b,a as C,S as h,I as d,B as r,h as m,M as S,l as $,X as w,i as f,F as x}from"./main-BRmJZcHt.js";import{V as z}from"./ViewHeader-BsnaspKw.js";import{L as E}from"./ListHeader-CCD_nIHb.js";import{C as D,b as R}from"./Card-Clkvh43Q.js";import{E as T}from"./EmptyState-ccT__JZG.js";import{E as F}from"./ErrorState-BSqf65ka.js";import{R as q}from"./refresh-ccw-DN_zCB1h.js";import{T as j}from"./trash-2-B_Y6HrfN.js";import"./Alert-pzFISNtS.js";import"./circle-alert-QQTU4Quz.js";import"./triangle-alert-BeY8LAv6.js";import"./circle-check-BMbe7Kkr.js";/**
2
2
  * @license lucide-react v0.460.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- {"version":3,"file":"DialogsView-Xd02dVAX.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/skip-forward.js","../../src/web/v8/views/Dialogs/DialogsView.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 SkipForward = createLucideIcon(\"SkipForward\", [\n [\"polygon\", { points: \"5 4 15 12 5 20 5 4\", key: \"16p6eg\" }],\n [\"line\", { x1: \"19\", x2: \"19\", y1: \"5\", y2: \"19\", key: \"futhcm\" }]\n]);\n\nexport { SkipForward as default };\n//# sourceMappingURL=skip-forward.js.map\n","/**\n * v8/views/Dialogs/DialogsView.tsx — Sprint S42, v9.3.0.\n *\n * Active dialog queue pulled from /api/dialogs. Per-row: view kind,\n * title, body preview, source, age, inline-confirm Dismiss (DELETE\n * /api/dialogs/:id). Empty state + manual Refresh button. No\n * window.confirm.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { Check, MessageSquare, RefreshCcw, SkipForward, Trash2, X } 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 { 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 { useWsMessage } from '../../data/useWebSocket.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface DialogItem {\n id: string;\n kind?: string;\n title?: string;\n body?: string;\n source?: string;\n createdAt?: number | string;\n}\n\nexport function DialogsView(): JSX.Element {\n const payload = useFetch<{ dialogs: DialogItem[] }>('/api/dialogs');\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n // Live: server broadcasts `dialog:show` on enqueue. Refresh on it.\n useWsMessage('dialog:show', () => { refresh(); });\n\n const drop = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/dialogs/${id}`, { 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 const decide = async (id: string, verdict: 'approve' | 'deny' | 'skip'): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/dialogs/${id}/${verdict}`, { method: 'POST', body: {} });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const dialogs = useMemo<DialogItem[]>(() => payload.data?.dialogs ?? [], [payload.data]);\n\n return (\n <Stack gap={4} data-testid=\"dialogs-view\">\n <ViewHeader\n title=\"Dialogs\"\n description=\"Active dialog queue (debug + manual dismiss).\"\n actions={\n <Inline gap={1}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"dialogs-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"dialogs-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n </Inline>\n }\n />\n <ListHeader title=\"Queue\" count={dialogs.length} testid=\"dialogs-list-header\" />\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && dialogs.length === 0 ? (\n <Stack gap={1}>\n <Skeleton style={{ height: 32 }} />\n <Skeleton style={{ height: 32 }} />\n </Stack>\n ) : payload.error && dialogs.length === 0 ? (\n <ErrorState\n block\n title=\"Couldn't load dialogs\"\n description=\"The dialog queue failed to fetch. Retry to refetch.\"\n error={payload.error}\n onRetry={refresh}\n testid=\"dialogs-error-state\"\n />\n ) : dialogs.length === 0 ? (\n <EmptyState\n icon={<MessageSquare size={28} aria-hidden />}\n title=\"No active dialogs\"\n description=\"Dialogs are confirmations and prompts the agent raises when it needs user input before proceeding. They appear here when the slash-command plugin queues one.\"\n />\n ) : (\n <Stack gap={1}>\n {dialogs.map((d) => {\n const isConfirming = confirmDelete === d.id;\n return (\n <div\n key={d.id}\n data-testid={`dialog-row-${d.id}`}\n style={{\n padding: 'var(--space-2)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n background: 'var(--surface-0)',\n }}\n >\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Stack gap={0} style={{ minWidth: 0 }}>\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>{d.title || d.id}</strong>\n {d.kind && (\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)', fontFamily: 'var(--font-mono)' }}>\n {d.kind}\n </span>\n )}\n {d.source && (\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)' }}>\n · {d.source}\n </span>\n )}\n </Inline>\n {d.body && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {d.body.length > 160 ? `${d.body.slice(0, 160)}…` : d.body}\n </span>\n )}\n </Stack>\n <Inline gap={1}>\n <Button\n variant=\"primary\"\n onClick={() => void decide(d.id, 'approve')}\n data-testid={`dialog-approve-${d.id}`}\n aria-label={`Approve ${d.id}`}\n >\n <Check size={14} aria-hidden /> Approve\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => void decide(d.id, 'skip')}\n data-testid={`dialog-skip-${d.id}`}\n aria-label={`Skip ${d.id}`}\n >\n <SkipForward size={14} aria-hidden /> Skip\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => void decide(d.id, 'deny')}\n data-testid={`dialog-deny-${d.id}`}\n aria-label={`Deny ${d.id}`}\n >\n <X size={14} aria-hidden /> Deny\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmDelete((cur) => (cur === d.id ? null : d.id))}\n data-testid={`dialog-dismiss-${d.id}`}\n aria-label={`Dismiss ${d.id}`}\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(d.id)} data-testid={`dialog-confirm-dismiss-${d.id}`}>\n <Trash2 size={14} aria-hidden /> Confirm\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)}>Cancel</Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </CardBody>\n </Card>\n </Stack>\n );\n}"],"names":["SkipForward","createLucideIcon","DialogsView","payload","useFetch","confirmDelete","setConfirmDelete","useState","error","setError","refresh","useCallback","useWsMessage","drop","id","fetchJson","err","FetchError","decide","verdict","dialogs","useMemo","_a","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCcw","ListHeader","Card","CardBody","Skeleton","ErrorState","EmptyState","MessageSquare","d","isConfirming","Check","X","cur","Trash2"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"DialogsView-HVyfrXpq.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/skip-forward.js","../../src/web/v8/views/Dialogs/DialogsView.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 SkipForward = createLucideIcon(\"SkipForward\", [\n [\"polygon\", { points: \"5 4 15 12 5 20 5 4\", key: \"16p6eg\" }],\n [\"line\", { x1: \"19\", x2: \"19\", y1: \"5\", y2: \"19\", key: \"futhcm\" }]\n]);\n\nexport { SkipForward as default };\n//# sourceMappingURL=skip-forward.js.map\n","/**\n * v8/views/Dialogs/DialogsView.tsx — Sprint S42, v9.3.0.\n *\n * Active dialog queue pulled from /api/dialogs. Per-row: view kind,\n * title, body preview, source, age, inline-confirm Dismiss (DELETE\n * /api/dialogs/:id). Empty state + manual Refresh button. No\n * window.confirm.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { Check, MessageSquare, RefreshCcw, SkipForward, Trash2, X } 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 { 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 { useWsMessage } from '../../data/useWebSocket.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface DialogItem {\n id: string;\n kind?: string;\n title?: string;\n body?: string;\n source?: string;\n createdAt?: number | string;\n}\n\nexport function DialogsView(): JSX.Element {\n const payload = useFetch<{ dialogs: DialogItem[] }>('/api/dialogs');\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n // Live: server broadcasts `dialog:show` on enqueue. Refresh on it.\n useWsMessage('dialog:show', () => { refresh(); });\n\n const drop = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/dialogs/${id}`, { 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 const decide = async (id: string, verdict: 'approve' | 'deny' | 'skip'): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/dialogs/${id}/${verdict}`, { method: 'POST', body: {} });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const dialogs = useMemo<DialogItem[]>(() => payload.data?.dialogs ?? [], [payload.data]);\n\n return (\n <Stack gap={4} data-testid=\"dialogs-view\">\n <ViewHeader\n title=\"Dialogs\"\n description=\"Active dialog queue (debug + manual dismiss).\"\n actions={\n <Inline gap={1}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"dialogs-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"dialogs-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n </Inline>\n }\n />\n <ListHeader title=\"Queue\" count={dialogs.length} testid=\"dialogs-list-header\" />\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && dialogs.length === 0 ? (\n <Stack gap={1}>\n <Skeleton style={{ height: 32 }} />\n <Skeleton style={{ height: 32 }} />\n </Stack>\n ) : payload.error && dialogs.length === 0 ? (\n <ErrorState\n block\n title=\"Couldn't load dialogs\"\n description=\"The dialog queue failed to fetch. Retry to refetch.\"\n error={payload.error}\n onRetry={refresh}\n testid=\"dialogs-error-state\"\n />\n ) : dialogs.length === 0 ? (\n <EmptyState\n icon={<MessageSquare size={28} aria-hidden />}\n title=\"No active dialogs\"\n description=\"Dialogs are confirmations and prompts the agent raises when it needs user input before proceeding. They appear here when the slash-command plugin queues one.\"\n />\n ) : (\n <Stack gap={1}>\n {dialogs.map((d) => {\n const isConfirming = confirmDelete === d.id;\n return (\n <div\n key={d.id}\n data-testid={`dialog-row-${d.id}`}\n style={{\n padding: 'var(--space-2)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n background: 'var(--surface-0)',\n }}\n >\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Stack gap={0} style={{ minWidth: 0 }}>\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>{d.title || d.id}</strong>\n {d.kind && (\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)', fontFamily: 'var(--font-mono)' }}>\n {d.kind}\n </span>\n )}\n {d.source && (\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)' }}>\n · {d.source}\n </span>\n )}\n </Inline>\n {d.body && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {d.body.length > 160 ? `${d.body.slice(0, 160)}…` : d.body}\n </span>\n )}\n </Stack>\n <Inline gap={1}>\n <Button\n variant=\"primary\"\n onClick={() => void decide(d.id, 'approve')}\n data-testid={`dialog-approve-${d.id}`}\n aria-label={`Approve ${d.id}`}\n >\n <Check size={14} aria-hidden /> Approve\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => void decide(d.id, 'skip')}\n data-testid={`dialog-skip-${d.id}`}\n aria-label={`Skip ${d.id}`}\n >\n <SkipForward size={14} aria-hidden /> Skip\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => void decide(d.id, 'deny')}\n data-testid={`dialog-deny-${d.id}`}\n aria-label={`Deny ${d.id}`}\n >\n <X size={14} aria-hidden /> Deny\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmDelete((cur) => (cur === d.id ? null : d.id))}\n data-testid={`dialog-dismiss-${d.id}`}\n aria-label={`Dismiss ${d.id}`}\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(d.id)} data-testid={`dialog-confirm-dismiss-${d.id}`}>\n <Trash2 size={14} aria-hidden /> Confirm\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)}>Cancel</Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </CardBody>\n </Card>\n </Stack>\n );\n}"],"names":["SkipForward","createLucideIcon","DialogsView","payload","useFetch","confirmDelete","setConfirmDelete","useState","error","setError","refresh","useCallback","useWsMessage","drop","id","fetchJson","err","FetchError","decide","verdict","dialogs","useMemo","_a","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCcw","ListHeader","Card","CardBody","Skeleton","ErrorState","EmptyState","MessageSquare","d","isConfirming","Check","X","cur","Trash2"],"mappings":"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","x_google_ignoreList":[0]}
@@ -1,6 +1,6 @@
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";/**
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,J as z,b as E,K as T,G as w,i as R,F as b}from"./main-BRmJZcHt.js";import{V as I}from"./ViewHeader-BsnaspKw.js";import{C as j,b as y}from"./Card-Clkvh43Q.js";import{E as N}from"./EmptyState-ccT__JZG.js";import{E as B}from"./ErrorState-BSqf65ka.js";import{R as F}from"./refresh-cw-KGm5eQgv.js";import{T as A}from"./triangle-alert-BeY8LAv6.js";import{C as D}from"./circle-check-BMbe7Kkr.js";import"./Alert-pzFISNtS.js";import"./circle-alert-QQTU4Quz.js";import"./refresh-ccw-DN_zCB1h.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 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};
6
+ */const H=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:D,warn:A,fail:H},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-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
+ {"version":3,"file":"DoctorView-Dm94WI2z.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-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
+ import{r as l,j as e}from"./cmdk-C3F6LD6N.js";import{g as d}from"./main-BRmJZcHt.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-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
+ {"version":3,"file":"EmptyState-ccT__JZG.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{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";/**
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,O as D,i as y,F as k}from"./main-BRmJZcHt.js";import{V as Z}from"./ViewHeader-BsnaspKw.js";import{L as M}from"./ListHeader-CCD_nIHb.js";import{C as _,b as L}from"./Card-Clkvh43Q.js";import{I as A}from"./Input-DV-vdaV8.js";import{S as w,a as E,b as R}from"./Sheet-BwMVGN-8.js";import{E as N}from"./EmptyState-ccT__JZG.js";import{D as U}from"./download-B-mPX5P_.js";import{R as q}from"./refresh-ccw-DN_zCB1h.js";import{P as H}from"./plus-Cps-8lcG.js";import{P as K}from"./pencil-Dkks7eIC.js";import{T as J}from"./trash-2-B_Y6HrfN.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]),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
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(_,{variant:"default",children:e.jsx(L,{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(N,{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
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};