@polderlabs/bizar 10.4.2 → 10.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/bizar-dash/dist/assets/{ActivityFeed-DtRtg-JN.js → ActivityFeed-RQeyFifx.js} +1 -1
  2. package/bizar-dash/dist/assets/{ActivityFeed-DtRtg-JN.js.map → ActivityFeed-RQeyFifx.js.map} +1 -1
  3. package/bizar-dash/dist/assets/{ActivityView-CoTXDyU_.js → ActivityView-CibyssPM.js} +1 -1
  4. package/bizar-dash/dist/assets/{ActivityView-CoTXDyU_.js.map → ActivityView-CibyssPM.js.map} +1 -1
  5. package/bizar-dash/dist/assets/AdminView-BjczABeB.js +11 -0
  6. package/bizar-dash/dist/assets/AdminView-BjczABeB.js.map +1 -0
  7. package/bizar-dash/dist/assets/{AgentActivity-CrX7LmQ6.js → AgentActivity-Bywt1twv.js} +1 -1
  8. package/bizar-dash/dist/assets/{AgentActivity-CrX7LmQ6.js.map → AgentActivity-Bywt1twv.js.map} +1 -1
  9. package/bizar-dash/dist/assets/AgentsView-BnOjjM74.js +15 -0
  10. package/bizar-dash/dist/assets/AgentsView-BnOjjM74.js.map +1 -0
  11. package/bizar-dash/dist/assets/{Alert-B6DjfRFI.js → Alert-BZGk39mB.js} +1 -1
  12. package/bizar-dash/dist/assets/{Alert-B6DjfRFI.js.map → Alert-BZGk39mB.js.map} +1 -1
  13. package/bizar-dash/dist/assets/{ArtifactsView-znhN8GTR.js → ArtifactsView-CfYB1le1.js} +3 -3
  14. package/bizar-dash/dist/assets/ArtifactsView-CfYB1le1.js.map +1 -0
  15. package/bizar-dash/dist/assets/{AuthView-Rk8eKUPr.js → AuthView-D4frSShw.js} +1 -1
  16. package/bizar-dash/dist/assets/{AuthView-Rk8eKUPr.js.map → AuthView-D4frSShw.js.map} +1 -1
  17. package/bizar-dash/dist/assets/Avatar-BYg0rkPA.js +6 -0
  18. package/bizar-dash/dist/assets/Avatar-BYg0rkPA.js.map +1 -0
  19. package/bizar-dash/dist/assets/{BackgroundJobsView-BLWuN9qz.js → BackgroundJobsView-DEStvILz.js} +1 -1
  20. package/bizar-dash/dist/assets/{BackgroundJobsView-BLWuN9qz.js.map → BackgroundJobsView-DEStvILz.js.map} +1 -1
  21. package/bizar-dash/dist/assets/{BackupView-CqbtcnuQ.js → BackupView-B875KQa4.js} +1 -1
  22. package/bizar-dash/dist/assets/{BackupView-CqbtcnuQ.js.map → BackupView-B875KQa4.js.map} +1 -1
  23. package/bizar-dash/dist/assets/Banner-C8HEcT5l.js +1 -0
  24. package/bizar-dash/dist/assets/Banner-C8HEcT5l.js.map +1 -0
  25. package/bizar-dash/dist/assets/{Card-rF59wHiO.js → Card-BtsmkhJa.js} +1 -1
  26. package/bizar-dash/dist/assets/{Card-rF59wHiO.js.map → Card-BtsmkhJa.js.map} +1 -1
  27. package/bizar-dash/dist/assets/ChatView-CkNS0SD8.js +9 -0
  28. package/bizar-dash/dist/assets/ChatView-CkNS0SD8.js.map +1 -0
  29. package/bizar-dash/dist/assets/{Chip-Dc2KmeWl.js → Chip-XPOk0d_E.js} +1 -1
  30. package/bizar-dash/dist/assets/{Chip-Dc2KmeWl.js.map → Chip-XPOk0d_E.js.map} +1 -1
  31. package/bizar-dash/dist/assets/{ClaudeSessionsView-CiaHQdDZ.js → ClaudeSessionsView-BprGo67K.js} +1 -1
  32. package/bizar-dash/dist/assets/{ClaudeSessionsView-CiaHQdDZ.js.map → ClaudeSessionsView-BprGo67K.js.map} +1 -1
  33. package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js +1 -0
  34. package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js.map +1 -0
  35. package/bizar-dash/dist/assets/{ConfigView-B2ysnTZU.js → ConfigView-BntUrW7s.js} +1 -1
  36. package/bizar-dash/dist/assets/{ConfigView-B2ysnTZU.js.map → ConfigView-BntUrW7s.js.map} +1 -1
  37. package/bizar-dash/dist/assets/DiagnosticsView-4x0Zu3yP.js +2 -0
  38. package/bizar-dash/dist/assets/DiagnosticsView-4x0Zu3yP.js.map +1 -0
  39. package/bizar-dash/dist/assets/DialogsView-Xd02dVAX.js +6 -0
  40. package/bizar-dash/dist/assets/DialogsView-Xd02dVAX.js.map +1 -0
  41. package/bizar-dash/dist/assets/{DoctorView-BQwqvMAh.js → DoctorView-DepBdQGR.js} +2 -2
  42. package/bizar-dash/dist/assets/{DoctorView-BQwqvMAh.js.map → DoctorView-DepBdQGR.js.map} +1 -1
  43. package/bizar-dash/dist/assets/{EmptyState-D65J5FQN.js → EmptyState-DjKtY1Qi.js} +1 -1
  44. package/bizar-dash/dist/assets/{EmptyState-D65J5FQN.js.map → EmptyState-DjKtY1Qi.js.map} +1 -1
  45. package/bizar-dash/dist/assets/{EnvVarsView-DX-3oGH-.js → EnvVarsView-S4Pbm128.js} +3 -3
  46. package/bizar-dash/dist/assets/{EnvVarsView-DX-3oGH-.js.map → EnvVarsView-S4Pbm128.js.map} +1 -1
  47. package/bizar-dash/dist/assets/{ErrorState-DULZnttJ.js → ErrorState-CBJbEQ8B.js} +1 -1
  48. package/bizar-dash/dist/assets/{ErrorState-DULZnttJ.js.map → ErrorState-CBJbEQ8B.js.map} +1 -1
  49. package/bizar-dash/dist/assets/EvalView-BeAyMCD1.js +1 -0
  50. package/bizar-dash/dist/assets/{EvalView-CpdFu_ID.js.map → EvalView-BeAyMCD1.js.map} +1 -1
  51. package/bizar-dash/dist/assets/{GoalsView-Br8oPPfb.js → GoalsView-BZr8In4c.js} +1 -1
  52. package/bizar-dash/dist/assets/{GoalsView-Br8oPPfb.js.map → GoalsView-BZr8In4c.js.map} +1 -1
  53. package/bizar-dash/dist/assets/{Grid-BSXhsCPC.js → Grid--WKvqu5h.js} +1 -1
  54. package/bizar-dash/dist/assets/{Grid-BSXhsCPC.js.map → Grid--WKvqu5h.js.map} +1 -1
  55. package/bizar-dash/dist/assets/{HistoryView-D0J3aoZF.js → HistoryView-djEbzqtk.js} +1 -1
  56. package/bizar-dash/dist/assets/{HistoryView-D0J3aoZF.js.map → HistoryView-djEbzqtk.js.map} +1 -1
  57. package/bizar-dash/dist/assets/{Input-CZmRw5QX.js → Input-h_nSOtwm.js} +1 -1
  58. package/bizar-dash/dist/assets/{Input-CZmRw5QX.js.map → Input-h_nSOtwm.js.map} +1 -1
  59. package/bizar-dash/dist/assets/LibrariesView-Vez8CvNq.js +6 -0
  60. package/bizar-dash/dist/assets/{LibrariesView-B1YX9wzp.js.map → LibrariesView-Vez8CvNq.js.map} +1 -1
  61. package/bizar-dash/dist/assets/{LightRAGView-CykR0t9y.js → LightRAGView-DvqzQoBp.js} +1 -1
  62. package/bizar-dash/dist/assets/{LightRAGView-CykR0t9y.js.map → LightRAGView-DvqzQoBp.js.map} +1 -1
  63. package/bizar-dash/dist/assets/{ListHeader-Dpun-r36.js → ListHeader-CM8QoIWG.js} +1 -1
  64. package/bizar-dash/dist/assets/{ListHeader-Dpun-r36.js.map → ListHeader-CM8QoIWG.js.map} +1 -1
  65. package/bizar-dash/dist/assets/{MemoryView-BbER5ZKt.js → MemoryView-DnL8E2vI.js} +1 -1
  66. package/bizar-dash/dist/assets/{MemoryView-BbER5ZKt.js.map → MemoryView-DnL8E2vI.js.map} +1 -1
  67. package/bizar-dash/dist/assets/{MessageBubble-5vUAquDx.js → MessageBubble-CrCJ0SYG.js} +1 -1
  68. package/bizar-dash/dist/assets/{MessageBubble-5vUAquDx.js.map → MessageBubble-CrCJ0SYG.js.map} +1 -1
  69. package/bizar-dash/dist/assets/MiscView-B2YQXhZ_.js +1 -0
  70. package/bizar-dash/dist/assets/MiscView-B2YQXhZ_.js.map +1 -0
  71. package/bizar-dash/dist/assets/{ModsView-P7gDeNHM.js → ModsView-BVM3X5xc.js} +1 -1
  72. package/bizar-dash/dist/assets/{ModsView-P7gDeNHM.js.map → ModsView-BVM3X5xc.js.map} +1 -1
  73. package/bizar-dash/dist/assets/NotificationsView-A-Xs8BL1.js +6 -0
  74. package/bizar-dash/dist/assets/NotificationsView-A-Xs8BL1.js.map +1 -0
  75. package/bizar-dash/dist/assets/ObsidianView-mI3qW9OP.js +1 -0
  76. package/bizar-dash/dist/assets/{ObsidianView-Ci80gnwS.js.map → ObsidianView-mI3qW9OP.js.map} +1 -1
  77. package/bizar-dash/dist/assets/OverviewView-By69Cr5H.js +1 -0
  78. package/bizar-dash/dist/assets/OverviewView-By69Cr5H.js.map +1 -0
  79. package/bizar-dash/dist/assets/{ProgressBar-BahmeJhP.js → ProgressBar-BnaBqv-W.js} +1 -1
  80. package/bizar-dash/dist/assets/{ProgressBar-BahmeJhP.js.map → ProgressBar-BnaBqv-W.js.map} +1 -1
  81. package/bizar-dash/dist/assets/ProjectsView-C81WTFka.js +11 -0
  82. package/bizar-dash/dist/assets/ProjectsView-C81WTFka.js.map +1 -0
  83. package/bizar-dash/dist/assets/{ProvidersView-BftGn8Cr.js → ProvidersView-2cn-TALE.js} +2 -2
  84. package/bizar-dash/dist/assets/{ProvidersView-BftGn8Cr.js.map → ProvidersView-2cn-TALE.js.map} +1 -1
  85. package/bizar-dash/dist/assets/{SchedulesView-CtNxtzN6.js → SchedulesView-o9AtIsH9.js} +1 -1
  86. package/bizar-dash/dist/assets/{SchedulesView-CtNxtzN6.js.map → SchedulesView-o9AtIsH9.js.map} +1 -1
  87. package/bizar-dash/dist/assets/{Select-0VcfTDeL.js → Select-CiGWEN8I.js} +1 -1
  88. package/bizar-dash/dist/assets/{Select-0VcfTDeL.js.map → Select-CiGWEN8I.js.map} +1 -1
  89. package/bizar-dash/dist/assets/{SettingsRow-BLic3DQl.js → SettingsRow-CflGJymA.js} +1 -1
  90. package/bizar-dash/dist/assets/{SettingsRow-BLic3DQl.js.map → SettingsRow-CflGJymA.js.map} +1 -1
  91. package/bizar-dash/dist/assets/{SettingsView-BjS3i4nr.js → SettingsView-2HSFJPPK.js} +1 -1
  92. package/bizar-dash/dist/assets/{SettingsView-BjS3i4nr.js.map → SettingsView-2HSFJPPK.js.map} +1 -1
  93. package/bizar-dash/dist/assets/{Sheet-BOProMs2.js → Sheet-B-CMP9-_.js} +1 -1
  94. package/bizar-dash/dist/assets/{Sheet-BOProMs2.js.map → Sheet-B-CMP9-_.js.map} +1 -1
  95. package/bizar-dash/dist/assets/{Slider-B0eLEEUt.js → Slider-Z4TP_CXY.js} +1 -1
  96. package/bizar-dash/dist/assets/{Slider-B0eLEEUt.js.map → Slider-Z4TP_CXY.js.map} +1 -1
  97. package/bizar-dash/dist/assets/{Sparkline-SSrdgyW0.js → Sparkline-cvkv2HbU.js} +1 -1
  98. package/bizar-dash/dist/assets/{Sparkline-SSrdgyW0.js.map → Sparkline-cvkv2HbU.js.map} +1 -1
  99. package/bizar-dash/dist/assets/{Switch-B3EQzb_q.js → Switch-jcYo4lmp.js} +1 -1
  100. package/bizar-dash/dist/assets/{Switch-B3EQzb_q.js.map → Switch-jcYo4lmp.js.map} +1 -1
  101. package/bizar-dash/dist/assets/{TasksView-SWjF_ZUQ.js → TasksView-CQaSFzWY.js} +2 -2
  102. package/bizar-dash/dist/assets/{TasksView-SWjF_ZUQ.js.map → TasksView-CQaSFzWY.js.map} +1 -1
  103. package/bizar-dash/dist/assets/{Textarea-QuofpMlq.js → Textarea-xnAybFGd.js} +1 -1
  104. package/bizar-dash/dist/assets/{Textarea-QuofpMlq.js.map → Textarea-xnAybFGd.js.map} +1 -1
  105. package/bizar-dash/dist/assets/UpdateView-BUAEcRCX.js +1 -0
  106. package/bizar-dash/dist/assets/UpdateView-BUAEcRCX.js.map +1 -0
  107. package/bizar-dash/dist/assets/{UsageView-BqOw6FBg.js → UsageView-DMFbBOfH.js} +1 -1
  108. package/bizar-dash/dist/assets/{UsageView-BqOw6FBg.js.map → UsageView-DMFbBOfH.js.map} +1 -1
  109. package/bizar-dash/dist/assets/{ViewHeader-B6P-C4GD.js → ViewHeader-C-t1U2cQ.js} +1 -1
  110. package/bizar-dash/dist/assets/{ViewHeader-B6P-C4GD.js.map → ViewHeader-C-t1U2cQ.js.map} +1 -1
  111. package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js +1 -0
  112. package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js.map +1 -0
  113. package/bizar-dash/dist/assets/{brain-CwZt9Kta.js → brain-DhAzcHUk.js} +1 -1
  114. package/bizar-dash/dist/assets/{brain-CwZt9Kta.js.map → brain-DhAzcHUk.js.map} +1 -1
  115. package/bizar-dash/dist/assets/{calendar-C5oK0_nM.js → calendar-B9Wbemh7.js} +1 -1
  116. package/bizar-dash/dist/assets/{calendar-C5oK0_nM.js.map → calendar-B9Wbemh7.js.map} +1 -1
  117. package/bizar-dash/dist/assets/{circle-D1Lc_P2a.js → circle-6NJF_Xl6.js} +1 -1
  118. package/bizar-dash/dist/assets/{circle-D1Lc_P2a.js.map → circle-6NJF_Xl6.js.map} +1 -1
  119. package/bizar-dash/dist/assets/{circle-alert-HdHe7m8K.js → circle-alert-Dz8lGfCZ.js} +1 -1
  120. package/bizar-dash/dist/assets/{circle-alert-HdHe7m8K.js.map → circle-alert-Dz8lGfCZ.js.map} +1 -1
  121. package/bizar-dash/dist/assets/{circle-check-Cs-xoV7R.js → circle-check-DFB50ojt.js} +1 -1
  122. package/bizar-dash/dist/assets/{circle-check-Cs-xoV7R.js.map → circle-check-DFB50ojt.js.map} +1 -1
  123. package/bizar-dash/dist/assets/{clock-DEIuPV60.js → clock-ClVA6-hQ.js} +1 -1
  124. package/bizar-dash/dist/assets/{clock-DEIuPV60.js.map → clock-ClVA6-hQ.js.map} +1 -1
  125. package/bizar-dash/dist/assets/{cmdk-DVxytz9i.js → cmdk-C3F6LD6N.js} +5 -5
  126. package/bizar-dash/dist/assets/{cmdk-DVxytz9i.js.map → cmdk-C3F6LD6N.js.map} +1 -1
  127. package/bizar-dash/dist/assets/{dnd-kit-DrHErSkw.js → dnd-kit-BAOLODOI.js} +1 -1
  128. package/bizar-dash/dist/assets/{dnd-kit-DrHErSkw.js.map → dnd-kit-BAOLODOI.js.map} +1 -1
  129. package/bizar-dash/dist/assets/{download-Clkq90Ct.js → download-BvJddD8D.js} +1 -1
  130. package/bizar-dash/dist/assets/{download-Clkq90Ct.js.map → download-BvJddD8D.js.map} +1 -1
  131. package/bizar-dash/dist/assets/{external-link-D5tq2o_I.js → external-link-DvL89gaZ.js} +1 -1
  132. package/bizar-dash/dist/assets/{external-link-D5tq2o_I.js.map → external-link-DvL89gaZ.js.map} +1 -1
  133. package/bizar-dash/dist/assets/{file-text-CQ12t7Oc.js → file-text-BOroDtZE.js} +1 -1
  134. package/bizar-dash/dist/assets/{file-text-CQ12t7Oc.js.map → file-text-BOroDtZE.js.map} +1 -1
  135. package/bizar-dash/dist/assets/{filter-BcbE37wP.js → filter-DwPjMRQt.js} +1 -1
  136. package/bizar-dash/dist/assets/{filter-BcbE37wP.js.map → filter-DwPjMRQt.js.map} +1 -1
  137. package/bizar-dash/dist/assets/{git-pull-request-D1qNDRia.js → git-pull-request-TDb1inux.js} +1 -1
  138. package/bizar-dash/dist/assets/{git-pull-request-D1qNDRia.js.map → git-pull-request-TDb1inux.js.map} +1 -1
  139. package/bizar-dash/dist/assets/{index-CASP1n-5.js → index-B1OIS316.js} +1 -1
  140. package/bizar-dash/dist/assets/{index-CASP1n-5.js.map → index-B1OIS316.js.map} +1 -1
  141. package/bizar-dash/dist/assets/{index-C4Vq_2LM.js → index-CR0TeJmc.js} +1 -1
  142. package/bizar-dash/dist/assets/{index-C4Vq_2LM.js.map → index-CR0TeJmc.js.map} +1 -1
  143. package/bizar-dash/dist/assets/{main-CcQfRfIJ.css → main-B7D_IMTh.css} +1 -1
  144. package/bizar-dash/dist/assets/main-BURAlktW.js +277 -0
  145. package/bizar-dash/dist/assets/main-BURAlktW.js.map +1 -0
  146. package/bizar-dash/dist/assets/{network-DJdvVaHx.js → network-BcCoCzIY.js} +1 -1
  147. package/bizar-dash/dist/assets/{network-DJdvVaHx.js.map → network-BcCoCzIY.js.map} +1 -1
  148. package/bizar-dash/dist/assets/{pause-DUn9L5PB.js → pause-BllItT2_.js} +1 -1
  149. package/bizar-dash/dist/assets/{pause-DUn9L5PB.js.map → pause-BllItT2_.js.map} +1 -1
  150. package/bizar-dash/dist/assets/{pencil-DVrBlYV3.js → pencil-DAwM-CC3.js} +1 -1
  151. package/bizar-dash/dist/assets/{pencil-DVrBlYV3.js.map → pencil-DAwM-CC3.js.map} +1 -1
  152. package/bizar-dash/dist/assets/{play-CZjsr3XM.js → play-mJh67AXo.js} +2 -2
  153. package/bizar-dash/dist/assets/{play-CZjsr3XM.js.map → play-mJh67AXo.js.map} +1 -1
  154. package/bizar-dash/dist/assets/{plug-BKuyIe5W.js → plug-BjfntCMC.js} +1 -1
  155. package/bizar-dash/dist/assets/{plug-BKuyIe5W.js.map → plug-BjfntCMC.js.map} +1 -1
  156. package/bizar-dash/dist/assets/{plus-77h62zZm.js → plus-Cm6-fo14.js} +1 -1
  157. package/bizar-dash/dist/assets/{plus-77h62zZm.js.map → plus-Cm6-fo14.js.map} +1 -1
  158. package/bizar-dash/dist/assets/{power-DLmx-gCP.js → power-CXN9y2KV.js} +1 -1
  159. package/bizar-dash/dist/assets/{power-DLmx-gCP.js.map → power-CXN9y2KV.js.map} +1 -1
  160. package/bizar-dash/dist/assets/{power-off-BFKzHXic.js → power-off-DUZqwMf9.js} +1 -1
  161. package/bizar-dash/dist/assets/{power-off-BFKzHXic.js.map → power-off-DUZqwMf9.js.map} +1 -1
  162. package/bizar-dash/dist/assets/{refresh-ccw-DenGBOcq.js → refresh-ccw-DA8_IB9l.js} +1 -1
  163. package/bizar-dash/dist/assets/{refresh-ccw-DenGBOcq.js.map → refresh-ccw-DA8_IB9l.js.map} +1 -1
  164. package/bizar-dash/dist/assets/{refresh-cw-ENBVR8hW.js → refresh-cw-DwlP59en.js} +1 -1
  165. package/bizar-dash/dist/assets/{refresh-cw-ENBVR8hW.js.map → refresh-cw-DwlP59en.js.map} +1 -1
  166. package/bizar-dash/dist/assets/{rotate-ccw-MxryaY7q.js → rotate-ccw-DMTASfAn.js} +1 -1
  167. package/bizar-dash/dist/assets/{rotate-ccw-MxryaY7q.js.map → rotate-ccw-DMTASfAn.js.map} +1 -1
  168. package/bizar-dash/dist/assets/{rotate-cw-CDOlRtUR.js → rotate-cw-BDX5SE2s.js} +1 -1
  169. package/bizar-dash/dist/assets/{rotate-cw-CDOlRtUR.js.map → rotate-cw-BDX5SE2s.js.map} +1 -1
  170. package/bizar-dash/dist/assets/{save-Db1b-1Uq.js → save-Y0jPK5D6.js} +1 -1
  171. package/bizar-dash/dist/assets/{save-Db1b-1Uq.js.map → save-Y0jPK5D6.js.map} +1 -1
  172. package/bizar-dash/dist/assets/{send-yz6HFZM5.js → send-C8wwPHhR.js} +2 -2
  173. package/bizar-dash/dist/assets/{send-yz6HFZM5.js.map → send-C8wwPHhR.js.map} +1 -1
  174. package/bizar-dash/dist/assets/{shield-alert-DY6RAaC8.js → shield-alert-DEvq9UG0.js} +1 -1
  175. package/bizar-dash/dist/assets/{shield-alert-DY6RAaC8.js.map → shield-alert-DEvq9UG0.js.map} +1 -1
  176. package/bizar-dash/dist/assets/{trash-2-Cv7U38jw.js → trash-2-D6qePV_q.js} +2 -2
  177. package/bizar-dash/dist/assets/{trash-2-Cv7U38jw.js.map → trash-2-D6qePV_q.js.map} +1 -1
  178. package/bizar-dash/dist/assets/{trending-up-CRPNagyX.js → trending-up-BZzo_1ic.js} +1 -1
  179. package/bizar-dash/dist/assets/{trending-up-CRPNagyX.js.map → trending-up-BZzo_1ic.js.map} +1 -1
  180. package/bizar-dash/dist/assets/{triangle-alert-tUTXbcEP.js → triangle-alert-B2oHbmoh.js} +1 -1
  181. package/bizar-dash/dist/assets/{triangle-alert-tUTXbcEP.js.map → triangle-alert-B2oHbmoh.js.map} +1 -1
  182. package/bizar-dash/dist/assets/{upload-Cq7uTsrT.js → upload-Dy59aZn6.js} +1 -1
  183. package/bizar-dash/dist/assets/{upload-Cq7uTsrT.js.map → upload-Dy59aZn6.js.map} +1 -1
  184. package/bizar-dash/dist/assets/{zap-5lAQBAPX.js → zap-DENVhJnO.js} +2 -2
  185. package/bizar-dash/dist/assets/{zap-5lAQBAPX.js.map → zap-DENVhJnO.js.map} +1 -1
  186. package/bizar-dash/dist/index.html +3 -3
  187. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  188. package/bizar-dash/src/web/v8/App.tsx +87 -6
  189. package/bizar-dash/src/web/v8/__tests__/chat-view.test.tsx +4 -4
  190. package/bizar-dash/src/web/v8/shell/AppShell.tsx +38 -2
  191. package/bizar-dash/src/web/v8/shell/Sidebar.tsx +52 -38
  192. package/bizar-dash/src/web/v8/shell/Topbar.tsx +62 -3
  193. package/bizar-dash/src/web/v8/ui/styles/globals.css +40 -0
  194. package/bizar-dash/src/web/v8/ui/theme/ThemeToggle.tsx +11 -6
  195. package/bizar-dash/src/web/v8/views/Admin/AdminView.tsx +32 -5
  196. package/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +36 -4
  197. package/bizar-dash/src/web/v8/views/Artifacts/ArtifactsView.tsx +1 -1
  198. package/bizar-dash/src/web/v8/views/Chat/ChatView.tsx +13 -1
  199. package/bizar-dash/src/web/v8/views/ClaudeSessions/NewSessionModal.tsx +136 -0
  200. package/bizar-dash/src/web/v8/views/Clipboard/ClipboardView.tsx +1 -1
  201. package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +14 -4
  202. package/bizar-dash/src/web/v8/views/Diagnostics/DiagnosticsView.tsx +50 -7
  203. package/bizar-dash/src/web/v8/views/Dialogs/DialogsView.tsx +1 -1
  204. package/bizar-dash/src/web/v8/views/Libraries/LibrariesView.tsx +6 -1
  205. package/bizar-dash/src/web/v8/views/Misc/MiscView.tsx +1 -1
  206. package/bizar-dash/src/web/v8/views/Notifications/NotificationsView.tsx +82 -13
  207. package/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +19 -0
  208. package/bizar-dash/src/web/v8/views/Projects/ProjectsView.tsx +21 -1
  209. package/bizar-dash/src/web/v8/views/Voice/VoiceView.tsx +1 -1
  210. package/bizar-dash/tests/admin-labels.test.mjs +42 -0
  211. package/bizar-dash/tests/admin-run-grouping.test.mjs +42 -0
  212. package/bizar-dash/tests/agents-preview-truncate.test.mjs +35 -0
  213. package/bizar-dash/tests/agents-summary-sanitize.test.ts +51 -0
  214. package/bizar-dash/tests/chat-new-session.test.mjs +63 -0
  215. package/bizar-dash/tests/empty-state-docs.test.mjs +55 -0
  216. package/bizar-dash/tests/focus-visible.test.mjs +30 -0
  217. package/bizar-dash/tests/kanban-empty-column.test.mjs +56 -0
  218. package/bizar-dash/tests/library-dedupe.test.mjs +62 -0
  219. package/bizar-dash/tests/notifications-dismiss-restore.test.mjs +85 -0
  220. package/bizar-dash/tests/palette-shortcut-hint.test.mjs +58 -0
  221. package/bizar-dash/tests/projects-filter.test.mjs +48 -0
  222. package/bizar-dash/tests/settings-labels.test.mjs +80 -0
  223. package/bizar-dash/tests/sidebar-distinct-icons.test.mjs +28 -0
  224. package/bizar-dash/tests/sidebar-responsive.test.tsx +48 -0
  225. package/bizar-dash/tests/sidebar-section-toggle.test.tsx +63 -0
  226. package/bizar-dash/tests/theme-toggle-icon.test.mjs +28 -0
  227. package/bizar-dash/tests/topbar-design-system.test.mjs +56 -0
  228. package/bizar-dash/vite.config.ts +8 -0
  229. package/package.json +1 -1
  230. package/packages/sdk/package.json +1 -1
  231. package/bizar-dash/dist/assets/AdminView-DNc5Ll7L.js +0 -11
  232. package/bizar-dash/dist/assets/AdminView-DNc5Ll7L.js.map +0 -1
  233. package/bizar-dash/dist/assets/AgentsView-Du-G_skK.js +0 -13
  234. package/bizar-dash/dist/assets/AgentsView-Du-G_skK.js.map +0 -1
  235. package/bizar-dash/dist/assets/ArtifactsView-znhN8GTR.js.map +0 -1
  236. package/bizar-dash/dist/assets/Avatar-B41upSD1.js +0 -6
  237. package/bizar-dash/dist/assets/Avatar-B41upSD1.js.map +0 -1
  238. package/bizar-dash/dist/assets/ChatView-CUriVEgU.js +0 -9
  239. package/bizar-dash/dist/assets/ChatView-CUriVEgU.js.map +0 -1
  240. package/bizar-dash/dist/assets/ClipboardView-DdP6aVso.js +0 -1
  241. package/bizar-dash/dist/assets/ClipboardView-DdP6aVso.js.map +0 -1
  242. package/bizar-dash/dist/assets/DiagnosticsView-88OZ5k0f.js +0 -2
  243. package/bizar-dash/dist/assets/DiagnosticsView-88OZ5k0f.js.map +0 -1
  244. package/bizar-dash/dist/assets/DialogsView-BcqDDCZQ.js +0 -6
  245. package/bizar-dash/dist/assets/DialogsView-BcqDDCZQ.js.map +0 -1
  246. package/bizar-dash/dist/assets/EvalView-CpdFu_ID.js +0 -1
  247. package/bizar-dash/dist/assets/LibrariesView-B1YX9wzp.js +0 -6
  248. package/bizar-dash/dist/assets/MiscView-DLNEGdML.js +0 -1
  249. package/bizar-dash/dist/assets/MiscView-DLNEGdML.js.map +0 -1
  250. package/bizar-dash/dist/assets/NotificationsView-DAm2O0yf.js +0 -6
  251. package/bizar-dash/dist/assets/NotificationsView-DAm2O0yf.js.map +0 -1
  252. package/bizar-dash/dist/assets/ObsidianView-Ci80gnwS.js +0 -1
  253. package/bizar-dash/dist/assets/OverviewView-rriw1GjA.js +0 -1
  254. package/bizar-dash/dist/assets/OverviewView-rriw1GjA.js.map +0 -1
  255. package/bizar-dash/dist/assets/ProjectsView-ChzM12bs.js +0 -11
  256. package/bizar-dash/dist/assets/ProjectsView-ChzM12bs.js.map +0 -1
  257. package/bizar-dash/dist/assets/UpdateView-CEHW2nd6.js +0 -6
  258. package/bizar-dash/dist/assets/UpdateView-CEHW2nd6.js.map +0 -1
  259. package/bizar-dash/dist/assets/VoiceView-CwrPwWgi.js +0 -1
  260. package/bizar-dash/dist/assets/VoiceView-CwrPwWgi.js.map +0 -1
  261. package/bizar-dash/dist/assets/main-Cxeu4LhG.js +0 -244
  262. package/bizar-dash/dist/assets/main-Cxeu4LhG.js.map +0 -1
@@ -21,6 +21,31 @@ import type { BizarAgent, CCAgent, WsMessage } from '../../data/types.js';
21
21
  import { AlertTriangle, Bot, Cpu, Pause, Play, Plus, RotateCw } from 'lucide-react';
22
22
  import { AgentHierarchy } from './AgentHierarchy.js';
23
23
 
24
+ /**
25
+ * Strip leaked LLM interior monologue from agent card snippets.
26
+ * Clips to the first sentence, caps at 140 chars.
27
+ */
28
+ export function sanitizeSummary(raw: string | undefined): string {
29
+ if (!raw) return '';
30
+ let s = raw.replace(/<thinking>[\s\S]*?<\/thinking>/gi, '');
31
+ s = s.split('\n').filter((l) => !l.includes('```')).join('\n');
32
+ s = s.replace(/\bworktree:\s*/g, '');
33
+ s = s.replace(/\/tmp\//g, '');
34
+ s = s.replace(/\bReason:\s*/g, '');
35
+ s = s.replace(/^\s*→\s*/gm, '');
36
+ s = s.trim();
37
+ if (!s) return '';
38
+ // Strip leading bracketed prefix — [Premise — …] or [Analysis] etc.
39
+ s = s.replace(/^\[[\w\s]+[-—]\s*/, '');
40
+ s = s.replace(/^\[[\w\s]+\]\s*/gi, '');
41
+ s = s.trim();
42
+ if (!s) return '';
43
+ const m = s.match(/^[^.!?\n]+[.!?]/);
44
+ const first = m ? m[0] : s;
45
+ if (first.length <= 140) return first;
46
+ return first.slice(0, 137) + '…';
47
+ }
48
+
24
49
  const SOURCE_STORAGE_KEY = 'bizar.agents.sourceFilter';
25
50
  const SOURCE_LABELS = {
26
51
  all: 'All',
@@ -83,24 +108,31 @@ function mapBizar(a: BizarAgent): AgentCardProps {
83
108
  };
84
109
  }
85
110
 
111
+ function truncatePreview(s: string, max = 80): string {
112
+ if (!s) return '';
113
+ return s.length <= max ? s : s.slice(0, max - 1) + '…';
114
+ }
115
+
86
116
  function mapCC(a: CCAgent): AgentCardProps {
87
117
  const raw = (a.status || a.state || 'idle').toLowerCase();
88
118
  const status: AgentStatus =
89
119
  raw === 'busy' || raw === 'working' ? 'busy' :
90
120
  raw === 'error' ? 'error' :
91
121
  raw === 'paused' ? 'paused' : 'idle';
122
+ const kind = a.kind === 'background' ? 'background' : 'interactive';
92
123
  return {
93
124
  id: `cc:${a.sessionId || a.id}`,
94
125
  name: a.name || a.sessionId?.slice(0, 8) || 'unknown',
95
- role: a.kind === 'background' ? 'CC background' : 'CC interactive',
126
+ role: kind === 'background' ? 'CC background' : 'CC interactive',
96
127
  status,
97
- currentTask: a.lastMessageSnippet || undefined,
128
+ currentTask: truncatePreview(sanitizeSummary(a.lastMessageSnippet)),
98
129
  lastActivity: a.lastMessageAt ? new Date(a.lastMessageAt).toLocaleTimeString() : (a.startedAt ? new Date(a.startedAt).toLocaleTimeString() : undefined),
99
130
  tasksToday: a.messageCount || 0,
100
131
  // CC agents don't expose successRate/tasksSucceeded — only messageCount.
101
132
  // Skip the metric strip for them; the badge + lastActivity carry the
102
- // signal.
103
- badges: [a.cwd?.split('/').slice(-2).join('/') || ''].filter(Boolean),
133
+ // signal. Include a kind chip so users can distinguish CC background
134
+ // sessions from interactive ones.
135
+ badges: [kind, a.cwd?.split('/').slice(-2).join('/') || ''].filter(Boolean),
104
136
  };
105
137
  }
106
138
 
@@ -94,7 +94,7 @@ export function ArtifactsView(): JSX.Element {
94
94
  <Skeleton style={{ height: 48 }} />
95
95
  </Stack>
96
96
  ) : artifacts.length === 0 ? (
97
- <EmptyState icon={<Layers size={28} aria-hidden />} title="No artifacts" description="Create one to get started." />
97
+ <EmptyState icon={<Layers size={28} aria-hidden />} title="No artifacts" description="Artifacts are generated code — HTML canvases, SVG diagrams, and React components — created by the agent during task work. Add one to get started." />
98
98
  ) : (
99
99
  <Stack gap={1}>
100
100
  {artifacts.map((a) => {
@@ -26,6 +26,7 @@ import { fetchJson, FetchError } from '../../data/fetcher.js';
26
26
  import { MessageBubble, EmptyTranscript } from '../../ui/chat/MessageBubble.js';
27
27
  import { readEventStream } from '../../ui/chat/EventStream.js';
28
28
  import type { ChatMessage, ChatSession, WsMessage } from '../../data/types.js';
29
+ import { NewSessionModal } from '../ClaudeSessions/NewSessionModal.js';
29
30
 
30
31
  interface ChatPayload {
31
32
  messages: ChatMessage[];
@@ -55,6 +56,7 @@ export function ChatView(): JSX.Element {
55
56
  const [busy, setBusy] = useState<boolean>(false);
56
57
  const [error, setError] = useState<string | null>(null);
57
58
  const [confirmDeleteId, setConfirmDeleteId] = useState<string | null>(null);
59
+ const [newSessionOpen, setNewSessionOpen] = useState<boolean>(false);
58
60
 
59
61
  // Seed active session from the first row in the response.
60
62
  useEffect(() => {
@@ -198,7 +200,7 @@ export function ChatView(): JSX.Element {
198
200
  <Button variant="ghost" onClick={() => void audit()} data-testid="chat-audit">
199
201
  <ShieldCheck size={14} aria-hidden /> Audit
200
202
  </Button>
201
- <Button variant="primary" onClick={() => void createSession()} data-testid="chat-create-session">
203
+ <Button variant="primary" onClick={() => setNewSessionOpen(true)} data-testid="chat-create-session">
202
204
  <MessageSquarePlus size={14} aria-hidden /> New session
203
205
  </Button>
204
206
  </Inline>
@@ -351,6 +353,16 @@ export function ChatView(): JSX.Element {
351
353
  </CardBody>
352
354
  </Card>
353
355
  </Inline>
356
+
357
+ <NewSessionModal
358
+ open={newSessionOpen}
359
+ onOpenChange={setNewSessionOpen}
360
+ onCreated={(id) => {
361
+ setActiveId(id);
362
+ void payload.refetch();
363
+ void sessionsPayload.refetch();
364
+ }}
365
+ />
354
366
  </Stack>
355
367
  );
356
368
  }
@@ -0,0 +1,136 @@
1
+ /**
2
+ * NewSessionModal — shared new-session Sheet, extracted from
3
+ * ClaudeSessionsView so ChatView can reuse the same form.
4
+ */
5
+
6
+ import { useState } from 'react';
7
+ import { Stack } from '../../ui/primitives/Stack.js';
8
+ import { Inline } from '../../ui/primitives/Inline.js';
9
+ import { Button } from '../../ui/controls/Button.js';
10
+ import { Input } from '../../ui/controls/Input.js';
11
+ import { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';
12
+ import { fetchJson, FetchError } from '../../data/fetcher.js';
13
+
14
+ interface NewSessionModalProps {
15
+ open: boolean;
16
+ onOpenChange: (open: boolean) => void;
17
+ onCreated: (id: string) => void;
18
+ }
19
+
20
+ export function NewSessionModal({ open, onOpenChange, onCreated }: NewSessionModalProps): JSX.Element {
21
+ return (
22
+ <Sheet open={open} onOpenChange={onOpenChange}>
23
+ <SheetContent side="right" title="New Claude session" description="Spawn a Claude Code session via the runner.">
24
+ <NewSessionForm
25
+ onCreated={(id) => {
26
+ onOpenChange(false);
27
+ onCreated(id);
28
+ }}
29
+ onCancel={() => onOpenChange(false)}
30
+ />
31
+ </SheetContent>
32
+ </Sheet>
33
+ );
34
+ }
35
+
36
+ interface NewSessionFormProps {
37
+ onCreated: (id: string) => void;
38
+ onCancel: () => void;
39
+ }
40
+
41
+ export function NewSessionForm({ onCreated, onCancel }: NewSessionFormProps): JSX.Element {
42
+ const [title, setTitle] = useState<string>('');
43
+ const [agent, setAgent] = useState<string>('general');
44
+ const [prompt, setPrompt] = useState<string>('');
45
+ const [directory, setDirectory] = useState<string>('');
46
+ const [busy, setBusy] = useState<boolean>(false);
47
+ const [error, setError] = useState<string | null>(null);
48
+
49
+ const submit = async (): Promise<void> => {
50
+ if (!agent.trim() || !prompt.trim() || busy) return;
51
+ setBusy(true);
52
+ setError(null);
53
+ try {
54
+ const res = await fetchJson<{ id: string }>('/api/claude-sessions/new', {
55
+ method: 'POST',
56
+ body: {
57
+ title: title.trim() || null,
58
+ agent: agent.trim(),
59
+ prompt: prompt.trim(),
60
+ directory: directory.trim() || undefined,
61
+ },
62
+ });
63
+ onCreated(res.id);
64
+ } catch (err) {
65
+ setError(err instanceof FetchError ? err.message : (err as Error).message);
66
+ } finally {
67
+ setBusy(false);
68
+ }
69
+ };
70
+
71
+ return (
72
+ <Stack gap={3} style={{ padding: 'var(--space-4)' }}>
73
+ <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>
74
+ <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Title (optional)</span>
75
+ <Input
76
+ value={title}
77
+ data-testid="claude-sessions-new-title"
78
+ onChange={(e) => setTitle((e.target as HTMLInputElement).value)}
79
+ />
80
+ </label>
81
+ <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>
82
+ <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Agent</span>
83
+ <Input
84
+ value={agent}
85
+ data-testid="claude-sessions-new-agent"
86
+ onChange={(e) => setAgent((e.target as HTMLInputElement).value)}
87
+ />
88
+ </label>
89
+ <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>
90
+ <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Seed prompt</span>
91
+ <textarea
92
+ value={prompt}
93
+ rows={4}
94
+ data-testid="claude-sessions-new-prompt"
95
+ onChange={(e) => setPrompt(e.target.value)}
96
+ style={{
97
+ background: 'var(--surface-0)',
98
+ border: '1px solid var(--border)',
99
+ borderRadius: 'var(--radius-md)',
100
+ padding: 'var(--space-2)',
101
+ color: 'var(--fg)',
102
+ fontFamily: 'var(--font-sans)',
103
+ fontSize: 'var(--fs-13)',
104
+ resize: 'vertical',
105
+ }}
106
+ />
107
+ </label>
108
+ <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>
109
+ <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Working directory (optional)</span>
110
+ <Input
111
+ value={directory}
112
+ data-testid="claude-sessions-new-directory"
113
+ onChange={(e) => setDirectory((e.target as HTMLInputElement).value)}
114
+ />
115
+ </label>
116
+ {error !== null && (
117
+ <span role="alert" data-testid="claude-sessions-new-error" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>
118
+ {error}
119
+ </span>
120
+ )}
121
+ <Inline justify="end" gap={2}>
122
+ <SheetClose asChild>
123
+ <Button variant="ghost" onClick={onCancel} data-testid="claude-sessions-new-cancel">Cancel</Button>
124
+ </SheetClose>
125
+ <Button
126
+ variant="primary"
127
+ onClick={() => void submit()}
128
+ disabled={busy || !agent.trim() || !prompt.trim()}
129
+ data-testid="claude-sessions-new-submit"
130
+ >
131
+ Create
132
+ </Button>
133
+ </Inline>
134
+ </Stack>
135
+ );
136
+ }
@@ -81,7 +81,7 @@ export function ClipboardView(): JSX.Element {
81
81
  <Skeleton style={{ height: 60 }} />
82
82
  </Stack>
83
83
  ) : clips.length === 0 ? (
84
- <EmptyState icon={<ClipboardPaste size={28} aria-hidden />} title="No saved clips" description="Save one with a URL + content." />
84
+ <EmptyState icon={<ClipboardPaste size={28} aria-hidden />} title="No saved clips" description="Clips are saved URL + text pairs captured from the clipboard during agent work. Each becomes a markdown note under clips/. Save one to get started." />
85
85
  ) : (
86
86
  <Stack gap={1}>
87
87
  {clips.map((c) => {
@@ -110,6 +110,14 @@ interface Project {
110
110
  cwd?: string;
111
111
  }
112
112
 
113
+ /** Mirror of ProjectsView.isTestProject — keeps test projects out of the palette. */
114
+ function isTestProject(p: Project): boolean {
115
+ return (
116
+ /^(bizar-(e2e|real-env|admin)|bh-(cold-boot|walk-proj))/.test(p.id) ||
117
+ (p.name != null && p.name === p.id)
118
+ );
119
+ }
120
+
113
121
  async function spawnAgent(
114
122
  kind: string,
115
123
  onToast?: AppCommandPaletteProps['onToast'],
@@ -197,10 +205,12 @@ export function AppCommandPalette(props: AppCommandPaletteProps): JSX.Element {
197
205
  void newTask(title, onToast);
198
206
  };
199
207
 
200
- const projectItems: NavItem[] = projects.map((p) => ({
201
- id: `project:${p.id}`,
202
- label: `Switch to ${p.name || p.id}`,
203
- }));
208
+ const projectItems: NavItem[] = projects
209
+ .filter((p) => !isTestProject(p))
210
+ .map((p) => ({
211
+ id: `project:${p.id}`,
212
+ label: `Switch to ${p.name || p.id}`,
213
+ }));
204
214
 
205
215
  return (
206
216
  <Dialog open={open} onOpenChange={onOpenChange}>
@@ -20,11 +20,13 @@ interface DiagnosticsHealth {
20
20
  }
21
21
 
22
22
  interface DiagnosticsSnapshot {
23
- health?: DiagnosticsHealth;
24
- uptime?: number;
25
23
  version?: string;
26
- memory?: { used?: number; total?: number };
24
+ uptime?: number;
25
+ memory?: { rss?: number; heapUsed?: number; heapTotal?: number };
27
26
  checks?: Array<{ name: string; status: string; message?: string }>;
27
+ counts?: Record<string, number | string | null>;
28
+ errors?: Array<{ line: string; ts: string | null }>;
29
+ service?: { running?: boolean; pid?: number };
28
30
  }
29
31
 
30
32
  interface LogsResponse {
@@ -53,9 +55,9 @@ export function DiagnosticsView(): JSX.Element {
53
55
  return () => clearInterval(id);
54
56
  }, [logs]);
55
57
 
56
- const health = snap.data?.health;
57
58
  const uptime = snap.data?.uptime;
58
59
  const checks = snap.data?.checks ?? [];
60
+ const counts = snap.data?.counts ?? {};
59
61
  const lines = logs.data?.lines ?? [];
60
62
  const logFile = logs.data?.file ?? null;
61
63
 
@@ -78,7 +80,13 @@ export function DiagnosticsView(): JSX.Element {
78
80
  <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Status</span>
79
81
  <Inline align="center" gap={2}>
80
82
  <Activity size={14} aria-hidden />
81
- <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.loading ? '…' : health?.status ?? 'unknown'}</strong>
83
+ <strong style={{ fontFamily: 'var(--font-mono)' }}>
84
+ {snap.loading ? '…' : (
85
+ snap.error ? 'error' :
86
+ !snap.data?.service?.running ? 'stopped' :
87
+ (snap.data?.errors?.length ?? 0) > 0 ? 'warn' : 'ok'
88
+ )}
89
+ </strong>
82
90
  </Inline>
83
91
  </Stack>
84
92
  </CardBody>
@@ -87,7 +95,7 @@ export function DiagnosticsView(): JSX.Element {
87
95
  <CardBody>
88
96
  <Stack gap={1}>
89
97
  <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Uptime</span>
90
- <strong style={{ fontFamily: 'var(--font-mono)' }}>{fmtUptime(uptime)}</strong>
98
+ <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.loading ? '…' : fmtUptime(uptime)}</strong>
91
99
  </Stack>
92
100
  </CardBody>
93
101
  </Card>
@@ -95,12 +103,47 @@ export function DiagnosticsView(): JSX.Element {
95
103
  <CardBody>
96
104
  <Stack gap={1}>
97
105
  <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Version</span>
98
- <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.data?.version ?? '—'}</strong>
106
+ <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.loading ? '…' : (snap.data?.version ?? '—')}</strong>
99
107
  </Stack>
100
108
  </CardBody>
101
109
  </Card>
102
110
  </Grid>
103
111
 
112
+ {snap.error && (
113
+ <Card variant="default" style={{ borderColor: 'var(--danger)' }}>
114
+ <CardBody>
115
+ <Stack gap={2}>
116
+ <Inline align="center" gap={2}>
117
+ <Activity size={14} aria-hidden style={{ color: 'var(--danger)' }} />
118
+ <strong style={{ color: 'var(--danger)' }}>Diagnostics fetch failed</strong>
119
+ </Inline>
120
+ <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{snap.error.message ?? String(snap.error)}</span>
121
+ <Button variant="secondary" size="sm" onClick={() => { void snap.refetch(); }}>
122
+ <RefreshCw size={12} aria-hidden /> Retry
123
+ </Button>
124
+ </Stack>
125
+ </CardBody>
126
+ </Card>
127
+ )}
128
+
129
+ {Object.keys(counts).length > 0 && (
130
+ <Card variant="default">
131
+ <CardBody>
132
+ <Stack gap={2}>
133
+ <strong>Counts</strong>
134
+ <Grid cols={4}>
135
+ {Object.entries(counts).map(([k, v]) => (
136
+ <Stack key={k} gap={0}>
137
+ <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>{k}</span>
138
+ <strong style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-13)' }}>{String(v ?? '—')}</strong>
139
+ </Stack>
140
+ ))}
141
+ </Grid>
142
+ </Stack>
143
+ </CardBody>
144
+ </Card>
145
+ )}
146
+
104
147
  {checks.length > 0 && (
105
148
  <Card variant="default">
106
149
  <CardBody>
@@ -103,7 +103,7 @@ export function DialogsView(): JSX.Element {
103
103
  <EmptyState
104
104
  icon={<MessageSquare size={28} aria-hidden />}
105
105
  title="No active dialogs"
106
- description="Dialogs enqueued via the slash-command plugin will appear here."
106
+ 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."
107
107
  />
108
108
  ) : (
109
109
  <Stack gap={1}>
@@ -84,7 +84,12 @@ export function LibrariesView(props: LibrariesViewProps): JSX.Element {
84
84
  if (bust > 0) res.refetch();
85
85
  }, [bust, res]);
86
86
 
87
- const items: LibraryItemProps[] = (res.data?.skills || res.data?.items || []).map(mapItem);
87
+ const items: LibraryItemProps[] = (res.data?.skills || res.data?.items || [])
88
+ .map(mapItem)
89
+ .reduce<LibraryItemProps[]>((acc, item) => {
90
+ if (!acc.some((existing) => existing.name === item.name)) acc.push(item);
91
+ return acc;
92
+ }, []);
88
93
 
89
94
  return (
90
95
  <Stack gap={5} data-testid={`${kind}-view`}>
@@ -45,7 +45,7 @@ interface TailscaleStatus {
45
45
  export function MiscView(): JSX.Element {
46
46
  return (
47
47
  <Stack gap={4} data-testid="misc-view">
48
- <ViewHeader title="Misc" description="Global search + Tailscale." />
48
+ <ViewHeader title="Misc" description="Global fuzzy search across projects, tasks, and agents — plus Tailscale VPN control." />
49
49
  <SearchPanel />
50
50
  <TailscalePanel />
51
51
  </Stack>
@@ -1,5 +1,5 @@
1
1
  import { useCallback, useEffect, useState } from 'react';
2
- import { Bell, CheckCheck, Trash2, RefreshCw } from 'lucide-react';
2
+ import { Bell, CheckCheck, Trash2, RefreshCw, RotateCcw } from 'lucide-react';
3
3
  import { Stack } from '../../ui/primitives/Stack.js';
4
4
  import { Inline } from '../../ui/primitives/Inline.js';
5
5
  import { ViewHeader } from '../../ui/data/ViewHeader.js';
@@ -16,7 +16,8 @@ import type { WsMessage } from '../../data/types.js';
16
16
  /**
17
17
  * NotificationsView — Sprint S35. Per-user notification stream backed
18
18
  * by `/api/notifications`. Pulls unread + read mixed, supports
19
- * mark-one-read, mark-all-read, and dismiss.
19
+ * mark-one-read, mark-all-read, dismiss with 5s undo, and
20
+ * "Show dismissed" with restore.
20
21
  */
21
22
 
22
23
  type Tone = 'neutral' | 'info' | 'success' | 'warning' | 'danger';
@@ -36,6 +37,12 @@ interface NotificationsResponse {
36
37
  stats?: { total: number; unread: number };
37
38
  }
38
39
 
40
+ interface UndoToast {
41
+ id: string;
42
+ item: NotificationItem;
43
+ timer: ReturnType<typeof setTimeout>;
44
+ }
45
+
39
46
  function toneFor(item: NotificationItem): Tone {
40
47
  if (item.tone && ['info', 'success', 'warning', 'danger', 'neutral'].includes(item.tone)) {
41
48
  return item.tone as Tone;
@@ -57,6 +64,9 @@ function fmtRel(iso: string | undefined): string {
57
64
  export function NotificationsView(): JSX.Element {
58
65
  const res = useFetch<NotificationsResponse>('/api/notifications?limit=200');
59
66
  const [items, setItems] = useState<NotificationItem[]>([]);
67
+ const [dismissed, setDismissed] = useState<NotificationItem[]>([]);
68
+ const [showDismissed, setShowDismissed] = useState(false);
69
+ const [undoToast, setUndoToast] = useState<UndoToast | null>(null);
60
70
  const [busy, setBusy] = useState<string | null>(null);
61
71
  const [error, setError] = useState<string | null>(null);
62
72
 
@@ -95,12 +105,29 @@ export function NotificationsView(): JSX.Element {
95
105
  }
96
106
  };
97
107
 
108
+ const restore = (item: NotificationItem): void => {
109
+ clearTimeout(undoToast?.timer);
110
+ setUndoToast(null);
111
+ setDismissed((prev) => prev.filter((n) => n.id !== item.id));
112
+ setItems((prev) => [item, ...prev]);
113
+ };
114
+
98
115
  const dismiss = async (id: string): Promise<void> => {
116
+ const item = items.find((n) => n.id === id);
117
+ if (!item) return;
99
118
  setBusy(id);
100
119
  setError(null);
101
120
  try {
102
121
  await fetchJson(`/api/notifications/${encodeURIComponent(id)}`, { method: 'DELETE' });
103
122
  setItems((prev) => prev.filter((n) => n.id !== id));
123
+ setDismissed((prev) => [item, ...prev]);
124
+
125
+ // 5-second undo window
126
+ const timer = setTimeout(() => {
127
+ setDismissed((prev) => prev.filter((n) => n.id !== id));
128
+ setUndoToast((cur) => (cur?.id === id ? null : cur));
129
+ }, 5_000);
130
+ setUndoToast({ id, item, timer });
104
131
  } catch (err) {
105
132
  setError(err instanceof FetchError ? err.message : (err as Error).message);
106
133
  } finally {
@@ -109,12 +136,13 @@ export function NotificationsView(): JSX.Element {
109
136
  };
110
137
 
111
138
  const unread = items.filter((n) => !n.read).length;
139
+ const visibleItems = showDismissed ? [...items, ...dismissed] : items;
112
140
 
113
141
  return (
114
142
  <Stack gap={5} data-testid="notifications-view">
115
143
  <ViewHeader
116
144
  title="Notifications"
117
- description={`${unread} unread of ${items.length} total. Backed by ~/.config/bizar/notifications.jsonl.`}
145
+ description={`${unread} unread of ${items.length} total${dismissed.length > 0 ? `, ${dismissed.length} dismissed` : ''}. Backed by ~/.config/bizar/notifications.jsonl.`}
118
146
  actions={
119
147
  <Inline gap={2} align="center">
120
148
  {error !== null && <span role="alert" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>}
@@ -124,6 +152,11 @@ export function NotificationsView(): JSX.Element {
124
152
  <Button variant="secondary" onClick={() => void markAll()} disabled={busy === 'all' || unread === 0} data-testid="notifications-mark-all">
125
153
  <CheckCheck size={14} aria-hidden /> Mark all read
126
154
  </Button>
155
+ {dismissed.length > 0 && (
156
+ <Button variant="ghost" onClick={() => setShowDismissed((v) => !v)} data-testid="notifications-toggle-dismissed">
157
+ {showDismissed ? 'Hide dismissed' : `Show dismissed (${dismissed.length})`}
158
+ </Button>
159
+ )}
127
160
  </Inline>
128
161
  }
129
162
  />
@@ -133,7 +166,7 @@ export function NotificationsView(): JSX.Element {
133
166
  <Skeleton style={{ height: 64 }} />
134
167
  <Skeleton style={{ height: 64 }} />
135
168
  </Stack>
136
- ) : items.length === 0 ? (
169
+ ) : items.length === 0 && dismissed.length === 0 ? (
137
170
  <EmptyState
138
171
  icon={<Bell size={32} aria-hidden />}
139
172
  title="No notifications"
@@ -141,15 +174,17 @@ export function NotificationsView(): JSX.Element {
141
174
  />
142
175
  ) : (
143
176
  <Stack gap={2}>
144
- {items.map((n) => {
177
+ {visibleItems.map((n) => {
178
+ const isDismissed = dismissed.some((d) => d.id === n.id);
145
179
  const tone = toneFor(n);
146
180
  return (
147
- <Card key={n.id} variant="default" style={{ opacity: n.read ? 0.7 : 1 }}>
181
+ <Card key={n.id} variant="default" style={{ opacity: isDismissed || n.read ? 0.7 : 1 }}>
148
182
  <CardBody>
149
183
  <Inline align="start" justify="between" gap={3}>
150
184
  <Stack gap={1} style={{ flex: 1, minWidth: 0 }}>
151
185
  <Inline align="center" gap={2}>
152
- {!n.read && <span aria-label="Unread" style={{ width: 8, height: 8, borderRadius: 'var(--radius-pill)', background: 'var(--accent)' }} />}
186
+ {isDismissed && <span data-testid={`notification-dismissed-badge-${n.id}`} style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>dismissed</span>}
187
+ {!n.read && !isDismissed && <span aria-label="Unread" style={{ width: 8, height: 8, borderRadius: 'var(--radius-pill)', background: 'var(--accent)' }} />}
153
188
  <strong style={{ fontSize: 'var(--fs-13)' }}>{n.title || n.source || n.id}</strong>
154
189
  {n.source && <Badge tone={tone}>{n.source}</Badge>}
155
190
  <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>{fmtRel(n.createdAt)}</span>
@@ -157,14 +192,22 @@ export function NotificationsView(): JSX.Element {
157
192
  {n.body && <span style={{ fontSize: 'var(--fs-13)', color: 'var(--fg-muted)' }}>{n.body}</span>}
158
193
  </Stack>
159
194
  <Inline gap={1}>
160
- {!n.read && (
161
- <Button variant="ghost" onClick={() => void markRead(n.id)} disabled={busy === n.id} data-testid={`notification-read-${n.id}`}>
162
- Mark read
195
+ {isDismissed ? (
196
+ <Button variant="ghost" onClick={() => restore(n)} data-testid={`notification-restore-${n.id}`}>
197
+ <RotateCcw size={12} aria-hidden /> Restore
163
198
  </Button>
199
+ ) : (
200
+ <>
201
+ {!n.read && (
202
+ <Button variant="ghost" onClick={() => void markRead(n.id)} disabled={busy === n.id} data-testid={`notification-read-${n.id}`}>
203
+ Mark read
204
+ </Button>
205
+ )}
206
+ <Button variant="ghost" onClick={() => void dismiss(n.id)} disabled={busy === n.id} data-testid={`notification-dismiss-${n.id}`}>
207
+ <Trash2 size={12} aria-hidden /> Dismiss
208
+ </Button>
209
+ </>
164
210
  )}
165
- <Button variant="ghost" onClick={() => void dismiss(n.id)} disabled={busy === n.id} data-testid={`notification-dismiss-${n.id}`}>
166
- <Trash2 size={12} aria-hidden /> Dismiss
167
- </Button>
168
211
  </Inline>
169
212
  </Inline>
170
213
  </CardBody>
@@ -173,6 +216,32 @@ export function NotificationsView(): JSX.Element {
173
216
  })}
174
217
  </Stack>
175
218
  )}
219
+ {undoToast !== null && (
220
+ <Card variant="default" data-testid="notifications-undo-toast" style={{ border: '1px solid var(--accent)', background: 'var(--surface-1)' }}>
221
+ <CardBody>
222
+ <Inline align="center" justify="between" gap={3}>
223
+ <span style={{ fontSize: 'var(--fs-13)' }}>
224
+ Notification dismissed.{' '}
225
+ <button
226
+ type="button"
227
+ onClick={() => {
228
+ clearTimeout(undoToast.timer);
229
+ setUndoToast(null);
230
+ restore(undoToast.item);
231
+ }}
232
+ style={{ background: 'none', border: 'none', color: 'var(--accent)', cursor: 'pointer', fontSize: 'inherit', padding: 0, textDecoration: 'underline' }}
233
+ data-testid="notifications-undo-btn"
234
+ >
235
+ Undo
236
+ </button>
237
+ </span>
238
+ <Button variant="ghost" size="sm" onClick={() => { clearTimeout(undoToast.timer); setUndoToast(null); }} data-testid="notifications-undo-close">
239
+
240
+ </Button>
241
+ </Inline>
242
+ </CardBody>
243
+ </Card>
244
+ )}
176
245
  </Stack>
177
246
  );
178
247
  }