@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.
- package/bizar-dash/dist/assets/{ActivityFeed-DtRtg-JN.js → ActivityFeed-RQeyFifx.js} +1 -1
- package/bizar-dash/dist/assets/{ActivityFeed-DtRtg-JN.js.map → ActivityFeed-RQeyFifx.js.map} +1 -1
- package/bizar-dash/dist/assets/{ActivityView-CoTXDyU_.js → ActivityView-CibyssPM.js} +1 -1
- package/bizar-dash/dist/assets/{ActivityView-CoTXDyU_.js.map → ActivityView-CibyssPM.js.map} +1 -1
- package/bizar-dash/dist/assets/AdminView-BjczABeB.js +11 -0
- package/bizar-dash/dist/assets/AdminView-BjczABeB.js.map +1 -0
- package/bizar-dash/dist/assets/{AgentActivity-CrX7LmQ6.js → AgentActivity-Bywt1twv.js} +1 -1
- package/bizar-dash/dist/assets/{AgentActivity-CrX7LmQ6.js.map → AgentActivity-Bywt1twv.js.map} +1 -1
- package/bizar-dash/dist/assets/AgentsView-BnOjjM74.js +15 -0
- package/bizar-dash/dist/assets/AgentsView-BnOjjM74.js.map +1 -0
- package/bizar-dash/dist/assets/{Alert-B6DjfRFI.js → Alert-BZGk39mB.js} +1 -1
- package/bizar-dash/dist/assets/{Alert-B6DjfRFI.js.map → Alert-BZGk39mB.js.map} +1 -1
- package/bizar-dash/dist/assets/{ArtifactsView-znhN8GTR.js → ArtifactsView-CfYB1le1.js} +3 -3
- package/bizar-dash/dist/assets/ArtifactsView-CfYB1le1.js.map +1 -0
- package/bizar-dash/dist/assets/{AuthView-Rk8eKUPr.js → AuthView-D4frSShw.js} +1 -1
- package/bizar-dash/dist/assets/{AuthView-Rk8eKUPr.js.map → AuthView-D4frSShw.js.map} +1 -1
- package/bizar-dash/dist/assets/Avatar-BYg0rkPA.js +6 -0
- package/bizar-dash/dist/assets/Avatar-BYg0rkPA.js.map +1 -0
- package/bizar-dash/dist/assets/{BackgroundJobsView-BLWuN9qz.js → BackgroundJobsView-DEStvILz.js} +1 -1
- package/bizar-dash/dist/assets/{BackgroundJobsView-BLWuN9qz.js.map → BackgroundJobsView-DEStvILz.js.map} +1 -1
- package/bizar-dash/dist/assets/{BackupView-CqbtcnuQ.js → BackupView-B875KQa4.js} +1 -1
- package/bizar-dash/dist/assets/{BackupView-CqbtcnuQ.js.map → BackupView-B875KQa4.js.map} +1 -1
- package/bizar-dash/dist/assets/Banner-C8HEcT5l.js +1 -0
- package/bizar-dash/dist/assets/Banner-C8HEcT5l.js.map +1 -0
- package/bizar-dash/dist/assets/{Card-rF59wHiO.js → Card-BtsmkhJa.js} +1 -1
- package/bizar-dash/dist/assets/{Card-rF59wHiO.js.map → Card-BtsmkhJa.js.map} +1 -1
- package/bizar-dash/dist/assets/ChatView-CkNS0SD8.js +9 -0
- package/bizar-dash/dist/assets/ChatView-CkNS0SD8.js.map +1 -0
- package/bizar-dash/dist/assets/{Chip-Dc2KmeWl.js → Chip-XPOk0d_E.js} +1 -1
- package/bizar-dash/dist/assets/{Chip-Dc2KmeWl.js.map → Chip-XPOk0d_E.js.map} +1 -1
- package/bizar-dash/dist/assets/{ClaudeSessionsView-CiaHQdDZ.js → ClaudeSessionsView-BprGo67K.js} +1 -1
- package/bizar-dash/dist/assets/{ClaudeSessionsView-CiaHQdDZ.js.map → ClaudeSessionsView-BprGo67K.js.map} +1 -1
- package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js +1 -0
- package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js.map +1 -0
- package/bizar-dash/dist/assets/{ConfigView-B2ysnTZU.js → ConfigView-BntUrW7s.js} +1 -1
- package/bizar-dash/dist/assets/{ConfigView-B2ysnTZU.js.map → ConfigView-BntUrW7s.js.map} +1 -1
- package/bizar-dash/dist/assets/DiagnosticsView-4x0Zu3yP.js +2 -0
- package/bizar-dash/dist/assets/DiagnosticsView-4x0Zu3yP.js.map +1 -0
- package/bizar-dash/dist/assets/DialogsView-Xd02dVAX.js +6 -0
- package/bizar-dash/dist/assets/DialogsView-Xd02dVAX.js.map +1 -0
- package/bizar-dash/dist/assets/{DoctorView-BQwqvMAh.js → DoctorView-DepBdQGR.js} +2 -2
- package/bizar-dash/dist/assets/{DoctorView-BQwqvMAh.js.map → DoctorView-DepBdQGR.js.map} +1 -1
- package/bizar-dash/dist/assets/{EmptyState-D65J5FQN.js → EmptyState-DjKtY1Qi.js} +1 -1
- package/bizar-dash/dist/assets/{EmptyState-D65J5FQN.js.map → EmptyState-DjKtY1Qi.js.map} +1 -1
- package/bizar-dash/dist/assets/{EnvVarsView-DX-3oGH-.js → EnvVarsView-S4Pbm128.js} +3 -3
- package/bizar-dash/dist/assets/{EnvVarsView-DX-3oGH-.js.map → EnvVarsView-S4Pbm128.js.map} +1 -1
- package/bizar-dash/dist/assets/{ErrorState-DULZnttJ.js → ErrorState-CBJbEQ8B.js} +1 -1
- package/bizar-dash/dist/assets/{ErrorState-DULZnttJ.js.map → ErrorState-CBJbEQ8B.js.map} +1 -1
- package/bizar-dash/dist/assets/EvalView-BeAyMCD1.js +1 -0
- package/bizar-dash/dist/assets/{EvalView-CpdFu_ID.js.map → EvalView-BeAyMCD1.js.map} +1 -1
- package/bizar-dash/dist/assets/{GoalsView-Br8oPPfb.js → GoalsView-BZr8In4c.js} +1 -1
- package/bizar-dash/dist/assets/{GoalsView-Br8oPPfb.js.map → GoalsView-BZr8In4c.js.map} +1 -1
- package/bizar-dash/dist/assets/{Grid-BSXhsCPC.js → Grid--WKvqu5h.js} +1 -1
- package/bizar-dash/dist/assets/{Grid-BSXhsCPC.js.map → Grid--WKvqu5h.js.map} +1 -1
- package/bizar-dash/dist/assets/{HistoryView-D0J3aoZF.js → HistoryView-djEbzqtk.js} +1 -1
- package/bizar-dash/dist/assets/{HistoryView-D0J3aoZF.js.map → HistoryView-djEbzqtk.js.map} +1 -1
- package/bizar-dash/dist/assets/{Input-CZmRw5QX.js → Input-h_nSOtwm.js} +1 -1
- package/bizar-dash/dist/assets/{Input-CZmRw5QX.js.map → Input-h_nSOtwm.js.map} +1 -1
- package/bizar-dash/dist/assets/LibrariesView-Vez8CvNq.js +6 -0
- package/bizar-dash/dist/assets/{LibrariesView-B1YX9wzp.js.map → LibrariesView-Vez8CvNq.js.map} +1 -1
- package/bizar-dash/dist/assets/{LightRAGView-CykR0t9y.js → LightRAGView-DvqzQoBp.js} +1 -1
- package/bizar-dash/dist/assets/{LightRAGView-CykR0t9y.js.map → LightRAGView-DvqzQoBp.js.map} +1 -1
- package/bizar-dash/dist/assets/{ListHeader-Dpun-r36.js → ListHeader-CM8QoIWG.js} +1 -1
- package/bizar-dash/dist/assets/{ListHeader-Dpun-r36.js.map → ListHeader-CM8QoIWG.js.map} +1 -1
- package/bizar-dash/dist/assets/{MemoryView-BbER5ZKt.js → MemoryView-DnL8E2vI.js} +1 -1
- package/bizar-dash/dist/assets/{MemoryView-BbER5ZKt.js.map → MemoryView-DnL8E2vI.js.map} +1 -1
- package/bizar-dash/dist/assets/{MessageBubble-5vUAquDx.js → MessageBubble-CrCJ0SYG.js} +1 -1
- package/bizar-dash/dist/assets/{MessageBubble-5vUAquDx.js.map → MessageBubble-CrCJ0SYG.js.map} +1 -1
- package/bizar-dash/dist/assets/MiscView-B2YQXhZ_.js +1 -0
- package/bizar-dash/dist/assets/MiscView-B2YQXhZ_.js.map +1 -0
- package/bizar-dash/dist/assets/{ModsView-P7gDeNHM.js → ModsView-BVM3X5xc.js} +1 -1
- package/bizar-dash/dist/assets/{ModsView-P7gDeNHM.js.map → ModsView-BVM3X5xc.js.map} +1 -1
- package/bizar-dash/dist/assets/NotificationsView-A-Xs8BL1.js +6 -0
- package/bizar-dash/dist/assets/NotificationsView-A-Xs8BL1.js.map +1 -0
- package/bizar-dash/dist/assets/ObsidianView-mI3qW9OP.js +1 -0
- package/bizar-dash/dist/assets/{ObsidianView-Ci80gnwS.js.map → ObsidianView-mI3qW9OP.js.map} +1 -1
- package/bizar-dash/dist/assets/OverviewView-By69Cr5H.js +1 -0
- package/bizar-dash/dist/assets/OverviewView-By69Cr5H.js.map +1 -0
- package/bizar-dash/dist/assets/{ProgressBar-BahmeJhP.js → ProgressBar-BnaBqv-W.js} +1 -1
- package/bizar-dash/dist/assets/{ProgressBar-BahmeJhP.js.map → ProgressBar-BnaBqv-W.js.map} +1 -1
- package/bizar-dash/dist/assets/ProjectsView-C81WTFka.js +11 -0
- package/bizar-dash/dist/assets/ProjectsView-C81WTFka.js.map +1 -0
- package/bizar-dash/dist/assets/{ProvidersView-BftGn8Cr.js → ProvidersView-2cn-TALE.js} +2 -2
- package/bizar-dash/dist/assets/{ProvidersView-BftGn8Cr.js.map → ProvidersView-2cn-TALE.js.map} +1 -1
- package/bizar-dash/dist/assets/{SchedulesView-CtNxtzN6.js → SchedulesView-o9AtIsH9.js} +1 -1
- package/bizar-dash/dist/assets/{SchedulesView-CtNxtzN6.js.map → SchedulesView-o9AtIsH9.js.map} +1 -1
- package/bizar-dash/dist/assets/{Select-0VcfTDeL.js → Select-CiGWEN8I.js} +1 -1
- package/bizar-dash/dist/assets/{Select-0VcfTDeL.js.map → Select-CiGWEN8I.js.map} +1 -1
- package/bizar-dash/dist/assets/{SettingsRow-BLic3DQl.js → SettingsRow-CflGJymA.js} +1 -1
- package/bizar-dash/dist/assets/{SettingsRow-BLic3DQl.js.map → SettingsRow-CflGJymA.js.map} +1 -1
- package/bizar-dash/dist/assets/{SettingsView-BjS3i4nr.js → SettingsView-2HSFJPPK.js} +1 -1
- package/bizar-dash/dist/assets/{SettingsView-BjS3i4nr.js.map → SettingsView-2HSFJPPK.js.map} +1 -1
- package/bizar-dash/dist/assets/{Sheet-BOProMs2.js → Sheet-B-CMP9-_.js} +1 -1
- package/bizar-dash/dist/assets/{Sheet-BOProMs2.js.map → Sheet-B-CMP9-_.js.map} +1 -1
- package/bizar-dash/dist/assets/{Slider-B0eLEEUt.js → Slider-Z4TP_CXY.js} +1 -1
- package/bizar-dash/dist/assets/{Slider-B0eLEEUt.js.map → Slider-Z4TP_CXY.js.map} +1 -1
- package/bizar-dash/dist/assets/{Sparkline-SSrdgyW0.js → Sparkline-cvkv2HbU.js} +1 -1
- package/bizar-dash/dist/assets/{Sparkline-SSrdgyW0.js.map → Sparkline-cvkv2HbU.js.map} +1 -1
- package/bizar-dash/dist/assets/{Switch-B3EQzb_q.js → Switch-jcYo4lmp.js} +1 -1
- package/bizar-dash/dist/assets/{Switch-B3EQzb_q.js.map → Switch-jcYo4lmp.js.map} +1 -1
- package/bizar-dash/dist/assets/{TasksView-SWjF_ZUQ.js → TasksView-CQaSFzWY.js} +2 -2
- package/bizar-dash/dist/assets/{TasksView-SWjF_ZUQ.js.map → TasksView-CQaSFzWY.js.map} +1 -1
- package/bizar-dash/dist/assets/{Textarea-QuofpMlq.js → Textarea-xnAybFGd.js} +1 -1
- package/bizar-dash/dist/assets/{Textarea-QuofpMlq.js.map → Textarea-xnAybFGd.js.map} +1 -1
- package/bizar-dash/dist/assets/UpdateView-BUAEcRCX.js +1 -0
- package/bizar-dash/dist/assets/UpdateView-BUAEcRCX.js.map +1 -0
- package/bizar-dash/dist/assets/{UsageView-BqOw6FBg.js → UsageView-DMFbBOfH.js} +1 -1
- package/bizar-dash/dist/assets/{UsageView-BqOw6FBg.js.map → UsageView-DMFbBOfH.js.map} +1 -1
- package/bizar-dash/dist/assets/{ViewHeader-B6P-C4GD.js → ViewHeader-C-t1U2cQ.js} +1 -1
- package/bizar-dash/dist/assets/{ViewHeader-B6P-C4GD.js.map → ViewHeader-C-t1U2cQ.js.map} +1 -1
- package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js +1 -0
- package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js.map +1 -0
- package/bizar-dash/dist/assets/{brain-CwZt9Kta.js → brain-DhAzcHUk.js} +1 -1
- package/bizar-dash/dist/assets/{brain-CwZt9Kta.js.map → brain-DhAzcHUk.js.map} +1 -1
- package/bizar-dash/dist/assets/{calendar-C5oK0_nM.js → calendar-B9Wbemh7.js} +1 -1
- package/bizar-dash/dist/assets/{calendar-C5oK0_nM.js.map → calendar-B9Wbemh7.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-D1Lc_P2a.js → circle-6NJF_Xl6.js} +1 -1
- package/bizar-dash/dist/assets/{circle-D1Lc_P2a.js.map → circle-6NJF_Xl6.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-alert-HdHe7m8K.js → circle-alert-Dz8lGfCZ.js} +1 -1
- package/bizar-dash/dist/assets/{circle-alert-HdHe7m8K.js.map → circle-alert-Dz8lGfCZ.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-check-Cs-xoV7R.js → circle-check-DFB50ojt.js} +1 -1
- package/bizar-dash/dist/assets/{circle-check-Cs-xoV7R.js.map → circle-check-DFB50ojt.js.map} +1 -1
- package/bizar-dash/dist/assets/{clock-DEIuPV60.js → clock-ClVA6-hQ.js} +1 -1
- package/bizar-dash/dist/assets/{clock-DEIuPV60.js.map → clock-ClVA6-hQ.js.map} +1 -1
- package/bizar-dash/dist/assets/{cmdk-DVxytz9i.js → cmdk-C3F6LD6N.js} +5 -5
- package/bizar-dash/dist/assets/{cmdk-DVxytz9i.js.map → cmdk-C3F6LD6N.js.map} +1 -1
- package/bizar-dash/dist/assets/{dnd-kit-DrHErSkw.js → dnd-kit-BAOLODOI.js} +1 -1
- package/bizar-dash/dist/assets/{dnd-kit-DrHErSkw.js.map → dnd-kit-BAOLODOI.js.map} +1 -1
- package/bizar-dash/dist/assets/{download-Clkq90Ct.js → download-BvJddD8D.js} +1 -1
- package/bizar-dash/dist/assets/{download-Clkq90Ct.js.map → download-BvJddD8D.js.map} +1 -1
- package/bizar-dash/dist/assets/{external-link-D5tq2o_I.js → external-link-DvL89gaZ.js} +1 -1
- package/bizar-dash/dist/assets/{external-link-D5tq2o_I.js.map → external-link-DvL89gaZ.js.map} +1 -1
- package/bizar-dash/dist/assets/{file-text-CQ12t7Oc.js → file-text-BOroDtZE.js} +1 -1
- package/bizar-dash/dist/assets/{file-text-CQ12t7Oc.js.map → file-text-BOroDtZE.js.map} +1 -1
- package/bizar-dash/dist/assets/{filter-BcbE37wP.js → filter-DwPjMRQt.js} +1 -1
- package/bizar-dash/dist/assets/{filter-BcbE37wP.js.map → filter-DwPjMRQt.js.map} +1 -1
- package/bizar-dash/dist/assets/{git-pull-request-D1qNDRia.js → git-pull-request-TDb1inux.js} +1 -1
- package/bizar-dash/dist/assets/{git-pull-request-D1qNDRia.js.map → git-pull-request-TDb1inux.js.map} +1 -1
- package/bizar-dash/dist/assets/{index-CASP1n-5.js → index-B1OIS316.js} +1 -1
- package/bizar-dash/dist/assets/{index-CASP1n-5.js.map → index-B1OIS316.js.map} +1 -1
- package/bizar-dash/dist/assets/{index-C4Vq_2LM.js → index-CR0TeJmc.js} +1 -1
- package/bizar-dash/dist/assets/{index-C4Vq_2LM.js.map → index-CR0TeJmc.js.map} +1 -1
- package/bizar-dash/dist/assets/{main-CcQfRfIJ.css → main-B7D_IMTh.css} +1 -1
- package/bizar-dash/dist/assets/main-BURAlktW.js +277 -0
- package/bizar-dash/dist/assets/main-BURAlktW.js.map +1 -0
- package/bizar-dash/dist/assets/{network-DJdvVaHx.js → network-BcCoCzIY.js} +1 -1
- package/bizar-dash/dist/assets/{network-DJdvVaHx.js.map → network-BcCoCzIY.js.map} +1 -1
- package/bizar-dash/dist/assets/{pause-DUn9L5PB.js → pause-BllItT2_.js} +1 -1
- package/bizar-dash/dist/assets/{pause-DUn9L5PB.js.map → pause-BllItT2_.js.map} +1 -1
- package/bizar-dash/dist/assets/{pencil-DVrBlYV3.js → pencil-DAwM-CC3.js} +1 -1
- package/bizar-dash/dist/assets/{pencil-DVrBlYV3.js.map → pencil-DAwM-CC3.js.map} +1 -1
- package/bizar-dash/dist/assets/{play-CZjsr3XM.js → play-mJh67AXo.js} +2 -2
- package/bizar-dash/dist/assets/{play-CZjsr3XM.js.map → play-mJh67AXo.js.map} +1 -1
- package/bizar-dash/dist/assets/{plug-BKuyIe5W.js → plug-BjfntCMC.js} +1 -1
- package/bizar-dash/dist/assets/{plug-BKuyIe5W.js.map → plug-BjfntCMC.js.map} +1 -1
- package/bizar-dash/dist/assets/{plus-77h62zZm.js → plus-Cm6-fo14.js} +1 -1
- package/bizar-dash/dist/assets/{plus-77h62zZm.js.map → plus-Cm6-fo14.js.map} +1 -1
- package/bizar-dash/dist/assets/{power-DLmx-gCP.js → power-CXN9y2KV.js} +1 -1
- package/bizar-dash/dist/assets/{power-DLmx-gCP.js.map → power-CXN9y2KV.js.map} +1 -1
- package/bizar-dash/dist/assets/{power-off-BFKzHXic.js → power-off-DUZqwMf9.js} +1 -1
- package/bizar-dash/dist/assets/{power-off-BFKzHXic.js.map → power-off-DUZqwMf9.js.map} +1 -1
- package/bizar-dash/dist/assets/{refresh-ccw-DenGBOcq.js → refresh-ccw-DA8_IB9l.js} +1 -1
- package/bizar-dash/dist/assets/{refresh-ccw-DenGBOcq.js.map → refresh-ccw-DA8_IB9l.js.map} +1 -1
- package/bizar-dash/dist/assets/{refresh-cw-ENBVR8hW.js → refresh-cw-DwlP59en.js} +1 -1
- package/bizar-dash/dist/assets/{refresh-cw-ENBVR8hW.js.map → refresh-cw-DwlP59en.js.map} +1 -1
- package/bizar-dash/dist/assets/{rotate-ccw-MxryaY7q.js → rotate-ccw-DMTASfAn.js} +1 -1
- package/bizar-dash/dist/assets/{rotate-ccw-MxryaY7q.js.map → rotate-ccw-DMTASfAn.js.map} +1 -1
- package/bizar-dash/dist/assets/{rotate-cw-CDOlRtUR.js → rotate-cw-BDX5SE2s.js} +1 -1
- package/bizar-dash/dist/assets/{rotate-cw-CDOlRtUR.js.map → rotate-cw-BDX5SE2s.js.map} +1 -1
- package/bizar-dash/dist/assets/{save-Db1b-1Uq.js → save-Y0jPK5D6.js} +1 -1
- package/bizar-dash/dist/assets/{save-Db1b-1Uq.js.map → save-Y0jPK5D6.js.map} +1 -1
- package/bizar-dash/dist/assets/{send-yz6HFZM5.js → send-C8wwPHhR.js} +2 -2
- package/bizar-dash/dist/assets/{send-yz6HFZM5.js.map → send-C8wwPHhR.js.map} +1 -1
- package/bizar-dash/dist/assets/{shield-alert-DY6RAaC8.js → shield-alert-DEvq9UG0.js} +1 -1
- package/bizar-dash/dist/assets/{shield-alert-DY6RAaC8.js.map → shield-alert-DEvq9UG0.js.map} +1 -1
- package/bizar-dash/dist/assets/{trash-2-Cv7U38jw.js → trash-2-D6qePV_q.js} +2 -2
- package/bizar-dash/dist/assets/{trash-2-Cv7U38jw.js.map → trash-2-D6qePV_q.js.map} +1 -1
- package/bizar-dash/dist/assets/{trending-up-CRPNagyX.js → trending-up-BZzo_1ic.js} +1 -1
- package/bizar-dash/dist/assets/{trending-up-CRPNagyX.js.map → trending-up-BZzo_1ic.js.map} +1 -1
- package/bizar-dash/dist/assets/{triangle-alert-tUTXbcEP.js → triangle-alert-B2oHbmoh.js} +1 -1
- package/bizar-dash/dist/assets/{triangle-alert-tUTXbcEP.js.map → triangle-alert-B2oHbmoh.js.map} +1 -1
- package/bizar-dash/dist/assets/{upload-Cq7uTsrT.js → upload-Dy59aZn6.js} +1 -1
- package/bizar-dash/dist/assets/{upload-Cq7uTsrT.js.map → upload-Dy59aZn6.js.map} +1 -1
- package/bizar-dash/dist/assets/{zap-5lAQBAPX.js → zap-DENVhJnO.js} +2 -2
- package/bizar-dash/dist/assets/{zap-5lAQBAPX.js.map → zap-DENVhJnO.js.map} +1 -1
- package/bizar-dash/dist/index.html +3 -3
- package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/bizar-dash/src/web/v8/App.tsx +87 -6
- package/bizar-dash/src/web/v8/__tests__/chat-view.test.tsx +4 -4
- package/bizar-dash/src/web/v8/shell/AppShell.tsx +38 -2
- package/bizar-dash/src/web/v8/shell/Sidebar.tsx +52 -38
- package/bizar-dash/src/web/v8/shell/Topbar.tsx +62 -3
- package/bizar-dash/src/web/v8/ui/styles/globals.css +40 -0
- package/bizar-dash/src/web/v8/ui/theme/ThemeToggle.tsx +11 -6
- package/bizar-dash/src/web/v8/views/Admin/AdminView.tsx +32 -5
- package/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +36 -4
- package/bizar-dash/src/web/v8/views/Artifacts/ArtifactsView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/Chat/ChatView.tsx +13 -1
- package/bizar-dash/src/web/v8/views/ClaudeSessions/NewSessionModal.tsx +136 -0
- package/bizar-dash/src/web/v8/views/Clipboard/ClipboardView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +14 -4
- package/bizar-dash/src/web/v8/views/Diagnostics/DiagnosticsView.tsx +50 -7
- package/bizar-dash/src/web/v8/views/Dialogs/DialogsView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/Libraries/LibrariesView.tsx +6 -1
- package/bizar-dash/src/web/v8/views/Misc/MiscView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/Notifications/NotificationsView.tsx +82 -13
- package/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +19 -0
- package/bizar-dash/src/web/v8/views/Projects/ProjectsView.tsx +21 -1
- package/bizar-dash/src/web/v8/views/Voice/VoiceView.tsx +1 -1
- package/bizar-dash/tests/admin-labels.test.mjs +42 -0
- package/bizar-dash/tests/admin-run-grouping.test.mjs +42 -0
- package/bizar-dash/tests/agents-preview-truncate.test.mjs +35 -0
- package/bizar-dash/tests/agents-summary-sanitize.test.ts +51 -0
- package/bizar-dash/tests/chat-new-session.test.mjs +63 -0
- package/bizar-dash/tests/empty-state-docs.test.mjs +55 -0
- package/bizar-dash/tests/focus-visible.test.mjs +30 -0
- package/bizar-dash/tests/kanban-empty-column.test.mjs +56 -0
- package/bizar-dash/tests/library-dedupe.test.mjs +62 -0
- package/bizar-dash/tests/notifications-dismiss-restore.test.mjs +85 -0
- package/bizar-dash/tests/palette-shortcut-hint.test.mjs +58 -0
- package/bizar-dash/tests/projects-filter.test.mjs +48 -0
- package/bizar-dash/tests/settings-labels.test.mjs +80 -0
- package/bizar-dash/tests/sidebar-distinct-icons.test.mjs +28 -0
- package/bizar-dash/tests/sidebar-responsive.test.tsx +48 -0
- package/bizar-dash/tests/sidebar-section-toggle.test.tsx +63 -0
- package/bizar-dash/tests/theme-toggle-icon.test.mjs +28 -0
- package/bizar-dash/tests/topbar-design-system.test.mjs +56 -0
- package/bizar-dash/vite.config.ts +8 -0
- package/package.json +1 -1
- package/packages/sdk/package.json +1 -1
- package/bizar-dash/dist/assets/AdminView-DNc5Ll7L.js +0 -11
- package/bizar-dash/dist/assets/AdminView-DNc5Ll7L.js.map +0 -1
- package/bizar-dash/dist/assets/AgentsView-Du-G_skK.js +0 -13
- package/bizar-dash/dist/assets/AgentsView-Du-G_skK.js.map +0 -1
- package/bizar-dash/dist/assets/ArtifactsView-znhN8GTR.js.map +0 -1
- package/bizar-dash/dist/assets/Avatar-B41upSD1.js +0 -6
- package/bizar-dash/dist/assets/Avatar-B41upSD1.js.map +0 -1
- package/bizar-dash/dist/assets/ChatView-CUriVEgU.js +0 -9
- package/bizar-dash/dist/assets/ChatView-CUriVEgU.js.map +0 -1
- package/bizar-dash/dist/assets/ClipboardView-DdP6aVso.js +0 -1
- package/bizar-dash/dist/assets/ClipboardView-DdP6aVso.js.map +0 -1
- package/bizar-dash/dist/assets/DiagnosticsView-88OZ5k0f.js +0 -2
- package/bizar-dash/dist/assets/DiagnosticsView-88OZ5k0f.js.map +0 -1
- package/bizar-dash/dist/assets/DialogsView-BcqDDCZQ.js +0 -6
- package/bizar-dash/dist/assets/DialogsView-BcqDDCZQ.js.map +0 -1
- package/bizar-dash/dist/assets/EvalView-CpdFu_ID.js +0 -1
- package/bizar-dash/dist/assets/LibrariesView-B1YX9wzp.js +0 -6
- package/bizar-dash/dist/assets/MiscView-DLNEGdML.js +0 -1
- package/bizar-dash/dist/assets/MiscView-DLNEGdML.js.map +0 -1
- package/bizar-dash/dist/assets/NotificationsView-DAm2O0yf.js +0 -6
- package/bizar-dash/dist/assets/NotificationsView-DAm2O0yf.js.map +0 -1
- package/bizar-dash/dist/assets/ObsidianView-Ci80gnwS.js +0 -1
- package/bizar-dash/dist/assets/OverviewView-rriw1GjA.js +0 -1
- package/bizar-dash/dist/assets/OverviewView-rriw1GjA.js.map +0 -1
- package/bizar-dash/dist/assets/ProjectsView-ChzM12bs.js +0 -11
- package/bizar-dash/dist/assets/ProjectsView-ChzM12bs.js.map +0 -1
- package/bizar-dash/dist/assets/UpdateView-CEHW2nd6.js +0 -6
- package/bizar-dash/dist/assets/UpdateView-CEHW2nd6.js.map +0 -1
- package/bizar-dash/dist/assets/VoiceView-CwrPwWgi.js +0 -1
- package/bizar-dash/dist/assets/VoiceView-CwrPwWgi.js.map +0 -1
- package/bizar-dash/dist/assets/main-Cxeu4LhG.js +0 -244
- package/bizar-dash/dist/assets/main-Cxeu4LhG.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AgentsView-Du-G_skK.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/clipboard-copy.js","../../../node_modules/lucide-react/dist/esm/icons/octagon.js","../../src/web/v8/ui/agents/AgentCard.tsx","../../src/web/v8/ui/agents/AgentLiveOutput.tsx","../../src/web/v8/ui/agents/AgentDetail.tsx","../../src/web/v8/views/Agents/AgentHierarchy.tsx","../../src/web/v8/views/Agents/AgentsView.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 ClipboardCopy = createLucideIcon(\"ClipboardCopy\", [\n [\"rect\", { width: \"8\", height: \"4\", x: \"8\", y: \"2\", rx: \"1\", ry: \"1\", key: \"tgr4d6\" }],\n [\"path\", { d: \"M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\", key: \"4jdomd\" }],\n [\"path\", { d: \"M16 4h2a2 2 0 0 1 2 2v4\", key: \"3hqy98\" }],\n [\"path\", { d: \"M21 14H11\", key: \"1bme5i\" }],\n [\"path\", { d: \"m15 10-4 4 4 4\", key: \"5dvupr\" }]\n]);\n\nexport { ClipboardCopy as default };\n//# sourceMappingURL=clipboard-copy.js.map\n","/**\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 Octagon = createLucideIcon(\"Octagon\", [\n [\n \"path\",\n {\n d: \"M2.586 16.726A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2h6.624a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586z\",\n key: \"2d38gg\"\n }\n ]\n]);\n\nexport { Octagon as default };\n//# sourceMappingURL=octagon.js.map\n","import { type ReactNode } from 'react';\nimport { Activity, Zap } from 'lucide-react';\nimport { cx } from '../utils/cx.js';\nimport { Avatar } from '../data/Avatar.js';\nimport { Badge } from '../data/Badge.js';\nimport { ProgressBar } from '../data/ProgressBar.js';\n\n/**\n * AgentCard — agent tile for the Agents roster.\n *\n * Per PLAN.md, agents are the orchestrator's running entities. Each card\n * shows: name, status (idle/busy/error), role, last activity, and a\n * three-row metrics strip (tasks succeeded/total, success rate, lastSeen).\n *\n * v9.4.0 S45 — replaced the dead single-point sparkline (line 140\n * guarded `tpmHistory.length > 1`, never true) with a data-driven\n * metric strip that always renders when the fields are supplied.\n */\n\nexport type AgentStatus = 'idle' | 'busy' | 'error' | 'paused';\n\nexport interface AgentCardProps {\n id: string;\n name: string;\n role: string;\n status: AgentStatus;\n /** Last activity label (\"2m ago\", \"Just now\"). */\n lastActivity?: string;\n /** Current task the agent is working on. */\n currentTask?: string;\n /** Number of tasks completed in the last 24h. */\n tasksToday?: number;\n /** Tasks succeeded (numerator of the ProgressBar). */\n tasksSucceeded?: number;\n /** Tasks total (denominator of the ProgressBar). */\n tasksTotal?: number;\n /** Success rate as 0..1. Tones the badge: >=0.8 success, >=0.5 warning, else danger. */\n successRate?: number;\n /** Last-seen timestamp in ms-since-epoch. Rendered as relative duration. */\n lastSeenMs?: number;\n /** Click handler — opens agent detail. */\n onOpen?: () => void;\n /** Custom badges row (model, owner). */\n badges?: ReactNode;\n className?: string;\n}\n\nconst STATUS_LABEL: Record<AgentStatus, string> = {\n idle: 'Idle',\n busy: 'Busy',\n error: 'Error',\n paused: 'Paused',\n};\n\nconst STATUS_TONE: Record<AgentStatus, 'success' | 'info' | 'danger' | 'neutral'> = {\n idle: 'neutral',\n busy: 'info',\n error: 'danger',\n paused: 'neutral',\n};\n\nconst STATUS_FG: Record<AgentStatus, string> = {\n idle: 'var(--fg-subtle)',\n busy: 'var(--info)',\n error: 'var(--danger)',\n paused: 'var(--warning)',\n};\n\n/** relativeTime — \"12s\", \"3m\", \"2h\", \"5d\". Returns \"—\" for missing / future timestamps. */\nfunction relativeTime(ms: number | undefined): string {\n if (typeof ms !== 'number' || !Number.isFinite(ms) || ms <= 0) return '—';\n const delta = Math.max(0, Date.now() - ms);\n const sec = Math.floor(delta / 1000);\n if (sec < 60) return `${sec}s ago`;\n const min = Math.floor(sec / 60);\n if (min < 60) return `${min}m ago`;\n const hr = Math.floor(min / 60);\n if (hr < 24) return `${hr}h ago`;\n const day = Math.floor(hr / 24);\n return `${day}d ago`;\n}\n\nfunction successTone(rate: number): 'success' | 'warning' | 'danger' {\n if (rate >= 0.8) return 'success';\n if (rate >= 0.5) return 'warning';\n return 'danger';\n}\n\nfunction lastSeenTone(ms: number | undefined): 'neutral' | 'danger' {\n if (typeof ms !== 'number' || !Number.isFinite(ms) || ms <= 0) return 'neutral';\n const days = (Date.now() - ms) / 86_400_000;\n return days > 1 ? 'danger' : 'neutral';\n}\n\nexport function AgentCard(props: AgentCardProps): JSX.Element {\n const {\n name,\n role,\n status,\n lastActivity,\n currentTask,\n tasksToday,\n tasksSucceeded,\n tasksTotal,\n successRate,\n lastSeenMs,\n onOpen,\n badges,\n className,\n } = props;\n\n const showMetrics =\n (typeof tasksSucceeded === 'number' && typeof tasksTotal === 'number') ||\n typeof successRate === 'number' ||\n typeof lastSeenMs === 'number';\n\n return (\n <button\n type=\"button\"\n onClick={onOpen}\n className={cx('v8-agent-card', `v8-agent-card--${status}`, className)}\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: 'var(--space-3)',\n width: '100%',\n padding: 'var(--space-4)',\n background: 'var(--surface-1)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-lg)',\n textAlign: 'left',\n cursor: 'pointer',\n font: 'inherit',\n color: 'inherit',\n transition: 'border-color var(--motion-fast) var(--ease-out)',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-3)' }}>\n <Avatar name={name} status={status === 'busy' ? 'busy' : status === 'error' ? 'busy' : status === 'idle' ? 'online' : 'away'} />\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ fontSize: 'var(--fs-14)', fontWeight: 600, color: 'var(--fg)', lineHeight: 'var(--lh-snug)' }}>\n {name}\n </div>\n <div style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', marginTop: 2 }}>\n {role}\n </div>\n </div>\n <Badge tone={STATUS_TONE[status]} dot>\n {STATUS_LABEL[status]}\n </Badge>\n </div>\n {currentTask !== undefined && (\n <div\n style={{\n fontSize: 'var(--fs-13)',\n color: 'var(--fg)',\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n padding: 'var(--space-2) var(--space-3)',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n title={currentTask}\n >\n {currentTask}\n </div>\n )}\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-3)', fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {lastActivity !== undefined && (\n <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>\n <Activity size={12} aria-hidden=\"true\" style={{ color: STATUS_FG[status] }} />\n {lastActivity}\n </span>\n )}\n {tasksToday !== undefined && (\n <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>\n <Zap size={12} aria-hidden=\"true\" />\n {tasksToday} today\n </span>\n )}\n </div>\n {showMetrics && (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-2)' }}>\n {typeof tasksSucceeded === 'number' && typeof tasksTotal === 'number' && tasksTotal > 0 && (\n <div data-testid=\"agent-card-tasks\" style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <div\n style={{\n display: 'flex',\n alignItems: 'baseline',\n justifyContent: 'space-between',\n fontSize: 'var(--fs-12)',\n color: 'var(--fg-muted)',\n }}\n >\n <span style={{ textTransform: 'uppercase', letterSpacing: '0.04em' }}>tasks</span>\n <code style={{ fontFamily: 'var(--font-mono)', color: 'var(--fg)' }}>\n {tasksSucceeded} / {tasksTotal}\n </code>\n </div>\n <ProgressBar value={tasksSucceeded} max={tasksTotal} tone=\"accent\" height={4} />\n </div>\n )}\n {typeof successRate === 'number' && (\n <div\n data-testid=\"agent-card-success\"\n style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}\n >\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>\n success\n </span>\n <Badge data-testid=\"agent-card-success-badge\" tone={successTone(successRate)}>\n {Math.round(successRate * 100)}% success\n </Badge>\n </div>\n )}\n {typeof lastSeenMs === 'number' && (\n <div\n data-testid=\"agent-card-lastseen\"\n style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}\n >\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>\n last seen\n </span>\n <Badge data-testid=\"agent-card-lastseen-badge\" tone={lastSeenTone(lastSeenMs)}>{relativeTime(lastSeenMs)}</Badge>\n </div>\n )}\n </div>\n )}\n {badges !== undefined && (\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>{badges}</div>\n )}\n <style>{`\n .v8-agent-card:hover { border-color: var(--accent); }\n `}</style>\n </button>\n );\n}","import { useEffect, useRef, useState } from 'react';\nimport { Pause, Play, RefreshCw } from 'lucide-react';\nimport { Stack } from '../primitives/Stack.js';\nimport { Inline } from '../primitives/Inline.js';\nimport { Button } from '../controls/Button.js';\n\n/**\n * AgentLiveOutput — Sprint S17. Live SSE tail of a CC agent's session\n * JSONL. Subscribes to `/api/agent-stream/live?sessionId=...` and\n * appends events as they arrive. Pause freezes the buffer (connection\n * stays open). Clear wipes the buffer.\n */\n\ninterface StreamEvent {\n type?: string;\n role?: string;\n content?: string;\n name?: string;\n input?: unknown;\n tool?: { name?: string; input?: unknown };\n result?: unknown;\n ts?: number;\n message?: string;\n}\n\nexport interface AgentLiveOutputProps {\n sessionId: string;\n /** When true the parent wants us to stop connecting (e.g. agent was killed). */\n paused?: boolean;\n}\n\nconst MAX_EVENTS = 500;\n\nexport function AgentLiveOutput(props: AgentLiveOutputProps): JSX.Element {\n const { sessionId, paused } = props;\n const [events, setEvents] = useState<StreamEvent[]>([]);\n const [status, setStatus] = useState<'connecting' | 'live' | 'paused' | 'error' | 'closed'>('connecting');\n const [error, setError] = useState<string | null>(null);\n const [pausedLocal, setPausedLocal] = useState<boolean>(false);\n const [autoScroll, setAutoScroll] = useState<boolean>(true);\n const containerRef = useRef<HTMLDivElement>(null);\n const sourceRef = useRef<EventSource | null>(null);\n\n useEffect(() => {\n if (paused || pausedLocal) {\n if (sourceRef.current) {\n sourceRef.current.close();\n sourceRef.current = null;\n }\n setStatus('paused');\n return;\n }\n if (typeof window === 'undefined' || typeof EventSource === 'undefined') {\n setStatus('error');\n setError('EventSource not available in this environment.');\n return;\n }\n setStatus('connecting');\n setError(null);\n const url = `/api/agent-stream/live?sessionId=${encodeURIComponent(sessionId)}`;\n const src = new EventSource(url);\n sourceRef.current = src;\n\n const onSnapshot = (ev: MessageEvent): void => {\n try {\n const data = JSON.parse(ev.data) as { events?: StreamEvent[] };\n if (Array.isArray(data.events)) setEvents(data.events.slice(-MAX_EVENTS));\n setStatus('live');\n } catch { /* malformed */ }\n };\n const onEvent = (ev: MessageEvent): void => {\n try {\n const data = JSON.parse(ev.data) as StreamEvent;\n setEvents((prev) => {\n const next = prev.length >= MAX_EVENTS ? prev.slice(prev.length - MAX_EVENTS + 1) : prev.slice();\n next.push(data);\n return next;\n });\n setStatus('live');\n } catch { /* malformed */ }\n };\n const onEnd = (ev: MessageEvent): void => {\n try {\n const data = JSON.parse(ev.data) as { reason?: string };\n setStatus('closed');\n setError(data.reason ? `Stream ended: ${data.reason}` : null);\n } catch { /* */ }\n };\n const onErrEv = (ev: MessageEvent): void => {\n try {\n const data = JSON.parse(ev.data) as { error?: string };\n setStatus('error');\n setError(data.error || 'stream error');\n } catch { /* */ }\n };\n src.addEventListener('snapshot', onSnapshot);\n src.addEventListener('event', onEvent);\n src.addEventListener('agent:event', onEvent);\n src.addEventListener('end', onEnd);\n src.addEventListener('error', onErrEv);\n src.onerror = () => {\n setStatus('error');\n setError('Connection dropped. Click Retry to reconnect.');\n };\n return () => {\n src.close();\n sourceRef.current = null;\n };\n }, [sessionId, paused, pausedLocal]);\n\n useEffect(() => {\n if (!autoScroll || !containerRef.current) return;\n const el = containerRef.current;\n el.scrollTop = el.scrollHeight;\n }, [events, autoScroll]);\n\n const renderEvent = (ev: StreamEvent, idx: number): JSX.Element => {\n const tone =\n ev.role === 'user' ? 'user' :\n ev.role === 'assistant' ? 'assistant' :\n ev.tool?.name ? 'tool' :\n 'system';\n const label =\n ev.tool?.name ? `${ev.tool.name}` :\n ev.role ? ev.role : (ev.type || 'event');\n const text =\n typeof ev.content === 'string' ? ev.content :\n ev.tool?.input ? JSON.stringify(ev.tool.input).slice(0, 240) :\n typeof ev.message === 'string' ? ev.message :\n ev.result ? JSON.stringify(ev.result).slice(0, 240) :\n JSON.stringify(ev).slice(0, 240);\n return (\n <div\n key={idx}\n style={{\n padding: '4px 8px',\n borderRadius: 'var(--radius-sm)',\n background:\n tone === 'user' ? 'color-mix(in oklch, var(--accent) 8%, var(--surface-0))' :\n tone === 'tool' ? 'color-mix(in oklch, var(--warning) 8%, var(--surface-0))' :\n tone === 'system' ? 'var(--surface-1)' :\n 'var(--surface-0)',\n fontFamily: 'var(--font-mono)',\n fontSize: 'var(--fs-12)',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n >\n <span style={{ color: 'var(--fg-muted)' }}>{label}: </span>\n <span style={{ color: 'var(--fg)' }}>{text}</span>\n </div>\n );\n };\n\n return (\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\">\n <Inline align=\"center\" gap={2}>\n <span\n aria-hidden\n style={{\n width: 8,\n height: 8,\n borderRadius: '50%',\n background:\n status === 'live' ? 'var(--success)' :\n status === 'connecting' ? 'var(--warning)' :\n status === 'paused' ? 'var(--fg-muted)' :\n status === 'closed' ? 'var(--fg-muted)' :\n 'var(--danger)',\n }}\n />\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {status === 'live' ? 'Live' :\n status === 'connecting' ? 'Connecting…' :\n status === 'paused' ? 'Paused' :\n status === 'closed' ? 'Closed' :\n 'Error'}\n {' · '}{events.length} events\n </span>\n </Inline>\n <Inline align=\"center\" gap={1}>\n <Button\n variant=\"ghost\"\n onClick={() => setPausedLocal((p) => !p)}\n title={pausedLocal ? 'Resume stream' : 'Pause stream'}\n aria-label={pausedLocal ? 'Resume stream' : 'Pause stream'}\n >\n {pausedLocal ? <Play size={12} aria-hidden /> : <Pause size={12} aria-hidden />}\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => setEvents([])}\n title=\"Clear buffer\"\n aria-label=\"Clear output\"\n >\n Clear\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => {\n setEvents([]);\n setPausedLocal(false);\n }}\n title=\"Reconnect\"\n aria-label=\"Reconnect stream\"\n >\n <RefreshCw size={12} aria-hidden /> Retry\n </Button>\n <label style={{ display: 'flex', alignItems: 'center', gap: 4, fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', cursor: 'pointer' }}>\n <input type=\"checkbox\" checked={autoScroll} onChange={(e) => setAutoScroll(e.target.checked)} />\n follow\n </label>\n </Inline>\n </Inline>\n {error !== null && (\n <div role=\"alert\" style={{ fontSize: 'var(--fs-12)', color: 'var(--danger)' }}>{error}</div>\n )}\n <div\n ref={containerRef}\n onScroll={(e) => {\n const el = e.currentTarget;\n const atBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 20;\n setAutoScroll(atBottom);\n }}\n style={{\n maxHeight: 280,\n minHeight: 120,\n overflowY: 'auto',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n display: 'flex',\n flexDirection: 'column',\n gap: 4,\n background: 'var(--surface-1)',\n }}\n role=\"log\"\n aria-live=\"polite\"\n aria-label=\"Agent live output\"\n >\n {events.length === 0 ? (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {status === 'connecting' ? 'Connecting to agent stream…' : 'No events yet.'}\n </span>\n ) : (\n events.map(renderEvent)\n )}\n </div>\n </Stack>\n );\n}","import { useEffect, useMemo, useState } from 'react';\nimport { Send, RotateCw, Octagon, ClipboardCopy, Activity as ActivityIcon } from 'lucide-react';\nimport { Avatar } from '../data/Avatar.js';\nimport { Badge } from '../data/Badge.js';\nimport { Button } from '../controls/Button.js';\nimport { Sheet, SheetContent } from '../feedback/Sheet.js';\nimport { Stack } from '../primitives/Stack.js';\nimport { Inline } from '../primitives/Inline.js';\nimport { Textarea } from '../controls/Textarea.js';\nimport { Skeleton } from '../feedback/Skeleton.js';\nimport { Card, CardBody } from '../data/Card.js';\nimport { AgentStreamPanel } from './AgentStreamPanel.js';\nimport { AgentLiveOutput } from './AgentLiveOutput.js';\nimport { fetchJson } from '../../data/fetcher.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport type { Task } from '../../data/types.js';\n\n/**\n * AgentDetail — Sprint S11. Right-side Drawer with live agent\n * detail and the control plane (Send prompt / Restart / Kill).\n *\n * Two flavors per `source`:\n * - `bizar:<name>` — hits `/api/agents/:name/invoke` and `/restart`.\n * - `cc:<sessionId>` — hits `/api/cc-agents/:id/send` and `/kill`.\n */\n\nexport type AgentSource = 'bizar' | 'claude-code';\n\nexport interface AgentDetailProps {\n /** Composite id from AgentsView (`bizar:<name>` or `cc:<sessionId>`). */\n agentId: string;\n name: string;\n role: string;\n status: 'idle' | 'busy' | 'error' | 'paused';\n currentTask?: string;\n startedAt?: number;\n messageCount?: number;\n lastMessageSnippet?: string;\n successRate?: number;\n tasksTotal?: number;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\nfunction parseId(agentId: string): { source: AgentSource; key: string } {\n if (agentId.startsWith('bizar:')) return { source: 'bizar', key: agentId.slice('bizar:'.length) };\n if (agentId.startsWith('cc:')) return { source: 'claude-code', key: agentId.slice('cc:'.length) };\n return { source: 'bizar', key: agentId };\n}\n\nexport function AgentDetail(props: AgentDetailProps): JSX.Element {\n const {\n agentId, name, role, status, currentTask, open, onOpenChange,\n startedAt, messageCount, lastMessageSnippet, successRate, tasksTotal,\n } = props;\n const { source, key } = parseId(agentId);\n const [prompt, setPrompt] = useState<string>('');\n const [busy, setBusy] = useState<string | null>(null);\n const [message, setMessage] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [lastProcessId, setLastProcessId] = useState<string | null>(null);\n\n // v9.5.0 S49 — agent↔task drilldown. `useFetch` is gated on `open` so\n // we don't burn a request every time the Sheet is mounted-hidden. We\n // client-filter for the current agent's name across both `workedBy`\n // (Bizar task-store) and `metadata.agent` (task-store progress events).\n const tasksQuery = useFetch<{ tasks?: Task[] }>(open ? '/api/tasks' : null);\n const myTasks = useMemo<Task[]>(() => {\n if (!open) return [];\n const all = tasksQuery.data?.tasks ?? [];\n return all.filter((t) => {\n const md = (t.metadata ?? {}) as { agent?: unknown };\n return (\n (typeof (t as unknown as { workedBy?: unknown }).workedBy === 'string'\n && (t as unknown as { workedBy: string }).workedBy === key)\n || md.agent === key\n );\n });\n }, [open, tasksQuery.data, key]);\n\n useEffect(() => {\n if (open) { setPrompt(''); setMessage(null); setError(null); setLastProcessId(null); }\n }, [open, agentId]);\n\n const runAction = async (\n label: string,\n method: 'POST',\n endpoint: string,\n body?: Record<string, unknown>,\n ): Promise<void> => {\n setBusy(label);\n setMessage(null);\n setError(null);\n try {\n const res = await fetchJson<{ ok?: boolean; sessionId?: string; processId?: string; error?: string }>(\n endpoint,\n { method, body },\n );\n if (res.ok) {\n const sessionExtra = res.sessionId ? ` (session ${res.sessionId.slice(0, 8)})` : '';\n if (res.processId) setLastProcessId(res.processId);\n setMessage(`${label} succeeded${sessionExtra}`);\n } else {\n setError(res.error || `${label} failed`);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setBusy(null);\n }\n };\n\n const sendPrompt = async (): Promise<void> => {\n if (!prompt.trim()) return;\n const trimmed = prompt.trim();\n setPrompt('');\n if (source === 'claude-code') {\n await runAction('Send prompt', 'POST', `/api/cc-agents/${encodeURIComponent(key)}/send`, { prompt: trimmed });\n } else {\n await runAction('Invoke agent', 'POST', `/api/agents/${encodeURIComponent(key)}/invoke`, { prompt: trimmed });\n }\n };\n\n const restart = async (): Promise<void> => {\n const ok = typeof window !== 'undefined' && typeof window.confirm === 'function'\n ? window.confirm(`Restart ${name}? The current session will be killed and a fresh one spawned.`)\n : true;\n if (!ok) return;\n if (source === 'claude-code') {\n // v9.0.5 — server now does kill+spawn in one shot, using the current\n // prompt as the new session's seed (fallback to \"continue\").\n const seed = prompt.trim() || 'continue from the last checkpoint';\n await runAction('Restart', 'POST', `/api/cc-agents/${encodeURIComponent(key)}/restart`, { prompt: seed });\n return;\n }\n await runAction('Restart', 'POST', `/api/agents/${encodeURIComponent(key)}/restart`);\n };\n\n const kill = async (): Promise<void> => {\n if (source === 'claude-code') {\n await runAction('Kill', 'POST', `/api/cc-agents/${encodeURIComponent(key)}/kill`);\n return;\n }\n // Confirm before destroying — DELETE is irreversible.\n const ok = typeof window !== 'undefined' && typeof window.confirm === 'function'\n ? window.confirm(`Delete Bizar agent \"${key}\"? This is irreversible.`)\n : true;\n if (!ok) return;\n setBusy('Kill');\n setMessage(null);\n setError(null);\n try {\n await fetchJson<{ ok?: boolean; error?: string }>(\n `/api/agents/${encodeURIComponent(key)}`,\n { method: 'DELETE' },\n );\n setMessage(`Killed ${name}`);\n // Server broadcasts agents:change; close the drawer so the user\n // sees the agent disappear from the grid.\n onOpenChange(false);\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setBusy(null);\n }\n };\n\n const copyId = async (): Promise<void> => {\n try {\n await navigator.clipboard.writeText(key);\n setMessage(`Copied \"${key}\"`);\n } catch {\n setError('Clipboard unavailable');\n }\n };\n\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <SheetContent side=\"right\" title={name}>\n <Stack gap={4} style={{ padding: 'var(--space-4)' }}>\n <Inline gap={3} align=\"center\">\n <Avatar name={name} status={status === 'busy' ? 'busy' : status === 'error' ? 'busy' : 'online'} />\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ fontSize: 'var(--fs-13)', color: 'var(--fg-muted)' }}>{role}</div>\n <Inline gap={2} style={{ marginTop: 4 }} wrap>\n <Badge tone={status === 'busy' ? 'info' : status === 'error' ? 'danger' : 'neutral'} dot>\n {status}\n </Badge>\n <Badge tone=\"accent\">{source === 'bizar' ? 'Bizar agent' : 'Claude Code'}</Badge>\n {startedAt !== undefined && (\n <Badge tone=\"neutral\" title={new Date(startedAt).toLocaleString()}>\n up {formatDuration(Date.now() - startedAt)}\n </Badge>\n )}\n {typeof messageCount === 'number' && (\n <Badge tone=\"neutral\">{messageCount} msg</Badge>\n )}\n {typeof tasksTotal === 'number' && (\n <Badge tone=\"neutral\">{tasksTotal} tasks</Badge>\n )}\n {typeof successRate === 'number' && (\n <Badge tone={successRate >= 0.8 ? 'success' : successRate >= 0.5 ? 'warning' : 'danger'}>\n {Math.round(successRate * 100)}% success\n </Badge>\n )}\n </Inline>\n </div>\n </Inline>\n\n {typeof lastMessageSnippet === 'string' && lastMessageSnippet.length > 0 && (\n <div\n style={{\n padding: 'var(--space-2) var(--space-3)',\n background: 'var(--surface-1)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n fontSize: 'var(--fs-12)',\n color: 'var(--fg-muted)',\n fontStyle: 'italic',\n }}\n title={lastMessageSnippet}\n >\n “{lastMessageSnippet.length > 240 ? `${lastMessageSnippet.slice(0, 240)}…` : lastMessageSnippet}”\n </div>\n )}\n\n {currentTask !== undefined && (\n <div\n style={{\n padding: 'var(--space-3)',\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n fontSize: 'var(--fs-13)',\n }}\n >\n <div style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', marginBottom: 4 }}>\n <ActivityIcon size={12} aria-hidden style={{ verticalAlign: 'middle', marginRight: 4 }} />\n Current task\n </div>\n {currentTask}\n </div>\n )}\n\n <Stack gap={2}>\n <label\n htmlFor={`agent-prompt-${agentId}`}\n style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}\n >\n Send a prompt\n </label>\n <Textarea\n id={`agent-prompt-${agentId}`}\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n placeholder={source === 'claude-code' ? 'Type a follow-up for this background agent…' : 'Invoke this Bizar agent with…'}\n rows={3}\n disabled={busy !== null}\n />\n <Inline gap={2}>\n <Button\n variant=\"primary\"\n onClick={() => { void sendPrompt(); }}\n disabled={!prompt.trim() || busy !== null}\n >\n <Send size={14} aria-hidden /> {busy === 'Send prompt' || busy === 'Invoke agent' ? <Skeleton style={{ width: 60, height: 14 }} /> : 'Send'}\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() => { void restart(); }}\n disabled={busy !== null || source === 'claude-code'}\n title={source === 'claude-code' ? 'Use command palette to spawn a fresh agent' : undefined}\n >\n <RotateCw size={14} aria-hidden /> Restart\n </Button>\n <Button\n variant=\"danger\"\n onClick={() => { void kill(); }}\n disabled={busy !== null}\n title={source === 'claude-code' ? 'Kill the CC background session' : `Delete Bizar agent \"${key}\"`}\n >\n <Octagon size={14} aria-hidden /> Kill\n </Button>\n <Button variant=\"ghost\" onClick={() => { void copyId(); }}>\n <ClipboardCopy size={14} aria-hidden /> Copy id\n </Button>\n </Inline>\n </Stack>\n\n {message !== null && (\n <div\n role=\"status\"\n style={{\n padding: 'var(--space-2) var(--space-3)',\n background: 'color-mix(in oklch, var(--success) 12%, var(--surface-0))',\n border: '1px solid color-mix(in oklch, var(--success) 40%, var(--border))',\n borderRadius: 'var(--radius-md)',\n fontSize: 'var(--fs-12)',\n color: 'var(--success)',\n }}\n >\n {message}\n </div>\n )}\n {lastProcessId !== null && (\n <div\n style={{\n padding: 'var(--space-2) var(--space-3)',\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n fontSize: 'var(--fs-12)',\n color: 'var(--fg-muted)',\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-2)',\n }}\n >\n <span style={{ textTransform: 'uppercase', letterSpacing: '0.04em' }}>PID</span>\n <code\n data-testid=\"agent-process-id\"\n style={{\n fontFamily: 'var(--font-mono)',\n color: 'var(--fg)',\n background: 'var(--surface-1)',\n padding: '2px 6px',\n borderRadius: 'var(--radius-sm)',\n }}\n >\n {lastProcessId}\n </code>\n </div>\n )}\n {error !== null && (\n <div\n role=\"alert\"\n style={{\n padding: 'var(--space-2) var(--space-3)',\n background: 'color-mix(in oklch, var(--danger) 12%, var(--surface-0))',\n border: '1px solid color-mix(in oklch, var(--danger) 40%, var(--border))',\n borderRadius: 'var(--radius-md)',\n fontSize: 'var(--fs-12)',\n color: 'var(--danger)',\n }}\n >\n {error}\n </div>\n )}\n\n {/* Live stream — only meaningful for Claude Code sessions (they have\n a backing JSONL log). Bizar agents have no equivalent surface. */}\n {/* v9.5.0 S49 — agent↔task drilldown. Renders the tasks this agent\n is currently working on (filtered by workedBy / metadata.agent),\n so the user can see \"what is my orchestrator doing right now\"\n without bouncing between this Sheet and the Tasks board. */}\n <Stack gap={2}>\n <div\n style={{\n fontSize: 'var(--fs-12)',\n color: 'var(--fg-muted)',\n textTransform: 'uppercase',\n letterSpacing: '0.04em',\n }}\n >\n Assigned tasks ({myTasks.length})\n </div>\n {tasksQuery.loading && myTasks.length === 0 ? (\n <Skeleton style={{ height: 48 }} />\n ) : myTasks.length === 0 ? (\n <Card variant=\"outlined\">\n <CardBody>\n <span data-testid=\"agent-tasks-empty\" style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n No tasks assigned to this agent.\n </span>\n </CardBody>\n </Card>\n ) : (\n <Stack gap={1}>\n {myTasks.map((t) => (\n <div\n key={t.id}\n data-testid={`agent-tasks-${t.id}`}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-2)',\n padding: 'var(--space-2) var(--space-3)',\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n fontSize: 'var(--fs-13)',\n }}\n >\n <code style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{t.id}</code>\n <span style={{ flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>\n {t.title}\n </span>\n <Badge tone={t.status === 'doing' ? 'info' : t.status === 'blocked' ? 'danger' : 'neutral'}>\n {t.status ?? 'queued'}\n </Badge>\n </div>\n ))}\n </Stack>\n )}\n </Stack>\n {source === 'claude-code' && (\n <Stack gap={2}>\n <div\n style={{\n fontSize: 'var(--fs-12)',\n color: 'var(--fg-muted)',\n textTransform: 'uppercase',\n letterSpacing: '0.04em',\n }}\n >\n <ActivityIcon size={12} aria-hidden style={{ verticalAlign: 'middle', marginRight: 4 }} />\n Live output\n </div>\n <AgentLiveOutput sessionId={key} paused={busy === 'Kill'} />\n </Stack>\n )}\n </Stack>\n </SheetContent>\n </Sheet>\n );\n}\n\n/** formatDuration — human-readable \"3m 12s\" / \"1h 4m\" / \"2d 5h\". */\nfunction formatDuration(ms: number): string {\n if (!Number.isFinite(ms) || ms < 0) return '—';\n const sec = Math.floor(ms / 1000);\n if (sec < 60) return `${sec}s`;\n const min = Math.floor(sec / 60);\n if (min < 60) return `${min}m ${sec % 60}s`;\n const hr = Math.floor(min / 60);\n if (hr < 24) return `${hr}h ${min % 60}m`;\n const day = Math.floor(hr / 24);\n return `${day}d ${hr % 24}h`;\n}","import { useCallback, useMemo, useState } from 'react';\nimport { ChevronDown, ChevronRight, GitBranch, Network } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { useWsMessage } from '../../data/useWebSocket.js';\nimport type { BizarAgent } from '../../data/types.js';\n\n/**\n * AgentHierarchy — v9.4.0 S45.\n *\n * Reads `/api/agents/hierarchy` (returns `{ roots: Array<{ name, agent,\n * children }>, all: BizarAgent[] }` from `agents-store.mjs:230-251`).\n * Renders a collapsible tree where each node is a Bizar agent. Children\n * render indented beneath their parent. Live updates via `agents:change`\n * WS event triggers refetch.\n */\n\nexport interface HierarchyNode {\n name: string;\n agent: BizarAgent | null;\n children: HierarchyNode[];\n}\n\ninterface HierarchyResponse {\n roots?: HierarchyNode[];\n all?: BizarAgent[];\n}\n\nfunction statusToTone(status: string | undefined): 'neutral' | 'info' | 'success' | 'warning' | 'danger' {\n const s = (status || '').toLowerCase();\n if (s === 'busy' || s === 'working') return 'info';\n if (s === 'idle') return 'neutral';\n if (s === 'error' || s === 'stuck') return 'danger';\n if (s === 'paused') return 'warning';\n return 'neutral';\n}\n\nfunction statusLabel(status: string | undefined): string {\n const s = (status || '').toLowerCase();\n if (s === 'working') return 'working';\n if (!s) return 'idle';\n return s;\n}\n\nfunction relativeMs(ms: number | undefined | null): string {\n if (typeof ms !== 'number' || !Number.isFinite(ms) || ms <= 0) return '—';\n const delta = Math.max(0, Date.now() - ms);\n const sec = Math.floor(delta / 1000);\n if (sec < 60) return `${sec}s ago`;\n const min = Math.floor(sec / 60);\n if (min < 60) return `${min}m ago`;\n const hr = Math.floor(min / 60);\n if (hr < 24) return `${hr}h ago`;\n return `${Math.floor(hr / 24)}d ago`;\n}\n\ninterface NodeRowProps {\n node: HierarchyNode;\n depth: number;\n expanded: Set<string>;\n onToggle: (name: string) => void;\n}\n\nfunction NodeRow({ node, depth, expanded, onToggle }: NodeRowProps): JSX.Element {\n const hasChildren = node.children.length > 0;\n const isOpen = expanded.has(node.name);\n const agent = node.agent;\n const tone = statusToTone(agent?.status);\n const status = statusLabel(agent?.status);\n return (\n <>\n <div\n data-testid={`agent-hierarchy-node-${node.name}`}\n style={{\n display: 'grid',\n gridTemplateColumns: 'auto 1fr auto auto',\n alignItems: 'center',\n gap: 'var(--space-3)',\n padding: 'var(--space-2) var(--space-3)',\n paddingLeft: `calc(var(--space-3) + ${depth * 24}px)`,\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n background: 'var(--surface-1)',\n }}\n >\n {hasChildren ? (\n <button\n type=\"button\"\n data-testid={`agent-hierarchy-toggle-${node.name}`}\n aria-label={isOpen ? 'Collapse' : 'Expand'}\n onClick={() => onToggle(node.name)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 22,\n height: 22,\n borderRadius: 'var(--radius-sm)',\n border: '1px solid var(--border)',\n background: 'var(--surface-0)',\n color: 'var(--fg-muted)',\n cursor: 'pointer',\n padding: 0,\n }}\n >\n {isOpen ? <ChevronDown size={12} aria-hidden /> : <ChevronRight size={12} aria-hidden />}\n </button>\n ) : (\n <span aria-hidden style={{ width: 22, height: 22, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', color: 'var(--fg-subtle)' }}>\n <GitBranch size={12} />\n </span>\n )}\n <div style={{ minWidth: 0 }}>\n <div style={{ fontSize: 'var(--fs-13)', fontWeight: 600, color: 'var(--fg)' }}>{node.name}</div>\n {agent && (\n <div style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {agent.role || agent.category || agent.mode || 'agent'}\n {agent.parent && agent.parent !== node.name && (\n <> · parent <code style={{ fontFamily: 'var(--font-mono)' }}>{agent.parent}</code></>\n )}\n </div>\n )}\n </div>\n {typeof agent?.lastSeen === 'number' && agent.lastSeen > 0 && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', fontFamily: 'var(--font-mono)' }}>\n {relativeMs(agent.lastSeen)}\n </span>\n )}\n <Badge tone={tone} dot>{status}</Badge>\n </div>\n {hasChildren && isOpen && node.children.map((child) => (\n <NodeRow key={child.name} node={child} depth={depth + 1} expanded={expanded} onToggle={onToggle} />\n ))}\n </>\n );\n}\n\nexport function AgentHierarchy(): JSX.Element {\n const data = useFetch<HierarchyResponse>('/api/agents/hierarchy');\n const [expanded, setExpanded] = useState<Set<string>>(() => new Set());\n // Track which root names we auto-expanded on first load so subsequent\n // user toggles of those roots are honored.\n const [autoRoots, setAutoRoots] = useState<Set<string>>(() => new Set());\n\n const seenRoots = useMemo(() => data.data?.roots?.map((n) => n.name) ?? [], [data.data]);\n\n // On first successful load, auto-expand every root and remember the set so\n // a future toggle of a root is a real state change (no longer masked by\n // the auto-expand).\n if (autoRoots.size === 0 && seenRoots.length > 0) {\n setAutoRoots(new Set(seenRoots));\n setExpanded(new Set(seenRoots));\n }\n\n const onAgentsChange = useCallback(() => data.refetch(), [data]);\n useWsMessage('agents:change', onAgentsChange);\n\n const toggle = useCallback((name: string) => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (next.has(name)) next.delete(name);\n else next.add(name);\n return next;\n });\n }, []);\n\n if (data.loading && !data.data) {\n return (\n <Stack gap={3}>\n <Skeleton style={{ height: 48 }} />\n <Skeleton style={{ height: 48 }} />\n <Skeleton style={{ height: 48 }} />\n </Stack>\n );\n }\n\n const roots = data.data?.roots ?? [];\n if (roots.length === 0) {\n return (\n <Card>\n <CardBody>\n <EmptyState\n icon={<Network size={32} aria-hidden />}\n title=\"No hierarchy yet\"\n description=\"Agents have no parent links in their frontmatter. Add `parent:` to an agent's .md frontmatter to nest it beneath another agent.\"\n data-testid=\"agent-hierarchy-empty\"\n />\n </CardBody>\n </Card>\n );\n }\n\n return (\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\">\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {roots.length} root agent{roots.length === 1 ? '' : 's'} · {data.data?.all?.length ?? 0} total\n </span>\n </Inline>\n <Stack gap={2}>\n {roots.map((root) => (\n <NodeRow key={root.name} node={root} depth={0} expanded={expanded} onToggle={toggle} />\n ))}\n </Stack>\n </Stack>\n );\n}","import { useCallback, useEffect, useMemo, useState } from '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 { ListHeader } from '../../ui/data/ListHeader.js';\nimport { AgentCard, type AgentCardProps, type AgentStatus } from '../../ui/agents/AgentCard.js';\nimport { AgentDetail } from '../../ui/agents/AgentDetail.js';\nimport { Chip } from '../../ui/data/Chip.js';\nimport { Banner } from '../../ui/feedback/Banner.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { ErrorState } from '../../ui/feedback/ErrorState.js';\nimport { Sheet, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { useWsMessage } from '../../data/useWebSocket.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport type { BizarAgent, CCAgent, WsMessage } from '../../data/types.js';\nimport { AlertTriangle, Bot, Cpu, Pause, Play, Plus, RotateCw } from 'lucide-react';\nimport { AgentHierarchy } from './AgentHierarchy.js';\n\nconst SOURCE_STORAGE_KEY = 'bizar.agents.sourceFilter';\nconst SOURCE_LABELS = {\n all: 'All',\n bizar: 'Bizar',\n 'claude-code': 'Claude Code',\n} as const;\ntype SourceFilter = keyof typeof SOURCE_LABELS;\nconst VALID_SOURCES = Object.keys(SOURCE_LABELS) as SourceFilter[];\n\nfunction readPersistedSource(): SourceFilter {\n if (typeof localStorage === 'undefined') return 'all';\n const v = localStorage.getItem(SOURCE_STORAGE_KEY);\n return VALID_SOURCES.includes(v as SourceFilter) ? (v as SourceFilter) : 'all';\n}\n\n/** relativeTimeMs — \"12s\", \"3m\", \"2h\", \"5d\". Returns \"—\" for missing/future timestamps. */\nfunction relativeTimeMs(ms: number): string {\n if (!Number.isFinite(ms) || ms <= 0) return '—';\n const delta = Math.max(0, Date.now() - ms);\n const sec = Math.floor(delta / 1000);\n if (sec < 60) return `${sec}s ago`;\n const min = Math.floor(sec / 60);\n if (min < 60) return `${min}m ago`;\n const hr = Math.floor(min / 60);\n if (hr < 24) return `${hr}h ago`;\n return `${Math.floor(hr / 24)}d ago`;\n}\n\n/**\n * AgentsView — Sprint S10. Unified Bizar + Claude Code agents.\n *\n * Two REST calls (Bizar agents from `/api/agents`, CC from\n * `/api/cc-agents`) merged into a single grid. A `source` filter\n * chip switches between `bizar | claude-code | all`. Live updates\n * via `agents:change` and `agent:status` WS events.\n */\n\nfunction mapBizar(a: BizarAgent): AgentCardProps {\n const raw = (a.status || 'idle').toLowerCase();\n const status: AgentStatus =\n raw === 'busy' || raw === 'working' ? 'busy' :\n raw === 'error' || raw === 'stuck' ? 'error' :\n raw === 'paused' ? 'paused' : 'idle';\n return {\n id: `bizar:${a.name}`,\n name: a.name,\n role: a.role || a.category || a.mode || 'agent',\n status,\n currentTask: a.currentTaskId ? `Task ${a.currentTaskId}` : undefined,\n lastActivity: a.lastSeen ? new Date(a.lastSeen).toLocaleTimeString() : undefined,\n tasksToday: a.tasksTotal || 0,\n // v9.4.0 — pass real metrics for the new AgentCard strip. The old\n // `tpmHistory` field was dead because AgentCard only renders the\n // sparkline when `length > 1` and we always passed a single point.\n tasksSucceeded: typeof a.tasksSucceeded === 'number' ? a.tasksSucceeded : undefined,\n tasksTotal: typeof a.tasksTotal === 'number' ? a.tasksTotal : undefined,\n successRate: typeof a.successRate === 'number' ? a.successRate : undefined,\n lastSeenMs: typeof a.lastSeen === 'number' && a.lastSeen > 0 ? a.lastSeen : undefined,\n badges: a.tags || [],\n };\n}\n\nfunction mapCC(a: CCAgent): AgentCardProps {\n const raw = (a.status || a.state || 'idle').toLowerCase();\n const status: AgentStatus =\n raw === 'busy' || raw === 'working' ? 'busy' :\n raw === 'error' ? 'error' :\n raw === 'paused' ? 'paused' : 'idle';\n return {\n id: `cc:${a.sessionId || a.id}`,\n name: a.name || a.sessionId?.slice(0, 8) || 'unknown',\n role: a.kind === 'background' ? 'CC background' : 'CC interactive',\n status,\n currentTask: a.lastMessageSnippet || undefined,\n lastActivity: a.lastMessageAt ? new Date(a.lastMessageAt).toLocaleTimeString() : (a.startedAt ? new Date(a.startedAt).toLocaleTimeString() : undefined),\n tasksToday: a.messageCount || 0,\n // CC agents don't expose successRate/tasksSucceeded — only messageCount.\n // Skip the metric strip for them; the badge + lastActivity carry the\n // signal.\n badges: [a.cwd?.split('/').slice(-2).join('/') || ''].filter(Boolean),\n };\n}\n\nexport function AgentsView(): JSX.Element {\n const bizar = useFetch<{ agents?: BizarAgent[] }>('/api/agents');\n const cc = useFetch<{ agents?: CCAgent[]; error?: string }>('/api/cc-agents');\n const stuck = useFetch<{ stuck?: BizarAgent[] }>('/api/agents/stuck');\n const [source, setSource] = useState<SourceFilter>(readPersistedSource);\n const [mode, setMode] = useState<'roster' | 'hierarchy'>('roster');\n useEffect(() => {\n if (typeof localStorage !== 'undefined') localStorage.setItem(SOURCE_STORAGE_KEY, source);\n }, [source]);\n const [bizarList, setBizarList] = useState<BizarAgent[]>([]);\n const [ccList, setCCList] = useState<CCAgent[]>([]);\n const [initialized, setInitialized] = useState(false);\n const [openId, setOpenId] = useState<string | null>(null);\n const [createDraft, setCreateDraft] = useState<{ name: string; role: string } | null>(null);\n const [creating, setCreating] = useState(false);\n const [createError, setCreateError] = useState<string | null>(null);\n const [restartingNames, setRestartingNames] = useState<Set<string>>(() => new Set());\n\n const saveCreate = async (): Promise<void> => {\n if (createDraft === null || !createDraft.name.trim()) return;\n setCreating(true);\n setCreateError(null);\n try {\n await fetchJson('/api/agents', { method: 'POST', body: { name: createDraft.name.trim(), role: createDraft.role.trim() || 'agent' } });\n setCreateDraft(null);\n bizar.refetch();\n } catch (err) {\n setCreateError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setCreating(false);\n }\n };\n\n // v9.5.0 S48 — inline Restart from the stuck banner. One-click recovery\n // without forcing the user to drill into the per-agent Sheet. The\n // server broadcasts agents:change on success so the banner refreshes.\n const restartStuck = async (name: string): Promise<void> => {\n setRestartingNames((prev) => new Set(prev).add(name));\n try {\n await fetchJson(`/api/agents/${encodeURIComponent(name)}/restart`, { method: 'POST' });\n stuck.refetch();\n bizar.refetch();\n } catch (err) {\n setCreateError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setRestartingNames((prev) => {\n const next = new Set(prev);\n next.delete(name);\n return next;\n });\n }\n };\n\n // v10-S1 — inline Pause/Resume on the stuck banner. Pause stops\n // heartbeat drain (status='paused'); Resume re-enables\n // (status='idle' so Odin picks the agent up again on the next\n // spawn). Uses the same in-flight Set pattern as restartStuck so\n // all three actions disable each other per-row while pending.\n const [busyStuckNames, setBusyStuckNames] = useState<Set<string>>(() => new Set());\n const setStuckActionStatus = async (name: string, status: 'paused' | 'idle'): Promise<void> => {\n setBusyStuckNames((prev) => new Set(prev).add(name));\n try {\n await fetchJson(`/api/agents/${encodeURIComponent(name)}/status`, {\n method: 'POST',\n body: { status },\n });\n stuck.refetch();\n bizar.refetch();\n } catch (err) {\n setCreateError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusyStuckNames((prev) => {\n const next = new Set(prev);\n next.delete(name);\n return next;\n });\n }\n };\n\n // v10-S1 — bulk Pause-all-stuck. Fires status='paused' for every\n // agent currently in /api/agents/stuck. Used when a wedged cluster\n // needs to be drained before restart. Per-row actions are still\n // available for selective triage.\n const [bulkBusy, setBulkBusy] = useState<boolean>(false);\n const bulkPauseStuck = async (): Promise<void> => {\n const list = stuck.data?.stuck ?? [];\n if (list.length === 0) return;\n setBulkBusy(true);\n try {\n await Promise.all(list.map((a) =>\n fetchJson(`/api/agents/${encodeURIComponent(a.name)}/status`, {\n method: 'POST',\n body: { status: 'paused' },\n }).catch((err) => {\n setCreateError(err instanceof FetchError ? err.message : (err as Error).message);\n return null;\n }),\n ));\n stuck.refetch();\n bizar.refetch();\n } finally {\n setBulkBusy(false);\n }\n };\n\n useEffect(() => {\n if (!initialized && bizar.data?.agents !== undefined && cc.data?.agents !== undefined) {\n setInitialized(true);\n setBizarList(bizar.data.agents);\n setCCList(cc.data.agents);\n }\n }, [bizar.data, cc.data, initialized]);\n\n const onAgentsChange = useCallback(() => {\n // Bust both caches; the next mount will re-fetch (cheap because\n // the dashboard views are lazy-mounted).\n bizar.refetch();\n cc.refetch();\n }, [bizar, cc]);\n useWsMessage('agents:change', onAgentsChange);\n\n const onAgentStatus = useCallback((msg: WsMessage) => {\n if (msg.type !== 'agent:status') return;\n const a = (msg as Extract<WsMessage, { type: 'agent:status' }>).agent;\n if (!a || !a.name) return;\n setBizarList((prev) => {\n const idx = prev.findIndex((x) => x.name === a.name);\n if (idx === -1) return [...prev, a];\n const copy = prev.slice();\n copy[idx] = { ...copy[idx], ...a };\n return copy;\n });\n }, []);\n useWsMessage('agent:status', onAgentStatus);\n\n const cards = useMemo(() => {\n const out: Array<AgentCardProps & { source: 'bizar' | 'claude-code' }> = [];\n if (source !== 'claude-code') {\n for (const a of bizarList) out.push({ ...mapBizar(a), source: 'bizar' });\n }\n if (source !== 'bizar') {\n for (const a of ccList) out.push({ ...mapCC(a), source: 'claude-code' });\n }\n return out;\n }, [bizarList, ccList, source]);\n\n return (\n <Stack gap={5} data-testid=\"agents-view\">\n <ViewHeader\n title=\"Agents\"\n description=\"Bizar agents (frontmatter-driven) and Claude Code background agents.\"\n actions={\n <Button variant=\"primary\" onClick={() => setCreateDraft({ name: '', role: '' })} data-testid=\"agent-create-open\">\n <Plus size={14} aria-hidden /> New agent\n </Button>\n }\n />\n <ListHeader\n title=\"Roster\"\n count={cards.length}\n description={stuck.data?.stuck && stuck.data.stuck.length > 0 ? `${stuck.data.stuck.length} stuck` : undefined}\n testid=\"agents-list-header\"\n />\n {(stuck.data?.stuck ?? []).length > 0 && (\n <Banner\n tone=\"warning\"\n data-testid=\"agents-stuck-banner\"\n action={\n <Inline gap={2}>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => { void bulkPauseStuck(); }}\n disabled={bulkBusy}\n data-testid=\"agents-stuck-bulk-pause\"\n title=\"Pause every stuck agent at once\"\n >\n <Pause size={12} aria-hidden /> {bulkBusy ? 'Pausing…' : 'Pause all'}\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => setMode('hierarchy')}>\n View details\n </Button>\n </Inline>\n }\n >\n <Stack gap={2}>\n <Inline align=\"center\" gap={2}>\n <AlertTriangle size={14} aria-hidden style={{ color: 'var(--warning)' }} />\n <span>\n {(stuck.data?.stuck ?? []).length} agent{stuck.data && stuck.data.stuck && stuck.data.stuck.length === 1 ? '' : 's'} stuck (no heartbeat >5m)\n </span>\n </Inline>\n <Stack gap={1}>\n {(stuck.data?.stuck ?? []).map((s) => {\n const restarting = restartingNames.has(s.name);\n const paused = s.status === 'paused';\n const busy = restarting || busyStuckNames.has(s.name);\n return (\n <Inline key={s.name} align=\"center\" justify=\"between\" gap={2} data-testid={`agents-stuck-row-${s.name}`}>\n <Inline gap={2} align=\"center\">\n <code style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)' }}>{s.name}</code>\n <Badge tone={paused ? 'warning' : 'danger'}>{paused ? 'paused' : (s.status || 'stuck')}</Badge>\n {typeof s.lastSeen === 'number' && s.lastSeen > 0 && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n last seen {relativeTimeMs(s.lastSeen)}\n </span>\n )}\n </Inline>\n <Inline gap={1}>\n {paused ? (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled={busy}\n onClick={() => { void setStuckActionStatus(s.name, 'idle'); }}\n data-testid={`agents-stuck-resume-${s.name}`}\n >\n <Play size={12} aria-hidden /> Resume\n </Button>\n ) : (\n <Button\n variant=\"secondary\"\n size=\"sm\"\n disabled={busy}\n onClick={() => { void setStuckActionStatus(s.name, 'paused'); }}\n data-testid={`agents-stuck-pause-${s.name}`}\n >\n <Pause size={12} aria-hidden /> Pause\n </Button>\n )}\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={busy}\n onClick={() => { void restartStuck(s.name); }}\n data-testid={`agents-stuck-restart-${s.name}`}\n >\n <RotateCw size={12} aria-hidden /> {restarting ? 'Restarting…' : 'Restart'}\n </Button>\n </Inline>\n </Inline>\n );\n })}\n </Stack>\n </Stack>\n </Banner>\n )}\n <Inline align=\"center\" justify=\"between\" wrap gap={2}>\n <Inline gap={2}>\n {(['all', 'bizar', 'claude-code'] as SourceFilter[]).map((id) => (\n <Chip\n key={id}\n selected={source === id}\n onClick={() => setSource(id)}\n >\n {id === 'bizar' ? <Bot size={12} aria-hidden /> : id === 'claude-code' ? <Cpu size={12} aria-hidden /> : null}{' '}\n {SOURCE_LABELS[id]}\n </Chip>\n ))}\n </Inline>\n <Inline gap={2}>\n <Chip\n data-testid=\"agents-mode-roster\"\n selected={mode === 'roster'}\n onClick={() => setMode('roster')}\n >\n Roster\n </Chip>\n <Chip\n data-testid=\"agents-mode-hierarchy\"\n selected={mode === 'hierarchy'}\n onClick={() => setMode('hierarchy')}\n >\n Hierarchy\n </Chip>\n </Inline>\n </Inline>\n {mode === 'hierarchy' ? (\n <AgentHierarchy />\n ) : cards.length === 0 && (bizar.loading || cc.loading) ? (\n <Grid cols={3}>\n <Skeleton style={{ height: 140 }} />\n <Skeleton style={{ height: 140 }} />\n <Skeleton style={{ height: 140 }} />\n </Grid>\n ) : cards.length === 0 && (bizar.error || cc.error) ? (\n <ErrorState\n block\n title=\"Couldn't load agents\"\n description=\"Both bizar and CC roster endpoints failed. Retry to refetch.\"\n error={bizar.error ?? cc.error}\n onRetry={() => { void bizar.refetch(); void cc.refetch(); }}\n testid=\"agents-error\"\n />\n ) : cards.length === 0 ? (\n <span style={{ color: 'var(--fg-muted)' }}>\n No agents yet. Run <code>/loop</code> or spawn one via the command palette.\n </span>\n ) : (\n <Grid cols={3}>\n {cards.map((c) => (\n <AgentCard key={c.id} {...c} onOpen={() => setOpenId(c.id)} />\n ))}\n </Grid>\n )}\n\n {openId !== null && (() => {\n const sel = cards.find((c) => c.id === openId);\n if (!sel) return null;\n const ccSource = sel.source === 'claude-code' ? ccList.find((a) => sel.id === `cc:${a.sessionId || a.id}`) : undefined;\n const bzSource = sel.source === 'bizar' ? bizarList.find((a) => sel.id === `bizar:${a.name}`) : undefined;\n return (\n <AgentDetail\n agentId={sel.id}\n name={sel.name}\n role={sel.role}\n status={sel.status}\n currentTask={sel.currentTask}\n startedAt={ccSource?.startedAt ?? bzSource?.lastSeen}\n messageCount={ccSource?.messageCount}\n lastMessageSnippet={ccSource?.lastMessageSnippet}\n successRate={bzSource?.successRate}\n tasksTotal={bzSource?.tasksTotal}\n open={openId !== null}\n onOpenChange={(o) => { if (!o) setOpenId(null); }}\n />\n );\n })()}\n\n {/* v9.2.0 — create-agent Sheet. Closes the audit-flagged \"no way\n to add a new agent\" HIGH gap. */}\n <Sheet open={createDraft !== null} onOpenChange={(o) => { if (!o) setCreateDraft(null); }}>\n <SheetContent side=\"right\" title=\"New agent\">\n {createDraft !== null && (\n <Stack gap={4} style={{ padding: 'var(--space-4)' }}>\n <Stack gap={2}>\n <label htmlFor=\"agent-create-name\" style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Name</label>\n <Input\n id=\"agent-create-name\"\n value={createDraft.name}\n onChange={(e) => setCreateDraft({ ...createDraft, name: e.target.value })}\n placeholder=\"e.g. frigg\"\n disabled={creating}\n data-testid=\"agent-create-name\"\n />\n </Stack>\n <Stack gap={2}>\n <label htmlFor=\"agent-create-role\" style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Role (optional)</label>\n <Input\n id=\"agent-create-role\"\n value={createDraft.role}\n onChange={(e) => setCreateDraft({ ...createDraft, role: e.target.value })}\n placeholder=\"e.g. code-review\"\n disabled={creating}\n data-testid=\"agent-create-role\"\n />\n </Stack>\n {createError !== null && <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{createError}</span>}\n <Inline gap={2}>\n <Button variant=\"primary\" onClick={() => { void saveCreate(); }} disabled={creating || !createDraft.name.trim()} data-testid=\"agent-create-submit\">\n Create agent\n </Button>\n <Button variant=\"ghost\" onClick={() => setCreateDraft(null)} disabled={creating}>\n Cancel\n </Button>\n </Inline>\n </Stack>\n )}\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}"],"names":["ClipboardCopy","createLucideIcon","Octagon","STATUS_LABEL","STATUS_TONE","STATUS_FG","relativeTime","ms","delta","sec","min","hr","successTone","rate","lastSeenTone","AgentCard","props","name","role","status","lastActivity","currentTask","tasksToday","tasksSucceeded","tasksTotal","successRate","lastSeenMs","onOpen","badges","className","showMetrics","jsxs","cx","jsx","Avatar","Badge","Activity","Zap","ProgressBar","MAX_EVENTS","AgentLiveOutput","sessionId","paused","events","setEvents","useState","setStatus","error","setError","pausedLocal","setPausedLocal","autoScroll","setAutoScroll","containerRef","useRef","sourceRef","useEffect","url","src","onSnapshot","ev","data","onEvent","prev","next","onEnd","onErrEv","el","renderEvent","idx","tone","_a","label","_b","text","_c","Stack","Inline","Button","p","Play","Pause","RefreshCw","e","atBottom","parseId","agentId","AgentDetail","open","onOpenChange","startedAt","messageCount","lastMessageSnippet","source","key","prompt","setPrompt","busy","setBusy","message","setMessage","lastProcessId","setLastProcessId","tasksQuery","useFetch","myTasks","useMemo","t","md","runAction","method","endpoint","body","res","fetchJson","sessionExtra","err","sendPrompt","trimmed","restart","seed","kill","copyId","Sheet","SheetContent","formatDuration","ActivityIcon","Textarea","Send","Skeleton","RotateCw","Card","CardBody","statusToTone","s","statusLabel","relativeMs","NodeRow","node","depth","expanded","onToggle","hasChildren","isOpen","agent","Fragment","ChevronDown","ChevronRight","GitBranch","child","AgentHierarchy","setExpanded","autoRoots","setAutoRoots","seenRoots","n","onAgentsChange","useCallback","useWsMessage","toggle","roots","EmptyState","Network","root","SOURCE_STORAGE_KEY","SOURCE_LABELS","VALID_SOURCES","readPersistedSource","v","relativeTimeMs","mapBizar","a","raw","mapCC","AgentsView","bizar","cc","stuck","setSource","mode","setMode","bizarList","setBizarList","ccList","setCCList","initialized","setInitialized","openId","setOpenId","createDraft","setCreateDraft","creating","setCreating","createError","setCreateError","restartingNames","setRestartingNames","saveCreate","FetchError","restartStuck","busyStuckNames","setBusyStuckNames","setStuckActionStatus","bulkBusy","setBulkBusy","bulkPauseStuck","list","onAgentStatus","msg","x","copy","cards","out","ViewHeader","Plus","ListHeader","Banner","AlertTriangle","_d","restarting","id","Chip","Bot","Cpu","Grid","ErrorState","c","sel","ccSource","bzSource","o","Input"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ArtifactsView-znhN8GTR.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/file-code.js","../../src/web/v8/views/Artifacts/ClaudeArtifactView.tsx","../../src/web/v8/views/Artifacts/ArtifactsView.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 FileCode = createLucideIcon(\"FileCode\", [\n [\"path\", { d: \"M10 12.5 8 15l2 2.5\", key: \"1tg20x\" }],\n [\"path\", { d: \"m14 12.5 2 2.5-2 2.5\", key: \"yinavb\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z\", key: \"1mlx9k\" }]\n]);\n\nexport { FileCode as default };\n//# sourceMappingURL=file-code.js.map\n","/**\n * v8/views/Artifacts/ClaudeArtifactView.tsx — v10.1.0.\n *\n * Renders Claude-* kind artifacts (HTML / SVG / React) inside a\n * sandboxed iframe. The server hands us a fully-compiled HTML envelope\n * (returned from GET /api/artifacts/:slug/render) and we drop it into\n * `srcdoc`. The iframe has `sandbox` set so even if a malicious escape\n * slips past server-side filtering, the runtime is still constrained.\n *\n * Two render modes:\n * 1. <iframe srcdoc> — for full-envelope artifacts (default).\n * 2. Plain `<div>` for an `mdx` kind fallback (handled by caller).\n */\n\nimport { useState } from 'react';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { AlertTriangle, ShieldCheck, ExternalLink } from 'lucide-react';\nimport { Button } from '../../ui/controls/Button.js';\n\nexport interface ClaudeRenderPayload {\n slug: string;\n kind: 'claude-html' | 'claude-svg' | 'claude-react' | 'mdx';\n html?: string;\n blocks?: unknown[];\n frontmatter?: Record<string, unknown>;\n warnings?: Array<{ message?: string; pattern?: string }>;\n safeMode?: boolean;\n compiledAt?: string;\n}\n\nexport function ClaudeArtifactView({\n payload,\n slug,\n}: {\n payload: ClaudeRenderPayload;\n slug: string;\n}): JSX.Element {\n const [showSource, setShowSource] = useState(false);\n\n if (payload.kind === 'mdx') {\n // Legacy fallback — the server returns no `html` for mdx; just show\n // the compiled block count.\n return (\n <Card variant=\"default\" data-testid={`claude-view-${slug}`}>\n <CardBody>\n <Inline align=\"center\" gap={2}>\n <ShieldCheck size={14} aria-hidden style={{ color: 'var(--fg-muted)' }} />\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n Legacy MDX — {Array.isArray(payload.blocks) ? `${payload.blocks.length} blocks` : 'no blocks'}\n </span>\n </Inline>\n </CardBody>\n </Card>\n );\n }\n\n if (!payload.html) {\n return (\n <Card variant=\"default\" data-testid={`claude-view-${slug}`}>\n <CardBody>\n <span role=\"alert\" style={{ color: 'var(--danger)' }}>\n No HTML returned by the compiler.\n </span>\n </CardBody>\n </Card>\n );\n }\n\n return (\n <Stack gap={2} data-testid={`claude-view-${slug}`}>\n {payload.safeMode && (\n <Inline\n align=\"center\"\n gap={2}\n style={{\n padding: 'var(--space-2)',\n background: 'var(--callout-warning-bg, #fdf6e3)',\n border: '1px solid var(--callout-warning-border, #e0c97d)',\n borderRadius: 'var(--radius-sm)',\n fontSize: 'var(--fs-12)',\n }}\n role=\"status\"\n data-testid={`claude-safe-${slug}`}\n >\n <AlertTriangle size={14} aria-hidden style={{ color: '#b58900' }} />\n <span>\n Safe mode — the compiler stripped potentially dangerous\n patterns in this artifact.\n </span>\n </Inline>\n )}\n {payload.warnings && payload.warnings.length > 0 && (\n <details\n style={{\n fontSize: 'var(--fs-12)',\n color: 'var(--fg-muted)',\n padding: 'var(--space-2)',\n background: 'var(--surface-1)',\n borderRadius: 'var(--radius-sm)',\n }}\n >\n <summary>{payload.warnings.length} warning(s)</summary>\n <ul style={{ marginTop: 'var(--space-1)' }}>\n {payload.warnings.map((w, i) => (\n <li key={i}>\n <code style={{ fontFamily: 'var(--font-mono)' }}>\n {w.pattern}\n </code>{' '}\n — {w.message}\n </li>\n ))}\n </ul>\n </details>\n )}\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)' }}>\n {payload.kind} · compiled {payload.compiledAt ? new Date(payload.compiledAt).toLocaleTimeString() : 'now'}\n </span>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={() => setShowSource((v) => !v)} data-testid={`claude-source-${slug}`}>\n {showSource ? 'Hide source' : 'Show source'}\n </Button>\n <a\n href={`/api/artifacts/${slug}/view`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-testid={`claude-blank-${slug}`}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: 'var(--space-1)',\n fontSize: 'var(--fs-12)',\n padding: 'var(--space-1) var(--space-2)',\n color: 'var(--fg)',\n textDecoration: 'none',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n background: 'var(--surface-0)',\n }}\n >\n <ExternalLink size={12} aria-hidden /> Open in new tab\n </a>\n </Inline>\n </Inline>\n <iframe\n title={`claude-artifact-${slug}`}\n data-testid={`claude-iframe-${slug}`}\n sandbox=\"allow-scripts allow-same-origin\"\n srcDoc={payload.html}\n style={{\n width: '100%',\n height: 480,\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n background: 'white',\n }}\n />\n {showSource && (\n <pre\n data-testid={`claude-source-text-${slug}`}\n style={{\n padding: 'var(--space-2)',\n background: 'var(--surface-1)',\n borderRadius: 'var(--radius-sm)',\n fontSize: 'var(--fs-11)',\n maxHeight: 320,\n overflow: 'auto',\n fontFamily: 'var(--font-mono)',\n whiteSpace: 'pre-wrap',\n }}\n >\n {payload.html}\n </pre>\n )}\n </Stack>\n );\n}","/**\n * v8/views/Artifacts/ArtifactsView.tsx — Sprint S43, v9.3.0 → v10.1.0\n * (Claude Artifacts swap).\n *\n * Artifacts list (GET /api/artifacts) with per-row open-to-detail\n * (right-hand Sheet using GET /api/artifacts/:slug + /render) and\n * inline-confirm Delete (DELETE /api/artifacts/:slug). Add Sheet\n * posts a new artifact (POST /api/artifacts {slug, kind, source, ...}).\n *\n * v10.1.0 — Detail panel dispatches by `kind`:\n * - claude-html / claude-svg / claude-react → sandboxed iframe\n * via <ClaudeArtifactView>\n * - mdx → legacy block-renderer fallback\n *\n * The AddForm gains a `kind` dropdown + a textarea bound to `source`;\n * the textarea defaults to the kind-specific starting template.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Layers, Plus, Trash2, RefreshCcw, FileCode, ExternalLink } 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 { Textarea } from '../../ui/controls/Textarea.js';\nimport { Sheet, 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';\nimport { ClaudeArtifactView, type ClaudeRenderPayload } from './ClaudeArtifactView.js';\n\ninterface Artifact {\n slug: string;\n title?: string;\n kind?: 'mdx' | 'claude-html' | 'claude-svg' | 'claude-react';\n description?: string;\n createdAt?: string | number;\n updatedAt?: string | number;\n planMdx?: string;\n source?: string;\n frontmatter?: Record<string, unknown>;\n}\n\nexport function ArtifactsView(): JSX.Element {\n const payload = useFetch<{ artifacts: Artifact[] }>('/api/artifacts');\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [adding, setAdding] = useState<boolean>(false);\n const [activeSlug, setActiveSlug] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const artifacts = useMemo<Artifact[]>(() => payload.data?.artifacts ?? [], [payload.data]);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const drop = async (slug: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/artifacts/${slug}`, { method: 'DELETE' });\n setConfirmDelete(null);\n if (activeSlug === slug) setActiveSlug(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <Stack gap={4} data-testid=\"artifacts-view\">\n <ViewHeader\n title=\"Artifacts\"\n description=\"Generated artifacts (plans, diagrams, canvases).\"\n actions={\n <Inline align=\"center\" gap={2}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"artifacts-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"artifacts-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setAdding(true)} data-testid=\"artifacts-add\">\n <Plus size={14} aria-hidden /> Add\n </Button>\n </Inline>\n }\n />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && artifacts.length === 0 ? (\n <Stack gap={1}>\n <Skeleton style={{ height: 48 }} />\n <Skeleton style={{ height: 48 }} />\n </Stack>\n ) : artifacts.length === 0 ? (\n <EmptyState icon={<Layers size={28} aria-hidden />} title=\"No artifacts\" description=\"Create one to get started.\" />\n ) : (\n <Stack gap={1}>\n {artifacts.map((a) => {\n const isConfirming = confirmDelete === a.slug;\n return (\n <div\n key={a.slug}\n data-testid={`artifact-row-${a.slug}`}\n style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)' }}\n >\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Stack gap={0} style={{ minWidth: 0, flex: 1 }}>\n <Inline align=\"center\" gap={2}>\n <FileCode size={12} aria-hidden style={{ color: 'var(--fg-muted)' }} />\n <strong style={{ fontSize: 'var(--fs-13)' }}>{a.title || a.slug}</strong>\n <code style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>{a.slug}</code>\n {a.kind && <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)' }}>· {a.kind}</span>}\n </Inline>\n {a.description && <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{a.description}</span>}\n </Stack>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={() => setActiveSlug((cur) => (cur === a.slug ? null : a.slug))} data-testid={`artifact-open-${a.slug}`} aria-label={`Open ${a.slug}`}>\n <ExternalLink size={14} aria-hidden /> Open\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete((cur) => (cur === a.slug ? null : a.slug))} data-testid={`artifact-delete-${a.slug}`} aria-label={`Delete ${a.slug}`}>\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(a.slug)} data-testid={`artifact-confirm-delete-${a.slug}`}>\n Confirm delete\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\n <Sheet open={adding} onOpenChange={setAdding}>\n <SheetContent side=\"right\" title=\"Add artifact\" description=\"Slug + kind + initial source.\">\n <AddForm\n onSubmit={async (body) => {\n await fetchJson('/api/artifacts', { method: 'POST', body });\n setAdding(false);\n refresh();\n }}\n onCancel={() => setAdding(false)}\n />\n </SheetContent>\n </Sheet>\n\n <Sheet open={activeSlug !== null} onOpenChange={(open) => { if (!open) setActiveSlug(null); }}>\n <SheetContent side=\"right\" title={activeSlug ?? ''} description=\"Artifact detail\">\n {activeSlug !== null && <ArtifactDetail slug={activeSlug} refresh={refresh} />}\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n\nfunction AddForm({\n onSubmit,\n onCancel,\n}: {\n onSubmit: (body: { slug: string; title?: string; description?: string; kind?: string; source?: string; planMdx?: string }) => Promise<void>;\n onCancel: () => void;\n}): JSX.Element {\n const [slug, setSlug] = useState<string>('');\n const [title, setTitle] = useState<string>('');\n const [description, setDescription] = useState<string>('');\n const [kind, setKind] = useState<'mdx' | 'claude-html' | 'claude-svg' | 'claude-react'>('claude-html');\n const [source, setSource] = useState<string>(KIND_TEMPLATES['claude-html']);\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n // When the user changes kind, swap the textarea content to a starter\n // template for that kind. They can still edit further.\n const onKindChange = (next: 'mdx' | 'claude-html' | 'claude-svg' | 'claude-react'): void => {\n setKind(next);\n setSource(KIND_TEMPLATES[next]);\n };\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Slug</span>\n <Input value={slug} onChange={(e) => setSlug((e.target as HTMLInputElement).value)} data-testid=\"artifact-form-slug\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Title</span>\n <Input value={title} onChange={(e) => setTitle((e.target as HTMLInputElement).value)} data-testid=\"artifact-form-title\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Description</span>\n <Input value={description} onChange={(e) => setDescription((e.target as HTMLInputElement).value)} data-testid=\"artifact-form-description\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Kind</span>\n <select\n value={kind}\n onChange={(e) => onKindChange(e.target.value as typeof kind)}\n data-testid=\"artifact-form-kind\"\n style={{\n fontFamily: 'inherit',\n fontSize: 'var(--fs-12)',\n padding: 'var(--space-2)',\n background: 'var(--surface-0)',\n color: 'var(--fg)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n }}\n >\n <option value=\"claude-html\">Claude HTML</option>\n <option value=\"claude-svg\">Claude SVG</option>\n <option value=\"claude-react\">Claude React (JSX)</option>\n <option value=\"mdx\">Legacy MDX (glyphs)</option>\n </select>\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {kind === 'mdx' ? 'Plan MDX' : 'Source'}\n </span>\n <Textarea\n value={source}\n rows={kind === 'claude-react' ? 10 : 6}\n onChange={(e) => setSource((e.target as HTMLTextAreaElement).value)}\n data-testid={kind === 'mdx' ? 'artifact-form-mdx' : 'artifact-form-source'}\n />\n </label>\n {error !== null && <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>}\n <Inline justify=\"end\" gap={2}>\n <Button variant=\"ghost\" onClick={onCancel}>Cancel</Button>\n <Button\n variant=\"primary\"\n disabled={busy || !slug.trim()}\n data-testid=\"artifact-form-submit\"\n onClick={async () => {\n setBusy(true);\n setError(null);\n try {\n const body: { slug: string; title?: string; description?: string; kind: typeof kind; source?: string; planMdx?: string } = {\n slug: slug.trim(),\n title: title.trim() || undefined,\n description: description.trim() || undefined,\n kind,\n };\n if (source) {\n if (kind === 'mdx') body.planMdx = source; else body.source = source;\n }\n await onSubmit(body);\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n setBusy(false);\n }\n }}\n >\n {busy ? 'Creating…' : 'Create'}\n </Button>\n </Inline>\n </Stack>\n );\n}\n\nconst KIND_TEMPLATES: Record<'mdx' | 'claude-html' | 'claude-svg' | 'claude-react', string> = {\n mdx: '# Hello\\n\\nAdd some MDX here.',\n 'claude-html': '<!doctype html>\\n<h1 style=\"font-family:system-ui\">Hello artifact</h1>\\n<p>Edit me — click <em>Open</em> to preview.</p>',\n 'claude-svg': '<svg viewBox=\"0 0 100 100\" width=\"200\" height=\"200\">\\n <circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"#0b66c3\"/>\\n <text x=\"50\" y=\"55\" text-anchor=\"middle\" fill=\"white\" font-size=\"14\">SVG</text>\\n</svg>',\n 'claude-react': 'export default function App() {\\n const [n, setN] = React.useState(0);\\n return (\\n <div style={{ fontFamily: \"system-ui\", padding: 16 }}>\\n <h1>Hello</h1>\\n <button onClick={() => setN(n + 1)}>clicked {n}</button>\\n </div>\\n );\\n}',\n};\n\nfunction ArtifactDetail({ slug, refresh }: { slug: string; refresh: () => void }): JSX.Element {\n const payload = useFetch<Artifact>(`/api/artifacts/${slug}`);\n const renderPayload = useFetch<ClaudeRenderPayload>(`/api/artifacts/${slug}/render`);\n const kind = payload.data?.kind || 'mdx';\n const isClaude = kind === 'claude-html' || kind === 'claude-svg' || kind === 'claude-react';\n\n return (\n <Stack gap={2} style={{ padding: 'var(--space-4)' }}>\n {payload.loading && !payload.data ? (\n <Skeleton style={{ height: 80 }} />\n ) : payload.data ? (\n <Stack gap={2}>\n <Inline align=\"center\" gap={2}>\n <strong>{payload.data.title || payload.data.slug}</strong>\n <code style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>{payload.data.slug}</code>\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)' }}>· {kind}</span>\n </Inline>\n {payload.data.description && <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{payload.data.description}</span>}\n\n {/* Claude-* kinds render in a sandboxed iframe via the new\n <ClaudeArtifactView>. The server compiles the source on\n demand and returns iframe-ready HTML (srcdoc). */}\n {isClaude && (\n renderPayload.data ? (\n <ClaudeArtifactView payload={renderPayload.data} slug={slug} />\n ) : (\n <Skeleton style={{ height: 200 }} />\n )\n )}\n\n {/* Legacy MDX path keeps the original block-count summary. */}\n {!isClaude && renderPayload.data && (\n <span data-testid={`artifact-render-${slug}`} style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n Render: {Array.isArray(renderPayload.data.blocks) ? `${renderPayload.data.blocks.length} blocks` : 'no blocks'}\n </span>\n )}\n\n {/* Inline editor — kind switch + textarea + save. */}\n <Editor payload={payload.data} slug={slug} onSaved={() => { void payload.refetch(); void renderPayload.refetch(); refresh(); }} />\n </Stack>\n ) : (\n <span role=\"alert\" style={{ color: 'var(--danger)' }}>Not found</span>\n )}\n </Stack>\n );\n}\n\n/**\n * Inline editor: lets the user change the kind, edit the body, and\n * save via PUT /api/artifacts/:slug. After save we re-fetch both the\n * artifact + the compiled render so the iframe updates with the new\n * source on the next paint.\n */\nfunction Editor({\n payload,\n slug,\n onSaved,\n}: {\n payload: Artifact;\n slug: string;\n onSaved: () => void;\n}): JSX.Element {\n const initial = payload.source ?? payload.planMdx ?? '';\n const [editKind, setEditKind] = useState<typeof payload.kind>(payload.kind || 'mdx');\n const [editSource, setEditSource] = useState<string>(initial);\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n const [open, setOpen] = useState<boolean>(false);\n\n // Sync the textarea when the underlying artifact changes (e.g. when\n // the user opens a different slug in the same Sheet).\n useEffect(() => {\n setEditKind(payload.kind || 'mdx');\n setEditSource(payload.source ?? payload.planMdx ?? '');\n }, [payload.slug, payload.source, payload.planMdx, payload.kind]);\n\n const dirty =\n editKind !== (payload.kind || 'mdx') || editSource !== (payload.source ?? payload.planMdx ?? '');\n\n const save = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n try {\n await fetchJson(`/api/artifacts/${slug}`, {\n method: 'PUT',\n body: {\n kind: editKind,\n source: editKind === 'mdx' ? undefined : editSource,\n planMdx: editKind === 'mdx' ? editSource : undefined,\n },\n });\n onSaved();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={1} data-testid={`artifact-editor-${slug}`}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Button variant=\"ghost\" onClick={() => setOpen((v) => !v)} data-testid={`artifact-edit-toggle-${slug}`}>\n {open ? 'Close editor' : 'Edit'}\n </Button>\n {dirty && (\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--callout-warning-fg, #b58900)' }}>\n Unsaved changes\n </span>\n )}\n </Inline>\n {open && (\n <Stack gap={2}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Kind</span>\n <select\n value={editKind}\n onChange={(e) => setEditKind(e.target.value as typeof editKind)}\n data-testid={`artifact-edit-kind-${slug}`}\n style={{\n fontFamily: 'inherit',\n fontSize: 'var(--fs-12)',\n padding: 'var(--space-2)',\n background: 'var(--surface-0)',\n color: 'var(--fg)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n }}\n >\n <option value=\"claude-html\">Claude HTML</option>\n <option value=\"claude-svg\">Claude SVG</option>\n <option value=\"claude-react\">Claude React (JSX)</option>\n <option value=\"mdx\">Legacy MDX</option>\n </select>\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {editKind === 'mdx' ? 'Plan MDX' : 'Source'}\n </span>\n <Textarea\n value={editSource}\n rows={editKind === 'claude-react' ? 12 : 8}\n onChange={(e) => setEditSource((e.target as HTMLTextAreaElement).value)}\n data-testid={`artifact-edit-source-${slug}`}\n />\n </label>\n {error !== null && (\n <span role=\"alert\" data-testid={`artifact-edit-error-${slug}`} style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Inline gap={1}>\n <Button\n variant=\"primary\"\n disabled={busy || !dirty}\n onClick={() => void save()}\n data-testid={`artifact-edit-save-${slug}`}\n >\n {busy ? 'Saving…' : 'Save'}\n </Button>\n <Button\n variant=\"ghost\"\n disabled={busy || !dirty}\n onClick={() => {\n setEditKind(payload.kind || 'mdx');\n setEditSource(payload.source ?? payload.planMdx ?? '');\n setError(null);\n }}\n data-testid={`artifact-edit-revert-${slug}`}\n >\n Revert\n </Button>\n </Inline>\n </Stack>\n )}\n </Stack>\n );\n}"],"names":["FileCode","createLucideIcon","ClaudeArtifactView","payload","slug","showSource","setShowSource","useState","jsx","Card","CardBody","jsxs","Inline","ShieldCheck","Stack","AlertTriangle","w","i","Button","v","ExternalLink","ArtifactsView","useFetch","confirmDelete","setConfirmDelete","adding","setAdding","activeSlug","setActiveSlug","error","setError","artifacts","useMemo","_a","refresh","useCallback","drop","fetchJson","err","FetchError","ViewHeader","RefreshCcw","Plus","Skeleton","EmptyState","Layers","isConfirming","cur","Trash2","Sheet","SheetContent","AddForm","body","open","ArtifactDetail","onSubmit","onCancel","setSlug","title","setTitle","description","setDescription","kind","setKind","source","setSource","KIND_TEMPLATES","busy","setBusy","onKindChange","next","Input","e","Textarea","renderPayload","isClaude","Editor","onSaved","initial","editKind","setEditKind","editSource","setEditSource","setOpen","useEffect","dirty","save"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import{c as y,g as d}from"./main-Cxeu4LhG.js";import{r as f,j as t}from"./cmdk-DVxytz9i.js";/**
|
|
2
|
-
* @license lucide-react v0.460.0 - ISC
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the ISC license.
|
|
5
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const R=y("GitBranch",[["line",{x1:"6",x2:"6",y1:"3",y2:"15",key:"17qcm7"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}],["path",{d:"M18 9a9 9 0 0 1-9 9",key:"n2h4wq"}]]),I=f.forwardRef(function(r,a){const{tone:e="info",children:s,action:i,className:o,...l}=r;return t.jsxs("div",{ref:a,role:e==="danger"?"alert":"status",className:d("v8-banner",`v8-banner--${e}`,o),style:{display:"flex",alignItems:"center",gap:"var(--space-3)",padding:"var(--space-3) var(--space-4)",background:`color-mix(in oklch, var(--${e}) 8%, var(--surface-1))`,borderBottom:"1px solid var(--border)",fontSize:"var(--fs-13)",color:"var(--fg)"},...l,children:[t.jsx("div",{style:{flex:1,minWidth:0},children:s}),i!==void 0&&t.jsx("div",{style:{flexShrink:0},children:i})]})}),v={xs:20,sm:24,md:32,lg:40,xl:56},b={xs:"var(--fs-12)",sm:"var(--fs-12)",md:"var(--fs-13)",lg:"var(--fs-14)",xl:"var(--fs-18)"},k={online:"var(--success)",offline:"var(--fg-subtle)",busy:"var(--danger)",away:"var(--warning)"};function j(n){var s,i;const r=n.trim().split(/\s+/);if(r.length===0||r[0]===void 0)return"?";if(r.length===1)return(r[0]??"").slice(0,2).toUpperCase();const a=((s=r[0])==null?void 0:s[0])??"",e=((i=r[r.length-1])==null?void 0:i[0])??"";return`${a}${e}`.toUpperCase()}function S(n){let r=0;for(let a=0;a<n.length;a++)r=r*31+n.charCodeAt(a)|0;return Math.abs(r)}const h=["oklch(0.65 0.15 240)","oklch(0.65 0.15 30)","oklch(0.65 0.15 140)","oklch(0.65 0.15 320)","oklch(0.65 0.15 80)","oklch(0.65 0.15 200)"],M=f.forwardRef(function(r,a){const{name:e,src:s,size:i="md",initials:o,status:l,className:u,style:x,...p}=r,c=v[i],m=o??j(e),g=h[S(e)%h.length];return t.jsxs("span",{ref:a,className:d("v8-avatar",`v8-avatar--${i}`,u),style:{position:"relative",display:"inline-flex",alignItems:"center",justifyContent:"center",width:c,height:c,borderRadius:"var(--radius-pill)",overflow:"hidden",background:g,color:"white",fontSize:b[i],fontWeight:600,flexShrink:0,userSelect:"none",...x},"aria-label":e,...p,children:[s!==void 0?t.jsx("img",{src:s,alt:"",style:{width:"100%",height:"100%",objectFit:"cover"}}):m,l!==void 0&&t.jsx("span",{"aria-hidden":"true",style:{position:"absolute",bottom:0,right:0,width:Math.max(6,Math.floor(c*.28)),height:Math.max(6,Math.floor(c*.28)),borderRadius:"var(--radius-pill)",background:k[l],border:"2px solid var(--surface-0)"}})]})});f.forwardRef(function(r,a){const{children:e,size:s="sm",className:i,style:o,...l}=r;return t.jsx("div",{ref:a,className:d("v8-avatar-stack",i),style:{display:"inline-flex",alignItems:"center",...o},...l,children:t.jsx(w,{size:s,children:e})})});function w({children:n,size:r}){const a=v[r];return t.jsx(t.Fragment,{children:Array.isArray(n)?n.map((e,s)=>t.jsx("span",{style:{marginLeft:s===0?0:-Math.floor(a*.3),border:"2px solid var(--surface-0)",borderRadius:"var(--radius-pill)",display:"inline-flex"},children:e},s)):t.jsx("span",{style:{border:"2px solid var(--surface-0)",borderRadius:"var(--radius-pill)"},children:n})})}export{M as A,I as B,R as G};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Avatar-B41upSD1.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/git-branch.js","../../src/web/v8/ui/feedback/Banner.tsx","../../src/web/v8/ui/data/Avatar.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 GitBranch = createLucideIcon(\"GitBranch\", [\n [\"line\", { x1: \"6\", x2: \"6\", y1: \"3\", y2: \"15\", key: \"17qcm7\" }],\n [\"circle\", { cx: \"18\", cy: \"6\", r: \"3\", key: \"1h7g24\" }],\n [\"circle\", { cx: \"6\", cy: \"18\", r: \"3\", key: \"fqmcym\" }],\n [\"path\", { d: \"M18 9a9 9 0 0 1-9 9\", key: \"n2h4wq\" }]\n]);\n\nexport { GitBranch as default };\n//# sourceMappingURL=git-branch.js.map\n","import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cx } from '../utils/cx.js';\n\n/**\n * Banner — a top-of-page contextual announcement.\n *\n * Use sparingly. Distinct from StatusBar (which is system-level) and\n * Alert (which is inline). Banner occupies its own row above the page header.\n */\nexport interface BannerProps extends HTMLAttributes<HTMLDivElement> {\n tone?: 'info' | 'warning' | 'success' | 'danger';\n children: ReactNode;\n action?: ReactNode;\n}\n\nexport const Banner = forwardRef<HTMLDivElement, BannerProps>(function Banner(props, ref) {\n const { tone = 'info', children, action, className, ...rest } = props;\n return (\n <div\n ref={ref}\n role={tone === 'danger' ? 'alert' : 'status'}\n className={cx('v8-banner', `v8-banner--${tone}`, className)}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-3)',\n padding: 'var(--space-3) var(--space-4)',\n background: `color-mix(in oklch, var(--${tone}) 8%, var(--surface-1))`,\n borderBottom: '1px solid var(--border)',\n fontSize: 'var(--fs-13)',\n color: 'var(--fg)',\n }}\n {...rest}\n >\n <div style={{ flex: 1, minWidth: 0 }}>{children}</div>\n {action !== undefined && <div style={{ flexShrink: 0 }}>{action}</div>}\n </div>\n );\n});","import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cx } from '../utils/cx.js';\n\n/**\n * Avatar — user/agent representation. Falls back to initials when no image.\n *\n * Sizes: xs (20) | sm (24) | md (32) | lg (40) | xl (56).\n * Renders a <span> by default; use `asChild` to swap for a button/link.\n */\nexport type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {\n name: string;\n src?: string;\n size?: AvatarSize;\n /** Override the generated initials. */\n initials?: string;\n /** Optional status dot (online/offline/busy). */\n status?: 'online' | 'offline' | 'busy' | 'away';\n}\n\nconst SIZE_PX: Record<AvatarSize, number> = { xs: 20, sm: 24, md: 32, lg: 40, xl: 56 };\nconst SIZE_FS: Record<AvatarSize, string> = {\n xs: 'var(--fs-12)',\n sm: 'var(--fs-12)',\n md: 'var(--fs-13)',\n lg: 'var(--fs-14)',\n xl: 'var(--fs-18)',\n};\n\nconst STATUS_FG = {\n online: 'var(--success)',\n offline: 'var(--fg-subtle)',\n busy: 'var(--danger)',\n away: 'var(--warning)',\n} as const;\n\nfunction deriveInitials(name: string): string {\n const parts = name.trim().split(/\\s+/);\n if (parts.length === 0 || parts[0] === undefined) return '?';\n if (parts.length === 1) {\n const first = parts[0] ?? '';\n return first.slice(0, 2).toUpperCase();\n }\n const first = parts[0]?.[0] ?? '';\n const last = parts[parts.length - 1]?.[0] ?? '';\n return `${first}${last}`.toUpperCase();\n}\n\n// Deterministic color from name — used as fallback when no image.\nfunction hashName(name: string): number {\n let h = 0;\n for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) | 0;\n return Math.abs(h);\n}\n\nconst FALLBACK_PALETTE = [\n 'oklch(0.65 0.15 240)',\n 'oklch(0.65 0.15 30)',\n 'oklch(0.65 0.15 140)',\n 'oklch(0.65 0.15 320)',\n 'oklch(0.65 0.15 80)',\n 'oklch(0.65 0.15 200)',\n];\n\nexport const Avatar = forwardRef<HTMLSpanElement, AvatarProps>(function Avatar(props, ref) {\n const { name, src, size = 'md', initials, status, className, style, ...rest } = props;\n const px = SIZE_PX[size];\n const init = initials ?? deriveInitials(name);\n const fallbackBg = FALLBACK_PALETTE[hashName(name) % FALLBACK_PALETTE.length];\n\n return (\n <span\n ref={ref}\n className={cx('v8-avatar', `v8-avatar--${size}`, className)}\n style={{\n position: 'relative',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: px,\n height: px,\n borderRadius: 'var(--radius-pill)',\n overflow: 'hidden',\n background: fallbackBg,\n color: 'white',\n fontSize: SIZE_FS[size],\n fontWeight: 600,\n flexShrink: 0,\n userSelect: 'none',\n ...style,\n }}\n aria-label={name}\n {...rest}\n >\n {src !== undefined ? (\n <img\n src={src}\n alt=\"\"\n style={{ width: '100%', height: '100%', objectFit: 'cover' }}\n />\n ) : (\n init\n )}\n {status !== undefined && (\n <span\n aria-hidden=\"true\"\n style={{\n position: 'absolute',\n bottom: 0,\n right: 0,\n width: Math.max(6, Math.floor(px * 0.28)),\n height: Math.max(6, Math.floor(px * 0.28)),\n borderRadius: 'var(--radius-pill)',\n background: STATUS_FG[status],\n border: '2px solid var(--surface-0)',\n }}\n />\n )}\n </span>\n );\n});\n\n/**\n * AvatarStack — overlapping avatars. Use for \"assigned to N people\" lists.\n */\nexport interface AvatarStackProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n size?: AvatarSize;\n max?: number;\n}\n\nexport const AvatarStack = forwardRef<HTMLDivElement, AvatarStackProps>(function AvatarStack(\n props,\n ref,\n) {\n const { children, size = 'sm', className, style, ...rest } = props;\n return (\n <div\n ref={ref}\n className={cx('v8-avatar-stack', className)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n ...style,\n }}\n {...rest}\n >\n <StackedChildren size={size}>{children}</StackedChildren>\n </div>\n );\n});\n\nfunction StackedChildren({ children, size }: { children: ReactNode; size: AvatarSize }) {\n const px = SIZE_PX[size];\n return (\n <>\n {Array.isArray(children)\n ? children.map((child, i) => (\n <span\n key={i}\n style={{\n marginLeft: i === 0 ? 0 : -Math.floor(px * 0.3),\n border: '2px solid var(--surface-0)',\n borderRadius: 'var(--radius-pill)',\n display: 'inline-flex',\n }}\n >\n {child}\n </span>\n ))\n : <span style={{ border: '2px solid var(--surface-0)', borderRadius: 'var(--radius-pill)' }}>{children}</span>}\n </>\n );\n}"],"names":["GitBranch","createLucideIcon","Banner","forwardRef","props","ref","tone","children","action","className","rest","jsxs","cx","jsx","SIZE_PX","SIZE_FS","STATUS_FG","deriveInitials","name","parts","first","_a","last","_b","hashName","h","i","FALLBACK_PALETTE","Avatar","src","size","initials","status","style","px","init","fallbackBg","StackedChildren","Fragment","child"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import{r as c,j as t}from"./cmdk-DVxytz9i.js";import{c as V,u as R,a as J,S as T,I as w,d as S,G as q,h as $,i as D,F as I}from"./main-Cxeu4LhG.js";import{V as K}from"./ViewHeader-B6P-C4GD.js";import{C as A,b as H}from"./Card-rF59wHiO.js";import{T as G}from"./Textarea-QuofpMlq.js";import{E as L}from"./EmptyState-D65J5FQN.js";import{E as Y,M as W}from"./MessageBubble-5vUAquDx.js";import{R as _}from"./refresh-cw-ENBVR8hW.js";import{S as Q}from"./send-yz6HFZM5.js";/**
|
|
2
|
-
* @license lucide-react v0.460.0 - ISC
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the ISC license.
|
|
5
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const B=V("MessageSquarePlus",[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z",key:"1lielz"}],["path",{d:"M12 7v6",key:"lw1j43"}],["path",{d:"M9 10h6",key:"9gxzsh"}]]);async function U(a,k,d){const{signal:i,onChunk:u,onEvent:g,onDone:l,onError:h}=d;try{const n=await fetch(a,{...k,signal:i});if(!n.ok||n.body===null)throw new Error(`HTTP ${n.status} reading ${a}`);const E=n.body.getReader(),b=new TextDecoder;let m="",C=!1;for(;!C&&!(i!=null&&i.aborted);){const{value:o,done:M}=await E.read();if(M)break;m+=b.decode(o,{stream:!0});const v=m.split(`
|
|
7
|
-
|
|
8
|
-
`);m=v.pop()??"";for(const x of v){const P=x.split(`
|
|
9
|
-
`).filter(f=>f.length>0);let p="",y="message";for(const f of P)f.startsWith("data:")?p+=f.slice(5).trim():f.startsWith("event:")&&(y=f.slice(6).trim());if(p.length!==0){if(y==="done"){C=!0,l==null||l();break}y!=="message"?g==null||g(y,p):u==null||u(p)}}}l==null||l()}catch(n){if(i!=null&&i.aborted)return;h==null||h(n instanceof Error?n:new Error(String(n)))}}function oe(){const a=R("/api/chat"),k=R("/api/chat/sessions"),[d,i]=c.useState(null),[u,g]=c.useState([]),[l,h]=c.useState(""),[n,E]=c.useState(""),[b,m]=c.useState(!1),[C,o]=c.useState(null),[M,v]=c.useState(null);c.useEffect(()=>{var e;d===null&&((e=a.data)!=null&&e.sessions.length)&&i(a.data.sessions[0].id)},[a.data,d]),c.useEffect(()=>{if(!a.data||d===null){g([]);return}g(a.data.messages.filter(e=>{var s;return((s=a.data)==null?void 0:s.sessions.find(j=>j.id===d))!==void 0}))},[a.data,d]);const x=c.useMemo(()=>{var e;return(((e=a.data)==null?void 0:e.sessions)??[]).map(s=>({id:s.id,messageCount:s.size>0?Math.floor(s.size/200):0}))},[a.data]),P=c.useCallback(e=>{e.type==="chat:message"&&e.message&&a.refetch()},[a]);J("chat:message",P);const p=async()=>{const e=n.trim();if(!e||b)return;o(null),m(!0),E("");const s={id:`local_${Date.now().toString(36)}`,ts:new Date().toISOString(),role:"user",content:e};g(r=>[...r,s]),h("");const j=new AbortController;try{await U("/api/chat",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({message:e,session:d??void 0})},{signal:j.signal,onChunk:r=>h(z=>z+r),onEvent:(r,z)=>{if(r==="session")try{const O=JSON.parse(z);O.session&&i(O.session)}catch{}else r==="error"&&o(z)},onDone:()=>h(""),onError:r=>o(r.message)}),a.refetch(),k.refetch()}catch(r){o(r instanceof Error?r.message:String(r))}finally{m(!1),h("")}},y=async()=>{var e;o(null);try{const s=await D("/api/chat/sessions",{method:"POST",body:{}});(e=s.session)!=null&&e.id&&(i(s.session.id),a.refetch(),k.refetch())}catch(s){o((s instanceof I,s.message))}},f=async e=>{o(null);try{await D("/api/chat/regenerate",{method:"POST",body:{messageId:e.id,session:d}}),a.refetch()}catch(s){o((s instanceof I,s.message))}},F=async()=>{o(null);try{await D("/api/chat/audit",{method:"POST",body:{session:d}})}catch(e){o((e instanceof I,e.message))}},N=e=>{v(s=>s===e?null:e)};return t.jsxs(T,{gap:4,"data-testid":"chat-view",children:[t.jsx(K,{title:"Chat",description:"Multi-turn Claude Code sessions for the active project. Streams over WebSocket.",actions:t.jsxs(w,{gap:2,align:"center",children:[C!==null&&t.jsx("span",{role:"alert","data-testid":"chat-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:C}),t.jsxs(S,{variant:"ghost",onClick:()=>void a.refetch(),"data-testid":"chat-refresh",children:[t.jsx(_,{size:14,"aria-hidden":!0})," Refresh"]}),t.jsxs(S,{variant:"ghost",onClick:()=>void F(),"data-testid":"chat-audit",children:[t.jsx(q,{size:14,"aria-hidden":!0})," Audit"]}),t.jsxs(S,{variant:"primary",onClick:()=>void y(),"data-testid":"chat-create-session",children:[t.jsx(B,{size:14,"aria-hidden":!0})," New session"]})]})}),t.jsxs(w,{align:"stretch",gap:3,wrap:!1,style:{minHeight:480},children:[t.jsx(A,{variant:"default",style:{width:260,flexShrink:0},children:t.jsx(H,{children:t.jsxs(T,{gap:2,children:[t.jsxs("strong",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:["Sessions (",x.length,")"]}),a.loading&&x.length===0?t.jsx($,{style:{height:32}}):x.length===0?t.jsx(L,{icon:t.jsx(B,{size:28,"aria-hidden":!0}),title:"No sessions",description:"Create one to start chatting."}):x.map(e=>{const s=e.id===d,j=M===e.id;return t.jsxs("div",{"data-testid":`chat-session-${e.id}`,style:{padding:"var(--space-2)",borderRadius:"var(--radius-sm)",border:s?"1px solid var(--accent)":"1px solid var(--border)",background:s?"color-mix(in oklch, var(--accent) 12%, transparent)":"var(--surface-0)",cursor:"pointer"},onClick:()=>{j||i(e.id)},children:[t.jsxs(w,{align:"center",justify:"between",gap:2,children:[t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--fs-12)"},children:e.id}),t.jsx("button",{type:"button",onClick:r=>{r.stopPropagation(),N(e.id)},"data-testid":`chat-session-delete-${e.id}`,"aria-label":`Delete session ${e.id}`,style:{background:"transparent",border:0,color:"var(--fg-muted)",cursor:"pointer",fontSize:"var(--fs-11)"},children:"×"})]}),e.messageCount!==void 0&&t.jsxs("div",{style:{fontSize:"var(--fs-11)",color:"var(--fg-muted)"},children:[e.messageCount," messages"]}),j&&t.jsxs(w,{gap:1,style:{marginTop:"var(--space-1)"},children:[t.jsx(S,{variant:"danger",onClick:r=>{r.stopPropagation(),v(null)},"data-testid":`chat-session-confirm-delete-${e.id}`,children:"Confirm delete"}),t.jsx(S,{variant:"ghost",onClick:r=>{r.stopPropagation(),v(null)},"data-testid":`chat-session-cancel-delete-${e.id}`,children:"Cancel"})]})]},e.id)})]})})}),t.jsx(A,{variant:"default",style:{flex:1,minWidth:0},children:t.jsx(H,{children:t.jsxs(T,{gap:2,style:{height:"100%"},children:[t.jsx("div",{"data-testid":"chat-transcript",style:{flex:1,minHeight:320,overflowY:"auto",padding:"var(--space-2)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",background:"var(--surface-0)"},children:a.loading&&u.length===0?t.jsx($,{style:{height:200}}):u.length===0&&l===""?t.jsx(Y,{}):t.jsxs(T,{gap:1,children:[u.map(e=>t.jsx(W,{message:e,onRegenerate:s=>void f(s)},e.id)),l!==""&&t.jsx(W,{message:{id:"streaming",ts:new Date().toISOString(),role:"assistant",content:l}})]})}),t.jsxs(w,{align:"end",gap:2,children:[t.jsx("span",{style:{flex:1,color:"var(--fg-muted)",fontSize:"var(--fs-11)"},children:"Enter to send · Shift+Enter newline"}),t.jsxs(S,{variant:"primary",onClick:()=>void p(),disabled:b||n.trim()==="","data-testid":"chat-send",children:[t.jsx(Q,{size:14,"aria-hidden":!0})," ",b?"Sending…":"Send"]})]}),t.jsx(G,{value:n,placeholder:"Ask Claude anything…",rows:4,"data-testid":"chat-input",onChange:e=>E(e.target.value),onKeyDown:e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),p())}})]})})})]})]})}export{oe as ChatView};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ChatView-CUriVEgU.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/message-square-plus.js","../../src/web/v8/ui/chat/EventStream.tsx","../../src/web/v8/views/Chat/ChatView.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 MessageSquarePlus = createLucideIcon(\"MessageSquarePlus\", [\n [\"path\", { d: \"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\", key: \"1lielz\" }],\n [\"path\", { d: \"M12 7v6\", key: \"lw1j43\" }],\n [\"path\", { d: \"M9 10h6\", key: \"9gxzsh\" }]\n]);\n\nexport { MessageSquarePlus as default };\n//# sourceMappingURL=message-square-plus.js.map\n","/**\n * v8/ui/chat/EventStream.tsx — text/event-stream reader.\n *\n * Thin helper over `fetch()` that parses `data:` lines from a server\n * response and yields each event to a callback. Used by the chat\n * composer (POST /api/chat sends, response is a stream) and by the\n * Claude session detail (GET /api/claude-sessions/:id/stream).\n *\n * The server emits either:\n * - JSON envelopes per line (`fetchJson`-compatible), used when\n * handlers prefer that shape;\n * - SSE-formatted `data:` lines for streaming tokens.\n *\n * This reader handles both. JSON-only payloads (no `data:` prefix)\n * are forwarded verbatim. `event:` lines are split into separate\n * callbacks when present.\n */\n\nexport interface EventStreamHandlers {\n onChunk?: (text: string) => void;\n onEvent?: (event: string, data: string) => void;\n onDone?: () => void;\n onError?: (err: Error) => void;\n}\n\nexport interface EventStreamOptions extends EventStreamHandlers {\n signal?: AbortSignal;\n}\n\nexport async function readEventStream(\n url: string,\n init: RequestInit,\n handlers: EventStreamOptions,\n): Promise<void> {\n const { signal, onChunk, onEvent, onDone, onError } = handlers;\n try {\n const response = await fetch(url, { ...init, signal });\n if (!response.ok || response.body === null) {\n throw new Error(`HTTP ${response.status} reading ${url}`);\n }\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let sawDone = false;\n // pump until the stream is fully drained or the caller aborts\n while (!sawDone) {\n if (signal?.aborted) break;\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n // SSE frames are separated by a blank line. Split and process.\n const frames = buffer.split('\\n\\n');\n buffer = frames.pop() ?? '';\n for (const frame of frames) {\n const lines = frame.split('\\n').filter((l) => l.length > 0);\n let data = '';\n let event = 'message';\n for (const line of lines) {\n if (line.startsWith('data:')) {\n data += line.slice(5).trim();\n } else if (line.startsWith('event:')) {\n event = line.slice(6).trim();\n }\n }\n if (data.length === 0) continue;\n if (event === 'done') {\n sawDone = true;\n onDone?.();\n break;\n }\n if (event !== 'message') {\n onEvent?.(event, data);\n } else {\n onChunk?.(data);\n }\n }\n }\n onDone?.();\n } catch (err) {\n if (signal?.aborted) return;\n onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n}\n","/**\n * v8/views/Chat/ChatView.tsx — Sprint S38, v9.3.0.\n *\n * Three-pane chat surface: session list (left) · transcript (center) ·\n * composer (bottom). Backed by `/api/chat` + `/api/chat/sessions` +\n * `/api/chat/regenerate` + `/api/chat/audit`. Live deltas arrive via\n * the `chat:delta` / `chat:message` WS events added in S37.\n *\n * No window.confirm / window.prompt. Session creation uses an inline\n * `+` button that POSTs and selects the new session on success.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { MessageSquarePlus, RefreshCw, Send, ShieldCheck } 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 { Textarea } from '../../ui/controls/Textarea.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { useWsMessage } from '../../data/useWebSocket.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport { MessageBubble, EmptyTranscript } from '../../ui/chat/MessageBubble.js';\nimport { readEventStream } from '../../ui/chat/EventStream.js';\nimport type { ChatMessage, ChatSession, WsMessage } from '../../data/types.js';\n\ninterface ChatPayload {\n messages: ChatMessage[];\n sessions: Array<{ id: string; file: string; mtime: number; size: number }>;\n}\n\ninterface SessionsPayload {\n sessions: Array<{ id: string; title?: string; updatedAt?: number; messageCount?: number; agent?: string | null }>;\n}\n\nfunction fmtRel(ts: number | undefined): string {\n if (!ts) return '';\n const delta = Math.max(0, Date.now() - ts);\n if (delta < 60_000) return 'just now';\n if (delta < 3_600_000) return `${Math.round(delta / 60_000)}m ago`;\n if (delta < 86_400_000) return `${Math.round(delta / 3_600_000)}h ago`;\n return new Date(ts).toLocaleString();\n}\n\nexport function ChatView(): JSX.Element {\n const payload = useFetch<ChatPayload>('/api/chat');\n const sessionsPayload = useFetch<SessionsPayload>('/api/chat/sessions');\n const [activeId, setActiveId] = useState<string | null>(null);\n const [transcript, setTranscript] = useState<ChatMessage[]>([]);\n const [streaming, setStreaming] = useState<string>('');\n const [draft, setDraft] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n const [confirmDeleteId, setConfirmDeleteId] = useState<string | null>(null);\n\n // Seed active session from the first row in the response.\n useEffect(() => {\n if (activeId === null && payload.data?.sessions.length) {\n setActiveId(payload.data.sessions[0].id);\n }\n }, [payload.data, activeId]);\n\n // Seed transcript from payload when active session changes.\n useEffect(() => {\n if (!payload.data || activeId === null) {\n setTranscript([]);\n return;\n }\n setTranscript(payload.data.messages.filter((m) => payload.data?.sessions.find((s) => s.id === activeId) !== undefined));\n }, [payload.data, activeId]);\n\n const sessions = useMemo<ChatSession[]>(() => {\n return (payload.data?.sessions ?? []).map((s) => ({\n id: s.id,\n messageCount: s.size > 0 ? Math.floor(s.size / 200) : 0,\n }));\n }, [payload.data]);\n\n const onChange = useCallback((msg: WsMessage) => {\n if (msg.type === 'chat:message' && msg.message) {\n // A new persisted turn arrived for the active session; refresh the transcript.\n void payload.refetch();\n }\n }, [payload]);\n useWsMessage('chat:message', onChange);\n\n const send = async (): Promise<void> => {\n const text = draft.trim();\n if (!text || busy) return;\n setError(null);\n setBusy(true);\n setDraft('');\n const optimistic: ChatMessage = {\n id: `local_${Date.now().toString(36)}`,\n ts: new Date().toISOString(),\n role: 'user',\n content: text,\n };\n setTranscript((prev) => [...prev, optimistic]);\n setStreaming('');\n const ctrl = new AbortController();\n try {\n await readEventStream(\n '/api/chat',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ message: text, session: activeId ?? undefined }),\n },\n {\n signal: ctrl.signal,\n onChunk: (chunk) => setStreaming((cur) => cur + chunk),\n onEvent: (event, data) => {\n if (event === 'session') {\n try {\n const parsed = JSON.parse(data) as { session?: string };\n if (parsed.session) setActiveId(parsed.session);\n } catch { /* swallow */ }\n } else if (event === 'error') {\n setError(data);\n }\n },\n onDone: () => setStreaming(''),\n onError: (err) => setError(err.message),\n },\n );\n // After stream completes the persisted turn is in the JSONL log;\n // pull a fresh transcript.\n void payload.refetch();\n void sessionsPayload.refetch();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setBusy(false);\n setStreaming('');\n }\n };\n\n const createSession = async (): Promise<void> => {\n setError(null);\n try {\n const res = await fetchJson<{ session?: ChatSession }>(\n '/api/chat/sessions',\n { method: 'POST', body: {} },\n );\n if (res.session?.id) {\n setActiveId(res.session.id);\n void payload.refetch();\n void sessionsPayload.refetch();\n }\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const regenerate = async (msg: ChatMessage): Promise<void> => {\n setError(null);\n try {\n await fetchJson('/api/chat/regenerate', { method: 'POST', body: { messageId: msg.id, session: activeId } });\n void payload.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const audit = async (): Promise<void> => {\n setError(null);\n try {\n await fetchJson('/api/chat/audit', { method: 'POST', body: { session: activeId } });\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const dropSession = (id: string): void => {\n // Inline confirm row pattern from F-061. No window.confirm.\n setConfirmDeleteId((cur) => (cur === id ? null : id));\n };\n\n return (\n <Stack gap={4} data-testid=\"chat-view\">\n <ViewHeader\n title=\"Chat\"\n description=\"Multi-turn Claude Code sessions for the active project. Streams over WebSocket.\"\n actions={\n <Inline gap={2} align=\"center\">\n {error !== null && (\n <span role=\"alert\" data-testid=\"chat-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => void payload.refetch()} data-testid=\"chat-refresh\">\n <RefreshCw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"ghost\" onClick={() => void audit()} data-testid=\"chat-audit\">\n <ShieldCheck size={14} aria-hidden /> Audit\n </Button>\n <Button variant=\"primary\" onClick={() => void createSession()} data-testid=\"chat-create-session\">\n <MessageSquarePlus size={14} aria-hidden /> New session\n </Button>\n </Inline>\n }\n />\n <Inline align=\"stretch\" gap={3} wrap={false} style={{ minHeight: 480 }}>\n {/* Session list */}\n <Card variant=\"default\" style={{ width: 260, flexShrink: 0 }}>\n <CardBody>\n <Stack gap={2}>\n <strong style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n Sessions ({sessions.length})\n </strong>\n {payload.loading && sessions.length === 0 ? (\n <Skeleton style={{ height: 32 }} />\n ) : sessions.length === 0 ? (\n <EmptyState\n icon={<MessageSquarePlus size={28} aria-hidden />}\n title=\"No sessions\"\n description=\"Create one to start chatting.\"\n />\n ) : (\n sessions.map((s) => {\n const isActive = s.id === activeId;\n const isConfirmingDelete = confirmDeleteId === s.id;\n return (\n <div\n key={s.id}\n data-testid={`chat-session-${s.id}`}\n style={{\n padding: 'var(--space-2)',\n borderRadius: 'var(--radius-sm)',\n border: isActive ? '1px solid var(--accent)' : '1px solid var(--border)',\n background: isActive ? 'color-mix(in oklch, var(--accent) 12%, transparent)' : 'var(--surface-0)',\n cursor: 'pointer',\n }}\n onClick={() => { if (!isConfirmingDelete) setActiveId(s.id); }}\n >\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <span style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)' }}>\n {s.id}\n </span>\n <button\n type=\"button\"\n onClick={(e) => { e.stopPropagation(); dropSession(s.id); }}\n data-testid={`chat-session-delete-${s.id}`}\n aria-label={`Delete session ${s.id}`}\n style={{\n background: 'transparent',\n border: 0,\n color: 'var(--fg-muted)',\n cursor: 'pointer',\n fontSize: 'var(--fs-11)',\n }}\n >\n ×\n </button>\n </Inline>\n {s.messageCount !== undefined && (\n <div style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)' }}>\n {s.messageCount} messages\n </div>\n )}\n {isConfirmingDelete && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button\n variant=\"danger\"\n onClick={(e) => { e.stopPropagation(); setConfirmDeleteId(null); }}\n data-testid={`chat-session-confirm-delete-${s.id}`}\n >\n Confirm delete\n </Button>\n <Button\n variant=\"ghost\"\n onClick={(e) => { e.stopPropagation(); setConfirmDeleteId(null); }}\n data-testid={`chat-session-cancel-delete-${s.id}`}\n >\n Cancel\n </Button>\n </Inline>\n )}\n </div>\n );\n })\n )}\n </Stack>\n </CardBody>\n </Card>\n\n {/* Transcript + composer */}\n <Card variant=\"default\" style={{ flex: 1, minWidth: 0 }}>\n <CardBody>\n <Stack gap={2} style={{ height: '100%' }}>\n <div\n data-testid=\"chat-transcript\"\n style={{\n flex: 1,\n minHeight: 320,\n overflowY: 'auto',\n padding: 'var(--space-2)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n background: 'var(--surface-0)',\n }}\n >\n {payload.loading && transcript.length === 0 ? (\n <Skeleton style={{ height: 200 }} />\n ) : transcript.length === 0 && streaming === '' ? (\n <EmptyTranscript />\n ) : (\n <Stack gap={1}>\n {transcript.map((m) => (\n <MessageBubble key={m.id} message={m} onRegenerate={(msg) => void regenerate(msg)} />\n ))}\n {streaming !== '' && (\n <MessageBubble\n message={{\n id: 'streaming',\n ts: new Date().toISOString(),\n role: 'assistant',\n content: streaming,\n }}\n />\n )}\n </Stack>\n )}\n </div>\n <Inline align=\"end\" gap={2}>\n <span style={{ flex: 1, color: 'var(--fg-muted)', fontSize: 'var(--fs-11)' }}>\n Enter to send · Shift+Enter newline\n </span>\n <Button variant=\"primary\" onClick={() => void send()} disabled={busy || draft.trim() === ''} data-testid=\"chat-send\">\n <Send size={14} aria-hidden /> {busy ? 'Sending…' : 'Send'}\n </Button>\n </Inline>\n <Textarea\n value={draft}\n placeholder=\"Ask Claude anything…\"\n rows={4}\n data-testid=\"chat-input\"\n onChange={(e) => setDraft((e.target as HTMLTextAreaElement).value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n void send();\n }\n }}\n />\n </Stack>\n </CardBody>\n </Card>\n </Inline>\n </Stack>\n );\n}"],"names":["MessageSquarePlus","createLucideIcon","readEventStream","url","init","handlers","signal","onChunk","onEvent","onDone","onError","response","reader","decoder","buffer","sawDone","value","done","frames","frame","lines","l","data","event","line","err","ChatView","payload","useFetch","sessionsPayload","activeId","setActiveId","useState","transcript","setTranscript","streaming","setStreaming","draft","setDraft","busy","setBusy","error","setError","confirmDeleteId","setConfirmDeleteId","useEffect","_a","m","s","sessions","useMemo","onChange","useCallback","msg","useWsMessage","send","text","optimistic","prev","ctrl","chunk","cur","parsed","createSession","res","fetchJson","FetchError","regenerate","audit","dropSession","id","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCw","ShieldCheck","Card","CardBody","Skeleton","EmptyState","isActive","isConfirmingDelete","e","EmptyTranscript","MessageBubble","Send","Textarea"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as s,j as e}from"./cmdk-DVxytz9i.js";import{u as k,S as h,I as f,d as n,h as y,_ as w,i as S,F as z}from"./main-Cxeu4LhG.js";import{V as E}from"./ViewHeader-B6P-C4GD.js";import{C as T,b as D}from"./Card-rF59wHiO.js";import{I as b}from"./Input-CZmRw5QX.js";import{T as C}from"./Textarea-QuofpMlq.js";import{S as R,a as $}from"./Sheet-BOProMs2.js";import{E as L}from"./EmptyState-D65J5FQN.js";import{R as F}from"./refresh-ccw-DenGBOcq.js";import{P as I}from"./plus-77h62zZm.js";import{E as P}from"./external-link-D5tq2o_I.js";import{T as U}from"./trash-2-Cv7U38jw.js";function Q(){const l=k("/api/clipboard/list"),[v,r]=s.useState(!1),[x,o]=s.useState(null),[u,d]=s.useState(null),p=s.useMemo(()=>{var t;return((t=l.data)==null?void 0:t.clips)??[]},[l.data]),c=s.useCallback(()=>{l.refetch()},[l]),g=async t=>{d(null);try{await S(`/api/clipboard/${t}`,{method:"DELETE"}),o(null),c()}catch(i){d((i instanceof z,i.message))}};return e.jsxs(h,{gap:4,"data-testid":"clipboard-view",children:[e.jsx(E,{title:"Clipboard",description:"Saved clips. Each becomes a markdown note under clips/.",actions:e.jsxs(f,{align:"center",gap:2,children:[u!==null&&e.jsx("span",{role:"alert","data-testid":"clipboard-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:u}),e.jsxs(n,{variant:"ghost",onClick:()=>void c(),"data-testid":"clipboard-refresh",children:[e.jsx(F,{size:14,"aria-hidden":!0})," Refresh"]}),e.jsxs(n,{variant:"primary",onClick:()=>r(!0),"data-testid":"clipboard-add",children:[e.jsx(I,{size:14,"aria-hidden":!0})," Save clip"]})]})}),e.jsx(T,{variant:"default",children:e.jsx(D,{children:l.loading&&p.length===0?e.jsxs(h,{gap:1,children:[e.jsx(y,{style:{height:60}}),e.jsx(y,{style:{height:60}})]}):p.length===0?e.jsx(L,{icon:e.jsx(w,{size:28,"aria-hidden":!0}),title:"No saved clips",description:"Save one with a URL + content."}):e.jsx(h,{gap:1,children:p.map(t=>{const i=x===t.id;return e.jsxs("div",{"data-testid":`clipboard-row-${t.id}`,style:{padding:"var(--space-2)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)"},children:[e.jsxs(f,{align:"center",justify:"between",gap:2,children:[e.jsxs(h,{gap:0,style:{minWidth:0,flex:1},children:[e.jsxs(f,{align:"center",gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:t.title||t.id}),t.url&&e.jsxs("a",{href:t.url,target:"_blank",rel:"noreferrer",style:{fontSize:"var(--fs-11)",color:"var(--accent)"},children:[e.jsx(P,{size:10,"aria-hidden":!0,style:{verticalAlign:"middle"}})," ",t.url]}),t.savedAt&&e.jsx("span",{style:{fontSize:"var(--fs-11)",color:"var(--fg-subtle)"},children:t.savedAt})]}),(t.selection||t.content)&&e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:(t.selection||t.content||"").length>200?`${(t.selection||t.content||"").slice(0,200)}…`:t.selection||t.content})]}),e.jsx(n,{variant:"ghost",onClick:()=>o(m=>m===t.id?null:t.id),"data-testid":`clipboard-delete-${t.id}`,"aria-label":`Delete ${t.id}`,children:e.jsx(U,{size:14,"aria-hidden":!0})})]}),i&&e.jsxs(f,{gap:1,style:{marginTop:"var(--space-1)"},children:[e.jsx(n,{variant:"danger",onClick:()=>void g(t.id),"data-testid":`clipboard-confirm-delete-${t.id}`,children:"Confirm delete"}),e.jsx(n,{variant:"ghost",onClick:()=>o(null),children:"Cancel"})]})]},t.id)})})})}),e.jsx(R,{open:v,onOpenChange:r,children:e.jsx($,{side:"right",title:"Save clip",description:"URL or content required.",children:e.jsx(A,{onSubmit:async t=>{await S("/api/clipboard/save",{method:"POST",body:t}),r(!1),c()},onCancel:()=>r(!1)})})})]})}function A({onSubmit:l,onCancel:v}){const[r,x]=s.useState(""),[o,u]=s.useState(""),[d,p]=s.useState(""),[c,g]=s.useState(""),[t,i]=s.useState(!1),[m,j]=s.useState(null);return e.jsxs(h,{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:"URL (optional)"}),e.jsx(b,{value:r,onChange:a=>x(a.target.value),"data-testid":"clipboard-form-url"})]}),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:"Title (optional)"}),e.jsx(b,{value:o,onChange:a=>u(a.target.value),"data-testid":"clipboard-form-title"})]}),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:"Content"}),e.jsx(C,{value:d,rows:6,onChange:a=>p(a.target.value),"data-testid":"clipboard-form-content"})]}),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:"Selection (optional)"}),e.jsx(C,{value:c,rows:3,onChange:a=>g(a.target.value),"data-testid":"clipboard-form-selection"})]}),m!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:m}),e.jsxs(f,{justify:"end",gap:2,children:[e.jsx(n,{variant:"ghost",onClick:v,children:"Cancel"}),e.jsx(n,{variant:"primary",disabled:t||!r.trim()&&!d.trim(),"data-testid":"clipboard-form-submit",onClick:async()=>{i(!0),j(null);try{await l({url:r.trim()||void 0,title:o.trim()||void 0,content:d.trim()||void 0,selection:c.trim()||void 0})}catch(a){j((a instanceof z,a.message)),i(!1)}},children:t?"Saving…":"Save"})]})]})}export{Q as ClipboardView};
|